pax_global_header00006660000000000000000000000064150655663010014521gustar00rootroot0000000000000052 comment=dbf36d9c67a667ec3c1986e2e52f3ebc707185ab TreeLine-3.2.1/000077500000000000000000000000001506556630100132335ustar00rootroot00000000000000TreeLine-3.2.1/.gitignore000066400000000000000000000000511506556630100152170ustar00rootroot00000000000000*.pyc *~ *.swp */__pycache__/ *.hgignore TreeLine-3.2.1/README.md000066400000000000000000000013511506556630100145120ustar00rootroot00000000000000# What is TreeLine? Do you have lots of sticky notes lying around with various useful information jotted down? Or many lists of books, movies, website logins, personal contacts, or things to do? Can you find them when you need them? Well, I often couldn't. So here's my answer. Some would call TreeLine an Outliner, others would call it a PIM. Basically, it just stores almost any kind of information. A tree structure makes it easy to keep things organized. And each node in the tree can contain several fields, forming a mini-database. The output format for each node can be defined, and the output can be shown on the screen, printed, or exported to html. # More Info See the [TreeLine homepage](http://treeline.bellz.org) for more info. TreeLine-3.2.1/doc/000077500000000000000000000000001506556630100140005ustar00rootroot00000000000000TreeLine-3.2.1/doc/INSTALL000066400000000000000000000011401506556630100150250ustar00rootroot00000000000000TreeLine Installation Notes Extract the source files from the treeline tar file, then change to the 'TreeLine' directory in a terminal. For a basic installation, simply execute the following command as root: 'python install.py' If your distribution defaults to Python 2.x, you may need to substitute "python3", "python3.9" or "python3.10" for "python" in these commands. To see all install options, use: 'python install.py -h'. To install TreeLine with a different prefix (the default is '/usr/local'), use: 'python install.py -p /prefix/path'. To skip dependency checks, use: 'python install.py -x'. TreeLine-3.2.1/doc/LICENSE000066400000000000000000000431031506556630100150060ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. TreeLine-3.2.1/doc/basichelp.html000066400000000000000000000122421506556630100166210ustar00rootroot00000000000000 basichelp Views
Tree View - The left-hand view shows a tree of node titles. Parent nodes can be opened and closed to display or hide their indented descendant nodes. Clicking on an already selected node allows the title to be edited. Right-click context menus are available for commonly used functions.

Breadcrumb View - The top pane shows the parent and ancestors of the selected node. It is blank if no nodes or multiple nodes are selected. Ancestors with blue text can be clicked to select those nodes.

Right-hand Views - The right pane is tabbed to show one of three different views of the data. The "Data Output" view shows the formatted text, the "Data Edit" view shows text edit boxes, and the "Title List" view shows an editable list of node titles.

When a parent node is selected in the tree, the right view will default to showing information about the selected node in an upper pane and information about the selected node's children in a lower pane. The "View > Show Child Pane" command will toggle the display of the child nodes. If the selected node has no children, the view will show a single pane with information about the selected node only.

When multiple nodes are selected in the tree (by holding down the shift or Ctrl keys while clicking), the right view will not display any child node information. It will instead show information about every selected node.

When no nodes are selected in the tree (by clicking on a blank area or Ctrl clicking to unselect), the right view will show information about the top-level (root) nodes.

Data Output View - The "Data Output" view shows formatted output text. It cannot be edited from this view.

When the "View > Show Output Descendants" command is toggled, the "Data Output" view will show an indented list with information about every descendant of a single selected node.

Data Edit View - The "Data Edit" view shows a text edit box for each data field within a node. It also shows the node types and the node titles. The types of edit boxes vary based on the field type. Some are just text editors, while others (such as choice fields, date fields, links, etc.) have pull-down menus or dialogs.

Title List View - The "Title List" view shows a list of node titles that can be modified using typical text editor methods. If a new line is typed, a new node is created with that title. If a line is deleted, the corresponding node is removed from the tree.

Editing
Node Menu - The commands in the "Node" menu operate on the selected nodes in the left tree view. There are commands to add or insert nodes, rename node titles and delete nodes. There are also commands to rearrange the tree by changing indent levels or moving nodes up or down. For many of the commands, the descendants of the selected nodes are also affected.

Edit Menu - The edit menu includes undo and redo commands that can fix problems. Cut, copy and paste commands can operate either on text in the right-hand view (if selected or active) or to tree nodes.

Format Menu - The format menu has text formatting commands that are active when using edit boxes in the Data Edit view.

Shortcuts - There are several shortcuts for use in tree editing. Drag and drop will move (or copy if the Ctrl button is held) nodes. Clicking on a selected node will rename it. Pressing the delete key will remove the selected nodes. If desired, these shortcuts can be disabled in "Tools > General Options".

Files
Templates - When starting a new file, a dialog box offers a choice of templates. The default has only a single text field for each node that contains the title. The Long Text template adds a second long text field for more output text. Other templates have various fields for contacts, book lists and to-do lists.

Sample Files - Various TreeLine sample files can be opened by using the "File > Open Sample" command. These have more detail and example content than the new file templates.

Data Types
Node Types - Multiple node data types can be defined in a TreeLine file. Each can contain different data fields and have different output formats. See the template and sample files for examples. Nodes can be set to a specific type using the "Data > Set Node Type" command.

Type Config - The "Data > Configure Data Types" command is used to modify node data types, fields and output formatting. Refer to the Detailed Usage section of the full documentation for details.
TreeLine-3.2.1/doc/basichelp_ru.html000066400000000000000000000372641506556630100173420ustar00rootroot00000000000000 basichelp <!-- Справка по о�новам --> Формы про�мотра (Views)
Панель Дерева (Tree View) - В панели �лева показывает�� дерево заголовков узлов. Родитель�кие узлы могут разворачивать�� и �ворачивать�� дл� показа или �крыти� их дочерних узлов - потомков, отображаемых � от�тупами. Щелчок по уже выбранному узлу позвол�ет редактировать его заголовок. Контек�тные меню, �одержащие ча�то и�пользуемые функции, могут вызывать�� по щелчку правой кнопкой мыши на узлах.

Панель �авигационной цепочки (Breadcrumb View) - �а верхней панели показывают�� родитель�кий �лемент и предки выбранного узла. Панель пу�та, е�ли не выбрано ни одного узла или выбрано не�колько узлов. По щелчку мыши на узлах предков, выделенных �иним цветом, можно выбрать и перейти к �тим узлам.

Панели Справа (Right-hand Views) - Панель �права �одержит вкладки, показывающие одно из трех различных пред�тавлений данных. Во вкладке «Вывод данных» ("Data Output") показывает�� отформатированный тек�т, во вкладке «Редактор Данных» ("Data Edit") отображают�� пол� дл� редактировани� тек�та, а во вкладке «Спи�ок заголовков» редактируемый �пи�ок заголовков узлов, выбранных в панели дерева.

Когда в дереве выбран родитель�кий узел, на панели �права по умолчанию будет отображать�� информаци� о выбранном узле на верхней ча�ти панели и информаци� о дочерних �лементах выбранного узла на нижней ча�ти панели. Команда "Вид > Показать Панель Дочернего Узла" ("View > Show Child Pane") будет переключать отображение дочерних узлов. Е�ли выбранный узел не имеет дочерних �лементов, во вкладке будет отображать�� одна панель � информацией только о выбранном узле.

Когда в дереве выбрано не�колько узлов (при удержании нажатой клавиши Shift или нажатии Ctrl), в панели �права не будет отображать�� информаци� о дочерних узлах. Вме�то �того будет показана информаци� о каждом выбранном узле.

Е�ли узлы в дереве не выбраны (при щелчке мышью в пу�той обла�ти или при нажатии кнопки мыши � одновременным нажатием Ctrl дл� отмены выбора узла), в панели �права отобразит�� информаци� об узле верхнего уровн� (корневом).

Панель «Вывод Данных» (Data Output View) - Во вкладке «Вывод Данных» отображает�� отформатированный дл� вывода тек�т. В �той панели тек�т не может редактировать��.

При переключении команды «Вид > Показать Вывод Потомков» ("View > Show Output Descendants") в панели «Вывод Данных» (Data Output View) отобразит�� �пи�ок �лементов � от�тупами, в котором каждый �лемент будет �одержать информацию о каждом потомке выбранного узла.

Панель «Редактор Данных» (Data Edit View) - Во вкладке «Редактор Данных» (Data Edit) отображают�� обла�ти редактировани� дл� каждого из полей данных в узле. В ней также показывают�� типы и заголовки [aka названи�] узлов. Типы обла�тей редактировани� различают�� в зави�имо�ти от типов полей. �екоторые из них �вл�ют�� про�то пол�ми дл� редактировани� тек�та, в то врем� как другие (например, пол� выбора, даты, ��ылок и т.д.) — выпадающими меню или диалоговыми окнами.

Панель «Спи�ок заголовков» (Title List View) - Во вкладке «Спи�ок Заголовков» ("Title List") отображает�� �пи�ок заголовков [aka названий] узлов, которые можно изменить [в �той панели] как в обычном тек�товом редакторе. Е�ли [при редактировании в �той панели] вводит�� нова� �трока, то [в результирующем дереве в �том ме�те] �оздает�� новый узел � �тим заголовком. Е�ли [при редактировании в �той панели] �трока удал�ет��, �оответ�твующий узел удал�ет�� из дерева.

Редактирование
Меню «Узел» (Node Menu) - Команды в меню «Узел» (Node) выполн�ют�� по отношению к выбранным узлам в панели � деревом, ра�полагающей�� �лева. Имеют�� команды дл� �оздани� или в�тавки узлов, переименовани� заголовков [aka имен] и удалени� узлов. В том чи�ле имеют�� команды дл� переупор�дочивани� �труктуры дерева, путем �мещени� узлов между уровн�ми и перемещени� их вверх или вниз. Многие команды также затрагивают потомков выбранных узлов.

Меню «Правка» (Edit Menu) - Меню «Правка» включает команды отмены и повтора, которые могут помочь и�править проблемы. Команды вырезани�, копировани� и в�тавки могут выполн�ть�� при редактировании тек�та в панели �права (е�ли она выбрана и активна) или к узлам в дереве.

Меню «Формат» (Format Menu) - В меню «Формат» наход�т�� команды форматировани� тек�та, которые �танов�т�� активными при и�пользовании обла�тей редактировани� в панели «Редактир Данных».

Бы�трый выбор команд (Shortcuts) - В приложении и�польуют�� не�колько �очетаний нажати� клавиш клавиатуры и мыши, примен�ющих�� при редактировании дерева. Перетащить и отпу�тить (drag and drop) переме�тит (или �копирует, е�ли удерживает�� кнопка Ctrl) узлы. Щелчок по выбранному узлу переименует его. �ажатие кнопки удалени� удалит выбранные узлы. При желании �ти команды можно отключить в меню «Ин�трументы > Общие Параметры» ("Tools > General Options").

Файлы
Шаблоны - Когда �оздает�� новый файл, открывает�� диалоговое окно, предлагающее выбрать один из шаблонов. По умолчанию в каждом узле имеет�� только одно тек�товое поле, �одержащее заголовок. В шаблон Длинный Тек�т (Long Text) добавлено второе поле типа Длинный Тек�т, предназначенное дл� вывода тек�та большого объема. В других шаблонах имеют�� различные пол� дл� контактов, �пи�ков книг и дел.

Файлы Примеров - При помощи команды «Файл > Открыть Пример» ("File > Open Sample") могут быть открыты различные файлы примеров TreeLine. В них �одержит�� более подробна� информаци�, чем в шаблонах новых файлов, и имеют�� образцы контента.

Типы Данных
Типы узлов - В файлах TreeLine можно определить разнообразные типы данных узла. Каждый тип узла может �одержать различные пол� данных и иметь различные форматы вывода. Смотрите примеры в файлах шаблонов и примеров. Узлам может быть при�воен конкретный тип при помощи команды «Данные > �азначить тип узла» ("Data > Set Node Type").

�а�тройка Типов - Команда «Данные > �а�троить Типы Данных» ("Data > Configure Data Types") примен�ет�� дл� изменени� типов данных узла, полей и форматировани� вывода. Обратите�ь к разделу Подробно�ти и�пользовани� в полной документации.
TreeLine-3.2.1/doc/documentation.trln000066400000000000000000006022571506556630100175660ustar00rootroot00000000000000{ "formats": [ { "bullets": true, "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Text", "fieldtype": "Text", "lines": 2 } ], "formathtml": true, "formatname": "BULLETS", "icon": "bullet_1", "outputlines": [ "{*Text*}" ], "spacebetween": false, "titleline": "{*Name*}" }, { "childtype": "BULLETS", "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "BULLET_HEADING", "outputlines": [ "{*Name*}" ], "spacebetween": false, "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "HEADINGS", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Text", "fieldtype": "Text", "lines": 8 } ], "formathtml": true, "formatname": "HEAD_PARA", "icon": "bullet_2", "outputlines": [ "{*Name*} - {*Text*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Text", "fieldtype": "Text", "lines": 8 } ], "formatname": "PARAGRAPH", "icon": "bullet_2", "outputlines": [ "{*Text*}" ], "titleline": "{*Name*}" } ], "nodes": [ { "children": [], "data": { "Name": "Minimize to system tray option", "Text": "A minimize to system tray option was added to General Options (under Features Available). If enabled, it adds a TreeLine system tray icon to toggle application display and hides the taskbar entry when TreeLine is minimized." }, "format": "BULLETS", "uid": "014e1392305b11e9ab99a44cc8e97404" }, { "children": [], "data": { "Name": "Minimize to tray", "Text": "A problem with the option to minimize to the system tray was fixed." }, "format": "BULLETS", "uid": "01d807fc9b0d11f091375847ca7850fa" }, { "children": [], "data": { "Name": "Automatic clone creation", "Text": "Cloned nodes can be created automatically from all identical nodes by using the \"Data > Clone All Matched Nodes\" command." }, "format": "BULLETS", "uid": "04a868f4bb0611e7aea13417ebd53aeb" }, { "children": [], "data": { "Name": "Multiple top-level nodes", "Text": "Multiple top-level (root) nodes are now permitted. When no nodes are selected in the tree (by clicking on a blank area or Ctrl clicking to unselect), the right-hand view will show information about all of the top-level nodes." }, "format": "BULLETS", "uid": "04da8386ba4811e7b3de3417ebd53aeb" }, { "children": [], "data": { "Name": "Updating multiple windows", "Text": "Properly update multiple windows after drag and drop tree changes." }, "format": "BULLETS", "uid": "0906c05bdc8f11ea94fbac675dac20af" }, { "children": [], "data": { "Name": "Reduce windows install size", "Text": "Some unnecessary libraries were eliminated from the Windows installer to reduce download sizes and installed space requirements." }, "format": "BULLETS", "uid": "10c539e2305c11e9a392a44cc8e97404" }, { "children": [], "data": { "Name": "Right view update", "Text": "Properly update the right-hand views after using a new window command." }, "format": "BULLETS", "uid": "145bd91a334c11e896b1d66a6ab671cb" }, { "children": [], "data": { "Name": "Avoid unfocused title edit", "Text": "A click on a tree node to restore tree focus no longer starts editing the node title." }, "format": "BULLETS", "uid": "15da7fde786a11e881c8a44cc8e97404" }, { "children": [], "data": { "Name": "Remove redundant newlines in files", "Text": "Some redundant newline characters were removed from text storage in TreeLine files." }, "format": "BULLETS", "uid": "192373c6305511e9ab21a44cc8e97404" }, { "children": [], "data": { "Name": "Restore data editor cursor & scroll positions", "Text": "Restore the cursor and scroll positions of data editors when the editors are re-created after focus changes." }, "format": "BULLETS", "uid": "194b052fe5d811e9a0d1a44cc8e97404" }, { "children": [ "3e749de3e5d811e98227a44cc8e97404", "194b0537e5d811e989a1a44cc8e97404", "194b0534e5d811e985f6a44cc8e97404" ], "data": { "Name": "October 6, 2019 - Release 3.1.2 (stable release)" }, "format": "HEADINGS", "uid": "194b0533e5d811e9b5fea44cc8e97404" }, { "children": [ "8cdb2406e5df11e9a06da44cc8e97404", "8e8e418ae5dc11e98404a44cc8e97404", "9139627ee5db11e98a21a44cc8e97404", "194b0536e5d811e991b3a44cc8e97404", "fcc1b718e5df11e9a7f9a44cc8e97404" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "194b0534e5d811e985f6a44cc8e97404" }, { "children": [], "data": { "Name": "Treepad import", "Text": "Fix error due to character encoding when importing files from Treepad." }, "format": "BULLETS", "uid": "194b0536e5d811e991b3a44cc8e97404" }, { "children": [ "194b052fe5d811e9a0d1a44cc8e97404", "ea0c9b24e79911e98abe7054d2175f18", "4212597ee5e011e99b51a44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "194b0537e5d811e989a1a44cc8e97404" }, { "children": [], "data": { "Name": "Enable evaluate HTML tags option", "Text": "The Evaluate HTML tags control was enabled for date, time, boolean and math fields. This allows HTML tags to be evaluated or ignored in more field types." }, "format": "BULLETS", "uid": "1b73aaf4305811e98bb7a44cc8e97404" }, { "children": [], "data": { "Name": "Remove unique ID", "Text": "To improve efficiency, user visible node unique IDs that depend on the node's data have been removed." }, "format": "BULLETS", "uid": "1d015318bb0511e7a2ac3417ebd53aeb" }, { "children": [], "data": { "Name": "Config dialog state", "Text": "Preserve the modified status of the config dialog when switching between windows displaying different files." }, "format": "BULLETS", "uid": "1db7e950fe8011edbb2654b2039ee1f3" }, { "children": [], "data": { "Name": "Reuse TreeLine windows", "Text": "When a file is opened in an existing window, the window is now reused (not just replaced) to eliminate flashing." }, "format": "BULLETS", "uid": "1e3a82e4bb0411e7b7f33417ebd53aeb" }, { "children": [], "data": { "Name": "Child type limits", "Text": "Fix a bug that prevented child type limits from being set back to all types." }, "format": "BULLETS", "uid": "1e7004a8fe8111edbb2654b2039ee1f3" }, { "children": [], "data": { "Name": "Current date/time math field references", "Text": "Added support for current date and time references to math fields. Special field names ({*Now_Date*}, {*Now_Time*} and {*Now_Date_Time*}) must be manually typed in equations." }, "format": "BULLETS", "uid": "221ca8f0305911e99f3fa44cc8e97404" }, { "children": [], "data": { "Name": "German outline nuimbering", "Text": "Add support for German outline numbering using double letters in some levels (thanks to Teresa M)." }, "format": "BULLETS", "uid": "228fa647dc8c11eab28aac675dac20af" }, { "children": [], "data": { "Name": "Empty data edit views", "Text": "Fix a bug in Data Edit views when no fields are visible due to hidden numbering or math fields." }, "format": "BULLETS", "uid": "23b9a763dc8b11ea9dafac675dac20af" }, { "children": [], "data": { "Name": "Save as without filename", "Text": "Fix a minor bug affecting default directories for save-as and export commands when there is not already a file name set." }, "format": "BULLETS", "uid": "25ab9320482011e989f27054d2175f18" }, { "children": [], "data": { "Name": "Math field crash", "Text": "Avoid a crash when bad field name modifiers are in a math field equation." }, "format": "BULLETS", "uid": "273a36a82ca911eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "Limit installer deletions", "Text": "In the Windows installer, improve the deletion of files from older versions and avoid problems if installing into a directory shared with other applications." }, "format": "BULLETS", "uid": "2767e530e80411e8aec9a44cc8e97404" }, { "children": [], "data": { "Name": "Math field restrictions", "Text": "Update math field equation restrictions to work with Python 3.8." }, "format": "BULLETS", "uid": "27950877dc8a11ea8902ac675dac20af" }, { "children": [], "data": { "Name": "Fallback character encoding", "Text": "Add fallbacks to UTF-8 encoding if the OS encoding fails on import and export." }, "format": "BULLETS", "uid": "280fe9c42ca911eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "Option to keep inaccessible recent files", "Text": "A new general option controls whether inaccessible files are removed from the recent file list at startup. The files are removed by default, but this can be changed to avoid losing listings of files stored on removable drives." }, "format": "BULLETS", "uid": "283565ba334211e8a34bd66a6ab671cb" }, { "children": [], "data": { "Name": "Breadcrumb View", "Text": "The top pane shows the parent and ancestors of the selected node. It is blank if no nodes or multiple nodes are selected. Ancestors with blue text can be clicked to select those nodes." }, "format": "HEAD_PARA", "uid": "28f8844ab58711e79d173417ebd53aeb" }, { "children": [ "f8ed5904813411f0b43b5847ca7850fa" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "293d508c813511f0b43b5847ca7850fa" }, { "children": [], "data": { "Name": "Conditional type copy/paste & drag/drop", "Text": "Fixed problems with copy / paste and drag / drop on nodes with conditional type settings." }, "format": "BULLETS", "uid": "299ba9e4334a11e881a6d66a6ab671cb" }, { "children": [], "data": { "Name": "Type structure visualization", "Text": "A new Show Configuration Structure command was added to the Data menu. This opens a read-only visualization of complex type structures as another TreeLine file." }, "format": "BULLETS", "uid": "2c9ba0c832ed11e9bf7f7054d2175f18" }, { "children": [], "data": { "Name": "Pretty print output", "Text": "An indent (pretty print) output option was added to General Options (under Features Available). This makes saved TreeLine JSON files easier for humans to read at the expense of somewhat larger file sizes." }, "format": "BULLETS", "uid": "2d4430dc305711e9a33aa44cc8e97404" }, { "children": [], "data": { "Name": "Open with bad references", "Text": "TreeLine files with invalid child references can now be opened. A warning message is given about the missing child nodes in the corrupt file." }, "format": "BULLETS", "uid": "2df5b030bbf711e88a1ca44cc8e97404" }, { "children": [], "data": { "Name": "MacPorts", "Text": "See MacPorts for a third-party port to macOS." }, "format": "PARAGRAPH", "uid": "2fa1be1fdc9511eaa00dac675dac20af" }, { "children": [], "data": { "Name": "Live HTML Export", "Text": "A live tree HTML export creates an interactive view with expandable nodes and a descendant output pane." }, "format": "BULLETS", "uid": "31304c06792b11e888cfa44cc8e97404" }, { "children": [], "data": { "Name": "Restoring window geometry", "Text": "Fix issues with restoring window geometry with multiple monitors and changing configurations." }, "format": "BULLETS", "uid": "35d0914edc8911eab202ac675dac20af" }, { "children": [], "data": { "Name": "Multiple paste commands", "Text": "New paste commands have been added for adding nodes before and after siblings. There are also multiple paste commands for adding clones of nodes." }, "format": "BULLETS", "uid": "39c001f0bb0311e79e793417ebd53aeb" }, { "children": [], "data": { "Name": "Major rewrite", "Text": "This is a major rewrite of TreeLine. Once it becomes more stable, it will be released as TreeLine version 3.0.0. The 2.1.x unstable series is being discontinued (no stable 2.2.0 release is planned)." }, "format": "BULLETS", "uid": "3d2bb12eba3c11e79b223417ebd53aeb" }, { "children": [], "data": { "Name": "Chinese translation", "Text": "Add a simplified Chinese GUI translation (thanks to Qu Ray for translating)." }, "format": "BULLETS", "uid": "3e749de1e5d811e9a22ba44cc8e97404" }, { "children": [ "3e749de1e5d811e9a22ba44cc8e97404", "cef1d9fee5de11e998dea44cc8e97404" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "3e749de3e5d811e98227a44cc8e97404" }, { "children": [], "data": { "Name": "Time field AM/PM", "Text": "Now forces references to AM/PM in time field formats to be output regardless of system locale settings." }, "format": "BULLETS", "uid": "40ec6d5cbbf711e8bb93a44cc8e97404" }, { "children": [ "8062dece813311f0b43b5847ca7850fa", "293d508c813511f0b43b5847ca7850fa", "8062dd2a813311f0b43b5847ca7850fa" ], "data": { "Name": "August 30, 2025 - Release 3.2.0 (stable release)" }, "format": "HEADINGS", "uid": "414f6662813311f0b43b5847ca7850fa" }, { "children": [], "data": { "Name": "Outline numbering", "Text": "Change lettered outline numbering sequences to match standards. The sequences change from ...Y, Z, AA, AB, AC... to ...Y, Z, AA, BB, CC..." }, "format": "BULLETS", "uid": "4212597ee5e011e99b51a44cc8e97404" }, { "children": [], "data": { "Name": "Title list select in tree command", "Text": "A Select in Tree command was added to the Title List's right-click context menu. It selects the node corresponding to the current line in the Title List editor. This makes it easier to edit or add children to an item." }, "format": "BULLETS", "uid": "42fb4166305a11e99fd7a44cc8e97404" }, { "children": [], "data": { "Name": "Title edit mouse move", "Text": "Fixed node title editing errors caused by moving the mouse to a data edit box with the title edit still active." }, "format": "BULLETS", "uid": "45491730786a11e8b8e2a44cc8e97404" }, { "children": [], "data": { "Name": "Enter key selects current node", "Text": "The enter key now selects a tree node after the first title letter(s) are typed to make it current (shown with a box around the title)." }, "format": "BULLETS", "uid": "456aa5ca793111e89a30a44cc8e97404" }, { "children": [ "66faed8adc9411ea965eac675dac20af", "d8a76c1fdc9411eaab2dac675dac20af" ], "data": { "Name": "macOS" }, "format": "BULLET_HEADING", "uid": "460699ebdc9411ea89afac675dac20af" }, { "children": [], "data": { "Name": "Dark theme option", "Text": "An optional dark color theme was added to General Options (under Appearances)." }, "format": "BULLETS", "uid": "46f3d0a4305e11e9892fa44cc8e97404" }, { "children": [], "data": { "Name": "Relative paths", "Text": "Avoid issues resolving relative paths between different Windows drive letters in external link fields." }, "format": "BULLETS", "uid": "46fc4054334b11e89299d66a6ab671cb" }, { "children": [], "data": { "Name": "Major rewrite", "Text": "This is a major rewrite of TreeLine. Once it becomes fully stable, it will be released as TreeLine version 3.0.0." }, "format": "BULLETS", "uid": "4bc47247786711e88b26a44cc8e97404" }, { "children": [ "4bc47249786711e8a3d5a44cc8e97404", "4bc4724c786711e8a8d9a44cc8e97404", "4bc4724f786711e89bdca44cc8e97404" ], "data": { "Name": "June 30, 2018 - Release 2.9.2 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "4bc47248786711e8a8bfa44cc8e97404" }, { "children": [ "4bc4724a786711e8a4dda44cc8e97404", "4bc47247786711e88b26a44cc8e97404", "4bc4724b786711e895e2a44cc8e97404" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "4bc47249786711e8a3d5a44cc8e97404" }, { "children": [], "data": { "Name": "Development snapshot", "Text": "This is a development snapshot of TreeLine that should be considered a release candidate for an upcoming stable release. Many bugs have been fixed. User testing and bug reports are appreciated." }, "format": "BULLETS", "uid": "4bc4724a786711e8a4dda44cc8e97404" }, { "children": [], "data": { "Name": "Translations", "Text": "A GUI translations is available in German. All other translations are out of date and have not been included. Volunteers are needed to update translations in several languages." }, "format": "BULLETS", "uid": "4bc4724b786711e895e2a44cc8e97404" }, { "children": [ "57c4de74786911e89c3fa44cc8e97404", "71b708ac786911e88d64a44cc8e97404", "a7d7f61e786911e89bbca44cc8e97404", "15da7fde786a11e881c8a44cc8e97404", "456aa5ca793111e89a30a44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "4bc4724c786711e8a8d9a44cc8e97404" }, { "children": [ "e4fc680a786911e899d3a44cc8e97404", "45491730786a11e8b8e2a44cc8e97404", "f011a5d8786911e8ace3a44cc8e97404" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "4bc4724f786711e89bdca44cc8e97404" }, { "children": [ "97cd921c2ca811eda95c54b2039ee1f3", "97cd914a2ca811eda95c54b2039ee1f3", "4f1367d62ca811eda95c54b2039ee1f3" ], "data": { "Name": "September 10, 2022 - Release 3.1.5 (stable release)" }, "format": "HEADINGS", "uid": "4f1366fa2ca811eda95c54b2039ee1f3" }, { "children": [ "4f136a742ca811eda95c54b2039ee1f3", "280fe9c42ca911eda95c54b2039ee1f3", "273a36a82ca911eda95c54b2039ee1f3" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "4f1367d62ca811eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "Encrypted password", "Text": "Fix a bug preventing a second-try password entry from opening an encrypted file." }, "format": "BULLETS", "uid": "4f136a742ca811eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "Print preview", "Text": "Fixed the appearance of the print preview when a dark theme is being used." }, "format": "BULLETS", "uid": "513e664c9b0d11f091375847ca7850fa" }, { "children": [], "data": { "Name": "Multi-session controls", "Text": "Fix problems detecting existing TreeLine sessions when opening files (mostly in Linux)." }, "format": "BULLETS", "uid": "5337587ddc8811eaaaedac675dac20af" }, { "children": [], "data": { "Name": "Clone removal", "Text": "The new \"Data > Detach Clones\" command converts cloned nodes in selected branches back into independent nodes." }, "format": "BULLETS", "uid": "5647bc8cbb0611e783853417ebd53aeb" }, { "children": [], "data": { "Name": "German translation", "Text": "The German GUI translation was updated (thanks to Maria Seliger)." }, "format": "BULLETS", "uid": "57c4de74786911e89c3fa44cc8e97404" }, { "children": [ "57d4af20fe7f11edbb2654b2039ee1f3", "57d4acd2fe7f11edbb2654b2039ee1f3" ], "data": { "Name": "June 3, 2023 - Release 3.1.6 (stable release)" }, "format": "HEADINGS", "uid": "57d4ac00fe7f11edbb2654b2039ee1f3" }, { "children": [ "1e7004a8fe8111edbb2654b2039ee1f3", "1db7e950fe8011edbb2654b2039ee1f3", "57d4ad9afe7f11edbb2654b2039ee1f3", "df7baad6fe8011edbb2654b2039ee1f3", "67cea5cefe8011edbb2654b2039ee1f3" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "57d4acd2fe7f11edbb2654b2039ee1f3" }, { "children": [], "data": { "Name": "Close dialogs with escape key", "Text": "Fix problems occurring when the escape key is used to close various non-modal dialogs." }, "format": "BULLETS", "uid": "57d4ad9afe7f11edbb2654b2039ee1f3" }, { "children": [], "data": { "Name": "External file modification", "Text": "Detect external file modifications by checking the file's last modified time just prior to saving." }, "format": "BULLETS", "uid": "57d4ae62fe7f11edbb2654b2039ee1f3" }, { "children": [ "57d4ae62fe7f11edbb2654b2039ee1f3", "a4ab733cfe8011edbb2654b2039ee1f3" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "57d4af20fe7f11edbb2654b2039ee1f3" }, { "children": [], "data": { "Name": "Linux menus", "Text": "Added a desktop specification file to the Linux installer for desktop environment menu support." }, "format": "BULLETS", "uid": "58dddee4010f11e88925d66a6ab671cb" }, { "children": [], "data": { "Name": "Setting types", "Text": "Each tree node can be set to a type format independently." }, "format": "BULLETS", "uid": "5c1d58ac792a11e8b78ca44cc8e97404" }, { "children": [], "data": { "Name": "Category level swap", "Text": "A new \"Swap Category Levels\" command swaps child and grandchild nodes beneath a selected node. A child node with multiple nodes under it will become cloned under each one. Any existing grandchild clones will become individual nodes with multiple children." }, "format": "BULLETS", "uid": "5c90e0b0bb0611e78e443417ebd53aeb" }, { "children": [], "data": { "Name": "Cloned nodes", "Text": "Cloned nodes (the same nodes with multiple parents/locations) can be created using special paste commands or by automatically matching identical nodes." }, "format": "BULLETS", "uid": "5f12f768b32c11e7a41a3417ebd53aeb" }, { "children": [], "data": { "Name": "Library updates", "Text": "Update the libraries used to build the Windows binaries to Python 3.8 and Qt/PyQt 5.14." }, "format": "BULLETS", "uid": "603e11fadf2011eaa12e7054d2175f18" }, { "children": [ "2fa1be1fdc9511eaa00dac675dac20af" ], "data": { "Name": "macOS" }, "format": "BULLET_HEADING", "uid": "611e03ffdc9411ea930eac675dac20af" }, { "children": [ "6515826e9b0c11f091375847ca7850fa" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "65157efe9b0c11f091375847ca7850fa" }, { "children": [ "65157efe9b0c11f091375847ca7850fa", "651580529b0c11f091375847ca7850fa" ], "data": { "Name": "September 27, 2025 - Release 3.2.1 (stable release)" }, "format": "HEADINGS", "uid": "65157f8a9b0c11f091375847ca7850fa" }, { "children": [ "78f991de9b0d11f091375847ca7850fa", "651580ac9b0c11f091375847ca7850fa", "513e664c9b0d11f091375847ca7850fa", "a5a948289b0d11f091375847ca7850fa", "01d807fc9b0d11f091375847ca7850fa" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "651580529b0c11f091375847ca7850fa" }, { "children": [], "data": { "Name": "Print page sizes", "Text": "An error setting some page sizes for printing was fixed." }, "format": "BULLETS", "uid": "651580ac9b0c11f091375847ca7850fa" }, { "children": [], "data": { "Name": "Color themes", "Text": "Added an easily selectable light-colored theme option." }, "format": "BULLETS", "uid": "6515826e9b0c11f091375847ca7850fa" }, { "children": [], "data": { "Name": "TreeLine Export", "Text": "Files can be exported that are compatible with older versions of TreeLine (1.x and 2.x), with a \".trl\" file extension. Some newer features, such as cloned nodes and multiple root nodes may not be completely preserved. TreeLine subtrees can also be exported to save just selected branches of the tree to a file using the current TreeLine version." }, "format": "HEAD_PARA", "uid": "65289b36b97611e783eb3417ebd53aeb" }, { "children": [], "data": { "Name": "Custom time dialog", "Text": "Added a custom time select dialog box for editing Time and TimeDate fields." }, "format": "BULLETS", "uid": "653f2f90334c11e8a7c9d66a6ab671cb" }, { "children": [], "data": { "Name": "Printing long nodes", "Text": "Multiple issues with printing long nodes were fixed." }, "format": "BULLETS", "uid": "6610203dd2c111e8a95ad66a6ab671cb" }, { "children": [ "66102040d2c111e8a210d66a6ab671cb", "66102041d2c111e8bd85d66a6ab671cb" ], "data": { "Name": "October 20, 2018 - Release 3.0.2 (stable release)" }, "format": "HEADINGS", "uid": "6610203fd2c111e8b033d66a6ab671cb" }, { "children": [ "66102049d2c111e8bb55d66a6ab671cb" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "66102040d2c111e8a210d66a6ab671cb" }, { "children": [ "66102043d2c111e88d57d66a6ab671cb", "6610203dd2c111e8a95ad66a6ab671cb", "66102048d2c111e89f4cd66a6ab671cb" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "66102041d2c111e8bd85d66a6ab671cb" }, { "children": [], "data": { "Name": "Windows printing", "Text": "Fixed nonfunctional printing commands under Windows by building the Windows binary using PyInstaller rather than cx_Freeze." }, "format": "BULLETS", "uid": "66102043d2c111e88d57d66a6ab671cb" }, { "children": [], "data": { "Name": "Blanks as zeros", "Text": "Fixed problems saving files when the blanks as zeros property was changed for math fields." }, "format": "BULLETS", "uid": "66102048d2c111e89f4cd66a6ab671cb" }, { "children": [], "data": { "Name": "Python 3.7", "Text": "Upgraded the Windows binary from Python 3.6 to Python 3.7." }, "format": "BULLETS", "uid": "66102049d2c111e8bb55d66a6ab671cb" }, { "children": [], "data": { "Name": "Not supported", "Text": "Due to a lack of Macs for testing, TreeLine on macOS is not formally supported." }, "format": "BULLETS", "uid": "66faed8adc9411ea965eac675dac20af" }, { "children": [], "data": { "Name": "Live HTML export", "Text": "Fix a bug using child count fields in live HTML exports." }, "format": "BULLETS", "uid": "67cea5cefe8011edbb2654b2039ee1f3" }, { "children": [ "67e95a5fbbf611e8b8bda44cc8e97404", "67e95a60bbf611e8a80ca44cc8e97404" ], "data": { "Name": "September 29, 2018 - Release 3.0.1 (stable release)" }, "format": "HEADINGS", "uid": "67e95a5bbbf611e891f7a44cc8e97404" }, { "children": [ "f966db0cc23f11e8b80fd66a6ab671cb", "67e95a61bbf611e8989ca44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "67e95a5fbbf611e8b8bda44cc8e97404" }, { "children": [ "67e95a64bbf611e8960fa44cc8e97404", "2df5b030bbf711e88a1ca44cc8e97404", "dc700fb4c24211e8b88dd66a6ab671cb", "40ec6d5cbbf711e8bb93a44cc8e97404", "9550a81ac24111e89029d66a6ab671cb", "71e2f25cc24211e88524d66a6ab671cb", "a757f64ac24211e8a95fd66a6ab671cb", "bdc8628ec2bd11e889e57054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "67e95a60bbf611e8a80ca44cc8e97404" }, { "children": [], "data": { "Name": "About dialog text box", "Text": "Added a read-only text box to the Help > About dialog to allow copying of the version and library information." }, "format": "BULLETS", "uid": "67e95a61bbf611e8989ca44cc8e97404" }, { "children": [], "data": { "Name": "Old file import", "Text": "Fixed a problem opening old TreeLine files that had format changes in File Info fields." }, "format": "BULLETS", "uid": "67e95a64bbf611e8960fa44cc8e97404" }, { "children": [], "data": { "Name": "Data in config structure", "Text": "Added many Show Configuration Structure data fields to show detailed settings for type formats and field formats.." }, "format": "BULLETS", "uid": "6a6067d4482011e989f27054d2175f18" }, { "children": [], "data": { "Name": "Select top node at open", "Text": "The top root node is now selected at file open if there is not a recent selection state to restore. Previously these files opened with no selection, which could cause confusion." }, "format": "BULLETS", "uid": "6a98186e305c11e99fbfa44cc8e97404" }, { "children": [], "data": { "Name": "Insert date command", "Text": "Add an Insert Date command that adds a timestamp to text field edit boxes." }, "format": "BULLETS", "uid": "6c916f15dc8c11ea9dbeac675dac20af" }, { "children": [], "data": { "Name": "Child type limits", "Text": "Child node types that are available to be set can be limited. A new pull-down list of child type limits is in the \"Type Config\" tab of the configuration dialog if the advanced functions are shown." }, "format": "BULLETS", "uid": "6dc88226bb0711e7894d3417ebd53aeb" }, { "children": [ "6df9a0c6ba3b11e7925d3417ebd53aeb", "6df9a0c9ba3b11e7a9793417ebd53aeb" ], "data": { "Name": "January 28, 2018 - Release 2.9.0 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "6df9a0c5ba3b11e78e7e3417ebd53aeb" }, { "children": [ "6df9a0c7ba3b11e7b7bd3417ebd53aeb", "3d2bb12eba3c11e79b223417ebd53aeb", "6df9a0c8ba3b11e78d783417ebd53aeb" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "6df9a0c6ba3b11e7925d3417ebd53aeb" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It could contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) is recommended for critical work." }, "format": "BULLETS", "uid": "6df9a0c7ba3b11e7b7bd3417ebd53aeb" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations are out of date and have not been included. Volunteers are needed to update translations in several languages." }, "format": "BULLETS", "uid": "6df9a0c8ba3b11e78d783417ebd53aeb" }, { "children": [ "6df9a0caba3b11e78b283417ebd53aeb", "d1d8e56eba4011e784ab3417ebd53aeb", "04da8386ba4811e7b3de3417ebd53aeb", "e6ad9f6eba4311e796bd3417ebd53aeb", "cd28e024bb0211e79c553417ebd53aeb", "1e3a82e4bb0411e7b7f33417ebd53aeb", "98132868ba4511e7b7283417ebd53aeb", "39c001f0bb0311e79e793417ebd53aeb", "04a868f4bb0611e7aea13417ebd53aeb", "5647bc8cbb0611e783853417ebd53aeb", "5c90e0b0bb0611e78e443417ebd53aeb", "6dc88226bb0711e7894d3417ebd53aeb", "7697b826bb0411e788433417ebd53aeb", "1d015318bb0511e7a2ac3417ebd53aeb", "f5983b38bb0411e795e13417ebd53aeb", "58dddee4010f11e88925d66a6ab671cb" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "6df9a0c9ba3b11e7a9793417ebd53aeb" }, { "children": [], "data": { "Name": "New file format", "Text": "TreeLine files now uses a new JSON format in place of the old XML format. This provides more flexibility for structuring new features like cloned nodes and multiple root nodes. A new file extension (\".trln) helps to distinguish these files." }, "format": "BULLETS", "uid": "6df9a0caba3b11e78b283417ebd53aeb" }, { "children": [], "data": { "Name": "Maintain expanded nodes", "Text": "The expand/collapse status of nearby nodes is maintained while editing the node structure. This includes adding, deleting, moving and indenting nodes." }, "format": "BULLETS", "uid": "71b708ac786911e88d64a44cc8e97404" }, { "children": [], "data": { "Name": "Complex data menu commands", "Text": "Fixed various errors when applying advanced clone and category commands from the Data menu to complex node structures." }, "format": "BULLETS", "uid": "71e2f25cc24211e88524d66a6ab671cb" }, { "children": [], "data": { "Name": "Date and time formats", "Text": "The Date, Time and DateTime fields have new format strings that enable extra text to be added to the date output." }, "format": "BULLETS", "uid": "7697b826bb0411e788433417ebd53aeb" }, { "children": [], "data": { "Name": "Number field formatting", "Text": "Fixed problems with number field formatting when using a \",\" radix with exponents." }, "format": "BULLETS", "uid": "7716c96e334a11e896bfd66a6ab671cb" }, { "children": [], "data": { "Name": "Drag and drop", "Text": "Fixed errors that occurred when dragging and dropping nodes and files." }, "format": "BULLETS", "uid": "78f991de9b0d11f091375847ca7850fa" }, { "children": [], "data": { "Name": "Math field expressions", "Text": "Evaluate math expressions contained in fields that are referenced by math field equations. " }, "format": "BULLETS", "uid": "7a9ace43dc8a11ea9e9bac675dac20af" }, { "children": [], "data": { "Name": "Translations", "Text": "Translations of the TreeLine GUI are available in German and Spanish. The translation should load automatically if the OS locale is properly set. Alternatively, \"--lang xx\" can be appended to the command that starts TreeLine, where \"xx\" is the two-letter language code (\"en\", \"de\" or \"es\")." }, "format": "HEAD_PARA", "uid": "7e9b3b88c24511e896c7d66a6ab671cb" }, { "children": [], "data": { "Name": "Word count equation", "Text": "Added a word count function for math field types." }, "format": "BULLETS", "uid": "7f0da0fc813511f0b43b5847ca7850fa" }, { "children": [ "7ffeb672dc8711ea86ddac675dac20af", "7ffeb670dc8711ea81aeac675dac20af", "7ffeb66edc8711eaaa13ac675dac20af" ], "data": { "Name": "August 16, 2020 - Release 3.1.3 (stable release)" }, "format": "HEADINGS", "uid": "7ffeb66ddc8711ea9a87ac675dac20af" }, { "children": [ "d9119485dc8711ea92dcac675dac20af", "8d9c1717dc8811ea9c40ac675dac20af", "cf9c139fdc8e11ea8261ac675dac20af", "88bb6300dc8e11ea9a73ac675dac20af", "b6a4a6bddc8911ea8612ac675dac20af", "23b9a763dc8b11ea9dafac675dac20af", "0906c05bdc8f11ea94fbac675dac20af", "35d0914edc8911eab202ac675dac20af", "f2a0c0a1dc8d11ea8921ac675dac20af", "5337587ddc8811eaaaedac675dac20af" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "7ffeb66edc8711eaaa13ac675dac20af" }, { "children": [ "27950877dc8a11ea8902ac675dac20af", "c1f8dca5dc9511ea8f76ac675dac20af", "603e11fadf2011eaa12e7054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "7ffeb670dc8711ea81aeac675dac20af" }, { "children": [ "dca5b84fdc8a11eab098ac675dac20af", "6c916f15dc8c11ea9dbeac675dac20af", "7a9ace43dc8a11ea9e9bac675dac20af", "228fa647dc8c11eab28aac675dac20af" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "7ffeb672dc8711ea86ddac675dac20af" }, { "children": [ "800a0972305111e9a7fea44cc8e97404", "f7bbd909305111e9be43a44cc8e97404", "800a0975305111e9a018a44cc8e97404", "800a0976305111e9bd43a44cc8e97404" ], "data": { "Name": "February 20, 2019 - Release 3.1.0 (beta release)" }, "format": "HEADINGS", "uid": "800a0971305111e991cda44cc8e97404" }, { "children": [ "800a0973305111e9b7b9a44cc8e97404", "800a0974305111e99f0fa44cc8e97404" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "800a0972305111e9a7fea44cc8e97404" }, { "children": [], "data": { "Name": "Beta release", "Text": "This is a beta release of TreeLine. Some new features have not been extensively tested, but major bugs are unlikely. Testing and bug reports are appreciated, but those with very critical work should consider using the stable release (TreeLine 3.0.x)." }, "format": "BULLETS", "uid": "800a0973305111e9b7b9a44cc8e97404" }, { "children": [], "data": { "Name": "Translations", "Text": "GUI translations are available in German and Spanish, but they still require minor updates to cover recent changes. Volunteers are also needed to update or create translations in additional languages." }, "format": "BULLETS", "uid": "800a0974305111e99f0fa44cc8e97404" }, { "children": [ "6a98186e305c11e99fbfa44cc8e97404", "800a0977305111e98c38a44cc8e97404", "10c539e2305c11e9a392a44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "800a0975305111e9a018a44cc8e97404" }, { "children": [ "800a097a305111e9950ba44cc8e97404", "192373c6305511e9ab21a44cc8e97404" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "800a0976305111e9bd43a44cc8e97404" }, { "children": [], "data": { "Name": "Gray out data edit view math fields", "Text": "Non-editable math fields in the Data Edit view show as gray when the mouse hovers over them." }, "format": "BULLETS", "uid": "800a0977305111e98c38a44cc8e97404" }, { "children": [], "data": { "Name": "Titles from HTML text fields", "Text": "Fixed the truncation of node titles that are generated from the first line of HTML Text fields." }, "format": "BULLETS", "uid": "800a097a305111e9950ba44cc8e97404" }, { "children": [ "8062dd8e813311f0b43b5847ca7850fa", "c31396d6813411f0b43b5847ca7850fa", "9fdb2b84813411f0b43b5847ca7850fa" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "8062dd2a813311f0b43b5847ca7850fa" }, { "children": [], "data": { "Name": "Closing windows", "Text": "Fixed errors closing a window if the same file is open in another window." }, "format": "BULLETS", "uid": "8062dd8e813311f0b43b5847ca7850fa" }, { "children": [ "8062df28813311f0b43b5847ca7850fa", "7f0da0fc813511f0b43b5847ca7850fa" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "8062dece813311f0b43b5847ca7850fa" }, { "children": [], "data": { "Name": "Port to Qt6", "Text": "Made extensive updates to port TreeLine to the Qt6 and PyQt6 libraries." }, "format": "BULLETS", "uid": "8062df28813311f0b43b5847ca7850fa" }, { "children": [], "data": { "Name": "Numbering", "Text": "Fix incorrect numbering updates in some situations with mixed node types." }, "format": "BULLETS", "uid": "84b24010482211e989f27054d2175f18" }, { "children": [], "data": { "Name": "Circular math errors", "Text": "Fix problems opening files that contain circular reference errors in math fields." }, "format": "BULLETS", "uid": "88bb6300dc8e11ea9a73ac675dac20af" }, { "children": [], "data": { "Name": "Truncated text export", "Text": "Fix a bug that truncated plain text exports after the first line." }, "format": "BULLETS", "uid": "8cdb2406e5df11e9a06da44cc8e97404" }, { "children": [], "data": { "Name": "Find & replace error", "Text": "Avoid an application error when a Find and Replace command causes fields to contain invalid data." }, "format": "BULLETS", "uid": "8d9c1717dc8811ea9c40ac675dac20af" }, { "children": [], "data": { "Name": "Title list select in tree", "Text": "Enable the title list view's select in tree context menu to be used on new child nodes." }, "format": "BULLETS", "uid": "8e8e418ae5dc11e98404a44cc8e97404" }, { "children": [], "data": { "Name": "Copy command errors", "Text": "Fix errors shown when using copy commands after closing TreeLine windows." }, "format": "BULLETS", "uid": "90dbc4e4334b11e892d0d66a6ab671cb" }, { "children": [], "data": { "Name": "Dark mode tooltips", "Text": "Modify dark mode colors to make tool tips visible." }, "format": "BULLETS", "uid": "9139627ee5db11e98a21a44cc8e97404" }, { "children": [], "data": { "Name": "Purge old field data", "Text": "Data from fields that were removed from the configuration is now purged when a file is saved. This avoids missing matches in the Clone All Matched Nodes command." }, "format": "BULLETS", "uid": "9550a81ac24111e89029d66a6ab671cb" }, { "children": [], "data": { "Name": "Old TreeLine Import", "Text": "Files from older versions of TreeLine (1.x or 2.x) can be imported. These files are in XML format and generally have a \".trl\" file extension (current files are in JSON format with a \".trln\" file extension). Unlike other file imports, these older files will import without showing the import dialog box when using the \"File > Open\" command." }, "format": "HEAD_PARA", "uid": "95547c38b97411e7a42a3417ebd53aeb" }, { "children": [], "data": { "Name": "Major rewrite", "Text": "This is a major rewrite of TreeLine. Once it becomes more stable, it will be released as TreeLine version 3.0.0. The 2.1.x unstable series is being discontinued (no stable 2.2.0 release is planned)." }, "format": "BULLETS", "uid": "95a6e905333f11e886edd66a6ab671cb" }, { "children": [ "95a6e90b333f11e8976fd66a6ab671cb", "95a6e90e333f11e88696d66a6ab671cb", "b16866da333f11e88adbd66a6ab671cb" ], "data": { "Name": "March 31, 2018 - Release 2.9.1 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "95a6e90a333f11e89efed66a6ab671cb" }, { "children": [ "95a6e90c333f11e8b766d66a6ab671cb", "95a6e905333f11e886edd66a6ab671cb", "95a6e90d333f11e8b88ed66a6ab671cb" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "95a6e90b333f11e8976fd66a6ab671cb" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It has improved but could still contain bugs. Testing and bug reports are appreciated, but those with very critical work should consider using the stable release (TreeLine 2.0.x)." }, "format": "BULLETS", "uid": "95a6e90c333f11e8b766d66a6ab671cb" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations are out of date and have not been included. Volunteers are needed to update translations in several languages." }, "format": "BULLETS", "uid": "95a6e90d333f11e8b88ed66a6ab671cb" }, { "children": [ "b1cd1f82334111e8b89ad66a6ab671cb", "dd22e382334111e894e6d66a6ab671cb", "653f2f90334c11e8a7c9d66a6ab671cb", "283565ba334211e8a34bd66a6ab671cb" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "95a6e90e333f11e88696d66a6ab671cb" }, { "children": [], "data": { "Name": "Child count equation references", "Text": "Eliminate a problem defining math field equations that include child count references." }, "format": "BULLETS", "uid": "95d970aa481f11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Printed line width", "Text": "For better visibility, increase the width of tree structure lines in printed and PDF output files." }, "format": "BULLETS", "uid": "97cd8dda2ca811eda95c54b2039ee1f3" }, { "children": [ "97cd8dda2ca811eda95c54b2039ee1f3", "c5c45e3e2d4411eda95c54b2039ee1f3", "c771aa162ca911eda95c54b2039ee1f3", "c8eb2e4e2ca911eda95c54b2039ee1f3" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "97cd914a2ca811eda95c54b2039ee1f3" }, { "children": [ "97cd93ac2ca811eda95c54b2039ee1f3" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "97cd921c2ca811eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "Strike-through font", "Text": "Add a command for strike-through font formatting." }, "format": "BULLETS", "uid": "97cd93ac2ca811eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "Native cloned nodes", "Text": "Cloned nodes now have a more native and efficient implementation. This allows the same nodes to have multiple parents. The new breadcrumb view shows a list of clones for the selected node that can be clicked to select the other instances." }, "format": "BULLETS", "uid": "98132868ba4511e7b7283417ebd53aeb" }, { "children": [], "data": { "Name": "Format Menu", "Text": "The format menu has text formatting commands that are active when using edit boxes in the Data Edit view." }, "format": "HEAD_PARA", "uid": "997af664b58811e7ac243417ebd53aeb" }, { "children": [], "data": { "Name": "Ancestor field references", "Text": "Fixed problems with advanced ancestor field output references in some tree locations." }, "format": "BULLETS", "uid": "9a8a1400334c11e89838d66a6ab671cb" }, { "children": [], "data": { "Name": "Old TreeLine import/export", "Text": "Files from older versions of TreeLine (2.x and 1.x) can be imported and exported." }, "format": "BULLETS", "uid": "9bd80f34b32b11e7be613417ebd53aeb" }, { "children": [], "data": { "Name": "Portable config", "Text": "Problems with writing config files in Windows portable installations were fixed." }, "format": "BULLETS", "uid": "9c08f39de80311e8b791a44cc8e97404" }, { "children": [ "9c08f3a0e80311e8b2e0a44cc8e97404" ], "data": { "Name": "November 17, 2018 - Release 3.0.3 (stable release)" }, "format": "HEADINGS", "uid": "9c08f39ee80311e8a510a44cc8e97404" }, { "children": [ "9c08f3a1e80311e884dca44cc8e97404", "9c08f39de80311e8b791a44cc8e97404", "9c08f3a2e80311e88128a44cc8e97404", "2767e530e80411e8aec9a44cc8e97404" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "9c08f3a0e80311e8b2e0a44cc8e97404" }, { "children": [], "data": { "Name": "Child count fields", "Text": "Fixed an error when adding child count fields to the output format." }, "format": "BULLETS", "uid": "9c08f3a1e80311e884dca44cc8e97404" }, { "children": [], "data": { "Name": "Config file error handling", "Text": "Improved error handling after failing to read or write config files." }, "format": "BULLETS", "uid": "9c08f3a2e80311e88128a44cc8e97404" }, { "children": [], "data": { "Name": "Generic XML input", "Text": "Improved the handling of multi-line text in generic XML import." }, "format": "BULLETS", "uid": "9fdb2b84813411f0b43b5847ca7850fa" }, { "children": [], "data": { "Name": "Colors", "Text": "The default GUI colors can be changed using the \"Tools > Customize Colors\" dialog. A dark theme is available, or individual colors can be selected." }, "format": "HEAD_PARA", "uid": "9ff09734dc9011ea887bac675dac20af" }, { "children": [], "data": { "Name": "Convert between Choice and Combination", "Text": "Preserve the choices in the field format when switching between Choice and Combination field types." }, "format": "BULLETS", "uid": "a4ab733cfe8011edbb2654b2039ee1f3" }, { "children": [], "data": { "Name": "Time editor", "Text": "Fixed the appearance of the time edit widget when used with a dark theme." }, "format": "BULLETS", "uid": "a5a948289b0d11f091375847ca7850fa" }, { "children": [], "data": { "Name": "Complex undo operations", "Text": "Fixed some problems with using the Undo command after complex operations." }, "format": "BULLETS", "uid": "a757f64ac24211e8a95fd66a6ab671cb" }, { "children": [], "data": { "Name": "Save state for discarded files", "Text": "The expanded/collapsed and selected tree states are now saved even if changes were discarded in the previous session." }, "format": "BULLETS", "uid": "a7d7f61e786911e89bbca44cc8e97404" }, { "children": [], "data": { "Name": "Pull-downs on repeated dialog boxes", "Text": "Fixed issues on Windows with pull-down combo boxes not working after repeatedly showing some dialogs (mostly find and filter dialogs)." }, "format": "BULLETS", "uid": "a7fa190c334911e88d18d66a6ab671cb" }, { "children": [], "data": { "Name": "Child Type Limits", "Text": "In addition to setting the default child type, the child node types that are available to be set can be limited. There is a pull-down list of child type limits in the \"Type Config\" tab of the configuration dialog if the advanced functions are shown. Only checked types will show up in the type lists when using the \"Data > Set Node Type\" command on a child node." }, "format": "HEAD_PARA", "uid": "aa6f6ca4bb0711e7bbf43417ebd53aeb" }, { "children": [ "90dbc4e4334b11e892d0d66a6ab671cb", "299ba9e4334a11e881a6d66a6ab671cb", "e46163b4334b11e88512d66a6ab671cb", "a7fa190c334911e88d18d66a6ab671cb", "f817e5b6334a11e89349d66a6ab671cb", "7716c96e334a11e896bfd66a6ab671cb", "46fc4054334b11e89299d66a6ab671cb", "9a8a1400334c11e89838d66a6ab671cb", "145bd91a334c11e896b1d66a6ab671cb", "edd50b80334c11e8b5f5d66a6ab671cb", "b7ec7052334a11e88325d66a6ab671cb" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "b16866da333f11e88adbd66a6ab671cb" }, { "children": [], "data": { "Name": "Breadcrumb view", "Text": "An upper breadcrumb view shows titles of the selected node's ancestors; the titles can be clicked to select them in the tree." }, "format": "BULLETS", "uid": "b1b5d434b32911e780fd3417ebd53aeb" }, { "children": [], "data": { "Name": "Live tree HTML export", "Text": "A new HTML export uses Javascript and CSS to create a live tree view. Nodes in the tree can be expanded and collapsed, and a separate pane shows the output for all descendants of the selected node. One form of this export creates separate files that are linked to the existing TreeLine file. These files are intended for use on a web server (browser security usually prevents local access). Only the TreeLine file needs to be replaced to update the data (re-export is not required). The second form creates a single file (with embedded data) that can be accessed from a local web browser." }, "format": "BULLETS", "uid": "b1cd1f82334111e8b89ad66a6ab671cb" }, { "children": [], "data": { "Name": "Search and replace", "Text": "Added support for finding and replacing empty data fields using the search and replace command." }, "format": "BULLETS", "uid": "b398d8ee482211e989f27054d2175f18" }, { "children": [ "b5fe6aa030e111ebbc097054d2175f18" ], "data": { "Name": "November 27, 2020 - Release 3.1.4 (stable release)" }, "format": "HEADINGS", "uid": "b5fe698830e111ebbc097054d2175f18" }, { "children": [ "b5fe74c830e111ebbc097054d2175f18", "b5fe6f0030e111ebbc097054d2175f18", "b5fe737e30e111ebbc097054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "b5fe6aa030e111ebbc097054d2175f18" }, { "children": [], "data": { "Name": "Window closing error", "Text": "Avoid an error message when a window is closed with the focus on a dialog box." }, "format": "BULLETS", "uid": "b5fe6f0030e111ebbc097054d2175f18" }, { "children": [], "data": { "Name": "Math field root reference", "Text": "Fix a problem recalculating root references in field equations." }, "format": "BULLETS", "uid": "b5fe737e30e111ebbc097054d2175f18" }, { "children": [], "data": { "Name": "Python 3.9 compatible", "Text": "Fix an incompatibility with the new Python 3.9 version under Linux or running from source." }, "format": "BULLETS", "uid": "b5fe74c830e111ebbc097054d2175f18" }, { "children": [], "data": { "Name": "Font dialog bug", "Text": "Avoid problems with empty parameters in the font dialogs." }, "format": "BULLETS", "uid": "b6a4a6bddc8911ea8612ac675dac20af" }, { "children": [], "data": { "Name": "Output table spacing", "Text": "Fixed minor spacing issues for tables shown in output views and HTML exports." }, "format": "BULLETS", "uid": "b7ec7052334a11e88325d66a6ab671cb" }, { "children": [], "data": { "Name": "Math Fields", "Text": "For more complex output formatting, the math field can be used to combine other fields using various mathematical, relational and string operators. See the Math Type section for details." }, "format": "HEAD_PARA", "uid": "bbbf735ac24711e8b560d66a6ab671cb" }, { "children": [], "data": { "Name": "Cut last node", "Text": "Fix an error caused by attempting to use the Edit > Cut command when there is only one node." }, "format": "BULLETS", "uid": "bdc8628ec2bd11e889e57054d2175f18" }, { "children": [], "data": { "Name": "MacPorts reference", "Text": "References to a macOS port on MacPorts were added to the System Requirements and Installation documentation." }, "format": "BULLETS", "uid": "c1f8dca5dc9511ea8f76ac675dac20af" }, { "children": [], "data": { "Name": "Filter view icon", "Text": "Fixed a problem with the filter view when the tree icon is set to none." }, "format": "BULLETS", "uid": "c31396d6813411f0b43b5847ca7850fa" }, { "children": [], "data": { "Name": "Windows binaries", "Text": "Update the libraries used to build the Windows binaries to Python 3.10 and Qt/PyQt 5.15. Note that this eliminates support for Windows 7." }, "format": "BULLETS", "uid": "c5c45e3e2d4411eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "Russian translation", "Text": "Add a Russian translation of the GUI and the help files (thanks to Andrew Trofimov)." }, "format": "BULLETS", "uid": "c771aa162ca911eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "German translation", "Text": "Update the German GUI translation (thanks to Karsten)." }, "format": "BULLETS", "uid": "c8eb2e4e2ca911eda95c54b2039ee1f3" }, { "children": [], "data": { "Name": "Data editor hover", "Text": "By default, the edit boxes in the data edit view now activate when the mouse hovers over them. This eliminates the need to click to activate them. This feature can be disabled in general options if desired." }, "format": "BULLETS", "uid": "cd28e024bb0211e79c553417ebd53aeb" }, { "children": [], "data": { "Name": "Unlimited data editor height option", "Text": "Add a general option to extend the height of data editors with long text content. The default setting (limit the height to the window size) is unchanged. The new option uses the view scroll bars to access the full text length." }, "format": "BULLETS", "uid": "cef1d9fee5de11e998dea44cc8e97404" }, { "children": [], "data": { "Name": "Math field recalculation", "Text": "Perform a more complete recalculation of math fields after certain operations." }, "format": "BULLETS", "uid": "cf9c139fdc8e11ea8261ac675dac20af" }, { "children": [], "data": { "Name": "TreeLine 2 import / export", "Text": "Import and export filters are provided for older TreeLine version 2.x and 1.x files. The older files can be opened using the standard \"File > Open\" command." }, "format": "BULLETS", "uid": "d1d8e56eba4011e784ab3417ebd53aeb" }, { "children": [], "data": { "Name": "MacPorts", "Text": "There is a third-party port available on MacPorts." }, "format": "BULLETS", "uid": "d8a76c1fdc9411eaab2dac675dac20af" }, { "children": [], "data": { "Name": "Enable add child", "Text": "Make the Add Child command available after filtering has ended." }, "format": "BULLETS", "uid": "d9119485dc8711ea92dcac675dac20af" }, { "children": [ "ff3f7c98481e11e989f27054d2175f18", "db25ce66481e11e989f27054d2175f18" ], "data": { "Name": "March 17, 2019 - Release 3.1.1 (stable release)" }, "format": "HEADINGS", "uid": "db25cd62481e11e989f27054d2175f18" }, { "children": [ "e3690592481f11e989f27054d2175f18", "84b24010482211e989f27054d2175f18", "db25cf60481e11e989f27054d2175f18", "95d970aa481f11e989f27054d2175f18", "25ab9320482011e989f27054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "db25ce66481e11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Math equation with copied type", "Text": "Fix problems defining a math field equation on a recently copied data type." }, "format": "BULLETS", "uid": "db25cf60481e11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Sort root nodes", "Text": "The Sort command now properly sorts multiple root nodes when sorting the entire tree." }, "format": "BULLETS", "uid": "dc700fb4c24211e8b88dd66a6ab671cb" }, { "children": [], "data": { "Name": "Customize colors", "Text": "Add a more flexible tool for customizing GUI colors." }, "format": "BULLETS", "uid": "dca5b84fdc8a11eab098ac675dac20af" }, { "children": [], "data": { "Name": "Multi-level CSV import / export", "Text": "New forms of CSV table text imports and exports can work with multiple levels of child nodes, preserving the tree structure. The first column of the table includes a level number that is incremented for child relationships." }, "format": "BULLETS", "uid": "dd22e382334111e894e6d66a6ab671cb" }, { "children": [], "data": { "Name": "CSV import error", "Text": "Avoid a traceback error message when attempting to import a CSV file with a bad header row." }, "format": "BULLETS", "uid": "df7baad6fe8011edbb2654b2039ee1f3" }, { "children": [], "data": { "Name": "Dark mode printing", "Text": "Fix printing problems when using the dark theme." }, "format": "BULLETS", "uid": "e3690592481f11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Error after empty filter", "Text": "Avoid problems showing the tree view after closing a filter command that found no matches." }, "format": "BULLETS", "uid": "e46163b4334b11e88512d66a6ab671cb" }, { "children": [], "data": { "Name": "Deletion errors", "Text": "Several errors occurring when deleting or removing nodes have been fixed. These include problems when the mouse is pre-highlighting descendant nodes and when nodes to be deleted are selected in a separate window." }, "format": "BULLETS", "uid": "e4fc680a786911e899d3a44cc8e97404" }, { "children": [], "data": { "Name": "Breadcrumb view", "Text": "A new breadcrumb view pane above the other panes shows a sequence of ancestor titles for a selected node. The ancestors can be clicked to select them. For cloned nodes, multiple lines provide links to each instance's ancestor sequence." }, "format": "BULLETS", "uid": "e6ad9f6eba4311e796bd3417ebd53aeb" }, { "children": [], "data": { "Name": "Windows binary", "Text": "The Windows binary is now built using updated libraries (Qt 5.11 and PyQt 5.11)." }, "format": "BULLETS", "uid": "e7776f4da14511e88aefa44cc8e97404" }, { "children": [], "data": { "Name": "Major rewrite", "Text": "This is the first stable release of a major TreeLine rewrite. It includes all of the new features shown below in the 2.1.x and 2.9.x development series." }, "format": "BULLETS", "uid": "e8e10d32a14311e8ab90a44cc8e97404" }, { "children": [ "e8e10d34a14311e899cca44cc8e97404", "e8e10d38a14311e8a0c3a44cc8e97404", "e8e10d37a14311e8b0b3a44cc8e97404" ], "data": { "Name": "August 19, 2018 - Release 3.0.0 (new stable release)" }, "format": "HEADINGS", "uid": "e8e10d33a14311e88e24a44cc8e97404" }, { "children": [ "e8e10d32a14311e8ab90a44cc8e97404", "e8e10d35a14311e8aca9a44cc8e97404", "e8e10d36a14311e8b832a44cc8e97404" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "e8e10d34a14311e899cca44cc8e97404" }, { "children": [], "data": { "Name": "Compatibility", "Text": "TreeLine files now use a JSON format in place of the old XML format. This provides more flexibility for structuring new features like cloned nodes and multiple root nodes. A new file extension (\".trln) helps to distinguish files with the new format. Import and export filters are provided for older TreeLine version 2.x and 1.x files. The older files can be opened using the standard \"File > Open\" command." }, "format": "BULLETS", "uid": "e8e10d35a14311e8aca9a44cc8e97404" }, { "children": [], "data": { "Name": "Translations", "Text": "A GUI translations is available in German. All other translations are out of date and have not been included. Volunteers are needed to update translations in several languages." }, "format": "BULLETS", "uid": "e8e10d36a14311e8b832a44cc8e97404" }, { "children": [ "e7776f4da14511e88aefa44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "e8e10d37a14311e8b0b3a44cc8e97404" }, { "children": [ "e8e10d3ca14311e8b71da44cc8e97404" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "e8e10d38a14311e8a0c3a44cc8e97404" }, { "children": [], "data": { "Name": "Default font", "Text": "The default font for the application can now be set in Tools > Customize Fonts. This is useful for enlarging fonts on some systems with high screen resolutions. Options still exist to individually specify tree view, output view and editor fonts." }, "format": "BULLETS", "uid": "e8e10d3ca14311e8b71da44cc8e97404" }, { "children": [], "data": { "Name": "Add modified flag", "Text": "Add an asterisk after the file name in the title bar if a file has been modified." }, "format": "BULLETS", "uid": "ea0c9b24e79911e98abe7054d2175f18" }, { "children": [], "data": { "Name": "Category command disable", "Text": "Avoid problems running data category-based commands on selections without any child nodes." }, "format": "BULLETS", "uid": "edd50b80334c11e8b5f5d66a6ab671cb" }, { "children": [], "data": { "Name": "Initial field values", "Text": "Fixed errors occurring when field types are changed after initial default values have been set." }, "format": "BULLETS", "uid": "f011a5d8786911e8ace3a44cc8e97404" }, { "children": [], "data": { "Name": "Cloned nodes", "Text": "Nodes that are duplicated by cloning show up as separate clickable paths in the upper breadcrumb view." }, "format": "BULLETS", "uid": "f08b97be792b11e88588a44cc8e97404" }, { "children": [ "f16f7f70a25a11e7b7c67054d2175f18", "f16f87b8a25a11e7b7c67054d2175f18", "f16fbef4a25a11e7b7c67054d2175f18", "f16fc7aaa25a11e7b7c67054d2175f18", "f16fd236a25a11e7b7c67054d2175f18", "f16fe6fea25a11e7b7c67054d2175f18", "f1703d8ea25a11e7b7c67054d2175f18", "f1713464a25a11e7b7c67054d2175f18" ], "data": { "Name": "TreeLine Documentation" }, "format": "HEADINGS", "uid": "f16f7d90a25a11e7b7c67054d2175f18" }, { "children": [ "f16f82aea25a11e7b7c67054d2175f18", "f16f8498a25a11e7b7c67054d2175f18", "f16f85b0a25a11e7b7c67054d2175f18", "f16f86aaa25a11e7b7c67054d2175f18" ], "data": { "Name": "Introduction" }, "format": "HEADINGS", "uid": "f16f7f70a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Version", "Text": "This document covers TreeLine, Version 3.2.1, a stable release, dated September 27, 2025 by Doug Bell." }, "format": "PARAGRAPH", "uid": "f16f82aea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Why TreeLine?", "Text": "Do you have lots of sticky notes lying around with various useful information jotted down? Or many lists of books, movies, links, website logins, personal contacts, or things to do? Can you find them when you need them? Well, I often couldn't. So here's my answer." }, "format": "PARAGRAPH", "uid": "f16f8498a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Outliner vs. database", "Text": "TreeLine is both an outliner and a small database. It stores almost any kind of information. A tree structure makes it easy to keep things organized. And each node in the tree can contain several fields, forming a database. The output format for each node can be defined, and the output can be shown on the screen, printed, or exported to HTML or text." }, "format": "PARAGRAPH", "uid": "f16f85b0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "License", "Text": "Since I'm not in the software business, I'm making this program free for anyone to use, distribute and modify, as long as it stays non-proprietary. TreeLine 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. See the LICENSE file provided with this program for more information." }, "format": "PARAGRAPH", "uid": "f16f86aaa25a11e7b7c67054d2175f18" }, { "children": [ "f16f8aeca25a11e7b7c67054d2175f18", "f16f9654a25a11e7b7c67054d2175f18", "f16f9c44a25a11e7b7c67054d2175f18", "f16fa040a25a11e7b7c67054d2175f18", "f16fa31aa25a11e7b7c67054d2175f18", "f16fa806a25a11e7b7c67054d2175f18", "f16fadf6a25a11e7b7c67054d2175f18", "f16fb1dea25a11e7b7c67054d2175f18", "f16fb90ea25a11e7b7c67054d2175f18" ], "data": { "Name": "Features" }, "format": "HEADINGS", "uid": "f16f87b8a25a11e7b7c67054d2175f18" }, { "children": [ "f16f9050a25a11e7b7c67054d2175f18", "f16f921ca25a11e7b7c67054d2175f18", "f16f932aa25a11e7b7c67054d2175f18", "f16f9424a25a11e7b7c67054d2175f18", "f16f9550a25a11e7b7c67054d2175f18" ], "data": { "Name": "General" }, "format": "BULLET_HEADING", "uid": "f16f8aeca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Store information", "Text": "Stores almost any type of information, including plain text, rich text, HTML, numbers, dates, times, booleans, URLs, etc." }, "format": "BULLETS", "uid": "f16f9050a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Tree structure", "Text": "The tree structure helps keep things organized." }, "format": "BULLETS", "uid": "f16f921ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Fields", "Text": "Each node can have several fields that form a mini-database." }, "format": "BULLETS", "uid": "f16f932aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Node types", "Text": "Several node types, with different sets of fields, can be included in one file." }, "format": "BULLETS", "uid": "f16f9424a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Output format", "Text": "The node format, including fields, output lines, formatting and tree-view icon, can be defined for each node type." }, "format": "BULLETS", "uid": "f16f9550a25a11e7b7c67054d2175f18" }, { "children": [ "f16f9744a25a11e7b7c67054d2175f18", "f16f9834a25a11e7b7c67054d2175f18", "f16f992ea25a11e7b7c67054d2175f18", "f16f9a32a25a11e7b7c67054d2175f18", "f16f9b36a25a11e7b7c67054d2175f18", "b1b5d434b32911e780fd3417ebd53aeb" ], "data": { "Name": "Views" }, "format": "BULLET_HEADING", "uid": "f16f9654a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Tree view", "Text": "The left-hand view shows an indented, expandable list of titles" }, "format": "BULLETS", "uid": "f16f9744a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Right-hand views", "Text": "The right-hand view can show one of three views - for showing output, editing node data and editing node titles." }, "format": "BULLETS", "uid": "f16f9834a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Show parent and children", "Text": "The right-hand view is normally split to show data from the parent node and its children." }, "format": "BULLETS", "uid": "f16f992ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Show multiple selection", "Text": "If multiple nodes are selected, the right-hand view shows all of their data." }, "format": "BULLETS", "uid": "f16f9a32a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Show descendant output", "Text": "The output view can be set to show indented output from all descendant nodes." }, "format": "BULLETS", "uid": "f16f9b36a25a11e7b7c67054d2175f18" }, { "children": [ "f16f9d2aa25a11e7b7c67054d2175f18", "f16f9e2ea25a11e7b7c67054d2175f18", "f16f9f3ca25a11e7b7c67054d2175f18" ], "data": { "Name": "Navigation" }, "format": "BULLET_HEADING", "uid": "f16f9c44a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Find commands", "Text": "Find commands can search node data for text matches or for more specific rules." }, "format": "BULLETS", "uid": "f16f9d2aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Filtering", "Text": "Filtering commands show only matching nodes in a flat left-hand view." }, "format": "BULLETS", "uid": "f16f9e2ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Toggle selections", "Text": "Previous and next selection commands toggle selections to quickly move between parts of the tree." }, "format": "BULLETS", "uid": "f16f9f3ca25a11e7b7c67054d2175f18" }, { "children": [ "f16fa130a25a11e7b7c67054d2175f18", "5c1d58ac792a11e8b78ca44cc8e97404", "f16fa220a25a11e7b7c67054d2175f18" ], "data": { "Name": "Formatting" }, "format": "BULLET_HEADING", "uid": "f16fa040a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Configuration dialog", "Text": "The dialog for data type configuration has several tabs to easily set all type, field and output parameters." }, "format": "BULLETS", "uid": "f16fa130a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Format copies", "Text": "Formatting information can be copied from another TreeLine file." }, "format": "BULLETS", "uid": "f16fa220a25a11e7b7c67054d2175f18" }, { "children": [ "f16fa40aa25a11e7b7c67054d2175f18", "f16fa504a25a11e7b7c67054d2175f18", "f16fa5fea25a11e7b7c67054d2175f18", "f16fa70ca25a11e7b7c67054d2175f18" ], "data": { "Name": "File Handling" }, "format": "BULLET_HEADING", "uid": "f16fa31aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Undo/redo", "Text": "Undo and redo commands are available for all modifying operations." }, "format": "BULLETS", "uid": "f16fa40aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File formats", "Text": "TreeLine files use a JSON format, with options for automatically compressing or encrypting the files." }, "format": "BULLETS", "uid": "f16fa504a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Document templates", "Text": "Document templates for new files are preformatted to cover basic needs." }, "format": "BULLETS", "uid": "f16fa5fea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Printing", "Text": "The formatted output can be printed with parent/child lines, headers and footers." }, "format": "BULLETS", "uid": "f16fa70ca25a11e7b7c67054d2175f18" }, { "children": [ "f16fa8f6a25a11e7b7c67054d2175f18", "31304c06792b11e888cfa44cc8e97404", "f16fa9f0a25a11e7b7c67054d2175f18", "9bd80f34b32b11e7be613417ebd53aeb", "f16faaf4a25a11e7b7c67054d2175f18", "f16fabf8a25a11e7b7c67054d2175f18", "f16facf2a25a11e7b7c67054d2175f18" ], "data": { "Name": "File Import and Export" }, "format": "BULLET_HEADING", "uid": "f16fa806a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML export", "Text": "The data can be exported to single or multiple HTML files with optional navigation panes." }, "format": "BULLETS", "uid": "f16fa8f6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Text import/export", "Text": "Plain text, tab-indented text and delimited table files can be imported and exported." }, "format": "BULLETS", "uid": "f16fa9f0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Bookmark import/export", "Text": "Mozilla and XBEL format bookmark files can be imported and exported." }, "format": "BULLETS", "uid": "f16faaf4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Generic XML import/export", "Text": "Generic XML files can be imported and exported, allowing TreeLine to function as a crude XML editor." }, "format": "BULLETS", "uid": "f16fabf8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "ODF import/export", "Text": "ODF text documents can be imported and exported as outlines." }, "format": "BULLETS", "uid": "f16facf2a25a11e7b7c67054d2175f18" }, { "children": [ "f16faee6a25a11e7b7c67054d2175f18", "f16fafe0a25a11e7b7c67054d2175f18", "f16fb0daa25a11e7b7c67054d2175f18", "f08b97be792b11e88588a44cc8e97404" ], "data": { "Name": "Linking" }, "format": "BULLET_HEADING", "uid": "f16fadf6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Internal links", "Text": "Internal link fields select a linked node when clicked." }, "format": "BULLETS", "uid": "f16faee6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "External links", "Text": "External link fields can be used to open URLs in web browsers." }, "format": "BULLETS", "uid": "f16fafe0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Embedded links", "Text": "Both internal and external links can be embedded into text fields." }, "format": "BULLETS", "uid": "f16fb0daa25a11e7b7c67054d2175f18" }, { "children": [ "f16fb2cea25a11e7b7c67054d2175f18", "f16fb3c8a25a11e7b7c67054d2175f18", "f16fb4eaa25a11e7b7c67054d2175f18", "f16fb5e4a25a11e7b7c67054d2175f18", "5f12f768b32c11e7a41a3417ebd53aeb", "f16fb6dea25a11e7b7c67054d2175f18", "f16fb7f6a25a11e7b7c67054d2175f18" ], "data": { "Name": "Data Manipulation" }, "format": "BULLET_HEADING", "uid": "f16fb1dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sorting", "Text": "Nodes can be sorted by title or by predefined key fields." }, "format": "BULLETS", "uid": "f16fb2cea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math Fields", "Text": "Math fields can be defined that automatically calculate their contents based on numerical values in other nodes." }, "format": "BULLETS", "uid": "f16fb3c8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Numbering", "Text": "Numbering fields can be defined and automatically updated." }, "format": "BULLETS", "uid": "f16fb4eaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional types", "Text": "A node's icon and output format can be changed conditionally based on its data." }, "format": "BULLETS", "uid": "f16fb5e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spell check", "Text": "Text data can be spell checked (requires an external program - see the System Requirements section)." }, "format": "BULLETS", "uid": "f16fb6dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Arranging data", "Text": "Data can be automatically re-arranged using categories from data fields." }, "format": "BULLETS", "uid": "f16fb7f6a25a11e7b7c67054d2175f18" }, { "children": [ "f16fba08a25a11e7b7c67054d2175f18", "f16fbb02a25a11e7b7c67054d2175f18", "f16fbc06a25a11e7b7c67054d2175f18", "f16fbd00a25a11e7b7c67054d2175f18" ], "data": { "Name": "Customization" }, "format": "BULLET_HEADING", "uid": "f16fb90ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Customization", "Text": "There are many options for customizing both general and file-based attributes." }, "format": "BULLETS", "uid": "f16fba08a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Shortcuts and toolbars", "Text": "There are editors for keyboard shortcuts and toolbar commands." }, "format": "BULLETS", "uid": "f16fbb02a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Fonts", "Text": "Fonts used in the GUI, editors and output views can be customized." }, "format": "BULLETS", "uid": "f16fbc06a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Languages", "Text": "The user interface is available in simplified Chinese, English, German, Russian and Spanish. Translations into other languages are TBD." }, "format": "BULLETS", "uid": "f16fbd00a25a11e7b7c67054d2175f18" }, { "children": [ "f16fbfeea25a11e7b7c67054d2175f18", "f16fc4bca25a11e7b7c67054d2175f18", "460699ebdc9411ea89afac675dac20af" ], "data": { "Name": "System Requirements" }, "format": "HEADINGS", "uid": "f16fbef4a25a11e7b7c67054d2175f18" }, { "children": [ "f16fc0d4a25a11e7b7c67054d2175f18", "f16fc1cea25a11e7b7c67054d2175f18", "f16fc2c8a25a11e7b7c67054d2175f18", "f16fc3c2a25a11e7b7c67054d2175f18" ], "data": { "Name": "Linux" }, "format": "BULLET_HEADING", "uid": "f16fbfeea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Python", "Text": "Python (Version 3.9 or higher)" }, "format": "BULLETS", "uid": "f16fc0d4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Qt", "Text": "QT (Version 6.4 or higher)" }, "format": "BULLETS", "uid": "f16fc1cea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "PyQt", "Text": "PyQt (Version 6.4 or higher)" }, "format": "BULLETS", "uid": "f16fc2c8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spell check", "Text": "If spell checking is desired, either aspell, ispell or hunspell are required" }, "format": "BULLETS", "uid": "f16fc3c2a25a11e7b7c67054d2175f18" }, { "children": [ "f16fc5aca25a11e7b7c67054d2175f18", "f16fc6b0a25a11e7b7c67054d2175f18" ], "data": { "Name": "Windows" }, "format": "BULLET_HEADING", "uid": "f16fc4bca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Binary", "Text": "Should run on any computer running Windows 10 or 11." }, "format": "BULLETS", "uid": "f16fc5aca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spell check", "Text": "If spell checking is desired, an external program is required. Either aspell, ispell or hunspell must be installed." }, "format": "BULLETS", "uid": "f16fc6b0a25a11e7b7c67054d2175f18" }, { "children": [ "f16fc89aa25a11e7b7c67054d2175f18", "f16fcc96a25a11e7b7c67054d2175f18", "611e03ffdc9411ea930eac675dac20af" ], "data": { "Name": "Installation" }, "format": "HEADINGS", "uid": "f16fc7aaa25a11e7b7c67054d2175f18" }, { "children": [ "f16fc98aa25a11e7b7c67054d2175f18", "f16fcaa2a25a11e7b7c67054d2175f18", "f16fcb9ca25a11e7b7c67054d2175f18" ], "data": { "Name": "Linux" }, "format": "HEADINGS", "uid": "f16fc89aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Basic installation", "Text": "Extract the source files from the treeline tar file, then change to the TreeLine directory in a terminal. For a basic installation, simply execute the following command as root: \"python install.py\"." }, "format": "PARAGRAPH", "uid": "f16fc98aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Python 3", "Text": "If your distribution defaults to Python 2.x, you may need to substitute \"python3\" for \"python\" in these commands." }, "format": "PARAGRAPH", "uid": "f16fcaa2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Install options", "Text": "To see all install options, use: \"python install.py -h\". To install TreeLine with a different prefix (the default is /usr/local), use: \"python install.py -p /prefix/path\". To skip dependency checks, use: \"python install.py -x\"." }, "format": "PARAGRAPH", "uid": "f16fcb9ca25a11e7b7c67054d2175f18" }, { "children": [ "f16fcf3ea25a11e7b7c67054d2175f18", "f16fd042a25a11e7b7c67054d2175f18", "f16fd132a25a11e7b7c67054d2175f18" ], "data": { "Name": "Windows" }, "format": "HEADINGS", "uid": "f16fcc96a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "All users", "Text": "To install for all users, execute the \"TreeLine-x.x.x-install-all.exe\" file. Administrator permissions are required." }, "format": "PARAGRAPH", "uid": "f16fcf3ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Single user", "Text": "To install for a single user (administrator rights are not required), execute the \"TreeLine-x.x.x-install-user.exe\" file." }, "format": "PARAGRAPH", "uid": "f16fd042a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Portable install", "Text": "For a portable install, execute the \"TreeLine-x.x.x-install-user.exe\" file. The file association, shortcuts and uninstaller tasks should be unchecked. When TreeLine starts and prompts for the config file location, choose the program directory option." }, "format": "PARAGRAPH", "uid": "f16fd132a25a11e7b7c67054d2175f18" }, { "children": [ "f16fd326a25a11e7b7c67054d2175f18", "f16fdccca25a11e7b7c67054d2175f18", "f16fe0b4a25a11e7b7c67054d2175f18", "f16fe3fca25a11e7b7c67054d2175f18" ], "data": { "Name": "Basic Usage" }, "format": "HEADINGS", "uid": "f16fd236a25a11e7b7c67054d2175f18" }, { "children": [ "f16fd682a25a11e7b7c67054d2175f18", "28f8844ab58711e79d173417ebd53aeb", "f16fd858a25a11e7b7c67054d2175f18", "f16fd9aca25a11e7b7c67054d2175f18", "f16fdabaa25a11e7b7c67054d2175f18", "f16fdbc8a25a11e7b7c67054d2175f18" ], "data": { "Name": "Views" }, "format": "HEADINGS", "uid": "f16fd326a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Tree View", "Text": "The left-hand view shows a tree of node titles. Parent nodes can be opened and closed to display or hide their indented descendant nodes. Clicking on an already selected node allows the title to be edited. Right-click context menus are available for commonly used functions." }, "format": "HEAD_PARA", "uid": "f16fd682a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Right-hand Views", "Text": "The right pane is tabbed to show one of three different views of the data. The \"Data Output\" view shows the formatted text, the \"Data Edit\" view shows text edit boxes, and the \"Title List\" view shows an editable list of node titles.
\n
\nWhen a parent node is selected in the tree, the right view will default to showing information about the selected node in an upper pane and information about the selected node's children in a lower pane. The \"View > Show Child Pane\" command will toggle the display of the child nodes. If the selected node has no children, the view will show a single pane with information about the selected node only.
\n
\nWhen multiple nodes are selected in the tree (by holding down the shift or Ctrl keys while clicking), the right view will not display any child node information. It will instead show information about every selected node.
\n
\nWhen no nodes are selected in the tree (by clicking on a blank area or Ctrl clicking to unselect), the right view will show information about the top-level (root) nodes." }, "format": "HEAD_PARA", "uid": "f16fd858a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data Output View", "Text": "The \"Data Output\" view shows formatted output text. It cannot be edited from this view.
\n
\nWhen the \"View > Show Output Descendants\" command is toggled, the \"Data Output\" view will show an indented list with information about every descendant of a single selected node." }, "format": "HEAD_PARA", "uid": "f16fd9aca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data Edit View", "Text": "The \"Data Edit\" view shows a text edit box for each data field within a node. It also shows the node types and the node titles. The types of edit boxes vary based on the field type. Some are just text editors, while others (such as choice fields, date fields, links, etc.) have pull-down menus or dialogs." }, "format": "HEAD_PARA", "uid": "f16fdabaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Title List View", "Text": "The \"Title List\" view shows a list of node titles that can be modified using typical text editor methods. If a new line is typed, a new node is created with that title. If a line is deleted, the corresponding node is removed from the tree." }, "format": "HEAD_PARA", "uid": "f16fdbc8a25a11e7b7c67054d2175f18" }, { "children": [ "f16fddbca25a11e7b7c67054d2175f18", "f16fdeb6a25a11e7b7c67054d2175f18", "997af664b58811e7ac243417ebd53aeb", "f16fdfb0a25a11e7b7c67054d2175f18" ], "data": { "Name": "Editing" }, "format": "HEADINGS", "uid": "f16fdccca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Node Menu", "Text": "The commands in the \"Node\" menu operate on the selected nodes in the left tree view. There are commands to add or insert nodes, rename node titles and delete nodes. There are also commands to rearrange the tree by changing indent levels or moving nodes up or down. For many of the commands, the descendants of the selected nodes are also affected." }, "format": "HEAD_PARA", "uid": "f16fddbca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Edit Menu", "Text": "The edit menu includes undo and redo commands that can fix problems. Cut, copy and paste commands can operate either on text in the right-hand view (if selected or active) or to tree nodes." }, "format": "HEAD_PARA", "uid": "f16fdeb6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Shortcuts", "Text": "There are several shortcuts for use in tree editing. Drag and drop will move (or copy if the Ctrl button is held) nodes. Clicking on a selected node will rename it. Pressing the delete key will remove the selected nodes. If desired, these shortcuts can be disabled in \"Tools > General Options\"." }, "format": "HEAD_PARA", "uid": "f16fdfb0a25a11e7b7c67054d2175f18" }, { "children": [ "f16fe1cca25a11e7b7c67054d2175f18", "f16fe2c6a25a11e7b7c67054d2175f18" ], "data": { "Name": "Files" }, "format": "HEADINGS", "uid": "f16fe0b4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Templates", "Text": "When starting a new file, a dialog box offers a choice of templates. The default has only a single text field for each node that contains the title. The Long Text template adds a second long text field for more output text. Other templates have various fields for contacts, book lists and to-do lists." }, "format": "HEAD_PARA", "uid": "f16fe1cca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sample Files", "Text": "Various TreeLine sample files can be opened by using the \"File > Open Sample\" command. These have more detail and example content than the new file templates." }, "format": "HEAD_PARA", "uid": "f16fe2c6a25a11e7b7c67054d2175f18" }, { "children": [ "f16fe4eca25a11e7b7c67054d2175f18", "f16fe5f0a25a11e7b7c67054d2175f18" ], "data": { "Name": "Data Types" }, "format": "HEADINGS", "uid": "f16fe3fca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Node Types", "Text": "Multiple node data types can be defined in a TreeLine file. Each can contain different data fields and have different output formats. See the template and sample files for examples. Nodes can be set to a specific type using the \"Data > Set Node Type\" command." }, "format": "HEAD_PARA", "uid": "f16fe4eca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Type Config", "Text": "The \"Data > Configure Data Types\" command is used to modify node data types, fields and output formatting. Refer to the Detailed Usage section of the full documentation for details." }, "format": "HEAD_PARA", "uid": "f16fe5f0a25a11e7b7c67054d2175f18" }, { "children": [ "f16fe7e4a25a11e7b7c67054d2175f18", "f16fed0ca25a11e7b7c67054d2175f18", "f16ff2f2a25a11e7b7c67054d2175f18", "f1700936a25a11e7b7c67054d2175f18", "f1700f58a25a11e7b7c67054d2175f18", "f170146ca25a11e7b7c67054d2175f18", "f1701caaa25a11e7b7c67054d2175f18", "f170207ea25a11e7b7c67054d2175f18", "f170256aa25a11e7b7c67054d2175f18", "f1702c4aa25a11e7b7c67054d2175f18", "f170335ca25a11e7b7c67054d2175f18" ], "data": { "Name": "Detailed Usage" }, "format": "HEADINGS", "uid": "f16fe6fea25a11e7b7c67054d2175f18" }, { "children": [ "f16fe8dea25a11e7b7c67054d2175f18", "f16fe9e2a25a11e7b7c67054d2175f18", "f16feaf0a25a11e7b7c67054d2175f18", "f16fec08a25a11e7b7c67054d2175f18" ], "data": { "Name": "Tree Navigation and Search" }, "format": "HEADINGS", "uid": "f16fe7e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Keyboard Shortcuts", "Text": "There are several keyboard commands that can be used for tree navigation. The up and down arrow keys move the selection. The left and right arrows open and close the current node. The \"Home\", \"End\", \"Page Up\" and \"Page Down\" keys can be used to move quickly through the tree.
\n
\nAnother way to move through the tree is to type the first letter of a visible node title. Hitting the letter again highlights to the next possibility." }, "format": "HEAD_PARA", "uid": "f16fe8dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Selection", "Text": "Multiple nodes can be selected by holding down the CTRL or the SHIFT key when changing the active node. Individual nodes are added or removed from the selection when the CTRL key is held. The selection of all nodes between the old and new active nodes are toggled when SHIFT is held. The active node can be changed by using the mouse or by using any of the keyboard navigation methods.
\n
\nThe \"View > Previous Selection\" and \"View > Next Selection\" commands can be used to toggle through a history of selections, allowing faster navigation through the tree." }, "format": "HEAD_PARA", "uid": "f16fe9e2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Searching", "Text": "The \"Tools > Find Text\" command will search for text within the tree structure. The dialog box has options for searching all of the node data or only the node titles. There are also options for how to interpret the search text. Key words will match nodes with the search words found anywhere in the node. Key full words will only match complete words anywhere in the node. Full phrase will only match the complete phrase in the proper sequence. Finally, the regular expression option will search using Python regular expressions.
\n
\nThe \"Tools > Conditional Find\" command will search in particular node types and node fields. Various comparison operators can be selected to exactly match, to match a greater or lesser value, or part of the value. And the True/False operators give the same result regardless of the values. In general, the value is interpreted using the edit format for special field types. Multiple rules can be added, connected with logical \"and\" or \"or\" operators. The \"All Types\" option makes fields from every type are available, so that multiple node types to be part of the same search. The condition will be false for node types that do not contain that field name.
\n
\nThere is also a quick, incremental search of node titles. By default, it's bound to ctrl+/. Then, matching titles are found as the search string is typed. The F3 and shift+F3 keys can be used to go to the next or previous matches, respectively." }, "format": "HEAD_PARA", "uid": "f16feaf0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Filtering", "Text": "There are two filtering commands, \"Tools > Text Filter\" and \"Tools > Conditional Filter\". They work like the corresponding search commands above, except that they show all of the matching nodes in a flat list that replaces the tree view. The nodes can be selected and edited from this view. Use the \"End Filter\" button to restore the full tree view.
\n
\nSearches for Conditional Find and Conditional Filter can be saved in the dialog boxes and loaded again at another time." }, "format": "HEAD_PARA", "uid": "f16fec08a25a11e7b7c67054d2175f18" }, { "children": [ "f16fedfca25a11e7b7c67054d2175f18", "f16feef6a25a11e7b7c67054d2175f18", "f16feffaa25a11e7b7c67054d2175f18", "f16ff0f4a25a11e7b7c67054d2175f18", "f16ff1e4a25a11e7b7c67054d2175f18" ], "data": { "Name": "Defining Node Types" }, "format": "HEADINGS", "uid": "f16fed0ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Type List", "Text": "The \"Type List\" is the first tab of the \"Data > Configure Types Dialog\". The list of data types can be modified by the buttons on the right. New types can be added, and existing types can be copied, renamed or deleted." }, "format": "HEAD_PARA", "uid": "f16fedfca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Type Config", "Text": "\"Type Config\" is the second tab of the Configure Types Dialog. It contains a selection for the default child type. If set, this will be the initial type used for new children with this type of parent. If set to \"[None]\", children will default to either the type of their siblings or their parent.
\n
\nThe \"Change Icon\" button allows the selection of a custom tree icon for this data type. The \"Clear Select\" button on the icon dialog can be used to set the icon to \"None\", so that no icon will be displayed for this type. To avoid showing any tree icons, the \"Show icons in the tree view\" general option can be unset.
\n
\nThere are also options here for adding blanks lines between nodes, allowing HTML tags in the common format text, and changing the output to add bullets or tables." }, "format": "HEAD_PARA", "uid": "f16feef6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Field List", "Text": "The \"Field List\" is the third tab of the Configure Types Dialog. The list of fields within a data type can be modified by using the buttons on the right. New fields can be added, and existing fields can be moved, renamed or deleted. Sort keys can also be defined to specify the fields that are compared when nodes are sorted." }, "format": "HEAD_PARA", "uid": "f16feffaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Field Config", "Text": "\"Field Config\" is the fourth tab of the Configure Types Dialog. The field type and its output format string can be set, if applicable to the field. Extra prefix and suffix text to be output with the field can also be set, and a default field value for new nodes can be entered. The number of lines displayed in the editor for the field can also be specified. Finally, an option to evaluate HTML tags can be set to recognize HTML tags in Choice, AutoChoice, Combination, AutoCombination and RegularExpression fields. If this is set, special characters (angled brackets and quotation marks) will need to be manually escaped to show up in the field text." }, "format": "HEAD_PARA", "uid": "f16ff0f4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Output", "Text": "\"Output\" is the last tab of the Configure Types Dialog. The left half of the dialog shows the fields. The right half shows the formatting for the title (used for the node text in the tree view) and the node output. The formatting consists of text lines with embedded fields. The fields are shown as \"{*field_name*}\". The fields that are selected in the list (multiple fields can be selected by holding Ctrl or Shift keys while clicking) can be added to a format at the cursor position with the \">>\" keys. The field reference at the cursor can be removed with the \"<<\" keys." }, "format": "HEAD_PARA", "uid": "f16ff1e4a25a11e7b7c67054d2175f18" }, { "children": [ "f16ff3e2a25a11e7b7c67054d2175f18", "f16ff4dca25a11e7b7c67054d2175f18", "f16ff5f4a25a11e7b7c67054d2175f18", "f16ff7c0a25a11e7b7c67054d2175f18", "f16ff8f6a25a11e7b7c67054d2175f18", "f16ff9faa25a11e7b7c67054d2175f18", "f17005f8a25a11e7b7c67054d2175f18", "f1700710a25a11e7b7c67054d2175f18", "f16ffc02a25a11e7b7c67054d2175f18", "f16ffd06a25a11e7b7c67054d2175f18", "f16ffe14a25a11e7b7c67054d2175f18", "f16ffb08a25a11e7b7c67054d2175f18", "f16fff18a25a11e7b7c67054d2175f18", "f1700008a25a11e7b7c67054d2175f18", "f1700102a25a11e7b7c67054d2175f18", "f1700206a25a11e7b7c67054d2175f18", "f1700300a25a11e7b7c67054d2175f18", "f1700404a25a11e7b7c67054d2175f18", "f17004fea25a11e7b7c67054d2175f18", "f170081ea25a11e7b7c67054d2175f18" ], "data": { "Name": "Field Types" }, "format": "HEADINGS", "uid": "f16ff2f2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Field Options", "Text": "The field type and options are set in the \"Field Config\" tab of the \"Data > Configure Types Dialog\". The many different field types are described in the paragraphs below.
\n
\nSeveral of the field types use a formatting string to define their output. For a list of available formatting characters, use the \"Format Help\" button. Entries in the data editor which do not match the format will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with \"#####\"." }, "format": "HEAD_PARA", "uid": "f16ff3e2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Text Type", "Text": "The default field type is a text field. It is the most commonly used field. These fields are edited using edit boxes in the data editor view. There are several commands in the Format menu (and also in the context menu) for setting the font style and adding external or internal links. The edit box height expands when re-displayed after adding several lines of text. The minimum edit box height can also be set explicitly in the \"Field Config\" tab." }, "format": "HEAD_PARA", "uid": "f16ff4dca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML Text Type", "Text": "This type allows simple HTML tags to be used in the text. Commonly used tags include \"<b>bold</b>\", \"<u>underline</u>\", \"line break<br/>\", \"horizontal line<hr/>\", and various font tags. Complex block tags should generally be avoided. Carriage returns are ignored, and non-escaped \"<\", \">\" and \"&\" symbols do not display. " }, "format": "HEAD_PARA", "uid": "f16ff5f4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "One Line Text Type", "Text": "This type restricts the text length to a single line. It does not allow carriage returns but does not restrict line wrapping of a single long line." }, "format": "HEAD_PARA", "uid": "f16ff7c0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spaced Text Type", "Text": "This type holds plain text and preserves all spacing. Other formatting of the text is not permitted. It could be useful to use the \"Tools > Customize Fonts\" command to set the editor font to a mono-spaced font when using this field type." }, "format": "HEAD_PARA", "uid": "f16ff8f6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Number Type", "Text": "In the number type, special characters in the format define the display of the numbers. The format uses a string of \"#\" (optional digit) and \"0\" (required digit) characters to define the output formatting. For example, pi formatted with \"#.#\" is \"3.1\" and formatted with \"00.00\" is \"03.14\". Regardless of the formatting, digits to the left of the decimal point are not truncated, since that would display an incorrect result. But use care to show enough decimal places (either optional or required) to avoid problems with round-off error.
\n
\nThe radix character can be specified as either \".\" or \",\" to handle internationalization. For use as a thousands separator, use \"\\,\" or \"\\.\". For example, a large number may be formatted as \"#\\,###\\,###.##\" or as \"#\\.###\\.###,##\". Press the \"Format Help\" button from the field format dialog for more formatting details.
\n
\nUnlike most other formats, the number type also uses the output format for display in the Data Editor. Of course, any new entry with a reasonable format is correctly interpreted (but the correct radix character must be used)." }, "format": "HEAD_PARA", "uid": "f16ff9faa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Boolean Type", "Text": "This type gives two choices corresponding to true/false values. The format help menu includes typical values such as \"yes/no\", \"true/false\" and \"1/0\", but users can also enter their own word pair. The data editor boxes will accept either the currently set format or any of the typical values." }, "format": "HEAD_PARA", "uid": "f16ffb08a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Date Type", "Text": "In the date field type, special characters in the format (all starting with \"%\") are replaced by elements of the data, similar to number fields. Press the \"Format Help\" button from the field format dialog for formatting details. Non-special characters will be output as themselves.
\n
\nThere is also an edit format under \"Tools > General Options > Data Editor Formats\". This controls how date fields are displayed in the Data Editor view. Generally, entries in the data editor with various formats will be correctly interpreted regardless of this setting, but dates must use the correct day-month-year sequence. Also note that the date editor format does not support days of the week.
\n
\nA default initial field value of \"Now\" can be used to enter the date of node creation." }, "format": "HEAD_PARA", "uid": "f16ffc02a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Time Type", "Text": "In the time field type, special characters in the format (all starting with \"%\") are replaced by elements of the data, similar to number fields. Press the \"Format Help\" button from the field format dialog for formatting details. Non-special characters will be output as themselves.
\n
\nThere is also an edit format under \"Tools > General Options > Data Editor Formats\". This controls how time fields are displayed in the Data Editor view. Generally, entries in the data editor with various formats will be correctly interpreted regardless of this setting.
\n
\nA default initial field value of \"Now\" can be used to enter the time of node creation." }, "format": "HEAD_PARA", "uid": "f16ffd06a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "DateTime Type", "Text": "The DateTime field combines dates and times into a single field that is useful for timestamps. Special characters in the format (all starting with \"%\") are replaced by elements of the data, as in date and time fields. Press the \"Format Help\" button from the field format dialog for formatting details. Non-special characters will be output as themselves.
\n
\nThe DateTime edit format is uses the date and time formats located in \"Tools > General Options > Data Editor Formats\". The date and time formats are combined, separated by a space character.
\n
\nA default initial field value of \"Now\" can be used to enter the date and time of node creation." }, "format": "HEAD_PARA", "uid": "f16ffe14a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Choice Type", "Text": "The choice field type allows for the selection of text items from a pull-down edit list. The formatting strings for these types list the items separated with the \"/\" character (use \"//\" to get a literal \"/\" in an item). Entries in the data editor which do not match the choices will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with \"#####\"." }, "format": "HEAD_PARA", "uid": "f16fff18a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Auto Choice Type", "Text": "This field type is similar to the choice type, but without a format string. The entries in the pull-down menu are automatically generated from all previously used entries. Any entries that are typed will be available in the pull-down menu for future use. " }, "format": "HEAD_PARA", "uid": "f1700008a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Combination Type", "Text": "This is basically the equivalent of the choice type with multiple selection. The formatting string entries are separated by the \"/\" character. The pull-down menu shows check-boxes that are checked for currently selected nodes. By default, the selected entries are output separated by a comma and a space. This can be changed in the \"Type Config\" tab of the \"Data > Configure Types Dialog\". Click the \"Show Advanced\" button to see the separator setting." }, "format": "HEAD_PARA", "uid": "f1700102a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Auto Combination Type", "Text": "This field type is similar to the combination type, but without a format string. The entries in the pull-down menu are automatically generated from all previously used entries. Any entries that are typed will be available in the pull-down menu for future use. " }, "format": "HEAD_PARA", "uid": "f1700206a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "External Link Type", "Text": "This type can support various link protocols, including http and https for web pages, mailto for email addresses and file for local files. A pull down dialog in the data editor allows the selection of the protocol type and the entry of an address and a display name. In the edit boxes, the display name shows up in [brackets], and it is used as the text of the link in the output view. The \"file\" protocol also provides a button to browse for a path and buttons to choose either absolute or relative path names.
\n
\nClicking on the link in the output view or choosing \"Open Link\" from the right-click context menu in the edit box will open the link in a web browser. In Linux, setting the \"BROWSER\" environment variable to a string like \"mozilla %s\" will result in the desired browser being used." }, "format": "HEAD_PARA", "uid": "f1700300a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Internal Link Type", "Text": "These links create shortcuts to select nodes elsewhere in the tree structure. To create a link, click the pull-down arrow and then select the target node in the tree view. The display name is shown in brackets. It is initially set to the target node title, but it can be edited. The right-click context menu can be used to clear the link or to select the target node.
\n
\nClicking the link in the output view will select the target node in the tree view." }, "format": "HEAD_PARA", "uid": "f1700404a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Picture Type", "Text": "These links add referenced pictures to the output view. A pull down dialog in the data editor has a button to browse for picture files to be linked. It also allows absolute or relative paths to be used and has a small image preview." }, "format": "HEAD_PARA", "uid": "f17004fea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math Type", "Text": "Math field types are configured by defining equations. The equations can reference number fields, date fields, time fields, boolean fields, text fields and/or other math fields. The resulting values of math fields are automatically calculated for each node. Various mathematical, relational and string operators are available. The results can be numbers, text, boolean, dates or times.

To define a math field equation, press the \"Define Equation\" button in the \"Field Config\" tab of the \"Data > Configure Types Dialog\". This brings up a dialog with fields to reference on the left and math operators on the right. The \"Reference Level\" pull-down determines whether the reference is from the same node, the node's parent, the root node, or the node's children. The \"Result Type\" pull-down allows arithmetic, date, time, boolean or text results to be chosen. The \"Operator Type\" pull-down allows numeric, comparison or text operators to be shown in the operator list. The down-arrow buttons below the references and operators add the selected item to the equation text below. Portions of equations can also be typed directly in the equation text line editor.

References to child nodes must be enclosed in a grouping function, such as sum, max, min, mean or join. A math field can contain a parent or child reference to itself, but not a same-level reference to itself (a circular reference). The references only contain the field name, so they will reference a parent or child field with that name even if it is a different node type.

In equations, date fields are represented by the number of days since January 1, 1970, and time fields are the number of seconds since midnight. So date fields can be subtracted to give the number of days elapsed, and numbers of days can be added to or subtracted from dates to result in new dates. Time fields can be subtracted to give the number of seconds elapsed, and numbers of seconds can be added to or subtracted from times to result in new times. Also, special field names ({*Now_Date*}, {*Now_Time*} and {*Now_Date_Time*}) can be manually typed in equations to represent current dates and times. The \"Data->Regenerate References\" command may be needed to force re-evaluation of time-based references.

The \"if\" comparison operator can be used to make the result depend on the value of another field. The expression is written as \"true_value if condition else false_value\". Of course, the \"true_value\", \"condition\" and \"false_value\" strings must be replaced with valid fields or expressions. If this operator is inserted from the operator list (under comparisons), it will include parenthesis as placeholders. These parenthesis are optional in the equations.

The \"join\" text function is used to combine text from several other fields (or from child nodes). The first argument to the function is a separator string that is placed between each piece of text. The remaining argument(s) are the text to be joined.

By default, math fields are shown in the data edit view, but they are read-only. To hide them, uncheck the \"Show math fields in the Data Edit View\" box under \"Tools > General Options > Features Available\".

There is also an option under \"File > Properties\" that toggles whether blank fields are treated as zeros. If checked (the default), a blank field that is referenced by a math field has a value of zero (for numeric operations) or blank (for text operations). If unchecked, any blank references also cause equations that reference them to be blank.
" }, "format": "HEAD_PARA", "uid": "f17005f8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Numbering Type", "Text": "This type (not to be confused with the number type above) provides fields that are automatically filled in with the \"Data > Update Numbering\" command. The \"Format Help\" button in the field format dialog shows the output format options. A single format level will result in a simple sequential numbering scheme. Use of the \"/\" level separator will result in an outline-type numbering with different sequences at different levels. Use of the \".\" section separator will result in a \"2.3.5\" type numbering scheme.
\n
\nSince numbering fields are automatically populated, by default they are not shown in the data edit view. To show them, check the \"Show numbering fields in the Data Edit View\" box under \"Tools > General Options > Features Available\". When they are shown in the data edit view, they show up in section numbering style, regardless of the output format." }, "format": "HEAD_PARA", "uid": "f1700710a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Regular Expression Type", "Text": "This type allows arbitrary format strings to be matched that restrict the data to a particular format. It uses Python regular expression syntax. Entries in the data editor which do not match the format string expression will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with \"#####\"." }, "format": "HEAD_PARA", "uid": "f170081ea25a11e7b7c67054d2175f18" }, { "children": [ "f1700a26a25a11e7b7c67054d2175f18", "f1700b34a25a11e7b7c67054d2175f18", "f1700c38a25a11e7b7c67054d2175f18", "f1700d3ca25a11e7b7c67054d2175f18", "f1700e40a25a11e7b7c67054d2175f18", "bbbf735ac24711e8b560d66a6ab671cb" ], "data": { "Name": "Output Formatting Details" }, "format": "HEADINGS", "uid": "f1700936a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Output Format Examples", "Text": "Here is an example of output formatting for a book list:
\n
\n\"{*Title*}\"
\n(c) {*Copyright*}, Rating: {*Rating*}
\n{*PlotDescription*}
\n
\nEach of the field names in enclosed in {* *}, curly brackets and asterisks. For more examples, see the sample files that can be opened using the \"File > Open Sample\" command." }, "format": "HEAD_PARA", "uid": "f1700a26a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Title Formats", "Text": "When a node in the tree is renamed, the program attempts to match the title formatting pattern to set the appropriate fields (the same title matching occurs when editing lines in the \"Title List\" view). If the title formatting is too complex, it may not correctly guess the intent. Things like adjacent fields with no characters separating them should be avoided unless you do not wish to rename nodes from the tree.
\n
\nIf the text data used for a tree view title has multiple lines, only the first line will be used as the title." }, "format": "HEAD_PARA", "uid": "f1700b34a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Skipped Output Lines", "Text": "If all of the fields in an output format line are empty for a given node, then the line is skipped. No blank line or embedded text will be output for that line. Note that this does not apply to a line without any fields (only embedded text). Also, when a line ending with a <br/> or an <hr/> tag is skipped, the ending tag is retained." }, "format": "HEAD_PARA", "uid": "f1700c38a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML Tags", "Text": "By default, the \"Allow HTML rich text in formats\" option is unchecked in the \"Type Config\" tab of the Configure Types Dialog. So any HTML tags are treated as plain text. If the option is enabled, simple HTML formatting tags can be used in node output formats.
\n
\nCommonly used tags include \"<b>bold</b>\", \"<u>underline</u>\", \"line break<br/>\", \"horizontal line<hr/>\", and various font tags. Complex block tags should generally be avoided." }, "format": "HEAD_PARA", "uid": "f1700d3ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Other Field References", "Text": "References to fields that are not contained within the node can be added to the output. Pushing the \"Show Advanced\" button on the \"Output\" tab of the configure dialog makes a reference level selection become visible.
\n
\nIf the reference level is changed to \"File Info Reference\", fields containing file meta-data can be added to the output. These include the file name, path, size, modified date and modified time. These special fields are shown as \"{*!field_name*}\" in the title and output format editors.
\n
\nThere are field references to various ancestor nodes (parents, grandparents, etc.). These require the data type of the reference to be specified. This selection determines the field names that are available, but the data from any type with a matching field name will be shown in the output. References to fields from parent and grandparent nodes are shown as \"{**field_name*}\" and \"{***field_name*}\", respectively. There are also general ancestor references, shown as \"{*?field_name*}\", that take data from the closest ancestor with a matching field.
\n
\nReferences to child nodes can also be added, shown as \"{*&field_name*}\". These also require that the child data type be specified. The child data becomes embedded in the parent output. The child data is delimited with a separator string defined on the \"Type Config\" tab (with show advanced active). The separator defaults to a comma and a space, but can be set to <br/> or anything else.
\n
\nFinally, a \"Child Count\" reference can be added. This field will show the number of children (\"Level1\" field) or grandchildren (\"Level2\" field) of a node. These are shown as {*#Level1*} in the format editors.
\n
\nFor examples of these fields, see the \"sample_other_fields\" file (by using the \"File > Open Sample\" command)." }, "format": "HEAD_PARA", "uid": "f1700e40a25a11e7b7c67054d2175f18" }, { "children": [ "f1701156a25a11e7b7c67054d2175f18", "f170125aa25a11e7b7c67054d2175f18", "f1701368a25a11e7b7c67054d2175f18", "aa6f6ca4bb0711e7bbf43417ebd53aeb" ], "data": { "Name": "Type Format Details" }, "format": "HEADINGS", "uid": "f1700f58a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Generic and Derived Types", "Text": "Data types can be set to derive their field settings from a generic type. This allows types with different output formatting to always use the same set of fields. Any changes to the generic's list of fields and field types are automatically reflected in the fields of all derived types. This does not apply to a field's output formatting, which can still be set independently.
\n
\nThere are two methods for creating derived types. First, a derived option can be selected when copying a type on the \"Type List\" tab of the \"Data > Configure Types Dialog\". Alternately, a generic type can be specified from the derived type's \"Type Config\" tab of the dialog if the advanced functions are shown." }, "format": "HEAD_PARA", "uid": "f1701156a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional Types", "Text": "Conditional expressions can be used to automatically assign a data type based on each node's content. Conditions can be assigned only to a generic type and its associated derived types. This allows the automatic assignment of different output formatting or different icons depending on each node's field data.

The conditional dialog box is accessed from a button on the \"Type Config\" tab of the \"Data->Configure Types Dialog\" if the advanced functions are shown. Each line of the condition includes a field, an operator and a comparison value. The operators include equality, greater than, less than, starts with, ends with, and contains. There are also True and False operators that will toggle the type of all nodes simultaneously.

For special field types such as dates, times, and booleans, the comparison value should be entered in the same format that is used in the Data Editor window. In general, the starts with, ends with, and contains operators should not be used for these special fields, since the comparison is done using an internal data representation. Dates and times also support a special comparison value of \"Now\", which is always interpreted as the current date and time. The \"Data->Regenerate References\" command may be needed to force re-evaluation of time-based references.

The \"Add New Rule\" button is used to add additional condition lines. The lines can be joined with \"and\" or \"or\" operators. The \"Remove Rule\" button deletes the last condition line. If only a single line is present, the \"Remove Rule\" button completely removes the condition.

Conditions do not have to be set for all types in a family. If no conditions are true for a node, the program will select a blank condition rather than a false one.

For an example, see the \"sample_conditional_todo\" file (by using the \"File > Open Sample\" command)." }, "format": "HEAD_PARA", "uid": "f170125aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Copying Formats", "Text": "Another method for changing data type formatting is to copy the formats from another TreeLine file. This is done with the \"Data > Copy Types from File\" command. All types from the chosen file are copied. Any types in the current file with matching names are overwritten, but types with unique names are retained." }, "format": "HEAD_PARA", "uid": "f1701368a25a11e7b7c67054d2175f18" }, { "children": [ "f170155ca25a11e7b7c67054d2175f18", "f1701660a25a11e7b7c67054d2175f18", "f1701764a25a11e7b7c67054d2175f18", "f1701868a25a11e7b7c67054d2175f18", "f170198aa25a11e7b7c67054d2175f18", "f1701a8ea25a11e7b7c67054d2175f18" ], "data": { "Name": "Tree Data Operations" }, "format": "HEADINGS", "uid": "f170146ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sorting", "Text": "The \"Data > Sort Nodes\" command can sort nodes based on either node titles or key fields predefined in the node type configuration. The predefined sort fields can be changed in the \"Field Config\" tab of the Configure Types Dialog. The \"Sort Keys\" button brings up a list of fields that define a sort key sequence. The fields higher in the sequence have a higher priority. The direction for each key field can be flipped." }, "format": "HEAD_PARA", "uid": "f170155ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Numbering", "Text": "The \"Data > Update Numbering\" command updates the contents of fields with a special numbering field type. The field's output format defines how the numbers are displayed in the output, including whether individual numbers, outline numbers or a section numbering scheme are shown. See the Numbering Field Type for more information.
\n
\nNote that numbering fields are not shown in the data edit view unless \"Show numbering fields in the Data Edit View\" is checked under \"Tools > General Options > Features Available\". When they are shown in the data edit view, they show up in section numbering style, regardless of the output format." }, "format": "HEAD_PARA", "uid": "f1701660a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Find and Replace", "Text": "The \"Tools > Find and Replace\" command can be used to change the text in several nodes. The search text and replacement text are entered. Searching can be based on any match, full words only, or a Python regular expression. The operation can optionally be restricted to a particular node type and to a particular node field.
\n
\nReplacement using regular expressions is quite powerful. Searching for \".*\" will match all of the text in the field. The replacement string can contain back references that consist of a backslash and a number. The back references get replaced with the corresponding parenthesized group from the match. For example, \"\\2\" will be replaced with the text that matched the second group of parenthesis. The \"\\g<0>\" back-reference can be used to substitute the entire matching string." }, "format": "HEAD_PARA", "uid": "f1701764a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spell Check", "Text": "There is a spell check command in the \"Tools\" menu. Use of this command requires an external program to be installed (either aspell, ispell or hunspell- see the System Requirements section). If there are any misspelled words in the selected branch, a dialog will allow the word to be ignored, added to the dictionary, replaced with a suggestion or edited. This will spell check the text in all data fields of each node." }, "format": "HEAD_PARA", "uid": "f1701868a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Cloned Nodes", "Text": "Cloned nodes are used to duplicate sections of the tree. Editing their data or child structure in one location changes all locations. When a cloned node is selected, multiple lines are shown in the Breadcrumb view, showing ancestor nodes that have multiple parents. The selected node will appear black (not a link), but its clones can be clicked to select their location in the tree view.
\n
\nCloned nodes are created by copying nodes or branches and then using the special paste clone commands found in the \"Edit\" menu to paste them elsewhere. The clone link can be removed by deleting the nodes or by using the \"Data > Detach Clones\" command to convert them back to regular nodes.
\n
\nCloned nodes can also be created automatically by using the \"Data > Clone All Matched Nodes\" command. This will convert all identical nodes in the tree structure into cloned nodes.
\n
\nFor an example of cloned nodes with multiple parents, see the \"sample_genealogy\" file (by using the \"File > Open Sample\" command)." }, "format": "HEAD_PARA", "uid": "f170198aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Category-Based Arrangement", "Text": "The \"Data\" menu contains commands for arranging and flattening the data by category. These methods are used to automatically add and remove levels of nodes below the current node in the tree.
\n
\nThe \"Add Category Level\" command allows you to select one or more of the fields that the child nodes have in common. These fields are used to create new parent nodes for the children, grouping them by common categories. For example, in a list of books, picking the \"author_first_name\" and \"author_last_name\" fields will result in a tree with the books under new nodes for each unique author.
\n
\nThe \"Flatten by Category\" command is almost the opposite of \"Add Category Level\". It eliminates any descendant nodes with children, transferring their data fields to their children. It will rename fields instead of overwriting data with the same field names, but this command is most useful when the children and parents are different types with unique field names.
\n
\nThere is also a \"Swap Category Levels\" command that will swap the child and grandchild nodes beneath a selected node. A child node with multiple nodes under it will become cloned under each one. Any existing grandchild clones will become individual nodes with multiple children." }, "format": "HEAD_PARA", "uid": "f1701a8ea25a11e7b7c67054d2175f18" }, { "children": [ "f1701d90a25a11e7b7c67054d2175f18", "f1701e8aa25a11e7b7c67054d2175f18", "f1701f84a25a11e7b7c67054d2175f18" ], "data": { "Name": "Printing" }, "format": "HEADINGS", "uid": "f1701caaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Print Setup", "Text": "The dialog for print setup contains four tabs. The first, General Options, includes settings for what part of the tree to print, whether to include lines to child nodes and whether to allow page breaks between a parent an its first child node. It also has place to set the printer queue, to make pagination and print previews more accurate. The second tab, Page Setup, includes paper size, orientation, margins and columns. The third tab selects the font for printing. The last tab, Header/Footer, defines text and file data meta-fields for inclusion in headers and footers." }, "format": "HEAD_PARA", "uid": "f1701d90a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Print Preview", "Text": "The Print Preview window shows how the printout will look with current print settings. It can be dragged larger to show more detail, or the zoom settings can be changed. It also includes buttons for the Print Setup dialog and for printing." }, "format": "HEAD_PARA", "uid": "f1701e8aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Print to PDF", "Text": "This command prompts for a path and file name to export a PDF file. It uses the current printer settings." }, "format": "HEAD_PARA", "uid": "f1701f84a25a11e7b7c67054d2175f18" }, { "children": [ "f170216ea25a11e7b7c67054d2175f18", "f1702272a25a11e7b7c67054d2175f18", "f170236ca25a11e7b7c67054d2175f18", "f1702470a25a11e7b7c67054d2175f18" ], "data": { "Name": "File Handling" }, "format": "HEADINGS", "uid": "f170207ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File Compression", "Text": "A TreeLine file is in a JSON text format. There are options to compress the files (gzip format) to save storage space. Individual files can be set to compressed mode from either \"File > Properties\" or from the file type pull-down in the save-as dialog." }, "format": "HEAD_PARA", "uid": "f170216ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File Encryption", "Text": "There is a file encryption option to password protect TreeLine files. Individual files can be set to encrypted mode from either \"File > Properties\" or from the file type pull-down in the save-as dialog. The encryption uses an SHA hash function as a stream cipher - it should be fairly secure." }, "format": "HEAD_PARA", "uid": "f1702272a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Auto-Save", "Text": "An auto-save feature can store unsaved files with a \"~\" appended to the file name. The backup files are automatically removed when the file is saved or TreeLine exits cleanly. The auto-save time interval is set in the general options. Setting the interval to zero disables this feature." }, "format": "HEAD_PARA", "uid": "f170236ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved Tree States", "Text": "When opening a recently used file, TreeLine will restore the states of open and selected nodes. This information is stored in the user's TreeLine configuration files. If desired, this feature can be disabled with a general option." }, "format": "HEAD_PARA", "uid": "f1702470a25a11e7b7c67054d2175f18" }, { "children": [ "f170265aa25a11e7b7c67054d2175f18", "f170275ea25a11e7b7c67054d2175f18", "f1702b46a25a11e7b7c67054d2175f18", "95547c38b97411e7a42a3417ebd53aeb", "f1702858a25a11e7b7c67054d2175f18", "f1702952a25a11e7b7c67054d2175f18", "f1702a42a25a11e7b7c67054d2175f18" ], "data": { "Name": "File Import" }, "format": "HEADINGS", "uid": "f170256aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "General Information", "Text": "A TreeLine file is in a specific JSON text format. Other types of files can be imported using the \"File > Import\" command, which will show a dialog box where the type of import can be selected. Alternatively, using the \"File > Open\" command with a non-TreeLine file will also show this dialog." }, "format": "HEAD_PARA", "uid": "f170265aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Text Import", "Text": "Several different text formats can be selected for import. Tab indented text creates a node title from each line in the file, structured based on the number of tabs before each line.
\n
\nThe comma-delimited (CSV) and the tab delimited text tables use the first line as a header row to create field names, then each additional row becomes a node with field data taken from each column. The CSV import with level numbers creates a tree structure from level numbers in the first column that are incremented to show child relationships.
\n
\nThe plain text, one node per line import creates a flat tree of node titles.
\n
\nFinally, the plain text paragraph import creates long text nodes from text separated by blank lines." }, "format": "HEAD_PARA", "uid": "f170275ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Treepad Import", "Text": "Files from the Treepad shareware program can be imported. Only Treepad text nodes are supported." }, "format": "HEAD_PARA", "uid": "f1702858a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "XML Import", "Text": "TreeLine will import and export generic XML files. These routines do not have much intelligence - each XML element becomes a node and each XML attribute becomes a field. XML text content become fields named \"Element_Data\". This lets TreeLine function as a crude XML editor." }, "format": "HEAD_PARA", "uid": "f1702952a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "ODF Import", "Text": "TreeLine will import Open Document Format (ODF) text documents, from applications such as Apache OpenOffice and LibreOffice. The node structure is formed based on the heading styles assigned in the document. Any text under each heading is assigned to that heading's node. The import filter is intended for simple text outlines only. No formatting is maintained, and objects such as tables and pictures are not imported." }, "format": "HEAD_PARA", "uid": "f1702a42a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Bookmarks Import", "Text": "TreeLine will import bookmark files in both the Mozilla HTML format (Firefox browser) and the XBEL format (Konqueror, Galeon and Elinks browsers). Each bookmark becomes a node with a name and a link field. Some information in the files, such as visited dates and icon references, is not imported. For an example, see the \"sample_bookmarks\" file (by using the \"File > Open Sample\" command).
\n" }, "format": "HEAD_PARA", "uid": "f1702b46a25a11e7b7c67054d2175f18" }, { "children": [ "f1702d4ea25a11e7b7c67054d2175f18", "f1702e52a25a11e7b7c67054d2175f18", "f1702f60a25a11e7b7c67054d2175f18", "65289b36b97611e783eb3417ebd53aeb", "f1703064a25a11e7b7c67054d2175f18", "f170315ea25a11e7b7c67054d2175f18", "f1703262a25a11e7b7c67054d2175f18" ], "data": { "Name": "File Export" }, "format": "HEADINGS", "uid": "f1702c4aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "General Information", "Text": "Files are exported using the \"File > Export\" command. This will show a dialog box of available export types and options." }, "format": "HEAD_PARA", "uid": "f1702d4ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML Export", "Text": "The HTML export subtypes can export to a single page or to multiple pages. The single page export contains all of the indented output. A navigation pane on the left with links to anchors at node positions is optional.
\n
\nThe multiple HTML pages export has one web page per node. It includes a navigation pane on the left with links to the pages with sibling, parent and aunt/uncle nodes.
\n
\nMultiple HTML data tables export creates a table in each HTML file that contains the data for a set of siblings, as well as links to the parent and child pages.
\n
\nThe Live Tree HTML export uses Javascript and CSS to create an interactive view. Nodes in the tree can be expanded and collapsed, and a separate pane shows the output for all descendants of the selected node. The first form of this export creates separate files that are linked to the existing TreeLine file. These files are intended for use on a web server (browser security usually prevents local access). The HTML file stores the relative path from the TreeLine file to the initial export directory, so this relationship needs to be maintained on the web server. Only the TreeLine file needs to be replaced to update the data (re-export is not required).
\n
\nThe second form of Live Tree export creates a single file (with embedded data) that can be accessed from a local web browser. It appears the same as the first form on the browser." }, "format": "HEAD_PARA", "uid": "f1702e52a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Text Export", "Text": "Data can be exported to tabbed title text, comma-delimited (CSV) tables and tab-delimited tables. These formats are the same as the corresponding import formats.
\n
\nThere is also an unformatted text export the dumps all of the output into a text file without preserving the tree structure." }, "format": "HEAD_PARA", "uid": "f1702f60a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "XML Export", "Text": "TreeLine will import and export generic XML files. These routines do not have much intelligence - each node becomes an XML element and each field becomes an XML attribute, except for fields named \"Element_Data\" that become the element's text. This lets TreeLine function as a crude XML editor." }, "format": "HEAD_PARA", "uid": "f1703064a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "ODF Export", "Text": "TreeLine will export an outline to an Open Document Format (ODF) text document, compatible with Apache OpenOffice and LibreOffice. The title of each node is assigned a heading style at the appropriate level. Any other text in the output of each node becomes normal text under the heading. The export filter is intended for simple text outlines only. Any HTML formatting is stripped, and objects such as tables and pictures are not supported." }, "format": "HEAD_PARA", "uid": "f170315ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Bookmarks Export", "Text": "TreeLine will export bookmark files in both the Mozilla HTML format (Firefox browser) and the XBEL format (Konqueror, Galeon and Elinks browsers). TreeLine will look for a link field in each node that becomes the target of the bookmark." }, "format": "HEAD_PARA", "uid": "f1703262a25a11e7b7c67054d2175f18" }, { "children": [ "f1703442a25a11e7b7c67054d2175f18", "f1703546a25a11e7b7c67054d2175f18", "f170364aa25a11e7b7c67054d2175f18", "f1703744a25a11e7b7c67054d2175f18", "9ff09734dc9011ea887bac675dac20af", "f1703848a25a11e7b7c67054d2175f18", "7e9b3b88c24511e896c7d66a6ab671cb" ], "data": { "Name": "Customizations" }, "format": "HEADINGS", "uid": "f170335ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Options", "Text": "TreeLine's behavior can be modified with several settings available in \"Tools > General Options\". Most of these options are covered elsewhere in this document." }, "format": "HEAD_PARA", "uid": "f1703442a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Keyboard Shortcuts", "Text": "Keyboard shortcuts can be customized by using the \"Tools > Set Keyboard Shortcuts\" command. Simply type the new key sequence with the appropriate field selected." }, "format": "HEAD_PARA", "uid": "f1703546a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Toolbars", "Text": "An editor to customize the toolbars is available from \"Tools > Customize Toolbars\". The number of toolbars can be set, and the buttons on each can be defined." }, "format": "HEAD_PARA", "uid": "f170364aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Fonts", "Text": "The default font used in the application can be set using the \"Tools > Customize Fonts\" menu. There are also options to specify fonts used in the tree views, the output view and the editor views." }, "format": "HEAD_PARA", "uid": "f1703744a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Tree Icons", "Text": "There is an icons directory in the user configuration directory (\"~/.treeline-x.x/icons\" on Linux, \"Users\\<user>\\AppData\\roaming\\bellz\\treeline-x.x\\icons\" on Windows). Image files (PNG or BMP) placed into this directory are available for use as tree icons." }, "format": "HEAD_PARA", "uid": "f1703848a25a11e7b7c67054d2175f18" }, { "children": [ "65157f8a9b0c11f091375847ca7850fa", "414f6662813311f0b43b5847ca7850fa", "57d4ac00fe7f11edbb2654b2039ee1f3", "4f1366fa2ca811eda95c54b2039ee1f3", "b5fe698830e111ebbc097054d2175f18", "7ffeb66ddc8711ea9a87ac675dac20af", "194b0533e5d811e9b5fea44cc8e97404", "db25cd62481e11e989f27054d2175f18", "800a0971305111e991cda44cc8e97404", "9c08f39ee80311e8a510a44cc8e97404", "6610203fd2c111e8b033d66a6ab671cb", "67e95a5bbbf611e891f7a44cc8e97404", "e8e10d33a14311e88e24a44cc8e97404", "4bc47248786711e8a8bfa44cc8e97404", "95a6e90a333f11e89efed66a6ab671cb", "6df9a0c5ba3b11e78e7e3417ebd53aeb", "f1703e7ea25a11e7b7c67054d2175f18", "f1704752a25a11e7b7c67054d2175f18", "f170527ea25a11e7b7c67054d2175f18", "f170652aa25a11e7b7c67054d2175f18", "f1706be2a25a11e7b7c67054d2175f18", "f170748ea25a11e7b7c67054d2175f18", "f1708032a25a11e7b7c67054d2175f18", "f1708ae6a25a11e7b7c67054d2175f18", "f170ab34a25a11e7b7c67054d2175f18", "f170c1aaa25a11e7b7c67054d2175f18", "f170e900a25a11e7b7c67054d2175f18", "f170fddca25a11e7b7c67054d2175f18", "f1710e58a25a11e7b7c67054d2175f18", "f1711f24a25a11e7b7c67054d2175f18" ], "data": { "Name": "Revision History" }, "format": "HEADINGS", "uid": "f1703d8ea25a11e7b7c67054d2175f18" }, { "children": [ "f1703f8ca25a11e7b7c67054d2175f18", "f170427aa25a11e7b7c67054d2175f18" ], "data": { "Name": "March 26, 2017 - Release 2.1.2 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1703e7ea25a11e7b7c67054d2175f18" }, { "children": [ "f170407ca25a11e7b7c67054d2175f18", "f1704176a25a11e7b7c67054d2175f18" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "f1703f8ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It may contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) should probably be used for critical work." }, "format": "BULLETS", "uid": "f170407ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations have not yet been updated." }, "format": "BULLETS", "uid": "f1704176a25a11e7b7c67054d2175f18" }, { "children": [ "f1704360a25a11e7b7c67054d2175f18", "f170445aa25a11e7b7c67054d2175f18", "f1704554a25a11e7b7c67054d2175f18", "f170464ea25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170427aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "DateTime output", "Text": "Fix problems formatting DateTime fields in output views." }, "format": "BULLETS", "uid": "f1704360a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Internal links", "Text": "Fix dialog issues with clicking on targets when creating inline internal links." }, "format": "BULLETS", "uid": "f170445aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data view tabbing", "Text": "Fix a regression that prevented using the tab key to cycle between data edit view items." }, "format": "BULLETS", "uid": "f1704554a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Autosave restore", "Text": "Avoid opening two windows when restoring an auto-saved backup file." }, "format": "BULLETS", "uid": "f170464ea25a11e7b7c67054d2175f18" }, { "children": [ "f1704842a25a11e7b7c67054d2175f18", "f1704b30a25a11e7b7c67054d2175f18", "f1704d1aa25a11e7b7c67054d2175f18" ], "data": { "Name": "March 12, 2017 - Release 2.1.1 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1704752a25a11e7b7c67054d2175f18" }, { "children": [ "f1704928a25a11e7b7c67054d2175f18", "f1704a2ca25a11e7b7c67054d2175f18" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "f1704842a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It may contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) should probably be used for critical work." }, "format": "BULLETS", "uid": "f1704928a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations have not yet been updated." }, "format": "BULLETS", "uid": "f1704a2ca25a11e7b7c67054d2175f18" }, { "children": [ "f1704c20a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f1704b30a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Windows binary", "Text": "The Windows binary is now built using Python 3.6 and PyQt 5.8." }, "format": "BULLETS", "uid": "f1704c20a25a11e7b7c67054d2175f18" }, { "children": [ "f1704f54a25a11e7b7c67054d2175f18", "f170506ca25a11e7b7c67054d2175f18", "f1705166a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1704d1aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Set icon crash", "Text": "Fix a crash when changing the icon on the Type Config page of the Configure Data Types dialog box." }, "format": "BULLETS", "uid": "f1704f54a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Type list issues", "Text": "Fix inconsistent type selections on the Type List page of the Configure Data Types dialog box." }, "format": "BULLETS", "uid": "f170506ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Window placement", "Text": "Fix issues with restoring the placement of the TreeLine window in some multiple monitor setups." }, "format": "BULLETS", "uid": "f1705166a25a11e7b7c67054d2175f18" }, { "children": [ "f170536ea25a11e7b7c67054d2175f18", "f170565ca25a11e7b7c67054d2175f18", "f170603ea25a11e7b7c67054d2175f18", "f1706228a25a11e7b7c67054d2175f18" ], "data": { "Name": "February 20, 2017 - Release 2.1.0 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170527ea25a11e7b7c67054d2175f18" }, { "children": [ "f170545ea25a11e7b7c67054d2175f18", "f1705558a25a11e7b7c67054d2175f18" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "f170536ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) should probably be used for critical work." }, "format": "BULLETS", "uid": "f170545ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations have not yet been updated." }, "format": "BULLETS", "uid": "f1705558a25a11e7b7c67054d2175f18" }, { "children": [ "f170574ca25a11e7b7c67054d2175f18", "f1705850a25a11e7b7c67054d2175f18", "f1705954a25a11e7b7c67054d2175f18", "f1705a4ea25a11e7b7c67054d2175f18", "f1705b48a25a11e7b7c67054d2175f18", "f1705c4ca25a11e7b7c67054d2175f18", "f1705d46a25a11e7b7c67054d2175f18", "f1705e40a25a11e7b7c67054d2175f18", "f1705f3aa25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170565ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Port to Qt5", "Text": "TreeLine has been ported from the Qt4 library to the Qt5 library. The system requirements have been updated to Python 3.4 or higher, PyQt 5.4 or higher and Qt 5.4 or higher." }, "format": "BULLETS", "uid": "f170574ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Cloned nodes", "Text": "Cloned nodes that can duplicate sections of the tree have been added. Editing their data or child structure in one location changes all locations. They are created by copying nodes and then using the \"Edit->Paste Cloned Node\" command to paste them elsewhere. The clone link can be removed by deleting the nodes or by cutting them and pasting them back using the regular paste command." }, "format": "BULLETS", "uid": "f1705850a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "DateTime field", "Text": "Added a new DateTime field that combines dates and times into a single field that is useful for timestamps. The editor format is a combination of the date and time formats from the general options, separated by a space." }, "format": "BULLETS", "uid": "f1705954a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML in choice fields", "Text": "Added an option to allow HTML tags in Choice, AutoChoice, Combination, AutoCombination and RegularExpression fields. The control is in the Field Config tab of the Configure Data Types dialog. This option is disabled by default. If enabled, special characters (angled brackets and quotation marks) will need to be escaped to show up in text." }, "format": "BULLETS", "uid": "f1705a4ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved conditional rules", "Text": "Saved rules for Conditional Find and Conditional Filter commands are listed directly in the dialog boxes, making them easier to load and save." }, "format": "BULLETS", "uid": "f1705b48a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "CSV import/export", "Text": "Added comma-delimited (CSV) table import and export, similar to existing tab-delimited table import and export. The export only handles data from a single level of child nodes." }, "format": "BULLETS", "uid": "f1705c4ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Incremental title search", "Text": "Added a quick, incremental search of node titles. By default, it's bound to ctrl+/. Then, matching titles are found as the search string is typed. The F3 and shift+F3 keys can be used to go to the next or previous matches, respectively." }, "format": "BULLETS", "uid": "f1705d46a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Multiple field selection", "Text": "Multiple fields can now be selected in the Output page of the Configuration dialog, so several fields can be added to the formats simultaneously." }, "format": "BULLETS", "uid": "f1705e40a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Print settings", "Text": "A pull-down selector for printers has been added to the Print Setup dialog. This enables TreeLine to verify that the page size and margin settings are supported by the current printer." }, "format": "BULLETS", "uid": "f1705f3aa25a11e7b7c67054d2175f18" }, { "children": [ "f170612ea25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f170603ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "SpacedText Field special characters", "Text": "The SpacedText Field now allows special HTML characters (angled brackets and quotation marks) without requiring them to be manually escaped." }, "format": "BULLETS", "uid": "f170612ea25a11e7b7c67054d2175f18" }, { "children": [ "f170630ea25a11e7b7c67054d2175f18", "f1706426a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1706228a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Printed page splits", "Text": "The code that splits content into pages when printing has been improved. It now handles very long nodes better." }, "format": "BULLETS", "uid": "f170630ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Formatted field title edits", "Text": "When formatted fields (dates, times, etc.) are used in node titles, editing the titles in the tree or in the Title List pane will now work if the edit and output formats are similar." }, "format": "BULLETS", "uid": "f1706426a25a11e7b7c67054d2175f18" }, { "children": [ "f1706610a25a11e7b7c67054d2175f18", "f1706804a25a11e7b7c67054d2175f18" ], "data": { "Name": "October 3, 2015 - Release 2.0.2 (new stable release)" }, "format": "HEADINGS", "uid": "f170652aa25a11e7b7c67054d2175f18" }, { "children": [ "f1706700a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1706610a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data edit regression", "Text": "Fixed a major regression in 2.0.1 that broke data editors for most specialized field types (number, math, boolean, choice, etc.)" }, "format": "BULLETS", "uid": "f1706700a25a11e7b7c67054d2175f18" }, { "children": [ "f17068f4a25a11e7b7c67054d2175f18", "f17069e4a25a11e7b7c67054d2175f18", "f1706ae8a25a11e7b7c67054d2175f18" ], "data": { "Name": "Compatibility Notes" }, "format": "BULLET_HEADING", "uid": "f1706804a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File format", "Text": "There are some file format changes between TreeLine 1.4.x and this version of TreeLine." }, "format": "BULLETS", "uid": "f17068f4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File conversion", "Text": "Older files opened in this version are automatically converted when saved." }, "format": "BULLETS", "uid": "f17069e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File compatibility", "Text": "Files saved in this version may not be fully compatible with TreeLine 1.4.x." }, "format": "BULLETS", "uid": "f1706ae8a25a11e7b7c67054d2175f18" }, { "children": [ "f1706cd2a25a11e7b7c67054d2175f18", "f1706fb6a25a11e7b7c67054d2175f18" ], "data": { "Name": "September 26, 2015 - Release 2.0.1 (new stable release)" }, "format": "HEADINGS", "uid": "f1706be2a25a11e7b7c67054d2175f18" }, { "children": [ "f1706db8a25a11e7b7c67054d2175f18", "f1706ebca25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f1706cd2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Plugin options", "Text": "Added methods to the plugin interface that allow general program options to be queried and changed." }, "format": "BULLETS", "uid": "f1706db8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Table import errors", "Text": "Improve text table import error messages by including the line number where the problem is found." }, "format": "BULLETS", "uid": "f1706ebca25a11e7b7c67054d2175f18" }, { "children": [ "f170709ca25a11e7b7c67054d2175f18", "f1707196a25a11e7b7c67054d2175f18", "f1707290a25a11e7b7c67054d2175f18", "f1707380a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1706fb6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data edit undo", "Text": "Reduce the amount of work that a single undo command removes from editors in the data edit view." }, "format": "BULLETS", "uid": "f170709ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Configuration changes", "Text": "Fixed a bug that prevented setting the unique ID reference field on a newly created data type." }, "format": "BULLETS", "uid": "f1707196a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Legacy newline convert", "Text": "Preserve hard newlines in text fields when converting TreeLine 1.4.x files to this version." }, "format": "BULLETS", "uid": "f1707290a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Indent expand status", "Text": "Fix problems preserving expand/collapse node states when indenting and unindenting nodes." }, "format": "BULLETS", "uid": "f1707380a25a11e7b7c67054d2175f18" }, { "children": [ "f1707592a25a11e7b7c67054d2175f18", "f1707c5ea25a11e7b7c67054d2175f18" ], "data": { "Name": "May 17, 2015 - Release 2.0.0 (new stable release)" }, "format": "HEADINGS", "uid": "f170748ea25a11e7b7c67054d2175f18" }, { "children": [ "f1707682a25a11e7b7c67054d2175f18", "f170777ca25a11e7b7c67054d2175f18", "f1707876a25a11e7b7c67054d2175f18", "f1707966a25a11e7b7c67054d2175f18", "f1707a60a25a11e7b7c67054d2175f18", "f1707b5aa25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f1707592a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Treepad import update", "Text": "Modified the Treepad file import to use SpacedText fields to more closely match Treepad formatting." }, "format": "BULLETS", "uid": "f1707682a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Treepad export", "Text": "An optional plugin was written that can export files to the Treepad text file format." }, "format": "BULLETS", "uid": "f170777ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "New icon", "Text": "The TreeLine icon was replaced with a new one. Thanks to David Reimer for contributing the artwork." }, "format": "BULLETS", "uid": "f1707876a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Translation updates", "Text": "The German and Portuguese GUI translations were updated." }, "format": "BULLETS", "uid": "f1707966a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sample file updates", "Text": "Updated the long text sample file to include the SpacedText field type, and added a conditional equation to the math sample file." }, "format": "BULLETS", "uid": "f1707a60a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Documentation update", "Text": "Updated the Math Field section of the documentation." }, "format": "BULLETS", "uid": "f1707b5aa25a11e7b7c67054d2175f18" }, { "children": [ "f1707d44a25a11e7b7c67054d2175f18", "f1707e3ea25a11e7b7c67054d2175f18", "f1707f38a25a11e7b7c67054d2175f18" ], "data": { "Name": "Compatibility Notes" }, "format": "BULLET_HEADING", "uid": "f1707c5ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File format", "Text": "There are some file format changes between TreeLine 1.4.x and this version of TreeLine." }, "format": "BULLETS", "uid": "f1707d44a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File conversion", "Text": "Older files opened in this version are automatically converted when saved." }, "format": "BULLETS", "uid": "f1707e3ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File compatibility", "Text": "Files saved in this version may not be fully compatible with TreeLine 1.4.x." }, "format": "BULLETS", "uid": "f1707f38a25a11e7b7c67054d2175f18" }, { "children": [ "f1708118a25a11e7b7c67054d2175f18", "f17083fca25a11e7b7c67054d2175f18", "f1708802a25a11e7b7c67054d2175f18" ], "data": { "Name": "March 29, 2015 - Release 1.9.7 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1708032a25a11e7b7c67054d2175f18" }, { "children": [ "f1708208a25a11e7b7c67054d2175f18", "f1708302a25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f1708118a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field conditions", "Text": "Added comparison operators and conditional if statements to math field equations. The operators can be used with a new boolean result type, or as a part of numeric, date, time or text expressions." }, "format": "BULLETS", "uid": "f1708208a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field text operations", "Text": "Text operators were made available in math field equations, and the result type can be set to text. This allows math fields to combine text from other fields, replace sub-strings and change capitalization." }, "format": "BULLETS", "uid": "f1708302a25a11e7b7c67054d2175f18" }, { "children": [ "f17084eca25a11e7b7c67054d2175f18", "f17085f0a25a11e7b7c67054d2175f18", "f17086fea25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f17083fca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved status bar message", "Text": "Added a \"file saved\" status bar message." }, "format": "BULLETS", "uid": "f17084eca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "German translation", "Text": "Added a German GUI translation." }, "format": "BULLETS", "uid": "f17085f0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Portuguese translation", "Text": "Updated the Portuguese GUI translation." }, "format": "BULLETS", "uid": "f17086fea25a11e7b7c67054d2175f18" }, { "children": [ "f17088e8a25a11e7b7c67054d2175f18", "f17089e2a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1708802a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Combination editor", "Text": "Fixed a focus problem that made Combination and AutoCombination field editor pull-downs unusable." }, "format": "BULLETS", "uid": "f17088e8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Choice editor", "Text": "Fixed a focus problem that made the pull-downs in choice and boolean field editors unusable on Linux." }, "format": "BULLETS", "uid": "f17089e2a25a11e7b7c67054d2175f18" }, { "children": [ "f1708bcca25a11e7b7c67054d2175f18", "f17097aca25a11e7b7c67054d2175f18", "f170a2eca25a11e7b7c67054d2175f18" ], "data": { "Name": "March 10, 2015 - Release 1.9.6 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1708ae6a25a11e7b7c67054d2175f18" }, { "children": [ "f1708cbca25a11e7b7c67054d2175f18", "f1708db6a25a11e7b7c67054d2175f18", "f1708ea6a25a11e7b7c67054d2175f18", "f1708faaa25a11e7b7c67054d2175f18", "f17090aea25a11e7b7c67054d2175f18", "f17091e4a25a11e7b7c67054d2175f18", "f17092dea25a11e7b7c67054d2175f18", "f1709644a25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f1708bcca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "OneLineText field", "Text": "Added a new OneLineText field type that restricts the text length to a single line." }, "format": "BULLETS", "uid": "f1708cbca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "All Types conditional test", "Text": "Added an All Types option to the conditional find and filter commands. This allows multiple node types to be found or filtered at the same time. The fields from every type are available for use in conditions. The conditions give a false result for all node types that do not contain that field name." }, "format": "BULLETS", "uid": "f1708db6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field dates and times", "Text": "Added support for date and time calculations using math fields. Math equation result types can be set to numeric, date or time output. Date fields can be subtracted to give the number of days elapsed, and numbers of days can be added to or subtracted from dates, resulting in new dates. Time fields can be subtracted to give the number of seconds elapsed, and numbers of seconds can be added to or subtracted from times, resulting in new times." }, "format": "BULLETS", "uid": "f1708ea6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field root references", "Text": "In math fields, added an equation reference level to reference fields in the root node. This provides a place for \"constant\" field values that can be referenced from any node but only need to be changed in one location." }, "format": "BULLETS", "uid": "f1708faaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Plugin interface", "Text": "Support was added for plugin extension modules. Most of the interface methods from TreeLine 1.4.x were duplicated to ease porting of old plugins. Of course, old plugins must be ported from Python 2.x to Python 3.x, and there are multi-window implementation differences. New interfaces allow the creation of new field types and the execution of any menu command. Sample plugins are available on the TreeLine download page." }, "format": "BULLETS", "uid": "f17090aea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Automatic HTML tags", "Text": "Added text formatting and link commands for HTML fields that add tags to the HTML content." }, "format": "BULLETS", "uid": "f17091e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Open in folder", "Text": "An open in folder command was added to external link field editors to open the directory in a file manager." }, "format": "BULLETS", "uid": "f17092dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Select All command", "Text": "Added the Select All command to global menus with a different default shortcut key (ctrl-L) to avoid conflicts with the add child shortcut." }, "format": "BULLETS", "uid": "f1709644a25a11e7b7c67054d2175f18" }, { "children": [ "f170989ca25a11e7b7c67054d2175f18", "f170998ca25a11e7b7c67054d2175f18", "f1709a7ca25a11e7b7c67054d2175f18", "f1709b8aa25a11e7b7c67054d2175f18", "f1709c7aa25a11e7b7c67054d2175f18", "f1709d6aa25a11e7b7c67054d2175f18", "f1709e50a25a11e7b7c67054d2175f18", "f1709f40a25a11e7b7c67054d2175f18", "f170a026a25a11e7b7c67054d2175f18", "f170a116a25a11e7b7c67054d2175f18", "f170a206a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f17097aca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data edit view focus", "Text": "Improved the focus handling for data edit view edit boxes. This eliminates the blue outline for boxes in inactive data edit views. It also makes tab-to-focus more predictable, including fully selecting single-line field types when they receive tab focus." }, "format": "BULLETS", "uid": "f170989ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data editor resize", "Text": "Data edit boxes are now automatically resized when editing is complete and the focus moves to another row." }, "format": "BULLETS", "uid": "f170998ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Drag external links", "Text": "Allow files to be drag & dropped on data edit boxes to create external links." }, "format": "BULLETS", "uid": "f1709a7ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Stay-on-top dialogs", "Text": "Small, non-modal dialogs, such as those for sorting, numbering, finding and filtering, have been set to stay on top, so they won't be obscured by TreeLine windows." }, "format": "BULLETS", "uid": "f1709b8aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Opening external links", "Text": "Made opening associated programs from external file links more consistent, especially in Linux." }, "format": "BULLETS", "uid": "f1709c7aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Copy types from file", "Text": "The copy types from file command now supports encrypted and compressed files." }, "format": "BULLETS", "uid": "f1709d6aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Wait cursors", "Text": "Added wait cursors to TreeLine operations that could be time consuming." }, "format": "BULLETS", "uid": "f1709e50a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Context menus", "Text": "Improved the consistency of context menus and shortcut commands used in edit boxes." }, "format": "BULLETS", "uid": "f1709f40a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Portuguese translation", "Text": "Added a nearly complete Portuguese GUI translation." }, "format": "BULLETS", "uid": "f170a026a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sample file languages", "Text": "Added support for sample TreeLine files to be provided in alternate languages." }, "format": "BULLETS", "uid": "f170a116a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Documentation translation", "Text": "Prepared the help file for translation into other languages," }, "format": "BULLETS", "uid": "f170a206a25a11e7b7c67054d2175f18" }, { "children": [ "f170a3d2a25a11e7b7c67054d2175f18", "f170a4b8a25a11e7b7c67054d2175f18", "f170a5a8a25a11e7b7c67054d2175f18", "f170a698a25a11e7b7c67054d2175f18", "f170a77ea25a11e7b7c67054d2175f18", "f170a86ea25a11e7b7c67054d2175f18", "f170a95ea25a11e7b7c67054d2175f18", "f170aa44a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170a2eca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Duplicate unique IDs", "Text": "Corrupted TreeLine files with the same unique ID assigned to multiple nodes no longer fail to open. The user is warned that unique IDs have been updated, which could break some internal links." }, "format": "BULLETS", "uid": "f170a3d2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional field list", "Text": "Fixed missing fields in the pull-down list in the conditional find and filter dialog boxes when a rule was re-used after a node type change. " }, "format": "BULLETS", "uid": "f170a4b8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field missing references", "Text": "Fixed problems with math fields that reference non-existing fields in parent or child nodes." }, "format": "BULLETS", "uid": "f170a5a8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field type updates", "Text": "Made math fields update properly after node type changes." }, "format": "BULLETS", "uid": "f170a698a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Rename bullet/table fields", "Text": "Fixed inconsistent updates after renaming fields used with bulleted or tabled output." }, "format": "BULLETS", "uid": "f170a77ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Copying descendants", "Text": "Made node copy-paste and drag-and-drop work when the initial selection includes both parent and child nodes. " }, "format": "BULLETS", "uid": "f170a86ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Tabbed text import", "Text": "When importing a tabbed text file with multiple top-level nodes, create a single higher-level node to prevent failure." }, "format": "BULLETS", "uid": "f170a95ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Custom toolbar dialog", "Text": "Fixed the availability of the move up button in the customize toolbar dialog when the second command in the list is selected." }, "format": "BULLETS", "uid": "f170aa44a25a11e7b7c67054d2175f18" }, { "children": [ "f170ac38a25a11e7b7c67054d2175f18", "f170afeea25a11e7b7c67054d2175f18", "f170b836a25a11e7b7c67054d2175f18" ], "data": { "Name": "December 31, 2014 - Release 1.9.5 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170ab34a25a11e7b7c67054d2175f18" }, { "children": [ "f170ad1ea25a11e7b7c67054d2175f18", "f170ae0ea25a11e7b7c67054d2175f18", "f170aefea25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170ac38a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field type", "Text": "Added a math field type that is configured by defining an equation. The field value is automatically calculated based on references to numerical values in other nodes. See the \"sample_math_fields\" file for a usage example." }, "format": "BULLETS", "uid": "f170ad1ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Clear formatting", "Text": "Added a Clear Formatting command that removes font changes and links from data editor text." }, "format": "BULLETS", "uid": "f170ae0ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "GUI Translations", "Text": "Made source code changes necessary to support user interface translations into other languages. The actual translation work remains to be done." }, "format": "BULLETS", "uid": "f170aefea25a11e7b7c67054d2175f18" }, { "children": [ "f170b0caa25a11e7b7c67054d2175f18", "f170b1baa25a11e7b7c67054d2175f18", "f170b2aaa25a11e7b7c67054d2175f18", "f170b390a25a11e7b7c67054d2175f18", "f170b480a25a11e7b7c67054d2175f18", "f170b570a25a11e7b7c67054d2175f18", "f170b656a25a11e7b7c67054d2175f18", "f170b746a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f170afeea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Combination field scroll bars", "Text": "Add scroll bars to the pull-down editors for combination fields with many entries." }, "format": "BULLETS", "uid": "f170b0caa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "External link truncation", "Text": "Reduce the truncation of external link URLs when generating default display names." }, "format": "BULLETS", "uid": "f170b1baa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File newlines", "Text": "Use Unix-style newlines for saved TreeLine files to keep files consistent across platforms." }, "format": "BULLETS", "uid": "f170b2aaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML panes", "Text": "Update the CSS code in exported HTML with navigation panes to improve the appearance in some browsers." }, "format": "BULLETS", "uid": "f170b390a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Undo optimization", "Text": "Optimize some undo information to reduce the amount of data in memory." }, "format": "BULLETS", "uid": "f170b480a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Move sample files", "Text": "Move sample files into a separate directory to avoid future translation conflicts." }, "format": "BULLETS", "uid": "f170b570a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Installer clarification", "Text": "Clarify a Linux installer error message when checking for the Python 3 version of PyQt." }, "format": "BULLETS", "uid": "f170b656a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Include MSVC files", "Text": "Include MSVCR DLL files in the Windows installer." }, "format": "BULLETS", "uid": "f170b746a25a11e7b7c67054d2175f18" }, { "children": [ "f170b91ca25a11e7b7c67054d2175f18", "f170ba0ca25a11e7b7c67054d2175f18", "f170baf2a25a11e7b7c67054d2175f18", "f170bbeca25a11e7b7c67054d2175f18", "f170bcf0a25a11e7b7c67054d2175f18", "f170bde0a25a11e7b7c67054d2175f18", "f170bed0a25a11e7b7c67054d2175f18", "f170bfc0a25a11e7b7c67054d2175f18", "f170c0a6a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170b836a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Applying config dialog settings", "Text": "Fix problems applying multiple configuration changes while the Configure Data Types dialog box remains open." }, "format": "BULLETS", "uid": "f170b91ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Title list line split", "Text": "In the Title List editor, splitting a title into two lines now creates a new node without losing the children and parameters of the original node." }, "format": "BULLETS", "uid": "f170ba0ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Title list undo", "Text": "Fix the undo command in the Title List View so that deleted lines/nodes are properly restored. " }, "format": "BULLETS", "uid": "f170baf2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sorting by fields", "Text": "When sorting nodes by fields, properly handle a reverse direction." }, "format": "BULLETS", "uid": "f170bbeca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Find and replace", "Text": "Fix problems with the find and replace command when a particular node type is specified." }, "format": "BULLETS", "uid": "f170bcf0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional types", "Text": "Fix problems defining conditional types from the Configure Data Types dialog box." }, "format": "BULLETS", "uid": "f170bde0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Apply font sizes", "Text": "Correctly apply font size formatting to selections with mixed font sizes." }, "format": "BULLETS", "uid": "f170bed0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Editor height", "Text": "Fix the height of long text field editors with customized data editor fonts." }, "format": "BULLETS", "uid": "f170bfc0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Base 64 image export", "Text": "Fix HTML export of Base 64 images." }, "format": "BULLETS", "uid": "f170c0a6a25a11e7b7c67054d2175f18" }, { "children": [ "f170c286a25a11e7b7c67054d2175f18", "f170e068a25a11e7b7c67054d2175f18", "f170e46ea25a11e7b7c67054d2175f18" ], "data": { "Name": "March 8, 2014 - Release 1.9.4 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170c1aaa25a11e7b7c67054d2175f18" }, { "children": [ "f170d8d4a25a11e7b7c67054d2175f18", "f170d9d8a25a11e7b7c67054d2175f18", "f170dac8a25a11e7b7c67054d2175f18", "f170dbb8a25a11e7b7c67054d2175f18", "f170dca8a25a11e7b7c67054d2175f18", "f170dd98a25a11e7b7c67054d2175f18", "f170de88a25a11e7b7c67054d2175f18", "f170df6ea25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170c286a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Documentation", "Text": "Created new documentation, including a TreeLine file with details and a text file with basic usage instructions. Both are accessible from the help menu." }, "format": "BULLETS", "uid": "f170d8d4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Font settings", "Text": "Added customizing of default fonts used in the tree, output and editor views." }, "format": "BULLETS", "uid": "f170d9d8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spaced text field", "Text": "Added a new SpacedText field type that holds plain text and preserves all spacing." }, "format": "BULLETS", "uid": "f170dac8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Combination editor", "Text": "Combination and auto combination field types now use a simpler checkbox style pull-down editor." }, "format": "BULLETS", "uid": "f170dbb8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Autosave option", "Text": "An autosave option was added." }, "format": "BULLETS", "uid": "f170dca8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unique ID output", "Text": "A unique ID reference field was added to the file info fields to allow node unique IDs to be included in output formats." }, "format": "BULLETS", "uid": "f170dd98a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Paste plain text", "Text": "A plain text paste command was added to paste non-formatted text to data editors." }, "format": "BULLETS", "uid": "f170de88a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Indent option", "Text": "Added an option to set the child indent offset amount." }, "format": "BULLETS", "uid": "f170df6ea25a11e7b7c67054d2175f18" }, { "children": [ "f170e162a25a11e7b7c67054d2175f18", "f170e252a25a11e7b7c67054d2175f18", "f170e36aa25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f170e068a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Print preview size", "Text": "The last size and position of the print preview window are remembered and restored." }, "format": "BULLETS", "uid": "f170e162a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Page breaks in nodes", "Text": "When printing, nodes with long text content are split between pages." }, "format": "BULLETS", "uid": "f170e252a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Export relative links", "Text": "In multiple page HTML exports, relative links in the content are adjusted based on the directory depth." }, "format": "BULLETS", "uid": "f170e36aa25a11e7b7c67054d2175f18" }, { "children": [ "f170e54aa25a11e7b7c67054d2175f18", "f170e63aa25a11e7b7c67054d2175f18", "f170e720a25a11e7b7c67054d2175f18", "f170e810a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170e46ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Blank nodes", "Text": "Fixed problems outputting completely blank nodes." }, "format": "BULLETS", "uid": "f170e54aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional rules", "Text": "Problems with the contains and true/false conditional rules were fixed." }, "format": "BULLETS", "uid": "f170e63aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Link dialogs", "Text": "Fixed issues displaying several editor link dialogs in quick succession." }, "format": "BULLETS", "uid": "f170e720a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Output config cursor", "Text": "In the configure data types dialog, the output format cursor no longer moves when switching to other field references." }, "format": "BULLETS", "uid": "f170e810a25a11e7b7c67054d2175f18" }, { "children": [ "f170e9dca25a11e7b7c67054d2175f18", "f170f12aa25a11e7b7c67054d2175f18", "f170f846a25a11e7b7c67054d2175f18" ], "data": { "Name": "January 19, 2014 - Release 1.9.3 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170e900a25a11e7b7c67054d2175f18" }, { "children": [ "f170eac2a25a11e7b7c67054d2175f18", "f170eba8a25a11e7b7c67054d2175f18", "f170ec8ea25a11e7b7c67054d2175f18", "f170ed74a25a11e7b7c67054d2175f18", "f170ee5aa25a11e7b7c67054d2175f18", "f170ef4aa25a11e7b7c67054d2175f18", "f170f030a25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170e9dca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Keyboard shortcuts", "Text": "Added controls in the Tools menu for customizing TreeLine's keyboard shortcuts." }, "format": "BULLETS", "uid": "f170eac2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Toolbars", "Text": "Controls for customizing TreeLine's toolbar buttons were added to the Tools menu." }, "format": "BULLETS", "uid": "f170eba8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional search", "Text": "New dialogs were created for conditional finding and filtering of nodes. Specific conditions can be applied to individual types and fields, and the conditions can be saved." }, "format": "BULLETS", "uid": "f170ec8ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Find and replace", "Text": "Find and replace functionality was added to search and change nodes' text data. The search can be limited to specific types and fields." }, "format": "BULLETS", "uid": "f170ed74a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Table output", "Text": "A new option for output data in tables was added to the Type Config pane of the Configure Data Types dialog. Each line of the output format becomes a column. Any text at the start of the format line that is followed by a colon becomes a table heading." }, "format": "BULLETS", "uid": "f170ee5aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Bullet output", "Text": "An option to add bullets to the output of child nodes was added to the Type Config pane of the Configure Data Types dialog." }, "format": "BULLETS", "uid": "f170ef4aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Toggle selections", "Text": "Added View > Previous Selection and Next Selection commands to step through the node selection history." }, "format": "BULLETS", "uid": "f170f030a25a11e7b7c67054d2175f18" }, { "children": [ "f170f210a25a11e7b7c67054d2175f18", "f170f2f6a25a11e7b7c67054d2175f18", "f170f418a25a11e7b7c67054d2175f18", "f170f4fea25a11e7b7c67054d2175f18", "f170f5e4a25a11e7b7c67054d2175f18", "f170f6d4a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f170f12aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Drop to reorder", "Text": "Nodes can now be reordered by dragging and dropping them between sibling nodes." }, "format": "BULLETS", "uid": "f170f210a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Date entry formats", "Text": "The keyboard entry of dates and times into fields was made more flexible by allowing entries such as 4-digit years that don't exactly match the entry format." }, "format": "BULLETS", "uid": "f170f2f6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Default link names", "Text": "Any text selection is now used as the default name for links inserted into text fields." }, "format": "BULLETS", "uid": "f170f418a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Anchor links", "Text": "Links to local named anchors in a node's HTML text content now work if they don't conflict with any node unique IDs." }, "format": "BULLETS", "uid": "f170f4fea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Line spacing", "Text": "Line spacing in output views was made more consistent." }, "format": "BULLETS", "uid": "f170f5e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved states", "Text": "Improved the efficiency of restoring node open/close states when opening files." }, "format": "BULLETS", "uid": "f170f6d4a25a11e7b7c67054d2175f18" }, { "children": [ "f170f936a25a11e7b7c67054d2175f18", "f170fa1ca25a11e7b7c67054d2175f18", "f170fb0ca25a11e7b7c67054d2175f18", "f170fbf2a25a11e7b7c67054d2175f18", "f170fce2a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170f846a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Paste font sizes", "Text": "Errors when pasting text with varying font sizes into data editors were fixed." }, "format": "BULLETS", "uid": "f170f936a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional data types", "Text": "Various issues with conditional data types were fixed, including problems with pasting conditional nodes and prompt updating when the types change." }, "format": "BULLETS", "uid": "f170fa1ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Drag undo", "Text": "Problems with undoing the dragging and dropping of a node were fixed." }, "format": "BULLETS", "uid": "f170fb0ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Expand branches", "Text": "Fix the extremely slow operation of the View > Expand Full Branch and Collapse Full Branch commands." }, "format": "BULLETS", "uid": "f170fbf2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Printed lines", "Text": "Fix improperly placed branch lines in printed output." }, "format": "BULLETS", "uid": "f170fce2a25a11e7b7c67054d2175f18" }, { "children": [ "f170fec2a25a11e7b7c67054d2175f18", "f171053ea25a11e7b7c67054d2175f18", "f17108e0a25a11e7b7c67054d2175f18" ], "data": { "Name": "October 22, 2013 - Release 1.9.2 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170fddca25a11e7b7c67054d2175f18" }, { "children": [ "f170ffa8a25a11e7b7c67054d2175f18", "f171008ea25a11e7b7c67054d2175f18", "f171017ea25a11e7b7c67054d2175f18", "f1710264a25a11e7b7c67054d2175f18", "f171034aa25a11e7b7c67054d2175f18", "f1710430a25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170fec2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spell check", "Text": "Added a spell check tool. This requires either aspell, ispell or hunspell to be installed." }, "format": "BULLETS", "uid": "f170ffa8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Numbering field type", "Text": "Included a node numbering field type with several formatting options. An update numbering command fills in the sequence." }, "format": "BULLETS", "uid": "f171008ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Add category level", "Text": "Added a command to add a category level based on a subset of data fields." }, "format": "BULLETS", "uid": "f171017ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Flatten by category", "Text": "Added a flatten by category command to combine parent fields into child nodes." }, "format": "BULLETS", "uid": "f1710264a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Flatten by link", "Text": "A new flatten by link command flattens the structure and provides internal links to the former parent nodes." }, "format": "BULLETS", "uid": "f171034aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Arrange by link", "Text": "An arrange by link command restores the structure based on parent internal links." }, "format": "BULLETS", "uid": "f1710430a25a11e7b7c67054d2175f18" }, { "children": [ "f171061aa25a11e7b7c67054d2175f18", "f171070aa25a11e7b7c67054d2175f18", "f17107f0a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f171053ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "URL drag-and-drop", "Text": "Allow file URL drag-and-drop on active external link data edit widgets." }, "format": "BULLETS", "uid": "f171061aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Share directory", "Text": "Change the Linux installer to use the 'share' directory in place of 'lib' for python files." }, "format": "BULLETS", "uid": "f171070aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Windows binary", "Text": "Update the Windows binary to use version 3.3 of Python." }, "format": "BULLETS", "uid": "f17107f0a25a11e7b7c67054d2175f18" }, { "children": [ "f17109bca25a11e7b7c67054d2175f18", "f1710aa2a25a11e7b7c67054d2175f18", "f1710b88a25a11e7b7c67054d2175f18", "f1710c78a25a11e7b7c67054d2175f18", "f1710d68a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f17108e0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Output line sequence", "Text": "Fix out of sequence output lines when output formats are longer than ten lines." }, "format": "BULLETS", "uid": "f17109bca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Node indenting", "Text": "Fix problems with unique IDs and internal links when indenting and unindenting nodes." }, "format": "BULLETS", "uid": "f1710aa2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Widget focus problems", "Text": "Avoid widget focus problems when editing data on conditional types." }, "format": "BULLETS", "uid": "f1710b88a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Format cursor position", "Text": "Maintain the output format cursor position when changing fields in the configure dialog." }, "format": "BULLETS", "uid": "f1710c78a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "XML import", "Text": "Fix importing of generic XML documents that have nodes with no data." }, "format": "BULLETS", "uid": "f1710d68a25a11e7b7c67054d2175f18" }, { "children": [ "f1710f48a25a11e7b7c67054d2175f18", "f17118a8a25a11e7b7c67054d2175f18" ], "data": { "Name": "May 2, 2013 - Release 1.9.1 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1710e58a25a11e7b7c67054d2175f18" }, { "children": [ "f171102ea25a11e7b7c67054d2175f18", "f171111ea25a11e7b7c67054d2175f18", "f171120ea25a11e7b7c67054d2175f18", "f17112fea25a11e7b7c67054d2175f18", "f17113eea25a11e7b7c67054d2175f18", "f17114dea25a11e7b7c67054d2175f18", "f17115d8a25a11e7b7c67054d2175f18", "f17116c8a25a11e7b7c67054d2175f18", "f17117b8a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f1710f48a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Compression and encryption", "Text": "Added TreeLine file compression and file encryption, controlled from a File > Properties dialog box." }, "format": "BULLETS", "uid": "f171102ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Restore tree states", "Text": "Tree node open/close states are restored for recent files." }, "format": "BULLETS", "uid": "f171111ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Derived data types", "Text": "Added derived data types that keep the field list of their generic type." }, "format": "BULLETS", "uid": "f171120ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional type setting", "Text": "Added conditional type setting that changes icons or output format based on field contents." }, "format": "BULLETS", "uid": "f17112fea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Other field references", "Text": "Other field references (file info, ancestors, children) can be used in node output formats and in print headers & footers." }, "format": "BULLETS", "uid": "f17113eea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML file export", "Text": "Added an HTML file export to a single file with a navigation pane on the side." }, "format": "BULLETS", "uid": "f17114dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Embedded blank lines", "Text": "Allow embedded blank lines in non-HTML node output formats." }, "format": "BULLETS", "uid": "f17115d8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Separator config option", "Text": "Added an output separator config option for combination fields and child references." }, "format": "BULLETS", "uid": "f17116c8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "First day of week option", "Text": "Add an option to set the first day of the week for calendar widgets." }, "format": "BULLETS", "uid": "f17117b8a25a11e7b7c67054d2175f18" }, { "children": [ "f1711998a25a11e7b7c67054d2175f18", "f1711a88a25a11e7b7c67054d2175f18", "f1711b6ea25a11e7b7c67054d2175f18", "f1711c54a25a11e7b7c67054d2175f18", "f1711d44a25a11e7b7c67054d2175f18", "f1711e2aa25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f17118a8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Drag multiple nodes", "Text": "Fixed problems with pasting or dragging multiple nodes." }, "format": "BULLETS", "uid": "f1711998a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Remove fields from multi-line output formats", "Text": "Made removing fields from multi-line output formats work properly." }, "format": "BULLETS", "uid": "f1711a88a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Prevent duplicate unique IDs", "Text": "Prevent duplicate unique IDs from being created after undoing the deletion of a branch." }, "format": "BULLETS", "uid": "f1711b6ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Fixed non-text nodes sorting", "Text": "Fixed node sorting of non-text nodes (numbers, dates, times, etc.)" }, "format": "BULLETS", "uid": "f1711c54a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Calendar widgets", "Text": "Avoid placing calendar widgets partially off screen if near the bottom." }, "format": "BULLETS", "uid": "f1711d44a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Automatic cell height", "Text": "Limit the automatic height increases for text edit cells to avoid confusing double scroll bars." }, "format": "BULLETS", "uid": "f1711e2aa25a11e7b7c67054d2175f18" }, { "children": [ "f171200aa25a11e7b7c67054d2175f18" ], "data": { "Name": "February 6, 2013 - Release 1.9.0 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1711f24a25a11e7b7c67054d2175f18" }, { "children": [ "f17120e6a25a11e7b7c67054d2175f18", "f17121d6a25a11e7b7c67054d2175f18", "f17122c6a25a11e7b7c67054d2175f18", "f17123aca25a11e7b7c67054d2175f18", "f171249ca25a11e7b7c67054d2175f18", "f171258ca25a11e7b7c67054d2175f18", "f1712690a25a11e7b7c67054d2175f18", "f1712776a25a11e7b7c67054d2175f18", "f1712866a25a11e7b7c67054d2175f18", "f1712960a25a11e7b7c67054d2175f18", "f1712a46a25a11e7b7c67054d2175f18", "f1712b36a25a11e7b7c67054d2175f18", "f1712c1ca25a11e7b7c67054d2175f18", "f1712d02a25a11e7b7c67054d2175f18", "f1712df2a25a11e7b7c67054d2175f18", "f1712ed8a25a11e7b7c67054d2175f18", "f1712fbea25a11e7b7c67054d2175f18", "f1713194a25a11e7b7c67054d2175f18", "f1713284a25a11e7b7c67054d2175f18", "f171336aa25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f171200aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Full Python 3 rewrite", "Text": "TreeLine has been fully rewritten using Python 3." }, "format": "BULLETS", "uid": "f17120e6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Direct model-view and ElementTree", "Text": "Improved performance due to direct use of model-view classes for views and ElementTree for input/output." }, "format": "BULLETS", "uid": "f17121d6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Table based data editor pane", "Text": "A table based data editor pane (much faster)." }, "format": "BULLETS", "uid": "f17122c6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "WYSIWYG data editor view.", "Text": "WYSIWYG formatting in the data editor view." }, "format": "BULLETS", "uid": "f17123aca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Real-time window updates ", "Text": "Real-time updates of the same file shown in multiple windows." }, "format": "BULLETS", "uid": "f171249ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Improved printing", "Text": "Improved printing and print preview performance." }, "format": "BULLETS", "uid": "f171258ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saves print options", "Text": "Saves print options with the TreeLine file." }, "format": "BULLETS", "uid": "f1712690a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Built-in PDF", "Text": "Built-in print to PDF function." }, "format": "BULLETS", "uid": "f1712776a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Searching options.", "Text": "More searching options." }, "format": "BULLETS", "uid": "f1712866a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Filtering command", "Text": "A filtering command shows matches in a simple list." }, "format": "BULLETS", "uid": "f1712960a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved sorting parameters", "Text": "Sorting parameters can be saved with each data type." }, "format": "BULLETS", "uid": "f1712a46a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Basic text field type", "Text": "The basic text field type allows formatting, preserves line breaks and allows HTML restricted characters." }, "format": "BULLETS", "uid": "f1712b36a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Calendar widget", "Text": "A calendar widget can be used for editing date fields." }, "format": "BULLETS", "uid": "f1712c1ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Easy internal links", "Text": "Internal link fields and inline internal links are easier to use." }, "format": "BULLETS", "uid": "f1712d02a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unified external links", "Text": "An external link type supports http, https, file and mailto protocols." }, "format": "BULLETS", "uid": "f1712df2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Support relative paths", "Text": "Relative paths are supported for external links and pictures." }, "format": "BULLETS", "uid": "f1712ed8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Regular expression field type", "Text": "A regular expression field type can match patterns (phone numbers, email addresses, etc.)" }, "format": "BULLETS", "uid": "f1712fbea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Node IDs automatically generated", "Text": "Unique node IDs are automatically generated and updated." }, "format": "BULLETS", "uid": "f1713194a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "New windows installer", "Text": "A new windows installer allows a single-user, non-administrator install." }, "format": "BULLETS", "uid": "f1713284a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Portable installs", "Text": "Includes better support for portable installs." }, "format": "BULLETS", "uid": "f171336aa25a11e7b7c67054d2175f18" }, { "children": [ "f171354aa25a11e7b7c67054d2175f18", "f1713644a25a11e7b7c67054d2175f18", "f171372aa25a11e7b7c67054d2175f18" ], "data": { "Name": "Contacts" }, "format": "HEADINGS", "uid": "f1713464a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Mailing list", "Text": "There is a low-volume mailing list for users to discuss anything and everything about TreeLine. This is the place for development discussions (from roadmaps to feature suggestions to beta testing), release announcements, bug reports, and general user discussions (from new uses to tips & tricks to configuration samples).
\n
\nTo subscribe, go to lists.sourceforge.net/lists/listinfo/treeline-users
\n" }, "format": "HEAD_PARA", "uid": "f171354aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Email", "Text": "If you do not wish to subscribe to the mailing list, I can be contacted by email at: doug101 AT bellz DOT org " }, "format": "HEAD_PARA", "uid": "f1713644a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Updates", "Text": "I welcome any feedback, including reports of any bugs you find. Also, you can periodically check back to treeline.bellz.org for any updates." }, "format": "HEAD_PARA", "uid": "f171372aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Network drive issues", "Text": "Work around bugs when using files located on some types of Windows network drives." }, "format": "BULLETS", "uid": "f2a0c0a1dc8d11ea8921ac675dac20af" }, { "children": [], "data": { "Name": "Error handling", "Text": "Error handling has been improved. For most errors, a dialog box is shown with debugging information that can be copied into an email." }, "format": "BULLETS", "uid": "f5983b38bb0411e795e13417ebd53aeb" }, { "children": [ "42fb4166305a11e99fd7a44cc8e97404", "014e1392305b11e9ab99a44cc8e97404", "46f3d0a4305e11e9892fa44cc8e97404", "f7bbd90a305111e98209a44cc8e97404", "221ca8f0305911e99f3fa44cc8e97404", "2c9ba0c832ed11e9bf7f7054d2175f18", "2d4430dc305711e9a33aa44cc8e97404", "1b73aaf4305811e98bb7a44cc8e97404" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f7bbd909305111e9be43a44cc8e97404" }, { "children": [], "data": { "Name": "Regenerate references command", "Text": "A new Regenerate References command was added to the Data menu. It forces updates to all conditional types and math fields. It should only be necessary for comparisons to current dates/times or for externally modified data." }, "format": "BULLETS", "uid": "f7bbd90a305111e98209a44cc8e97404" }, { "children": [], "data": { "Name": "XML export", "Text": "Fixed problems with generic XML export from multiple root nodes." }, "format": "BULLETS", "uid": "f817e5b6334a11e89349d66a6ab671cb" }, { "children": [], "data": { "Name": "Number formatting", "Text": "Removed deprecated string escapes used when formatting numbers." }, "format": "BULLETS", "uid": "f8ed5904813411f0b43b5847ca7850fa" }, { "children": [], "data": { "Name": "Spanish translation", "Text": "Added a Spanish GUI translation (thanks to Diego)." }, "format": "BULLETS", "uid": "f966db0cc23f11e8b80fd66a6ab671cb" }, { "children": [], "data": { "Name": "Printing empty branches", "Text": "Fix an error caused by attempting to print an empty branch." }, "format": "BULLETS", "uid": "fcc1b718e5df11e9a7f9a44cc8e97404" }, { "children": [ "6a6067d4482011e989f27054d2175f18", "b398d8ee482211e989f27054d2175f18", "ff3f7da6481e11e989f27054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "ff3f7c98481e11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Translations", "Text": "Updated German and Spanish GUI translations (thanks to Maria Seliger and Diego)." }, "format": "BULLETS", "uid": "ff3f7da6481e11e989f27054d2175f18" } ], "properties": { "tlversion": "3.2.1", "topnodes": [ "f16f7d90a25a11e7b7c67054d2175f18" ] } }TreeLine-3.2.1/doc/documentation_ru.trln000066400000000000000000020110411506556630100202570ustar00rootroot00000000000000{ "formats": [ { "bullets": true, "fields": [ { "fieldname": "Name", "fieldtype": "HtmlText", "sortkeynum": 1 }, { "fieldname": "Name_src", "fieldtype": "Text", "sortkeynum": 2 }, { "fieldname": "Text", "fieldtype": "HtmlText", "lines": 2 }, { "fieldname": "Text_src", "fieldtype": "HtmlText", "lines": 2 }, { "fieldname": "number", "fieldtype": "DateTime", "format": "%B %-d, %Y %-I:%M:%S %p" } ], "formathtml": true, "formatname": "BULLETS", "icon": "bullet_1", "outputlines": [ "{*Text*}{*intlink*}" ], "spacebetween": false, "titleline": "{*Name*}" }, { "childtype": "BULLETS", "fields": [ { "fieldname": "Name", "fieldtype": "Text", "sortkeynum": 1 }, { "fieldname": "Name_src", "fieldtype": "Text", "sortkeynum": 2 } ], "formathtml": true, "formatname": "BULLET_HEADING", "outputlines": [ "{*Name*}" ], "spacebetween": false, "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "HtmlText", "sortkeynum": 1 }, { "fieldname": "Name_src", "fieldtype": "HtmlText", "sortkeynum": 2 } ], "formathtml": true, "formatname": "HEADINGS", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "HtmlText", "sortkeynum": 1 }, { "fieldname": "Name_src", "fieldtype": "Text", "sortkeynum": 2 }, { "fieldname": "Text", "fieldtype": "HtmlText", "lines": 8 }, { "fieldname": "Text_src", "fieldtype": "HtmlText", "lines": 8 } ], "formathtml": true, "formatname": "HEAD_PARA", "icon": "bullet_2", "outputlines": [ "
  • {*Name*} - {*Text*}
  • " ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text", "sortkeynum": 1 }, { "fieldname": "Name_src", "fieldtype": "Text", "sortkeynum": 2 }, { "fieldname": "Text", "fieldtype": "HtmlText", "lines": 8 }, { "fieldname": "Text_src", "fieldtype": "HtmlText", "lines": 8 } ], "formatname": "PARAGRAPH", "icon": "bullet_2", "outputlines": [ "{*Text*}" ], "titleline": "{*Name*}" } ], "nodes": [ { "children": [], "data": { "Name": "Minimize to system tray option", "Text": "A minimize to system tray option was added to General Options (under Features Available). If enabled, it adds a TreeLine system tray icon to toggle application display and hides the taskbar entry when TreeLine is minimized." }, "format": "BULLETS", "uid": "014e1392305b11e9ab99a44cc8e97404" }, { "children": [], "data": { "Name": "Automatic clone creation", "Text": "Cloned nodes can be created automatically from all identical nodes by using the \"Data > Clone All Matched Nodes\" command." }, "format": "BULLETS", "uid": "04a868f4bb0611e7aea13417ebd53aeb" }, { "children": [], "data": { "Name": "Multiple top-level nodes", "Text": "Multiple top-level (root) nodes are now permitted. When no nodes are selected in the tree (by clicking on a blank area or Ctrl clicking to unselect), the right-hand view will show information about all of the top-level nodes." }, "format": "BULLETS", "uid": "04da8386ba4811e7b3de3417ebd53aeb" }, { "children": [], "data": { "Name": "Updating multiple windows", "Text": "Properly update multiple windows after drag and drop tree changes." }, "format": "BULLETS", "uid": "0906c05bdc8f11ea94fbac675dac20af" }, { "children": [], "data": { "Name": "\u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u043f\u0435\u0447\u0430\u0442\u0438", "Name_src": "Print Preview", "Text": "\u0412 \u043e\u043a\u043d\u0435 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0440\u0430\u0441\u043f\u0435\u0447\u0430\u0442\u0430\u043d\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043f\u0435\u0447\u0430\u0442\u0438. \u041e\u043d \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d \u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0435\u0442\u0430\u043b\u0435\u0439, \u0438\u043b\u0438 \u0436\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u0412 \u043e\u043a\u043d\u0435 \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0435\u0447\u0430\u0442\u0438\u00bb \u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0435\u0447\u0430\u0442\u0438.", "Text_src": "The Print Preview window shows how the printout will look with current print settings. It can be dragged larger to show more detail, or the zoom settings can be changed. It also includes buttons for the Print Setup dialog and for printing." }, "format": "HEAD_PARA", "uid": "0a0d866469dd11eb9819001fd026534b" }, { "children": [], "data": { "Name": "Reduce windows install size", "Text": "Some unnecessary libraries were eliminated from the Windows installer to reduce download sizes and installed space requirements." }, "format": "BULLETS", "uid": "10c539e2305c11e9a392a44cc8e97404" }, { "children": [], "data": { "Name": "\u0410\u043f\u0435\u0447\u0430\u0442\u044c \u0432 PDF", "Name_src": "Print to PDF", "Text": "\u042d\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043f\u0443\u0442\u044c \u0438 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0444\u0430\u0439\u043b\u0430 \u0432 PDF \u0444\u043e\u0440\u043c\u0430\u0442. \u041f\u0440\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438\u043d\u0442\u0435\u0440\u0430.", "Text_src": "This command prompts for a path and file name to export a PDF file. It uses the current printer settings." }, "format": "HEAD_PARA", "uid": "12aaf67e69dd11eb9d47001fd026534b" }, { "children": [], "data": { "Name": "Right view update", "Text": "Properly update the right-hand views after using a new window command." }, "format": "BULLETS", "uid": "145bd91a334c11e896b1d66a6ab671cb" }, { "children": [], "data": { "Name": "Avoid unfocused title edit", "Text": "A click on a tree node to restore tree focus no longer starts editing the node title." }, "format": "BULLETS", "uid": "15da7fde786a11e881c8a44cc8e97404" }, { "children": [], "data": { "Name": "Remove redundant newlines in files", "Text": "Some redundant newline characters were removed from text storage in TreeLine files." }, "format": "BULLETS", "uid": "192373c6305511e9ab21a44cc8e97404" }, { "children": [], "data": { "Name": "Restore data editor cursor & scroll positions", "Text": "Restore the cursor and scroll positions of data editors when the editors are re-created after focus changes." }, "format": "BULLETS", "uid": "194b052fe5d811e9a0d1a44cc8e97404" }, { "children": [ "3e749de3e5d811e98227a44cc8e97404", "194b0537e5d811e989a1a44cc8e97404", "194b0534e5d811e985f6a44cc8e97404" ], "data": { "Name": "October 6, 2019 - Release 3.1.2 (stable release)" }, "format": "HEADINGS", "uid": "194b0533e5d811e9b5fea44cc8e97404" }, { "children": [ "8cdb2406e5df11e9a06da44cc8e97404", "8e8e418ae5dc11e98404a44cc8e97404", "9139627ee5db11e98a21a44cc8e97404", "194b0536e5d811e991b3a44cc8e97404", "fcc1b718e5df11e9a7f9a44cc8e97404" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "194b0534e5d811e985f6a44cc8e97404" }, { "children": [], "data": { "Name": "Treepad import", "Text": "Fix error due to character encoding when importing files from Treepad." }, "format": "BULLETS", "uid": "194b0536e5d811e991b3a44cc8e97404" }, { "children": [ "194b052fe5d811e9a0d1a44cc8e97404", "ea0c9b24e79911e98abe7054d2175f18", "4212597ee5e011e99b51a44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "194b0537e5d811e989a1a44cc8e97404" }, { "children": [], "data": { "Name": "Enable evaluate HTML tags option", "Text": "The Evaluate HTML tags control was enabled for date, time, boolean and math fields. This allows HTML tags to be evaluated or ignored in more field types." }, "format": "BULLETS", "uid": "1b73aaf4305811e98bb7a44cc8e97404" }, { "children": [], "data": { "Name": "Remove unique ID", "Text": "To improve efficiency, user visible node unique IDs that depend on the node's data have been removed." }, "format": "BULLETS", "uid": "1d015318bb0511e7a2ac3417ebd53aeb" }, { "children": [], "data": { "Name": "Reuse TreeLine windows", "Text": "When a file is opened in an existing window, the window is now reused (not just replaced) to eliminate flashing." }, "format": "BULLETS", "uid": "1e3a82e4bb0411e7b7f33417ebd53aeb" }, { "children": [], "data": { "Name": "Current date/time math field references", "Text": "Added support for current date and time references to math fields. Special field names ({*Now_Date*}, {*Now_Time*} and {*Now_Date_Time*}) must be manually typed in equations." }, "format": "BULLETS", "uid": "221ca8f0305911e99f3fa44cc8e97404" }, { "children": [], "data": { "Name": "German outline nuimbering", "Text": "Add support for German outline numbering using double letters in some levels (thanks to Teresa M)." }, "format": "BULLETS", "uid": "228fa647dc8c11eab28aac675dac20af" }, { "children": [], "data": { "Name": "Empty data edit views", "Text": "Fix a bug in Data Edit views when no fields are visible due to hidden numbering or math fields." }, "format": "BULLETS", "uid": "23b9a763dc8b11ea9dafac675dac20af" }, { "children": [], "data": { "Name": "Save as without filename", "Text": "Fix a minor bug affecting default directories for save-as and export commands when there is not already a file name set." }, "format": "BULLETS", "uid": "25ab9320482011e989f27054d2175f18" }, { "children": [], "data": { "Name": "Limit installer deletions", "Text": "In the Windows installer, improve the deletion of files from older versions and avoid problems if installing into a directory shared with other applications." }, "format": "BULLETS", "uid": "2767e530e80411e8aec9a44cc8e97404" }, { "children": [], "data": { "Name": "Math field restrictions", "Text": "Update math field equation restrictions to work with Python 3.8." }, "format": "BULLETS", "uid": "27950877dc8a11ea8902ac675dac20af" }, { "children": [], "data": { "Name": "Option to keep inaccessible recent files", "Text": "A new general option controls whether inaccessible files are removed from the recent file list at startup. The files are removed by default, but this can be changed to avoid losing listings of files stored on removable drives." }, "format": "BULLETS", "uid": "283565ba334211e8a34bd66a6ab671cb" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u044c \u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 (Breadcrumb View)", "Name_src": "Breadcrumb View", "Text": "\u041d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438 \u043f\u0440\u0435\u0434\u043a\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430. \u041f\u0430\u043d\u0435\u043b\u044c \u043f\u0443\u0441\u0442\u0430, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u0438\u043b\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0437\u043b\u043e\u0432. \u041f\u043e \u0449\u0435\u043b\u0447\u043a\u0443 \u043c\u044b\u0448\u0438 \u043d\u0430 \u0443\u0437\u043b\u0430\u0445 \u043f\u0440\u0435\u0434\u043a\u043e\u0432, \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u043d\u0438\u043c \u0446\u0432\u0435\u0442\u043e\u043c, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u044d\u0442\u0438\u043c \u0443\u0437\u043b\u0430\u043c.", "Text_src": "The top pane shows the parent and ancestors of the selected node. It is blank if no nodes or multiple nodes are selected. Ancestors with blue text can be clicked to select those nodes." }, "format": "HEAD_PARA", "uid": "28f8844ab58711e79d173417ebd53aeb" }, { "children": [], "data": { "Name": "Conditional type copy/paste & drag/drop", "Text": "Fixed problems with copy / paste and drag / drop on nodes with conditional type settings." }, "format": "BULLETS", "uid": "299ba9e4334a11e881a6d66a6ab671cb" }, { "children": [], "data": { "Name": "Type structure visualization", "Text": "A new Show Configuration Structure command was added to the Data menu. This opens a read-only visualization of complex type structures as another TreeLine file." }, "format": "BULLETS", "uid": "2c9ba0c832ed11e9bf7f7054d2175f18" }, { "children": [], "data": { "Name": "Pretty print output", "Text": "An indent (pretty print) output option was added to General Options (under Features Available). This makes saved TreeLine JSON files easier for humans to read at the expense of somewhat larger file sizes." }, "format": "BULLETS", "uid": "2d4430dc305711e9a33aa44cc8e97404" }, { "children": [], "data": { "Name": "Open with bad references", "Text": "TreeLine files with invalid child references can now be opened. A warning message is given about the missing child nodes in the corrupt file." }, "format": "BULLETS", "uid": "2df5b030bbf711e88a1ca44cc8e97404" }, { "children": [], "data": { "Name": "\u041f\u043e\u0440\u0442\u044b \u043d\u0430 MacOs", "Name_src": "MacPorts", "Text": "\u0421\u043c. \u041f\u043e\u0440\u0442\u044b \u043d\u0430 MacOs \u0434\u043b\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u043f\u043e\u0440\u0442\u0430 \u043d\u0430 macOS.", "Text_src": "See MacPorts for a third-party port to macOS." }, "format": "PARAGRAPH", "uid": "2fa1be1fdc9511eaa00dac675dac20af" }, { "children": [], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 HTML", "Name_src": "Live HTML Export", "Text": "\u041f\u0440\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 HTML \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u0443\u0437\u043b\u0430\u043c\u0438 \u0438 \u043f\u0430\u043d\u0435\u043b\u044c\u044e \u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432.", "Text_src": "A live tree HTML export creates an interactive view with expandable nodes and a descendant output pane." }, "format": "BULLETS", "uid": "31304c06792b11e888cfa44cc8e97404" }, { "children": [], "data": { "Name": "Restoring window geometry", "Text": "Fix issues with restoring window geometry with multiple monitors and changing configurations." }, "format": "BULLETS", "uid": "35d0914edc8911eab202ac675dac20af" }, { "children": [], "data": { "Name": "Multiple paste commands", "Text": "New paste commands have been added for adding nodes before and after siblings. There are also multiple paste commands for adding clones of nodes." }, "format": "BULLETS", "uid": "39c001f0bb0311e79e793417ebd53aeb" }, { "children": [], "data": { "Name": "Major rewrite", "Text": "This is a major rewrite of TreeLine. Once it becomes more stable, it will be released as TreeLine version 3.0.0. The 2.1.x unstable series is being discontinued (no stable 2.2.0 release is planned)." }, "format": "BULLETS", "uid": "3d2bb12eba3c11e79b223417ebd53aeb" }, { "children": [], "data": { "Name": "Chinese translation", "Text": "Add a simplified Chinese GUI translation (thanks to Qu Ray for translating)." }, "format": "BULLETS", "uid": "3e749de1e5d811e9a22ba44cc8e97404" }, { "children": [ "3e749de1e5d811e9a22ba44cc8e97404", "cef1d9fee5de11e998dea44cc8e97404" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "3e749de3e5d811e98227a44cc8e97404" }, { "children": [], "data": { "Name": "Time field AM/PM", "Text": "Now forces references to AM/PM in time field formats to be output regardless of system locale settings." }, "format": "BULLETS", "uid": "40ec6d5cbbf711e8bb93a44cc8e97404" }, { "children": [], "data": { "Name": "Outline numbering", "Text": "Change lettered outline numbering sequences to match standards. The sequences change from ...Y, Z, AA, AB, AC... to ...Y, Z, AA, BB, CC..." }, "format": "BULLETS", "uid": "4212597ee5e011e99b51a44cc8e97404" }, { "children": [], "data": { "Name": "Title list select in tree command", "Text": "A Select in Tree command was added to the Title List's right-click context menu. It selects the node corresponding to the current line in the Title List editor. This makes it easier to edit or add children to an item." }, "format": "BULLETS", "uid": "42fb4166305a11e99fd7a44cc8e97404" }, { "children": [], "data": { "Name": "Title edit mouse move", "Text": "Fixed node title editing errors caused by moving the mouse to a data edit box with the title edit still active." }, "format": "BULLETS", "uid": "45491730786a11e8b8e2a44cc8e97404" }, { "children": [], "data": { "Name": "Enter key selects current node", "Text": "The enter key now selects a tree node after the first title letter(s) are typed to make it current (shown with a box around the title)." }, "format": "BULLETS", "uid": "456aa5ca793111e89a30a44cc8e97404" }, { "children": [ "66faed8adc9411ea965eac675dac20af", "d8a76c1fdc9411eaab2dac675dac20af" ], "data": { "Name": "macOS" }, "format": "BULLET_HEADING", "uid": "460699ebdc9411ea89afac675dac20af" }, { "children": [], "data": { "Name": "Dark theme option", "Text": "An optional dark color theme was added to General Options (under Appearances)." }, "format": "BULLETS", "uid": "46f3d0a4305e11e9892fa44cc8e97404" }, { "children": [], "data": { "Name": "Relative paths", "Text": "Avoid issues resolving relative paths between different Windows drive letters in external link fields." }, "format": "BULLETS", "uid": "46fc4054334b11e89299d66a6ab671cb" }, { "children": [], "data": { "Name": "Major rewrite", "Text": "This is a major rewrite of TreeLine. Once it becomes fully stable, it will be released as TreeLine version 3.0.0." }, "format": "BULLETS", "uid": "4bc47247786711e88b26a44cc8e97404" }, { "children": [ "4bc47249786711e8a3d5a44cc8e97404", "4bc4724c786711e8a8d9a44cc8e97404", "4bc4724f786711e89bdca44cc8e97404" ], "data": { "Name": "June 30, 2018 - Release 2.9.2 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "4bc47248786711e8a8bfa44cc8e97404" }, { "children": [ "4bc4724a786711e8a4dda44cc8e97404", "4bc47247786711e88b26a44cc8e97404", "4bc4724b786711e895e2a44cc8e97404" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "4bc47249786711e8a3d5a44cc8e97404" }, { "children": [], "data": { "Name": "Development snapshot", "Text": "This is a development snapshot of TreeLine that should be considered a release candidate for an upcoming stable release. Many bugs have been fixed. User testing and bug reports are appreciated." }, "format": "BULLETS", "uid": "4bc4724a786711e8a4dda44cc8e97404" }, { "children": [], "data": { "Name": "Translations", "Text": "A GUI translations is available in German. All other translations are out of date and have not been included. Volunteers are needed to update translations in several languages." }, "format": "BULLETS", "uid": "4bc4724b786711e895e2a44cc8e97404" }, { "children": [ "57c4de74786911e89c3fa44cc8e97404", "71b708ac786911e88d64a44cc8e97404", "a7d7f61e786911e89bbca44cc8e97404", "15da7fde786a11e881c8a44cc8e97404", "456aa5ca793111e89a30a44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "4bc4724c786711e8a8d9a44cc8e97404" }, { "children": [ "e4fc680a786911e899d3a44cc8e97404", "45491730786a11e8b8e2a44cc8e97404", "f011a5d8786911e8ace3a44cc8e97404" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "4bc4724f786711e89bdca44cc8e97404" }, { "children": [], "data": { "Name": "Multi-session controls", "Text": "Fix problems detecting existing TreeLine sessions when opening files (mostly in Linux)." }, "format": "BULLETS", "uid": "5337587ddc8811eaaaedac675dac20af" }, { "children": [], "data": { "Name": "Clone removal", "Text": "The new \"Data > Detach Clones\" command converts cloned nodes in selected branches back into independent nodes." }, "format": "BULLETS", "uid": "5647bc8cbb0611e783853417ebd53aeb" }, { "children": [], "data": { "Name": "German translation", "Text": "The German GUI translation was updated (thanks to Maria Seliger)." }, "format": "BULLETS", "uid": "57c4de74786911e89c3fa44cc8e97404" }, { "children": [], "data": { "Name": "Linux menus", "Text": "Added a desktop specification file to the Linux installer for desktop environment menu support." }, "format": "BULLETS", "uid": "58dddee4010f11e88925d66a6ab671cb" }, { "children": [], "data": { "Name": "\u041d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b", "Name_src": "Setting types", "Text": "\u041a\u0430\u0436\u0434\u043e\u043c\u0443 \u0443\u0437\u043b\u0443 \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0430.", "Text_src": "Each tree node can be set to a type format independently." }, "format": "BULLETS", "uid": "5c1d58ac792a11e8b78ca44cc8e97404" }, { "children": [], "data": { "Name": "Category level swap", "Text": "A new \"Swap Category Levels\" command swaps child and grandchild nodes beneath a selected node. A child node with multiple nodes under it will become cloned under each one. Any existing grandchild clones will become individual nodes with multiple children." }, "format": "BULLETS", "uid": "5c90e0b0bb0611e78e443417ebd53aeb" }, { "children": [], "data": { "Name": "\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b", "Name_src": "Cloned nodes", "Text": "\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b (\u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0443\u0437\u043b\u044b \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f\u043c\u0438 / \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438) \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0438\u043b\u0438 \u043f\u0443\u0442\u0435\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432.", "Text_src": "Cloned nodes (the same nodes with multiple parents/locations) can be created using special paste commands or by automatically matching identical nodes." }, "format": "BULLETS", "uid": "5f12f768b32c11e7a41a3417ebd53aeb" }, { "children": [], "data": { "Name": "Library updates", "Text": "Update the libraries used to build the Windows binaries to Python 3.8 and Qt/PyQt 5.14." }, "format": "BULLETS", "uid": "603e11fadf2011eaa12e7054d2175f18" }, { "children": [ "2fa1be1fdc9511eaa00dac675dac20af" ], "data": { "Name": "macOS" }, "format": "BULLET_HEADING", "uid": "611e03ffdc9411ea930eac675dac20af" }, { "children": [], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u0444\u0430\u0439\u043b\u044b TreeLine", "Name_src": "TreeLine Export", "Text": "\u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u0444\u0430\u0439\u043b\u044b, \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u0441\u043e \u0441\u0442\u0430\u0440\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 TreeLine (1.x \u0438 2.x), \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u00ab.trl\u00bb. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438, \u043f\u0440\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 TreeLine \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0435\u0432\u044c\u044f TreeLine, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0444\u0430\u0439\u043b \u0441\u0442\u0430\u0440\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0432\u0435\u0442\u0432\u0438 \u0434\u0435\u0440\u0435\u0432\u0430.", "Text_src": "Files can be exported that are compatible with older versions of TreeLine (1.x and 2.x), with a \".trl\" file extension. Some newer features, such as cloned nodes and multiple root nodes may not be completely preserved. TreeLine subtrees can also be exported to save just selected branches of the tree to a file using the current TreeLine version." }, "format": "HEAD_PARA", "uid": "65289b36b97611e783eb3417ebd53aeb" }, { "children": [], "data": { "Name": "Custom time dialog", "Text": "Added a custom time select dialog box for editing Time and TimeDate fields." }, "format": "BULLETS", "uid": "653f2f90334c11e8a7c9d66a6ab671cb" }, { "children": [], "data": { "Name": "Printing long nodes", "Text": "Multiple issues with printing long nodes were fixed." }, "format": "BULLETS", "uid": "6610203dd2c111e8a95ad66a6ab671cb" }, { "children": [ "66102040d2c111e8a210d66a6ab671cb", "66102041d2c111e8bd85d66a6ab671cb" ], "data": { "Name": "October 20, 2018 - Release 3.0.2 (stable release)" }, "format": "HEADINGS", "uid": "6610203fd2c111e8b033d66a6ab671cb" }, { "children": [ "66102049d2c111e8bb55d66a6ab671cb" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "66102040d2c111e8a210d66a6ab671cb" }, { "children": [ "66102043d2c111e88d57d66a6ab671cb", "6610203dd2c111e8a95ad66a6ab671cb", "66102048d2c111e89f4cd66a6ab671cb" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "66102041d2c111e8bd85d66a6ab671cb" }, { "children": [], "data": { "Name": "Windows printing", "Text": "Fixed nonfunctional printing commands under Windows by building the Windows binary using PyInstaller rather than cx_Freeze." }, "format": "BULLETS", "uid": "66102043d2c111e88d57d66a6ab671cb" }, { "children": [], "data": { "Name": "Blanks as zeros", "Text": "Fixed problems saving files when the blanks as zeros property was changed for math fields." }, "format": "BULLETS", "uid": "66102048d2c111e89f4cd66a6ab671cb" }, { "children": [], "data": { "Name": "Python 3.7", "Text": "Upgraded the Windows binary from Python 3.6 to Python 3.7." }, "format": "BULLETS", "uid": "66102049d2c111e8bb55d66a6ab671cb" }, { "children": [], "data": { "Name": "\u041d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f", "Name_src": "Not supported", "Text": "\u0412 \u0441\u0438\u0434\u0443 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043e\u0432 Mac \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f TreeLine \u043d\u0430 macOS \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f.", "Text_src": "Due to a lack of Macs for testing, TreeLine on macOS is not formally supported." }, "format": "BULLETS", "uid": "66faed8adc9411ea965eac675dac20af" }, { "children": [ "67e95a5fbbf611e8b8bda44cc8e97404", "67e95a60bbf611e8a80ca44cc8e97404" ], "data": { "Name": "September 29, 2018 - Release 3.0.1 (stable release)" }, "format": "HEADINGS", "uid": "67e95a5bbbf611e891f7a44cc8e97404" }, { "children": [ "f966db0cc23f11e8b80fd66a6ab671cb", "67e95a61bbf611e8989ca44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "67e95a5fbbf611e8b8bda44cc8e97404" }, { "children": [ "67e95a64bbf611e8960fa44cc8e97404", "2df5b030bbf711e88a1ca44cc8e97404", "dc700fb4c24211e8b88dd66a6ab671cb", "40ec6d5cbbf711e8bb93a44cc8e97404", "9550a81ac24111e89029d66a6ab671cb", "71e2f25cc24211e88524d66a6ab671cb", "a757f64ac24211e8a95fd66a6ab671cb", "bdc8628ec2bd11e889e57054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "67e95a60bbf611e8a80ca44cc8e97404" }, { "children": [], "data": { "Name": "About dialog text box", "Text": "Added a read-only text box to the Help > About dialog to allow copying of the version and library information." }, "format": "BULLETS", "uid": "67e95a61bbf611e8989ca44cc8e97404" }, { "children": [], "data": { "Name": "Old file import", "Text": "Fixed a problem opening old TreeLine files that had format changes in File Info fields." }, "format": "BULLETS", "uid": "67e95a64bbf611e8960fa44cc8e97404" }, { "children": [], "data": { "Name": "Data in config structure", "Text": "Added many Show Configuration Structure data fields to show detailed settings for type formats and field formats.." }, "format": "BULLETS", "uid": "6a6067d4482011e989f27054d2175f18" }, { "children": [], "data": { "Name": "Select top node at open", "Text": "The top root node is now selected at file open if there is not a recent selection state to restore. Previously these files opened with no selection, which could cause confusion." }, "format": "BULLETS", "uid": "6a98186e305c11e99fbfa44cc8e97404" }, { "children": [], "data": { "Name": "Insert date command", "Text": "Add an Insert Date command that adds a timestamp to text field edit boxes." }, "format": "BULLETS", "uid": "6c916f15dc8c11ea9dbeac675dac20af" }, { "children": [], "data": { "Name": "Child type limits", "Text": "Child node types that are available to be set can be limited. A new pull-down list of child type limits is in the \"Type Config\" tab of the configuration dialog if the advanced functions are shown." }, "format": "BULLETS", "uid": "6dc88226bb0711e7894d3417ebd53aeb" }, { "children": [ "6df9a0c6ba3b11e7925d3417ebd53aeb", "6df9a0c9ba3b11e7a9793417ebd53aeb" ], "data": { "Name": "January 28, 2018 - Release 2.9.0 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "6df9a0c5ba3b11e78e7e3417ebd53aeb" }, { "children": [ "6df9a0c7ba3b11e7b7bd3417ebd53aeb", "3d2bb12eba3c11e79b223417ebd53aeb", "6df9a0c8ba3b11e78d783417ebd53aeb" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "6df9a0c6ba3b11e7925d3417ebd53aeb" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It could contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) is recommended for critical work." }, "format": "BULLETS", "uid": "6df9a0c7ba3b11e7b7bd3417ebd53aeb" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations are out of date and have not been included. Volunteers are needed to update translations in several languages." }, "format": "BULLETS", "uid": "6df9a0c8ba3b11e78d783417ebd53aeb" }, { "children": [ "6df9a0caba3b11e78b283417ebd53aeb", "d1d8e56eba4011e784ab3417ebd53aeb", "04da8386ba4811e7b3de3417ebd53aeb", "e6ad9f6eba4311e796bd3417ebd53aeb", "cd28e024bb0211e79c553417ebd53aeb", "1e3a82e4bb0411e7b7f33417ebd53aeb", "98132868ba4511e7b7283417ebd53aeb", "39c001f0bb0311e79e793417ebd53aeb", "04a868f4bb0611e7aea13417ebd53aeb", "5647bc8cbb0611e783853417ebd53aeb", "5c90e0b0bb0611e78e443417ebd53aeb", "6dc88226bb0711e7894d3417ebd53aeb", "7697b826bb0411e788433417ebd53aeb", "1d015318bb0511e7a2ac3417ebd53aeb", "f5983b38bb0411e795e13417ebd53aeb", "58dddee4010f11e88925d66a6ab671cb" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "6df9a0c9ba3b11e7a9793417ebd53aeb" }, { "children": [], "data": { "Name": "New file format", "Text": "TreeLine files now uses a new JSON format in place of the old XML format. This provides more flexibility for structuring new features like cloned nodes and multiple root nodes. A new file extension (\".trln) helps to distinguish these files." }, "format": "BULLETS", "uid": "6df9a0caba3b11e78b283417ebd53aeb" }, { "children": [], "data": { "Name": "\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u044f \u043a \u041f\u0435\u0440\u0435\u0432\u043e\u0434\u0443", "Name_src": "Translation Notes", "Text": "\u041f\u0435\u0440\u0435\u0432\u043e\u0434 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Treeline \u0432\u0435\u0440\u0441\u0438\u0438 3.1.4 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a \u2014 \u0410. \u0422\u0440\u043e\u0444\u0438\u043c\u043e\u0432, 12.02.2021\u0433., 08.09.2022\u0433.\n
    \n
    \n\u0411\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u044b \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f Windows.\n
    \n
    \n\u0422\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u0441\u0430\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u0435\u043d \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0434\u0435\u0436\u0434\u0435, \u0447\u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d, \u043d\u043e \u0411\u0415\u0417 \u041a\u0410\u041a\u0418\u0425-\u041b\u0418\u0411\u041e \u0413\u0410\u0420\u0410\u041d\u0422\u0418\u0419.\n
    \n
    \n\u0412 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043f\u043e \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u043c \u043e\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430 \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u043d\u0435 \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u043e:\n
      \n
    • \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 > \u0412\u044b\u0432\u043e\u0434 > \u0423\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u0441\u044b\u043b\u043a\u0438\u00bb
    • \n
    • \u041a\u043d\u043e\u043f\u043a\u0438 \u00abYes\u00bb, \u00abNo\u00bb, \u00abCancel\u00bb, \u00abDiscard\u00bb \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u044b\u0445 \u043e\u043a\u043d\u0430\u0445 \u00ab\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f\u00bb, \u043e\u043a\u043d\u0435 \u00abTreeline\u00bb \u0432\u044b\u0445\u043e\u0434\u0430 \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f
    • \n
    \n
    \n\u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u043b\u0441\u044f \u0440\u0430\u0437\u0434\u0435\u043b \u00ab\u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439\u00bb.\n
    \n
    \n\u0412 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043c\u0435 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:\n
      \n
    • \u041f\u0443\u043d\u043a\u0442 \u00ab\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0432\u0435\u0442\u0432\u0438\u00bb \u043c\u0435\u043d\u044e \u00ab\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430\u00bb \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0438 \u043e\u0434\u043d\u043e\u0439 \u00ab\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0432\u0435\u0442\u0432\u0438\u00bb, \u043e\u0434\u043d\u0430\u043a\u043e \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u0441\u044f, \u0442.\u043a. \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0448\u0438\u0431\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u043e\u043c \u0432 \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b
    • \n
    • \u041f\u0443\u043d\u043a\u0442 \u00ab\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b\u00bb \u043c\u0435\u043d\u044e \u00ab\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430\u00bb \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u00ab\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430\u00bb, \u043e\u0434\u043d\u0430\u043a\u043e \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u0441\u044f, \u0442.\u043a. \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0448\u0438\u0431\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u043e\u043c \u0432 \u043d\u043e\u0432\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b
    • \n
    \n
    \n\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0435 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438 \u043d\u0435\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u044b \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 [\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b ...], \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0448\u0440\u0438\u0444\u0442\u043e\u043c \u043a\u0440\u0430\u0441\u043d\u043e\u0433\u043e \u0446\u0432\u0435\u0442\u0430.\n
    \n
    \n\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043d\u0435\u0441\u0435\u043d\u043d\u044b\u0439 \u0432 \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0442\u0435\u043a\u0441\u0442 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u0435 \u0441\u043a\u043e\u0431\u043a\u0438 \u2014 [].\n" }, "format": "PARAGRAPH", "uid": "6e4dd051678a11eb8f00001fd026534b" }, { "children": [], "data": { "Name": "Maintain expanded nodes", "Text": "The expand/collapse status of nearby nodes is maintained while editing the node structure. This includes adding, deleting, moving and indenting nodes." }, "format": "BULLETS", "uid": "71b708ac786911e88d64a44cc8e97404" }, { "children": [], "data": { "Name": "Complex data menu commands", "Text": "Fixed various errors when applying advanced clone and category commands from the Data menu to complex node structures." }, "format": "BULLETS", "uid": "71e2f25cc24211e88524d66a6ab671cb" }, { "children": [], "data": { "Name": "Date and time formats", "Text": "The Date, Time and DateTime fields have new format strings that enable extra text to be added to the date output." }, "format": "BULLETS", "uid": "7697b826bb0411e788433417ebd53aeb" }, { "children": [], "data": { "Name": "Number field formatting", "Text": "Fixed problems with number field formatting when using a \",\" radix with exponents." }, "format": "BULLETS", "uid": "7716c96e334a11e896bfd66a6ab671cb" }, { "children": [], "data": { "Name": "Math field expressions", "Text": "Evaluate math expressions contained in fields that are referenced by math field equations. " }, "format": "BULLETS", "uid": "7a9ace43dc8a11ea9e9bac675dac20af" }, { "children": [], "data": { "Name": "\u041b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438", "Name_src": "Translations", "Text": "\u0412 TreeLine \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u044b \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0430 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043a\u0438\u0442\u0430\u0439\u0441\u043a\u0438\u0439, \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0439, \u043d\u0435\u043c\u0435\u0446\u043a\u0438\u0439, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u0438 \u0438\u0441\u043f\u0430\u043d\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a\u0438. \u0415\u0441\u043b\u0438 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u041e\u0421 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b \u043a \u043a\u043e\u043c\u0430\u043d\u0434\u0435, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0449\u0435\u0439 TreeLine, \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u00ab--lang xx\u00bb, \u0433\u0434\u0435 \u00abxx\u00bb - \u044d\u0442\u043e \u0434\u0432\u0443\u0445\u0431\u0443\u043a\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u044f\u0437\u044b\u043a\u0430 (\u00abzh\u00bb, \u00aben\u00bb, \u00abde\u00bb, \u00abru\u00bb \u043b\u0438 \u00abes\u00bb).", "Text_src": "Translations of the TreeLine GUI are available in German and Spanish. The translation should load automatically if the OS locale is properly set. Alternatively, \"--lang xx\" can be appended to the command that starts TreeLine, where \"xx\" is the two-letter language code (\"en\", \"de\" or \"es\")." }, "format": "HEAD_PARA", "uid": "7e9b3b88c24511e896c7d66a6ab671cb" }, { "children": [ "7ffeb672dc8711ea86ddac675dac20af", "7ffeb670dc8711ea81aeac675dac20af", "7ffeb66edc8711eaaa13ac675dac20af" ], "data": { "Name": "August 16, 2020 - Release 3.1.3 (stable release)" }, "format": "HEADINGS", "uid": "7ffeb66ddc8711ea9a87ac675dac20af" }, { "children": [ "d9119485dc8711ea92dcac675dac20af", "8d9c1717dc8811ea9c40ac675dac20af", "cf9c139fdc8e11ea8261ac675dac20af", "88bb6300dc8e11ea9a73ac675dac20af", "b6a4a6bddc8911ea8612ac675dac20af", "23b9a763dc8b11ea9dafac675dac20af", "0906c05bdc8f11ea94fbac675dac20af", "35d0914edc8911eab202ac675dac20af", "f2a0c0a1dc8d11ea8921ac675dac20af", "5337587ddc8811eaaaedac675dac20af" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "7ffeb66edc8711eaaa13ac675dac20af" }, { "children": [ "27950877dc8a11ea8902ac675dac20af", "c1f8dca5dc9511ea8f76ac675dac20af", "603e11fadf2011eaa12e7054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "7ffeb670dc8711ea81aeac675dac20af" }, { "children": [ "dca5b84fdc8a11eab098ac675dac20af", "6c916f15dc8c11ea9dbeac675dac20af", "7a9ace43dc8a11ea9e9bac675dac20af", "228fa647dc8c11eab28aac675dac20af" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "7ffeb672dc8711ea86ddac675dac20af" }, { "children": [ "800a0972305111e9a7fea44cc8e97404", "f7bbd909305111e9be43a44cc8e97404", "800a0975305111e9a018a44cc8e97404", "800a0976305111e9bd43a44cc8e97404" ], "data": { "Name": "February 20, 2019 - Release 3.1.0 (beta release)" }, "format": "HEADINGS", "uid": "800a0971305111e991cda44cc8e97404" }, { "children": [ "800a0973305111e9b7b9a44cc8e97404", "800a0974305111e99f0fa44cc8e97404" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "800a0972305111e9a7fea44cc8e97404" }, { "children": [], "data": { "Name": "Beta release", "Text": "This is a beta release of TreeLine. Some new features have not been extensively tested, but major bugs are unlikely. Testing and bug reports are appreciated, but those with very critical work should consider using the stable release (TreeLine 3.0.x)." }, "format": "BULLETS", "uid": "800a0973305111e9b7b9a44cc8e97404" }, { "children": [], "data": { "Name": "Translations", "Text": "GUI translations are available in German and Spanish, but they still require minor updates to cover recent changes. Volunteers are also needed to update or create translations in additional languages." }, "format": "BULLETS", "uid": "800a0974305111e99f0fa44cc8e97404" }, { "children": [ "6a98186e305c11e99fbfa44cc8e97404", "800a0977305111e98c38a44cc8e97404", "10c539e2305c11e9a392a44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "800a0975305111e9a018a44cc8e97404" }, { "children": [ "800a097a305111e9950ba44cc8e97404", "192373c6305511e9ab21a44cc8e97404" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "800a0976305111e9bd43a44cc8e97404" }, { "children": [], "data": { "Name": "Gray out data edit view math fields", "Text": "Non-editable math fields in the Data Edit view show as gray when the mouse hovers over them." }, "format": "BULLETS", "uid": "800a0977305111e98c38a44cc8e97404" }, { "children": [], "data": { "Name": "Titles from HTML text fields", "Text": "Fixed the truncation of node titles that are generated from the first line of HTML Text fields." }, "format": "BULLETS", "uid": "800a097a305111e9950ba44cc8e97404" }, { "children": [], "data": { "Name": "Numbering", "Text": "Fix incorrect numbering updates in some situations with mixed node types." }, "format": "BULLETS", "uid": "84b24010482211e989f27054d2175f18" }, { "children": [], "data": { "Name": "Circular math errors", "Text": "Fix problems opening files that contain circular reference errors in math fields." }, "format": "BULLETS", "uid": "88bb6300dc8e11ea9a73ac675dac20af" }, { "children": [], "data": { "Name": "Truncated text export", "Text": "Fix a bug that truncated plain text exports after the first line." }, "format": "BULLETS", "uid": "8cdb2406e5df11e9a06da44cc8e97404" }, { "children": [], "data": { "Name": "Find & replace error", "Text": "Avoid an application error when a Find and Replace command causes fields to contain invalid data." }, "format": "BULLETS", "uid": "8d9c1717dc8811ea9c40ac675dac20af" }, { "children": [], "data": { "Name": "Title list select in tree", "Text": "Enable the title list view's select in tree context menu to be used on new child nodes." }, "format": "BULLETS", "uid": "8e8e418ae5dc11e98404a44cc8e97404" }, { "children": [], "data": { "Name": "Copy command errors", "Text": "Fix errors shown when using copy commands after closing TreeLine windows." }, "format": "BULLETS", "uid": "90dbc4e4334b11e892d0d66a6ab671cb" }, { "children": [], "data": { "Name": "Dark mode tooltips", "Text": "Modify dark mode colors to make tool tips visible." }, "format": "BULLETS", "uid": "9139627ee5db11e98a21a44cc8e97404" }, { "children": [], "data": { "Name": "Purge old field data", "Text": "Data from fields that were removed from the configuration is now purged when a file is saved. This avoids missing matches in the Clone All Matched Nodes command." }, "format": "BULLETS", "uid": "9550a81ac24111e89029d66a6ab671cb" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u043e\u0432 TreeLine \u0421\u0442\u0430\u0440\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438", "Name_src": "Old TreeLine Import", "Text": "\u0424\u0430\u0439\u043b\u044b \u0438\u0437 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0440\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 TreeLine (1.x \u0438\u043b\u0438 2.x) \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b. \u042d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0440\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u043c\u0435\u044e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442 XML \u0438 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u043c\u0435\u044e\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \".trl\" (\u0444\u0430\u0439\u043b\u044b \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u044e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442 JSON \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c \".trln\"). \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u043c\u043f\u043e\u0440\u0442\u0430, \u044d\u0442\u0438 \u0441\u0442\u0430\u0440\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0431\u0435\u0437 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0424\u0430\u0439\u043b > \u041e\u0442\u043a\u0440\u044b\u0442\u044c\u00bb.", "Text_src": "Files from older versions of TreeLine (1.x or 2.x) can be imported. These files are in XML format and generally have a \".trl\" file extension (current files are in JSON format with a \".trln\" file extension). Unlike other file imports, these older files will import without showing the import dialog box when using the \"File > Open\" command." }, "format": "HEAD_PARA", "uid": "95547c38b97411e7a42a3417ebd53aeb" }, { "children": [], "data": { "Name": "Major rewrite", "Text": "This is a major rewrite of TreeLine. Once it becomes more stable, it will be released as TreeLine version 3.0.0. The 2.1.x unstable series is being discontinued (no stable 2.2.0 release is planned)." }, "format": "BULLETS", "uid": "95a6e905333f11e886edd66a6ab671cb" }, { "children": [ "95a6e90b333f11e8976fd66a6ab671cb", "95a6e90e333f11e88696d66a6ab671cb", "b16866da333f11e88adbd66a6ab671cb" ], "data": { "Name": "March 31, 2018 - Release 2.9.1 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "95a6e90a333f11e89efed66a6ab671cb" }, { "children": [ "95a6e90c333f11e8b766d66a6ab671cb", "95a6e905333f11e886edd66a6ab671cb", "95a6e90d333f11e8b88ed66a6ab671cb" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "95a6e90b333f11e8976fd66a6ab671cb" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It has improved but could still contain bugs. Testing and bug reports are appreciated, but those with very critical work should consider using the stable release (TreeLine 2.0.x)." }, "format": "BULLETS", "uid": "95a6e90c333f11e8b766d66a6ab671cb" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations are out of date and have not been included. Volunteers are needed to update translations in several languages." }, "format": "BULLETS", "uid": "95a6e90d333f11e8b88ed66a6ab671cb" }, { "children": [ "b1cd1f82334111e8b89ad66a6ab671cb", "dd22e382334111e894e6d66a6ab671cb", "653f2f90334c11e8a7c9d66a6ab671cb", "283565ba334211e8a34bd66a6ab671cb" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "95a6e90e333f11e88696d66a6ab671cb" }, { "children": [], "data": { "Name": "Child count equation references", "Text": "Eliminate a problem defining math field equations that include child count references." }, "format": "BULLETS", "uid": "95d970aa481f11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Native cloned nodes", "Text": "Cloned nodes now have a more native and efficient implementation. This allows the same nodes to have multiple parents. The new breadcrumb view shows a list of clones for the selected node that can be clicked to select the other instances." }, "format": "BULLETS", "uid": "98132868ba4511e7b7283417ebd53aeb" }, { "children": [], "data": { "Name": "\u041c\u0435\u043d\u044e \u00ab\u0424\u043e\u0440\u043c\u0430\u0442\u00bb (Format Menu)", "Name_src": "Format Menu", "Text": "\u0412 \u043c\u0435\u043d\u044e \u00ab\u0424\u043e\u0440\u043c\u0430\u0442\u00bb \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u00ab\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb.", "Text_src": "The format menu has text formatting commands that are active when using edit boxes in the Data Edit view." }, "format": "HEAD_PARA", "uid": "997af664b58811e7ac243417ebd53aeb" }, { "children": [], "data": { "Name": "Ancestor field references", "Text": "Fixed problems with advanced ancestor field output references in some tree locations." }, "format": "BULLETS", "uid": "9a8a1400334c11e89838d66a6ab671cb" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442/\u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u043e\u0432 TreeLine \u0441\u0442\u0430\u0440\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439", "Name_src": "Old TreeLine import/export", "Text": "\u041c\u043e\u0436\u043d\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0440\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 TreeLine (2.x \u0438 1.x).", "Text_src": "Files from older versions of TreeLine (2.x and 1.x) can be imported and exported." }, "format": "BULLETS", "uid": "9bd80f34b32b11e7be613417ebd53aeb" }, { "children": [], "data": { "Name": "Portable config", "Text": "Problems with writing config files in Windows portable installations were fixed." }, "format": "BULLETS", "uid": "9c08f39de80311e8b791a44cc8e97404" }, { "children": [ "9c08f3a0e80311e8b2e0a44cc8e97404" ], "data": { "Name": "November 17, 2018 - Release 3.0.3 (stable release)" }, "format": "HEADINGS", "uid": "9c08f39ee80311e8a510a44cc8e97404" }, { "children": [ "9c08f3a1e80311e884dca44cc8e97404", "9c08f39de80311e8b791a44cc8e97404", "9c08f3a2e80311e88128a44cc8e97404", "2767e530e80411e8aec9a44cc8e97404" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "9c08f3a0e80311e8b2e0a44cc8e97404" }, { "children": [], "data": { "Name": "Child count fields", "Text": "Fixed an error when adding child count fields to the output format." }, "format": "BULLETS", "uid": "9c08f3a1e80311e884dca44cc8e97404" }, { "children": [], "data": { "Name": "Config file error handling", "Text": "Improved error handling after failing to read or write config files." }, "format": "BULLETS", "uid": "9c08f3a2e80311e88128a44cc8e97404" }, { "children": [], "data": { "Name": "\u0426\u0432\u0435\u0442\u0430", "Name_src": "Colors", "Text": "\u0426\u0432\u0435\u0442\u0430 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > Customize Colors [\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0446\u0432\u0435\u0442\u0430]\u00bb. \u041f\u043e\u043c\u0438\u043c\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u0435\u043c\u043d\u0430\u044f \u0442\u0435\u043c\u0430 \u0438\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0446\u0432\u0435\u0442\u0430.", "Text_src": "The default GUI colors can be changed using the \"Tools > Customize Colors\" dialog. A dark theme is available, or individual colors can be selected." }, "format": "HEAD_PARA", "uid": "9ff09734dc9011ea887bac675dac20af" }, { "children": [], "data": { "Name": "Complex undo operations", "Text": "Fixed some problems with using the Undo command after complex operations." }, "format": "BULLETS", "uid": "a757f64ac24211e8a95fd66a6ab671cb" }, { "children": [], "data": { "Name": "Save state for discarded files", "Text": "The expanded/collapsed and selected tree states are now saved even if changes were discarded in the previous session." }, "format": "BULLETS", "uid": "a7d7f61e786911e89bbca44cc8e97404" }, { "children": [], "data": { "Name": "Pull-downs on repeated dialog boxes", "Text": "Fixed issues on Windows with pull-down combo boxes not working after repeatedly showing some dialogs (mostly find and filter dialogs)." }, "format": "BULLETS", "uid": "a7fa190c334911e88d18d66a6ab671cb" }, { "children": [], "data": { "Name": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0422\u0438\u043f\u0430 \u0414\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0423\u0437\u043b\u0430", "Name_src": "Child Type Limits", "Text": "\u041f\u043e\u043c\u0438\u043c\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0442\u0438\u043f\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0443\u0437\u043b\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043c\u043e\u0436\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u044b \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432. \u041d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u0430\u00bb \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u043a\u0430\u0437\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a, \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432 \u0441\u043f\u0438\u0441\u043a\u0430\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0442\u0438\u043f \u0443\u0437\u043b\u0430\u00bb \u043d\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u043c \u0443\u0437\u043b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0442\u0438\u043f\u044b.", "Text_src": "In addition to setting the default child type, the child node types that are available to be set can be limited. There is a pull-down list of child type limits in the \"Type Config\" tab of the configuration dialog if the advanced functions are shown. Only checked types will show up in the type lists when using the \"Data > Set Node Type\" command on a child node." }, "format": "HEAD_PARA", "uid": "aa6f6ca4bb0711e7bbf43417ebd53aeb" }, { "children": [ "90dbc4e4334b11e892d0d66a6ab671cb", "299ba9e4334a11e881a6d66a6ab671cb", "e46163b4334b11e88512d66a6ab671cb", "a7fa190c334911e88d18d66a6ab671cb", "f817e5b6334a11e89349d66a6ab671cb", "7716c96e334a11e896bfd66a6ab671cb", "46fc4054334b11e89299d66a6ab671cb", "9a8a1400334c11e89838d66a6ab671cb", "145bd91a334c11e896b1d66a6ab671cb", "edd50b80334c11e8b5f5d66a6ab671cb", "b7ec7052334a11e88325d66a6ab671cb" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "b16866da333f11e88adbd66a6ab671cb" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 [\u043f\u0443\u0442\u0438]", "Name_src": "Breadcrumb view", "Text": "\u0412 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438, \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u0441\u0432\u0435\u0440\u0445\u0443 [\u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043f\u0440\u0430\u0432\u0430] \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 [\u0438\u043d\u0430\u0447\u0435 \u0438\u043c\u0435\u043d\u0430] \u043f\u0440\u0435\u0434\u043a\u043e\u0432 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430; \u043f\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0449\u0435\u043b\u043a\u043d\u0443\u0442\u044c \u043c\u044b\u0448\u044c\u044e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0438\u0445 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435.", "Text_src": "An upper breadcrumb view shows titles of the selected node's ancestors; the titles can be clicked to select them in the tree." }, "format": "BULLETS", "uid": "b1b5d434b32911e780fd3417ebd53aeb" }, { "children": [], "data": { "Name": "Live tree HTML export", "Text": "A new HTML export uses Javascript and CSS to create a live tree view. Nodes in the tree can be expanded and collapsed, and a separate pane shows the output for all descendants of the selected node. One form of this export creates separate files that are linked to the existing TreeLine file. These files are intended for use on a web server (browser security usually prevents local access). Only the TreeLine file needs to be replaced to update the data (re-export is not required). The second form creates a single file (with embedded data) that can be accessed from a local web browser." }, "format": "BULLETS", "uid": "b1cd1f82334111e8b89ad66a6ab671cb" }, { "children": [], "data": { "Name": "Search and replace", "Text": "Added support for finding and replacing empty data fields using the search and replace command." }, "format": "BULLETS", "uid": "b398d8ee482211e989f27054d2175f18" }, { "children": [ "b5fe6aa030e111ebbc097054d2175f18" ], "data": { "Name": "November 27, 2020 - Release 3.1.4 (stable release)" }, "format": "HEADINGS", "uid": "b5fe698830e111ebbc097054d2175f18" }, { "children": [ "b5fe74c830e111ebbc097054d2175f18", "b5fe6f0030e111ebbc097054d2175f18", "b5fe737e30e111ebbc097054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "b5fe6aa030e111ebbc097054d2175f18" }, { "children": [], "data": { "Name": "Window closing error", "Text": "Avoid an error message when a window is closed with the focus on a dialog box." }, "format": "BULLETS", "uid": "b5fe6f0030e111ebbc097054d2175f18" }, { "children": [], "data": { "Name": "Math field root reference", "Text": "Fix a problem recalculating root references in field equations." }, "format": "BULLETS", "uid": "b5fe737e30e111ebbc097054d2175f18" }, { "children": [], "data": { "Name": "Python 3.9 compatible", "Text": "Fix an incompatibility with the new Python 3.9 version under Linux or running from source." }, "format": "BULLETS", "uid": "b5fe74c830e111ebbc097054d2175f18" }, { "children": [], "data": { "Name": "Font dialog bug", "Text": "Avoid problems with empty parameters in the font dialogs." }, "format": "BULLETS", "uid": "b6a4a6bddc8911ea8612ac675dac20af" }, { "children": [], "data": { "Name": "Output table spacing", "Text": "Fixed minor spacing issues for tables shown in output views and HTML exports." }, "format": "BULLETS", "uid": "b7ec7052334a11e88325d66a6ab671cb" }, { "children": [], "data": { "Name": "\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u041f\u043e\u043b\u044f", "Name_src": "Math Fields", "Text": "\u0411\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445, \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0438 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u043c. \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0422\u0438\u043f.", "Text_src": "For more complex output formatting, the math field can be used to combine other fields using various mathematical, relational and string operators. See the Math Type section for details." }, "format": "HEAD_PARA", "uid": "bbbf735ac24711e8b560d66a6ab671cb" }, { "children": [], "data": { "Name": "Cut last node", "Text": "Fix an error caused by attempting to use the Edit > Cut command when there is only one node." }, "format": "BULLETS", "uid": "bdc8628ec2bd11e889e57054d2175f18" }, { "children": [], "data": { "Name": "MacPorts reference", "Text": "References to a macOS port on MacPorts were added to the System Requirements and Installation documentation." }, "format": "BULLETS", "uid": "c1f8dca5dc9511ea8f76ac675dac20af" }, { "children": [], "data": { "Name": "Data editor hover", "Text": "By default, the edit boxes in the data edit view now activate when the mouse hovers over them. This eliminates the need to click to activate them. This feature can be disabled in general options if desired." }, "format": "BULLETS", "uid": "cd28e024bb0211e79c553417ebd53aeb" }, { "children": [], "data": { "Name": "Unlimited data editor height option", "Text": "Add a general option to extend the height of data editors with long text content. The default setting (limit the height to the window size) is unchanged. The new option uses the view scroll bars to access the full text length." }, "format": "BULLETS", "uid": "cef1d9fee5de11e998dea44cc8e97404" }, { "children": [], "data": { "Name": "Math field recalculation", "Text": "Perform a more complete recalculation of math fields after certain operations." }, "format": "BULLETS", "uid": "cf9c139fdc8e11ea8261ac675dac20af" }, { "children": [], "data": { "Name": "TreeLine 2 import / export", "Text": "Import and export filters are provided for older TreeLine version 2.x and 1.x files. The older files can be opened using the standard \"File > Open\" command." }, "format": "BULLETS", "uid": "d1d8e56eba4011e784ab3417ebd53aeb" }, { "children": [], "data": { "Name": "\u041f\u043e\u0440\u0442\u044b \u043d\u0430 MacOs", "Name_src": "MacPorts", "Text": "\u041f\u043e\u0440\u0442 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 MacPorts. ", "Text_src": "There is a third-party port available on MacPorts." }, "format": "BULLETS", "uid": "d8a76c1fdc9411eaab2dac675dac20af" }, { "children": [], "data": { "Name": "Enable add child", "Text": "Make the Add Child command available after filtering has ended." }, "format": "BULLETS", "uid": "d9119485dc8711ea92dcac675dac20af" }, { "children": [ "ff3f7c98481e11e989f27054d2175f18", "db25ce66481e11e989f27054d2175f18" ], "data": { "Name": "March 17, 2019 - Release 3.1.1 (stable release)" }, "format": "HEADINGS", "uid": "db25cd62481e11e989f27054d2175f18" }, { "children": [ "e3690592481f11e989f27054d2175f18", "84b24010482211e989f27054d2175f18", "db25cf60481e11e989f27054d2175f18", "95d970aa481f11e989f27054d2175f18", "25ab9320482011e989f27054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "db25ce66481e11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Math equation with copied type", "Text": "Fix problems defining a math field equation on a recently copied data type." }, "format": "BULLETS", "uid": "db25cf60481e11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Sort root nodes", "Text": "The Sort command now properly sorts multiple root nodes when sorting the entire tree." }, "format": "BULLETS", "uid": "dc700fb4c24211e8b88dd66a6ab671cb" }, { "children": [], "data": { "Name": "Customize colors", "Text": "Add a more flexible tool for customizing GUI colors." }, "format": "BULLETS", "uid": "dca5b84fdc8a11eab098ac675dac20af" }, { "children": [], "data": { "Name": "Multi-level CSV import / export", "Text": "New forms of CSV table text imports and exports can work with multiple levels of child nodes, preserving the tree structure. The first column of the table includes a level number that is incremented for child relationships." }, "format": "BULLETS", "uid": "dd22e382334111e894e6d66a6ab671cb" }, { "children": [], "data": { "Name": "Dark mode printing", "Text": "Fix printing problems when using the dark theme." }, "format": "BULLETS", "uid": "e3690592481f11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Error after empty filter", "Text": "Avoid problems showing the tree view after closing a filter command that found no matches." }, "format": "BULLETS", "uid": "e46163b4334b11e88512d66a6ab671cb" }, { "children": [], "data": { "Name": "Deletion errors", "Text": "Several errors occurring when deleting or removing nodes have been fixed. These include problems when the mouse is pre-highlighting descendant nodes and when nodes to be deleted are selected in a separate window." }, "format": "BULLETS", "uid": "e4fc680a786911e899d3a44cc8e97404" }, { "children": [], "data": { "Name": "Breadcrumb view", "Text": "A new breadcrumb view pane above the other panes shows a sequence of ancestor titles for a selected node. The ancestors can be clicked to select them. For cloned nodes, multiple lines provide links to each instance's ancestor sequence." }, "format": "BULLETS", "uid": "e6ad9f6eba4311e796bd3417ebd53aeb" }, { "children": [], "data": { "Name": "Windows binary", "Text": "The Windows binary is now built using updated libraries (Qt 5.11 and PyQt 5.11)." }, "format": "BULLETS", "uid": "e7776f4da14511e88aefa44cc8e97404" }, { "children": [], "data": { "Name": "Major rewrite", "Text": "This is the first stable release of a major TreeLine rewrite. It includes all of the new features shown below in the 2.1.x and 2.9.x development series." }, "format": "BULLETS", "uid": "e8e10d32a14311e8ab90a44cc8e97404" }, { "children": [ "e8e10d34a14311e899cca44cc8e97404", "e8e10d38a14311e8a0c3a44cc8e97404", "e8e10d37a14311e8b0b3a44cc8e97404" ], "data": { "Name": "August 19, 2018 - Release 3.0.0 (new stable release)" }, "format": "HEADINGS", "uid": "e8e10d33a14311e88e24a44cc8e97404" }, { "children": [ "e8e10d32a14311e8ab90a44cc8e97404", "e8e10d35a14311e8aca9a44cc8e97404", "e8e10d36a14311e8b832a44cc8e97404" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "e8e10d34a14311e899cca44cc8e97404" }, { "children": [], "data": { "Name": "Compatibility", "Text": "TreeLine files now use a JSON format in place of the old XML format. This provides more flexibility for structuring new features like cloned nodes and multiple root nodes. A new file extension (\".trln) helps to distinguish files with the new format. Import and export filters are provided for older TreeLine version 2.x and 1.x files. The older files can be opened using the standard \"File > Open\" command." }, "format": "BULLETS", "uid": "e8e10d35a14311e8aca9a44cc8e97404" }, { "children": [], "data": { "Name": "Translations", "Text": "A GUI translations is available in German. All other translations are out of date and have not been included. Volunteers are needed to update translations in several languages." }, "format": "BULLETS", "uid": "e8e10d36a14311e8b832a44cc8e97404" }, { "children": [ "e7776f4da14511e88aefa44cc8e97404" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "e8e10d37a14311e8b0b3a44cc8e97404" }, { "children": [ "e8e10d3ca14311e8b71da44cc8e97404" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "e8e10d38a14311e8a0c3a44cc8e97404" }, { "children": [], "data": { "Name": "Default font", "Text": "The default font for the application can now be set in Tools > Customize Fonts. This is useful for enlarging fonts on some systems with high screen resolutions. Options still exist to individually specify tree view, output view and editor fonts." }, "format": "BULLETS", "uid": "e8e10d3ca14311e8b71da44cc8e97404" }, { "children": [], "data": { "Name": "Add modified flag", "Text": "Add an asterisk after the file name in the title bar if a file has been modified." }, "format": "BULLETS", "uid": "ea0c9b24e79911e98abe7054d2175f18" }, { "children": [], "data": { "Name": "Category command disable", "Text": "Avoid problems running data category-based commands on selections without any child nodes." }, "format": "BULLETS", "uid": "edd50b80334c11e8b5f5d66a6ab671cb" }, { "children": [], "data": { "Name": "Initial field values", "Text": "Fixed errors occurring when field types are changed after initial default values have been set." }, "format": "BULLETS", "uid": "f011a5d8786911e8ace3a44cc8e97404" }, { "children": [], "data": { "Name": "\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b", "Name_src": "Cloned nodes", "Text": "\u0423\u0437\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u0443\u0442\u0435\u043c \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 [\u043f\u0443\u0442\u0435\u0439] \u0441\u0432\u0435\u0440\u0445\u0443 \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u0437\u043b\u044b, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u043d\u0430\u0436\u0430\u0442\u0438\u044f.", "Text_src": "Nodes that are duplicated by cloning show up as separate clickable paths in the upper breadcrumb view." }, "format": "BULLETS", "uid": "f08b97be792b11e88588a44cc8e97404" }, { "children": [ "f16f7f70a25a11e7b7c67054d2175f18", "f16f87b8a25a11e7b7c67054d2175f18", "f16fbef4a25a11e7b7c67054d2175f18", "f16fc7aaa25a11e7b7c67054d2175f18", "f16fd236a25a11e7b7c67054d2175f18", "f16fe6fea25a11e7b7c67054d2175f18", "f1703d8ea25a11e7b7c67054d2175f18", "f1713464a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f TreeLine", "Name_src": "TreeLine Documentation" }, "format": "HEADINGS", "uid": "f16f7d90a25a11e7b7c67054d2175f18" }, { "children": [ "f16f82aea25a11e7b7c67054d2175f18", "f16f8498a25a11e7b7c67054d2175f18", "f16f85b0a25a11e7b7c67054d2175f18", "f16f86aaa25a11e7b7c67054d2175f18", "6e4dd051678a11eb8f00001fd026534b" ], "data": { "Name": "\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435", "Name_src": "Introduction" }, "format": "HEADINGS", "uid": "f16f7f70a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0412\u0435\u0440\u0441\u0438\u044f", "Name_src": "Version", "Text": "\u0412 \u044d\u0442\u043e\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043b\u0438\u0437 TreeLine, \u0432\u0435\u0440\u0441\u0438\u0438 3.2.1. \u043e\u0442 27 \u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f 2025 \u0433., \u0430\u0432\u0442\u043e\u0440 \u0414\u0443\u0433 \u0411\u0435\u043b\u043b (Doug Bell).", "Text_src": "This document covers TreeLine, Version 3.2.0, a stable release, dated August 30, 2025 by Doug Bell." }, "format": "PARAGRAPH", "uid": "f16f82aea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043e\u0447\u0435\u043c\u0443 TreeLine?", "Name_src": "Why TreeLine?", "Text": "\u0423 \u0432\u0430\u0441 \u043c\u0430\u0441\u0441\u0430 \u0441\u0442\u0438\u043a\u0435\u0440\u043e\u0432 \u0441 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u043d\u0430 \u043d\u0438\u0445 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u043e\u0439 \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439, \u0440\u0430\u0437\u0431\u0440\u043e\u0441\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0432\u0441\u044e\u0434\u0443? \u0418\u043b\u0438 \u043a\u0443\u0447\u0438 \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u043a\u043d\u0438\u0433, \u0444\u0438\u043b\u044c\u043c\u043e\u0432, \u0441\u0441\u044b\u043b\u043e\u043a, \u0443\u0447\u0435\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u043e\u0432, \u043b\u0438\u0447\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432 \u0438\u043b\u0438 \u0434\u0435\u043b? \u041c\u043e\u0436\u0435\u0442\u0435 \u043b\u0438 \u0432\u044b \u043d\u0430\u0439\u0442\u0438 \u0438\u0445, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b? \u0427\u0442\u043e \u0436, \u043c\u043d\u0435 \u0447\u0430\u0441\u0442\u043e \u043d\u0435 \u0443\u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c. \u0418\u0442\u0430\u043a, \u044d\u0442\u043e \u043c\u043e\u0439 \u043e\u0442\u0432\u0435\u0442.", "Text_src": "Do you have lots of sticky notes lying around with various useful information jotted down? Or many lists of books, movies, links, website logins, personal contacts, or things to do? Can you find them when you need them? Well, I often couldn't. So here's my answer." }, "format": "PARAGRAPH", "uid": "f16f8498a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0432\u043c\u0435\u0441\u0442\u043e \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445", "Name_src": "Outliner vs. database", "Text": "TreeLine \u2014 \u044d\u0442\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 \u043d\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f. \u0414\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0440\u044f\u0434\u043e\u043a. \u0410 \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0439, \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0449\u0438\u0445 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0441\u0432\u043e\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430, \u0430 \u0432\u044b\u0432\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435, \u0440\u0430\u0441\u043f\u0435\u0447\u0430\u0442\u0430\u043d \u0438\u043b\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u0432 HTML \u0438\u043b\u0438 \u0442\u0435\u043a\u0441\u0442.", "Text_src": "TreeLine is both an outliner and a small database. It stores almost any kind of information. A tree structure makes it easy to keep things organized. And each node in the tree can contain several fields, forming a database. The output format for each node can be defined, and the output can be shown on the screen, printed, or exported to HTML or text." }, "format": "PARAGRAPH", "uid": "f16f85b0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f", "Name_src": "License", "Text": "\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044f \u043d\u0435 \u0438\u0437 \u0431\u0438\u0437\u043d\u0435\u0441\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f, \u044f \u0434\u0435\u043b\u0430\u044e \u044d\u0442\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0439 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440 \u043f\u043e\u043a\u0430 \u043e\u043d\u0430 \u043d\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 \u0447\u0430\u0441\u0442\u043d\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e. TreeLine \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u043c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435\u043c; \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0442\u044c \u0438 / \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438 \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u041e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u0438 GNU, \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u043e\u0439 Free Software Foundation; \u043b\u0438\u0431\u043e \u0412\u0435\u0440\u0441\u0438\u0438 2 \u044d\u0442\u043e\u0439 \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u0438, \u043b\u0438\u0431\u043e (\u043f\u043e \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u044b\u0431\u043e\u0440\u0443) \u043b\u044e\u0431\u0443\u044e \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0437\u0434\u043d\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u042d\u0442\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0434\u0435\u0436\u0434\u0435, \u0447\u0442\u043e \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430, \u043d\u043e \u0411\u0415\u0417 \u041a\u0410\u041a\u0418\u0425-\u041b\u0418\u0411\u041e \u0413\u0410\u0420\u0410\u041d\u0422\u0418\u0419. \u0417\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e\u0431\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044c \u043a \u0444\u0430\u0439\u043b\u0443 LICENSE, \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u043c \u043a \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435.", "Text_src": "Since I'm not in the software business, I'm making this program free for anyone to use, distribute and modify, as long as it stays non-proprietary. TreeLine 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. See the LICENSE file provided with this program for more information." }, "format": "PARAGRAPH", "uid": "f16f86aaa25a11e7b7c67054d2175f18" }, { "children": [ "f16f8aeca25a11e7b7c67054d2175f18", "f16f9654a25a11e7b7c67054d2175f18", "f16f9c44a25a11e7b7c67054d2175f18", "f16fa040a25a11e7b7c67054d2175f18", "f16fa31aa25a11e7b7c67054d2175f18", "f16fa806a25a11e7b7c67054d2175f18", "f16fadf6a25a11e7b7c67054d2175f18", "f16fb1dea25a11e7b7c67054d2175f18", "f16fb90ea25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438", "Name_src": "Features" }, "format": "HEADINGS", "uid": "f16f87b8a25a11e7b7c67054d2175f18" }, { "children": [ "f16f9050a25a11e7b7c67054d2175f18", "f16f921ca25a11e7b7c67054d2175f18", "f16f932aa25a11e7b7c67054d2175f18", "f16f9424a25a11e7b7c67054d2175f18", "f16f9550a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041e\u0431\u0449\u0438\u0435", "Name_src": "General" }, "format": "BULLET_HEADING", "uid": "f16f8aeca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0425\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438", "Name_src": "Store information", "Text": "\u0425\u0440\u0430\u043d\u0438\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u043e\u0439 \u0442\u0438\u043f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442, \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442, HTML, \u0447\u0438\u0441\u043b\u0430, \u0434\u0430\u0442\u044b, \u0432\u0440\u0435\u043c\u044f, \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, URL-\u0430\u0434\u0440\u0435\u0441\u0430 \u0438 \u0442.\u0434.", "Text_src": "Stores almost any type of information, including plain text, rich text, HTML, numbers, dates, times, booleans, URLs, etc." }, "format": "BULLETS", "uid": "f16f9050a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0414\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430", "Name_src": "Tree structure", "Text": "\u0414\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435.", "Text_src": "The tree structure helps keep things organized." }, "format": "BULLETS", "uid": "f16f921ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043e\u043b\u044f", "Name_src": "Fields", "Text": "\u041a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. ", "Text_src": "Each node can have several fields that form a mini-database." }, "format": "BULLETS", "uid": "f16f932aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f\u044b \u0443\u0437\u043b\u043e\u0432", "Name_src": "Node types", "Text": "\u0412 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f\u043e\u0432 \u0443\u0437\u043b\u043e\u0432 \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043d\u0430\u0431\u043e\u0440\u0430\u043c\u0438 \u043f\u043e\u043b\u0435\u0439.", "Text_src": "Several node types, with different sets of fields, can be included in one file." }, "format": "BULLETS", "uid": "f16f9424a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0424\u043e\u0440\u043c\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430", "Name_src": "Output format", "Text": "\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0443\u0437\u043b\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0444\u043e\u0440\u043c\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043f\u043e\u043b\u0435\u0439, \u0441\u0442\u0440\u043e\u043a \u0432\u044b\u0432\u043e\u0434\u0430, \u0438\u0445 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0437\u043d\u0430\u0447\u043a\u043e\u0432 \u0434\u043b\u044f \u0434\u0435\u0440\u0435\u0432\u0430.", "Text_src": "The node format, including fields, output lines, formatting and tree-view icon, can be defined for each node type." }, "format": "BULLETS", "uid": "f16f9550a25a11e7b7c67054d2175f18" }, { "children": [ "f16f9744a25a11e7b7c67054d2175f18", "f16f9834a25a11e7b7c67054d2175f18", "f16f992ea25a11e7b7c67054d2175f18", "f16f9a32a25a11e7b7c67054d2175f18", "f16f9b36a25a11e7b7c67054d2175f18", "b1b5d434b32911e780fd3417ebd53aeb" ], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u0438", "Name_src": "Views" }, "format": "BULLET_HEADING", "uid": "f16f9654a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u044c \u0434\u0435\u0440\u0435\u0432\u0430", "Name_src": "Tree view", "Text": "\u0412 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043b\u0435\u0432\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u0432, \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 [\u0443\u0437\u043b\u043e\u0432].", "Text_src": "The left-hand view shows an indented, expandable list of titles" }, "format": "BULLETS", "uid": "f16f9744a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u0438 \u0441\u043f\u0440\u0430\u0432\u0430", "Name_src": "Right-hand views", "Text": "\u0424\u043e\u0440\u043c\u0430 \u0441\u043f\u0440\u0430\u0432\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043e\u0434\u043d\u0443 \u0438\u0437 \u0442\u0440\u0435\u0445 \u043f\u0430\u043d\u0435\u043b\u0435\u0439 \u2014 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u044b\u0432\u043e\u0434\u0430, \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432 \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0443\u0437\u043b\u043e\u0432.", "Text_src": "The right-hand view can show one of three views - for showing output, editing node data and editing node titles." }, "format": "BULLETS", "uid": "f16f9834a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043e\u043a\u0430\u0437 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432", "Name_src": "Show parent and children", "Text": "\u041f\u0430\u043d\u0435\u043b\u044c \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0431\u044b\u0447\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0430 \u043d\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u043e\u043a\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u0438 \u0435\u0433\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432.", "Text_src": "The right-hand view is normally split to show data from the parent node and its children." }, "format": "BULLETS", "uid": "f16f992ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043e\u043a\u0430\u0437 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0430", "Name_src": "Show multiple selection", "Text": "\u0415\u0441\u043b\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0437\u043b\u043e\u0432, \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043f\u0440\u0430\u0432\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435\u0441\u044f \u0432 \u043d\u0438\u0445.", "Text_src": "If multiple nodes are selected, the right-hand view shows all of their data." }, "format": "BULLETS", "uid": "f16f9a32a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043e\u043a\u0430\u0437 \u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432", "Name_src": "Show descendant output", "Text": "\u041f\u0430\u043d\u0435\u043b\u044c \u0432\u044b\u0432\u043e\u0434\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0432\u044b\u0432\u043e\u0434\u0430 \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432-\u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432 \u0441 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u043e\u0439 \u0432 \u0432\u0438\u0434\u0435 \u043e\u0442\u0441\u0442\u0443\u043f\u043e\u0432.", "Text_src": "The output view can be set to show indented output from all descendant nodes." }, "format": "BULLETS", "uid": "f16f9b36a25a11e7b7c67054d2175f18" }, { "children": [ "f16f9d2aa25a11e7b7c67054d2175f18", "f16f9e2ea25a11e7b7c67054d2175f18", "f16f9f3ca25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0443\u0442\u0438", "Name_src": "Navigation" }, "format": "BULLET_HEADING", "uid": "f16f9c44a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u043e\u0438\u0441\u043a\u0430", "Name_src": "Find commands", "Text": "\u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043c\u0430\u043d\u0434 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u0430 \u043f\u043e\u0438\u0441\u043a \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c.", "Text_src": "Find commands can search node data for text matches or for more specific rules." }, "format": "BULLETS", "uid": "f16f9d2aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f", "Name_src": "Filtering", "Text": "\u041f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0432 \u043b\u0435\u0432\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0438\u0435 \u0441 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438 [\u0444\u0438\u043b\u044c\u0442\u0440\u0430] \u0443\u0437\u043b\u044b. ", "Text_src": "Filtering commands show only matching nodes in a flat left-hand view." }, "format": "BULLETS", "uid": "f16f9e2ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u043e\u0440\u0430", "Name_src": "Toggle selections", "Text": "\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0430 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0432\u044b\u0431\u043e\u0440, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u0447\u0430\u0441\u0442\u044f\u043c\u0438 \u0434\u0435\u0440\u0435\u0432\u0430.", "Text_src": "Previous and next selection commands toggle selections to quickly move between parts of the tree." }, "format": "BULLETS", "uid": "f16f9f3ca25a11e7b7c67054d2175f18" }, { "children": [ "f16fa130a25a11e7b7c67054d2175f18", "5c1d58ac792a11e8b78ca44cc8e97404", "f16fa220a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435", "Name_src": "Formatting" }, "format": "BULLET_HEADING", "uid": "f16fa040a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041e\u043a\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438", "Name_src": "Configuration dialog", "Text": "\u0412 \u043e\u043a\u043d\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043a\u043b\u0430\u0434\u043e\u043a \u0434\u043b\u044f \u043b\u0435\u0433\u043a\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432, \u043f\u043e\u043b\u0435\u0439 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432\u044b\u0432\u043e\u0434\u0430.", "Text_src": "The dialog for data type configuration has several tabs to easily set all type, field and output parameters." }, "format": "BULLETS", "uid": "f16fa130a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041a\u043e\u043f\u0438\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430", "Name_src": "Format copies", "Text": "\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 TreeLine.", "Text_src": "Formatting information can be copied from another TreeLine file." }, "format": "BULLETS", "uid": "f16fa220a25a11e7b7c67054d2175f18" }, { "children": [ "f16fa40aa25a11e7b7c67054d2175f18", "f16fa504a25a11e7b7c67054d2175f18", "f16fa5fea25a11e7b7c67054d2175f18", "f16fa70ca25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0424\u0430\u0439\u043b\u043e\u0432", "Name_src": "File Handling" }, "format": "BULLET_HEADING", "uid": "f16fa31aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041e\u0442\u043c\u0435\u043d\u0430/\u041f\u043e\u0432\u0442\u043e\u0440", "Name_src": "Undo/redo", "Text": "\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442\u043c\u0435\u043d\u044b \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.", "Text_src": "Undo and redo commands are available for all modifying operations." }, "format": "BULLETS", "uid": "f16fa40aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0424\u043e\u0440\u043c\u0430\u0442\u044b \u0444\u0430\u0439\u043b\u043e\u0432", "Name_src": "File formats", "Text": "\u0424\u0430\u0439\u043b\u044b TreeLine \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442 JSON \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u0436\u0430\u0442\u0438\u044f \u0438\u043b\u0438 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432.", "Text_src": "TreeLine files use a JSON format, with options for automatically compressing or encrypting the files." }, "format": "BULLETS", "uid": "f16fa504a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0428\u0430\u0431\u043b\u043e\u043d\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432", "Name_src": "Document templates", "Text": "\u0428\u0430\u0431\u043b\u043e\u043d\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.", "Text_src": "Document templates for new files are preformatted to cover basic needs." }, "format": "BULLETS", "uid": "f16fa5fea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0435\u0447\u0430\u0442\u044c", "Name_src": "Printing", "Text": "\u041e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0441\u043f\u0435\u0447\u0430\u0442\u0430\u043d\u044b, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0438 \u0438\u0437 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445/\u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432, \u0432\u0435\u0440\u0445\u043d\u0438\u0435 \u0438 \u043d\u0438\u0436\u043d\u0438\u0435 \u043a\u043e\u043b\u043e\u043d\u0442\u0438\u0442\u0443\u043b\u044b.", "Text_src": "The formatted output can be printed with parent/child lines, headers and footers." }, "format": "BULLETS", "uid": "f16fa70ca25a11e7b7c67054d2175f18" }, { "children": [ "f16fa8f6a25a11e7b7c67054d2175f18", "31304c06792b11e888cfa44cc8e97404", "f16fa9f0a25a11e7b7c67054d2175f18", "9bd80f34b32b11e7be613417ebd53aeb", "f16faaf4a25a11e7b7c67054d2175f18", "f16fabf8a25a11e7b7c67054d2175f18", "f16facf2a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u043e\u0432", "Name_src": "File Import and Export" }, "format": "BULLET_HEADING", "uid": "f16fa806a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 HTML", "Name_src": "HTML export", "Text": "\u0414\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b HTML, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0432 \u0432\u0438\u0434\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0441 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0430\u043d\u0435\u043b\u044f\u043c\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438.", "Text_src": "The data can be exported to single or multiple HTML files with optional navigation panes." }, "format": "BULLETS", "uid": "f16fa8f6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442/\u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0442\u0435\u043a\u0441\u0442\u0430", "Name_src": "Text import/export", "Text": "\u041c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442, \u0442\u0435\u043a\u0441\u0442, \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0442\u0430\u0431\u0443\u043b\u044f\u0446\u0438\u0439, \u0438 \u0444\u0430\u0439\u043b\u044b \u0442\u0430\u0431\u043b\u0438\u0446 \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f\u043c\u0438.", "Text_src": "Plain text, tab-indented text and delimited table files can be imported and exported." }, "format": "BULLETS", "uid": "f16fa9f0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442/\u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a", "Name_src": "Bookmark import/export", "Text": "\u041c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0444\u0430\u0439\u043b\u044b \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445 Mozilla \u0438 XBEL.", "Text_src": "Mozilla and XBEL format bookmark files can be imported and exported." }, "format": "BULLETS", "uid": "f16faaf4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442/\u044d\u043a\u0441\u043f\u043e\u0440\u0442 XML \u043e\u0431\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430", "Name_src": "Generic XML import/export", "Text": "\u041c\u043e\u0436\u043d\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b XML \u043e\u0431\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c TreeLine \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 XML.", "Text_src": "Generic XML files can be imported and exported, allowing TreeLine to function as a crude XML editor." }, "format": "BULLETS", "uid": "f16fabf8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442/\u044d\u043a\u0441\u043f\u043e\u0440\u0442 ODF", "Name_src": "ODF import/export", "Text": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0430 ODF \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432 \u0432\u0438\u0434\u0435 \u0438\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440.", "Text_src": "ODF text documents can be imported and exported as outlines." }, "format": "BULLETS", "uid": "f16facf2a25a11e7b7c67054d2175f18" }, { "children": [ "f16faee6a25a11e7b7c67054d2175f18", "f16fafe0a25a11e7b7c67054d2175f18", "f16fb0daa25a11e7b7c67054d2175f18", "f08b97be792b11e88588a44cc8e97404" ], "data": { "Name": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043e\u043a", "Name_src": "Linking" }, "format": "BULLET_HEADING", "uid": "f16fadf6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438", "Name_src": "Internal links", "Text": "\u041f\u043e \u0449\u0435\u043b\u0447\u043a\u0443 \u043d\u0430 \u043f\u043e\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043e\u043a [\u0432 \u0444\u043e\u0440\u043c\u0435 \u0432\u044b\u0432\u043e\u0434\u0430 Treeline \u0438 \u0444\u0430\u0439\u043b\u0430\u0445, \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u044b, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0435 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438] \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043d\u0438\u043c\u0438 \u0443\u0437\u043b\u044b.", "Text_src": "Internal link fields select a linked node when clicked." }, "format": "BULLETS", "uid": "f16faee6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438", "Name_src": "External links", "Text": "\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438 [\u0432 \u0444\u043e\u0440\u043c\u0435 \u0432\u044b\u0432\u043e\u0434\u0430 Treeline \u0438 \u0444\u0430\u0439\u043b\u0430\u0445, \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u044b, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0435 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438] \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f URL \u0432 web-\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445.", "Text_src": "External link fields can be used to open URLs in web browsers." }, "format": "BULLETS", "uid": "f16fafe0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438", "Name_src": "Embedded links", "Text": "\u041a\u0430\u043a \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435, \u0442\u0430\u043a \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f.", "Text_src": "Both internal and external links can be embedded into text fields." }, "format": "BULLETS", "uid": "f16fb0daa25a11e7b7c67054d2175f18" }, { "children": [ "f16fb2cea25a11e7b7c67054d2175f18", "f16fb3c8a25a11e7b7c67054d2175f18", "f16fb4eaa25a11e7b7c67054d2175f18", "f16fb5e4a25a11e7b7c67054d2175f18", "5f12f768b32c11e7a41a3417ebd53aeb", "f16fb6dea25a11e7b7c67054d2175f18", "f16fb7f6a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438", "Name_src": "Data Manipulation" }, "format": "BULLET_HEADING", "uid": "f16fb1dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430", "Name_src": "Sorting", "Text": "\u0423\u0437\u043b\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 \u0438\u043b\u0438 \u043f\u043e \u043f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u043f\u043e\u043b\u044f\u043c.", "Text_src": "Nodes can be sorted by title or by predefined key fields." }, "format": "BULLETS", "uid": "f16fb2cea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043e\u043b\u044f", "Name_src": "Math Fields", "Text": "\u041c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044e\u0442 \u0438\u0445 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0437\u043b\u0430\u0445.", "Text_src": "Math fields can be defined that automatically calculate their contents based on numerical values in other nodes." }, "format": "BULLETS", "uid": "f16fb3c8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u044f", "Name_src": "Numbering", "Text": "\u041c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u043f\u043e\u043b\u044f \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.", "Text_src": "Numbering fields can be defined and automatically updated." }, "format": "BULLETS", "uid": "f16fb4eaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0423\u0441\u043b\u043e\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b", "Name_src": "Conditional types", "Text": "\u0417\u043d\u0430\u0447\u043a\u0438 \u0443\u0437\u043b\u0430 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0435\u0433\u043e \u0432\u044b\u0432\u043e\u0434\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0445\u0441\u044f \u0432 \u043d\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445.", "Text_src": "A node's icon and output format can be changed conditionally based on its data." }, "format": "BULLETS", "uid": "f16fb5e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f", "Name_src": "Spell check", "Text": "\u0412 \u043f\u043e\u043b\u044f\u0445 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u043d\u0435\u0448\u043d\u044f\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u2014 \u0441\u043c. \u0420\u0430\u0437\u0434\u0435\u043b \u00ab\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u00bb).", "Text_src": "Text data can be spell checked (requires an external program - see the System Requirements section)." }, "format": "BULLETS", "uid": "f16fb6dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445", "Name_src": "Arranging data", "Text": "\u0414\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445.", "Text_src": "Data can be automatically re-arranged using categories from data fields." }, "format": "BULLETS", "uid": "f16fb7f6a25a11e7b7c67054d2175f18" }, { "children": [ "f16fba08a25a11e7b7c67054d2175f18", "f16fbb02a25a11e7b7c67054d2175f18", "f16fbc06a25a11e7b7c67054d2175f18", "f16fbd00a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430", "Name_src": "Customization" }, "format": "BULLET_HEADING", "uid": "f16fb90ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430", "Name_src": "Customization", "Text": "\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u0430\u043a \u043e\u0431\u0449\u0438\u0445, \u0442\u0430\u043a \u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432.", "Text_src": "There are many options for customizing both general and file-based attributes." }, "format": "BULLETS", "uid": "f16fba08a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0413\u043e\u0440\u044f\u0447\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 \u0438 \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432", "Name_src": "Shortcuts and toolbars", "Text": "\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u044b \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0439 \u043a\u043b\u0430\u0432\u0438\u0448 \u0438 \u043a\u043e\u043c\u0430\u043d\u0434 \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432.", "Text_src": "There are editors for keyboard shortcuts and toolbar commands." }, "format": "BULLETS", "uid": "f16fbb02a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0428\u0440\u0438\u0444\u0442\u044b", "Name_src": "Fonts", "Text": "\u0428\u0440\u0438\u0444\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435\u0441\u044f \u0432 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430\u0445 \u0438 \u0444\u043e\u0440\u043c\u0430\u0445 \u0432\u044b\u0432\u043e\u0434\u0430, \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b.", "Text_src": "Fonts used in the GUI, editors and output views can be customized." }, "format": "BULLETS", "uid": "f16fbc06a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u042f\u0437\u044b\u043a\u0438", "Name_src": "Languages", "Text": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e\u043c \u043a\u0438\u0442\u0430\u0439\u0441\u043a\u043e\u043c, \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c, \u043d\u0435\u043c\u0435\u0446\u043a\u043e\u043c, \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u0438 \u0438\u0441\u043f\u0430\u043d\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0430\u0445. \u041f\u0435\u0440\u0435\u0432\u043e\u0434 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u044f\u0437\u044b\u043a\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c.", "Text_src": "The user interface is available in simplified Chinese, English, German and Spanish. Translations into other languages are TBD." }, "format": "BULLETS", "uid": "f16fbd00a25a11e7b7c67054d2175f18" }, { "children": [ "f16fbfeea25a11e7b7c67054d2175f18", "f16fc4bca25a11e7b7c67054d2175f18", "460699ebdc9411ea89afac675dac20af" ], "data": { "Name": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f", "Name_src": "System Requirements" }, "format": "HEADINGS", "uid": "f16fbef4a25a11e7b7c67054d2175f18" }, { "children": [ "f16fc0d4a25a11e7b7c67054d2175f18", "f16fc1cea25a11e7b7c67054d2175f18", "f16fc2c8a25a11e7b7c67054d2175f18", "f16fc3c2a25a11e7b7c67054d2175f18" ], "data": { "Name": "Linux" }, "format": "BULLET_HEADING", "uid": "f16fbfeea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Python", "Name_src": "Python", "Text": "Python (\u0412\u0435\u0440\u0441\u0438\u0438 3.9 \u0438\u043b\u0438 \u0432\u044b\u0448\u0435)", "Text_src": "Python (Version 3.9 or higher)" }, "format": "BULLETS", "uid": "f16fc0d4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Qt", "Name_src": "Qt", "Text": "QT (\u0412\u0435\u0440\u0441\u0438\u0438 6.4 \u0438\u043b\u0438 \u0432\u044b\u0448\u0435)", "Text_src": "QT (Version 6.4 or higher)" }, "format": "BULLETS", "uid": "f16fc1cea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "PyQt", "Name_src": "PyQt", "Text": "PyQt (\u0412\u0435\u0440\u0441\u0438\u0438 6.4 \u0438\u043b\u0438 \u0432\u044b\u0448\u0435)", "Text_src": "PyQt (Version 6.4 or higher)" }, "format": "BULLETS", "uid": "f16fc2c8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f", "Name_src": "Spell check", "Text": "\u0415\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f aspell, ispell \u0438\u043b\u0438 hunspell.", "Text_src": "If spell checking is desired, either aspell, ispell or hunspell are required" }, "format": "BULLETS", "uid": "f16fc3c2a25a11e7b7c67054d2175f18" }, { "children": [ "f16fc5aca25a11e7b7c67054d2175f18", "f16fc6b0a25a11e7b7c67054d2175f18" ], "data": { "Name": "Windows", "Name_src": "Windows" }, "format": "BULLET_HEADING", "uid": "f16fc4bca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0414\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434", "Name_src": "Binary", "Text": "\u0414\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c Windows 10 \u0438\u043b\u0438 11.", "Text_src": "Should run on any computer running Windows 10 or 11." }, "format": "BULLETS", "uid": "f16fc5aca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f", "Name_src": "Spell check", "Text": "\u0415\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f aspell, ispell \u0438\u043b\u0438 hunspell.", "Text_src": "If spell checking is desired, an external program is required. Either aspell, ispell or hunspell must be installed." }, "format": "BULLETS", "uid": "f16fc6b0a25a11e7b7c67054d2175f18" }, { "children": [ "f16fc89aa25a11e7b7c67054d2175f18", "f16fcc96a25a11e7b7c67054d2175f18", "611e03ffdc9411ea930eac675dac20af" ], "data": { "Name": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430", "Name_src": "Installation" }, "format": "HEADINGS", "uid": "f16fc7aaa25a11e7b7c67054d2175f18" }, { "children": [ "f16fc98aa25a11e7b7c67054d2175f18", "f16fcaa2a25a11e7b7c67054d2175f18", "f16fcb9ca25a11e7b7c67054d2175f18" ], "data": { "Name": "Linux" }, "format": "HEADINGS", "uid": "f16fc89aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0411\u0430\u0437\u043e\u0432\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430", "Name_src": "Basic installation", "Text": "\u0418\u0437\u0432\u043b\u0435\u043a\u0438\u0442\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0438\u0437 tar-\u0444\u0430\u0439\u043b\u0430 treeline, \u0437\u0430\u0442\u0435\u043c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 TreeLine. \u0414\u043b\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f root: \"python install.py\".", "Text_src": "Extract the source files from the treeline tar file, then change to the TreeLine directory in a terminal. For a basic installation, simply execute the following command as root: \"python install.py\"." }, "format": "PARAGRAPH", "uid": "f16fc98aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Python 3", "Name_src": "Python 3", "Text": "\u0415\u0441\u043b\u0438 \u0432 \u0432\u0430\u0448\u0435\u043c \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Python 2.x, \u0432\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u00abpython3\u00bb \u043d\u0430 \u00abpython\u00bb \u0432 \u044d\u0442\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445.", "Text_src": "If your distribution defaults to Python 2.x, you may need to substitute \"python3\" for \"python\" in these commands." }, "format": "PARAGRAPH", "uid": "f16fcaa2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438", "Name_src": "Install options", "Text": "\u0427\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0441\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435: \u00abpython install.py -h\u00bb. \u0427\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c TreeLine \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e / usr / local), \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435: \u00abpython install.py -p / prefix / path\u00bb. \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435: \u00abpython install.py -x\u00bb.", "Text_src": "To see all install options, use: \"python install.py -h\". To install TreeLine with a different prefix (the default is /usr/local), use: \"python install.py -p /prefix/path\". To skip dependency checks, use: \"python install.py -x\"." }, "format": "PARAGRAPH", "uid": "f16fcb9ca25a11e7b7c67054d2175f18" }, { "children": [ "f16fcf3ea25a11e7b7c67054d2175f18", "f16fd042a25a11e7b7c67054d2175f18", "f16fd132a25a11e7b7c67054d2175f18" ], "data": { "Name": "Windows", "Name_src": "Windows" }, "format": "HEADINGS", "uid": "f16fcc96a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0414\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439", "Name_src": "All users", "Text": "\u0427\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u00abTreeLine-x.x.x-install-all.exe\u00bb. \u0422\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430.", "Text_src": "To install for all users, execute the \"TreeLine-x.x.x-install-all.exe\" file. Administrator permissions are required." }, "format": "PARAGRAPH", "uid": "f16fcf3ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0414\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", "Name_src": "Single user", "Text": "\u0427\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f (\u043f\u0440\u0430\u0432\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f) \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u00abTreeLine-x.x.x-install-user.exe\u00bb.", "Text_src": "To install for a single user (administrator rights are not required), execute the \"TreeLine-x.x.x-install-user.exe\" file." }, "format": "PARAGRAPH", "uid": "f16fd042a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043e\u0440\u0442\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430", "Name_src": "Portable install", "Text": "\u0414\u043b\u044f \u043f\u043e\u0440\u0442\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u00abTreeLine-x.x.x-install-user.exe\u00bb. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043d\u044f\u0442\u044c \u0444\u043b\u0430\u0436\u043e\u043a \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u0438 \u0444\u0430\u0439\u043b\u043e\u0432, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u044f\u0440\u043b\u044b\u043a\u043e\u0432 \u0438 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0442\u043e\u0440\u0430. \u041a\u043e\u0433\u0434\u0430 TreeLine \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0438 \u0432\u044b\u0434\u0430\u0441\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b.", "Text_src": "For a portable install, execute the \"TreeLine-x.x.x-install-user.exe\" file. The file association, shortcuts and uninstaller tasks should be unchecked. When TreeLine starts and prompts for the config file location, choose the program directory option." }, "format": "PARAGRAPH", "uid": "f16fd132a25a11e7b7c67054d2175f18" }, { "children": [ "f16fd326a25a11e7b7c67054d2175f18", "f16fdccca25a11e7b7c67054d2175f18", "f16fe0b4a25a11e7b7c67054d2175f18", "f16fe3fca25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041e\u0441\u043d\u043e\u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f", "Name_src": "Basic Usage" }, "format": "HEADINGS", "uid": "f16fd236a25a11e7b7c67054d2175f18" }, { "children": [ "f16fd682a25a11e7b7c67054d2175f18", "28f8844ab58711e79d173417ebd53aeb", "f16fd858a25a11e7b7c67054d2175f18", "f16fd9aca25a11e7b7c67054d2175f18", "f16fdabaa25a11e7b7c67054d2175f18", "f16fdbc8a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0424\u043e\u0440\u043c\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 (Views)", "Name_src": "Views" }, "format": "HEADINGS", "uid": "f16fd326a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u044c \u0414\u0435\u0440\u0435\u0432\u0430 (Tree View)", "Name_src": "Tree View", "Text": "\u0412 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043b\u0435\u0432\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0435\u0440\u0435\u0432\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0443\u0437\u043b\u043e\u0432. \u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0443\u0437\u043b\u044b \u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0441\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0438\u043b\u0438 \u0441\u043a\u0440\u044b\u0442\u0438\u044f \u0438\u0445 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 \u2014 \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u0441 \u043e\u0442\u0441\u0442\u0443\u043f\u0430\u043c\u0438. \u0429\u0435\u043b\u0447\u043e\u043a \u043f\u043e \u0443\u0436\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u0443\u0437\u043b\u0443 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a. \u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u044b\u0435 \u043c\u0435\u043d\u044e, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0449\u0435\u043b\u0447\u043a\u0443 \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438 \u043d\u0430 \u0443\u0437\u043b\u0430\u0445.", "Text_src": "The left-hand view shows a tree of node titles. Parent nodes can be opened and closed to display or hide their indented descendant nodes. Clicking on an already selected node allows the title to be edited. Right-click context menus are available for commonly used functions." }, "format": "HEAD_PARA", "uid": "f16fd682a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u0438 \u0421\u043f\u0440\u0430\u0432\u0430 (Right-hand Views)", "Name_src": "Right-hand Views", "Text": "\u041f\u0430\u043d\u0435\u043b\u044c \u0441\u043f\u0440\u0430\u0432\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u043a\u043b\u0430\u0434\u043a\u0438, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043e\u0434\u043d\u043e \u0438\u0437 \u0442\u0440\u0435\u0445 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0439 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0412\u044b\u0432\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb (\"Data Output\") \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442, \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb (\"Data Edit\") \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430, \u0430 \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432\u00bb \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0443\u0437\u043b\u043e\u0432, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0434\u0435\u0440\u0435\u0432\u0430.\n

    \n\u041a\u043e\u0433\u0434\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0432\u044b\u0431\u0440\u0430\u043d \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0443\u0437\u0435\u043b, \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043f\u0440\u0430\u0432\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c \u0443\u0437\u043b\u0435 \u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u0438 \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0445 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u043d\u0430 \u043d\u0438\u0436\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u0430\u043d\u0435\u043b\u0438. \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \"\u0412\u0438\u0434 > \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u041f\u0430\u043d\u0435\u043b\u044c \u0414\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0423\u0437\u043b\u0430\" (\"View > Show Child Pane\") \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432. \u0415\u0441\u043b\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043e\u0434\u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u044c \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c \u0443\u0437\u043b\u0435.\n

    \n\u041a\u043e\u0433\u0434\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0437\u043b\u043e\u0432 (\u043f\u0440\u0438 \u0443\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0438 \u043d\u0430\u0436\u0430\u0442\u043e\u0439 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 Shift \u0438\u043b\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 Ctrl), \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u0430\u0445. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c \u0443\u0437\u043b\u0435.\n

    \n\u0415\u0441\u043b\u0438 \u0443\u0437\u043b\u044b \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u044b (\u043f\u0440\u0438 \u0449\u0435\u043b\u0447\u043a\u0435 \u043c\u044b\u0448\u044c\u044e \u0432 \u043f\u0443\u0441\u0442\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043b\u0438 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u043c\u044b\u0448\u0438 \u0441 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c Ctrl \u0434\u043b\u044f \u043e\u0442\u043c\u0435\u043d\u044b \u0432\u044b\u0431\u043e\u0440\u0430 \u0443\u0437\u043b\u0430), \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043f\u0440\u0430\u0432\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u0443\u0437\u043b\u0435 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f (\u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c).", "Text_src": "The right pane is tabbed to show one of three different views of the data. The \"Data Output\" view shows the formatted text, the \"Data Edit\" view shows text edit boxes, and the \"Title List\" view shows an editable list of node titles.<br />
    <br />
    When a parent node is selected in the tree, the right view will default to showing information about the selected node in an upper pane and information about the selected node's children in a lower pane. The \"View &gt; Show Child Pane\" command will toggle the display of the child nodes. If the selected node has no children, the view will show a single pane with information about the selected node only.<br />
    <br />
    When multiple nodes are selected in the tree (by holding down the shift or Ctrl keys while clicking), the right view will not display any child node information. It will instead show information about every selected node.<br />
    <br />
    When no nodes are selected in the tree (by clicking on a blank area or Ctrl clicking to unselect), the right view will show information about the top-level (root) nodes." }, "format": "HEAD_PARA", "uid": "f16fd858a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u044c \u00ab\u0412\u044b\u0432\u043e\u0434 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb (Data Output View)", "Name_src": "Data Output View", "Text": "\u0412\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0412\u044b\u0432\u043e\u0434 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0442\u0435\u043a\u0441\u0442. \u0412 \u044d\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.\n

    \n\u041f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0412\u0438\u0434 > \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0412\u044b\u0432\u043e\u0434 \u041f\u043e\u0442\u043e\u043c\u043a\u043e\u0432\u00bb (\"View > Show Output Descendants\") \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u00ab\u0412\u044b\u0432\u043e\u0434 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb (Data Output View) \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u043e\u0442\u0441\u0442\u0443\u043f\u0430\u043c\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u043e\u0442\u043e\u043c\u043a\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430.", "Text_src": "The \"Data Output\" view shows formatted output text. It cannot be edited from this view.<br />
    <br />
    When the \"View &gt; Show Output Descendants\" command is toggled, the \"Data Output\" view will show an indented list with information about every descendant of a single selected node." }, "format": "HEAD_PARA", "uid": "f16fd9aca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u044c \u00ab\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb (Data Edit View)", "Name_src": "Data Edit View", "Text": "\u0412\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb (Data Edit) \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0443\u0437\u043b\u0435. \u0412 \u043d\u0435\u0439 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u0438\u043f\u044b \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 [\u0438\u043d\u0430\u0447\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f] \u0443\u0437\u043b\u043e\u0432. \u0422\u0438\u043f\u044b \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u043e\u0432 \u043f\u043e\u043b\u0435\u0439. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u043d\u0438\u0445 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u044f\u043c\u0438 \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0434\u0440\u0443\u0433\u0438\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430, \u0434\u0430\u0442\u044b, \u0441\u0441\u044b\u043b\u043e\u043a \u0438 \u0442.\u0434.) \u2014 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u043c\u0438 \u043c\u0435\u043d\u044e \u0438\u043b\u0438 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u044b\u043c\u0438 \u043e\u043a\u043d\u0430\u043c\u0438.", "Text_src": "The \"Data Edit\" view shows a text edit box for each data field within a node. It also shows the node types and the node titles. The types of edit boxes vary based on the field type. Some are just text editors, while others (such as choice fields, date fields, links, etc.) have pull-down menus or dialogs." }, "format": "HEAD_PARA", "uid": "f16fdabaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u044c \u00ab\u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432\u00bb (Title List View)", "Name_src": "Title List View", "Text": "\u0412\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0421\u043f\u0438\u0441\u043e\u043a \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432\u00bb (\"Title List\") \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 [\u0438\u043d\u0430\u0447\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439] \u0443\u0437\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c [\u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438] \u043a\u0430\u043a \u0432 \u043e\u0431\u044b\u0447\u043d\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435. \u0415\u0441\u043b\u0438 [\u043f\u0440\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438] \u0432\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u0442\u043e [\u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u043c \u0434\u0435\u0440\u0435\u0432\u0435 \u0432 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435] \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u0443\u0437\u0435\u043b \u0441 \u044d\u0442\u0438\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c. \u0415\u0441\u043b\u0438 [\u043f\u0440\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438] \u0441\u0442\u0440\u043e\u043a\u0430 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0443\u0437\u0435\u043b \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437 \u0434\u0435\u0440\u0435\u0432\u0430.", "Text_src": "The \"Title List\" view shows a list of node titles that can be modified using typical text editor methods. If a new line is typed, a new node is created with that title. If a line is deleted, the corresponding node is removed from the tree." }, "format": "HEAD_PARA", "uid": "f16fdbc8a25a11e7b7c67054d2175f18" }, { "children": [ "f16fddbca25a11e7b7c67054d2175f18", "f16fdeb6a25a11e7b7c67054d2175f18", "997af664b58811e7ac243417ebd53aeb", "f16fdfb0a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435", "Name_src": "Editing" }, "format": "HEADINGS", "uid": "f16fdccca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041c\u0435\u043d\u044e \u00ab\u0423\u0437\u0435\u043b\u00bb (Node Menu)", "Name_src": "Node Menu", "Text": "\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u043c\u0435\u043d\u044e \u00ab\u0423\u0437\u0435\u043b\u00bb (Node) \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044e \u043a \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u0443\u0437\u043b\u0430\u043c \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441 \u0434\u0435\u0440\u0435\u0432\u043e\u043c, \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u0441\u043b\u0435\u0432\u0430. \u0418\u043c\u0435\u044e\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0443\u0437\u043b\u043e\u0432, \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 [\u0438\u043d\u0430\u0447\u0435 \u0438\u043c\u0435\u043d] \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0443\u0437\u043b\u043e\u0432. \u0412 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b \n\u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0435\u0440\u0435\u0432\u0430, \u043f\u0443\u0442\u0435\u043c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0443\u0437\u043b\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0443\u0440\u043e\u0432\u043d\u044f\u043c\u0438 \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0438\u0445 \u0432\u0432\u0435\u0440\u0445 \u0438\u043b\u0438 \u0432\u043d\u0438\u0437. \u041c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u044e\u0442 \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432.", "Text_src": "The commands in the \"Node\" menu operate on the selected nodes in the left tree view. There are commands to add or insert nodes, rename node titles and delete nodes. There are also commands to rearrange the tree by changing indent levels or moving nodes up or down. For many of the commands, the descendants of the selected nodes are also affected." }, "format": "HEAD_PARA", "uid": "f16fddbca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041c\u0435\u043d\u044e \u00ab\u041f\u0440\u0430\u0432\u043a\u0430\u00bb (Edit Menu)", "Name_src": "Edit Menu", "Text": "\u041c\u0435\u043d\u044e \u00ab\u041f\u0440\u0430\u0432\u043a\u0430\u00bb \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442\u043c\u0435\u043d\u044b \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u041a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u044b\u0440\u0435\u0437\u0430\u043d\u0438\u044f, \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0441\u043f\u0440\u0430\u0432\u0430 (\u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u0430 \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0430) \u0438\u043b\u0438 \u043a \u0443\u0437\u043b\u0430\u043c \u0432 \u0434\u0435\u0440\u0435\u0432\u0435.", "Text_src": "The edit menu includes undo and redo commands that can fix problems. Cut, copy and paste commands can operate either on text in the right-hand view (if selected or active) or to tree nodes." }, "format": "HEAD_PARA", "uid": "f16fdeb6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0432\u044b\u0431\u043e\u0440 \u043a\u043e\u043c\u0430\u043d\u0434 (Shortcuts)", "Name_src": "Shortcuts", "Text": "\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0443\u044e\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0439 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b \u0438 \u043c\u044b\u0448\u0438, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0445\u0441\u044f \u043f\u0440\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0434\u0435\u0440\u0435\u0432\u0430. \u041f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u044c \u0438 \u043e\u0442\u043f\u0443\u0441\u0442\u0438\u0442\u044c (drag and drop) \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442 (\u0438\u043b\u0438 \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442, \u0435\u0441\u043b\u0438 \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043d\u043e\u043f\u043a\u0430 Ctrl) \u0443\u0437\u043b\u044b. \u0429\u0435\u043b\u0447\u043e\u043a \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u0443\u0437\u043b\u0443 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0435\u0442 \u0435\u0433\u043e. \u041d\u0430\u0436\u0430\u0442\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0443\u0434\u0430\u043b\u0438\u0442 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b. \u041f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u044d\u0442\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043c\u0435\u043d\u044e \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041e\u0431\u0449\u0438\u0435 \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b\u00bb (\"Tools > General Options\").", "Text_src": "There are several shortcuts for use in tree editing. Drag and drop will move (or copy if the Ctrl button is held) nodes. Clicking on a selected node will rename it. Pressing the delete key will remove the selected nodes. If desired, these shortcuts can be disabled in \"Tools &gt; General Options\"." }, "format": "HEAD_PARA", "uid": "f16fdfb0a25a11e7b7c67054d2175f18" }, { "children": [ "f16fe1cca25a11e7b7c67054d2175f18", "f16fe2c6a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0424\u0430\u0439\u043b\u044b", "Name_src": "Files" }, "format": "HEADINGS", "uid": "f16fe0b4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0428\u0430\u0431\u043b\u043e\u043d\u044b", "Name_src": "Templates", "Text": "\u041a\u043e\u0433\u0434\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0435 \u043e\u043a\u043d\u043e, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0449\u0435\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0443\u0437\u043b\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a. \u0412 \u0448\u0430\u0431\u043b\u043e\u043d \u0414\u043b\u0438\u043d\u043d\u044b\u0439 \u0422\u0435\u043a\u0441\u0442 (Long Text) \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u043b\u0435 \u0442\u0438\u043f\u0430 \u0414\u043b\u0438\u043d\u043d\u044b\u0439 \u0422\u0435\u043a\u0441\u0442, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0435 \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043c\u0430. \u0412 \u0434\u0440\u0443\u0433\u0438\u0445 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432, \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u043a\u043d\u0438\u0433 \u0438 \u0434\u0435\u043b.", "Text_src": "When starting a new file, a dialog box offers a choice of templates. The default has only a single text field for each node that contains the title. The Long Text template adds a second long text field for more output text. Other templates have various fields for contacts, book lists and to-do lists." }, "format": "HEAD_PARA", "uid": "f16fe1cca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0424\u0430\u0439\u043b\u044b \u041f\u0440\u0438\u043c\u0435\u0440\u043e\u0432", "Name_src": "Sample Files", "Text": "\u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0424\u0430\u0439\u043b > \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u041f\u0440\u0438\u043c\u0435\u0440\u00bb (\"File > Open Sample\") \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 TreeLine. \u0412 \u043d\u0438\u0445 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0447\u0435\u043c \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u043d\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0437\u0446\u044b \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430.", "Text_src": "Various TreeLine sample files can be opened by using the \"File &gt; Open Sample\" command. These have more detail and example content than the new file templates." }, "format": "HEAD_PARA", "uid": "f16fe2c6a25a11e7b7c67054d2175f18" }, { "children": [ "f16fe4eca25a11e7b7c67054d2175f18", "f16fe5f0a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0422\u0438\u043f\u044b \u0414\u0430\u043d\u043d\u044b\u0445", "Name_src": "Data Types" }, "format": "HEADINGS", "uid": "f16fe3fca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f\u044b \u0443\u0437\u043b\u043e\u0432", "Name_src": "Node Types", "Text": "\u0412 \u0444\u0430\u0439\u043b\u0430\u0445 TreeLine \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u0430. \u041a\u0430\u0436\u0434\u044b\u0439 \u0442\u0438\u043f \u0443\u0437\u043b\u0430 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0438\u043c\u0435\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0432\u044b\u0432\u043e\u0434\u0430. \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u0423\u0437\u043b\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0438\u043f \n\u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0442\u0438\u043f \u0443\u0437\u043b\u0430\u00bb (\"Data > Set Node Type\").", "Text_src": "Multiple node data types can be defined in a TreeLine file. Each can contain different data fields and have different output formats. See the template and sample files for examples. Nodes can be set to a specific type using the \"Data &gt; Set Node Type\" command." }, "format": "HEAD_PARA", "uid": "f16fe4eca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u043e\u0432", "Name_src": "Type Config", "Text": "\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0422\u0438\u043f\u044b \u0414\u0430\u043d\u043d\u044b\u0445\u00bb (\"Data > Configure Data Types\") \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u0430, \u043f\u043e\u043b\u0435\u0439 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u044b\u0432\u043e\u0434\u0430. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u043a \u0440\u0430\u0437\u0434\u0435\u043b\u0443 \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043f\u043e\u043b\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.", "Text_src": "The \"Data &gt; Configure Data Types\" command is used to modify node data types, fields and output formatting. Refer to the Detailed Usage section of the full documentation for details." }, "format": "HEAD_PARA", "uid": "f16fe5f0a25a11e7b7c67054d2175f18" }, { "children": [ "f16fe7e4a25a11e7b7c67054d2175f18", "f16fed0ca25a11e7b7c67054d2175f18", "f16ff2f2a25a11e7b7c67054d2175f18", "f1700936a25a11e7b7c67054d2175f18", "f1700f58a25a11e7b7c67054d2175f18", "f170146ca25a11e7b7c67054d2175f18", "f1701caaa25a11e7b7c67054d2175f18", "f170207ea25a11e7b7c67054d2175f18", "f170256aa25a11e7b7c67054d2175f18", "f1702c4aa25a11e7b7c67054d2175f18", "f170335ca25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u0445", "Name_src": "Detailed Usage" }, "format": "HEADINGS", "uid": "f16fe6fea25a11e7b7c67054d2175f18" }, { "children": [ "f16fe8dea25a11e7b7c67054d2175f18", "f16fe9e2a25a11e7b7c67054d2175f18", "f16feaf0a25a11e7b7c67054d2175f18", "f16fec08a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443 \u0438 \u041f\u043e\u0438\u0441\u043a", "Name_src": "Tree Navigation and Search" }, "format": "HEADINGS", "uid": "f16fe7e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0413\u043e\u0440\u044f\u0447\u0438\u0435 \u041a\u043b\u0430\u0432\u0438\u0448\u0438", "Name_src": "Keyboard Shortcuts", "Text": "\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u044e\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043e\u0431\u0445\u043e\u0434\u0430 \u0434\u0435\u0440\u0435\u0432\u0430. \u041a\u043b\u0430\u0432\u0438\u0448\u0438 \u0441\u043e \u0441\u0442\u0440\u0435\u043b\u043a\u0430\u043c\u0438 \u0432\u0432\u0435\u0440\u0445 \u0438 \u0432\u043d\u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u044e\u0442 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435. \u0421\u0442\u0440\u0435\u043b\u043a\u0438 \u0432\u043b\u0435\u0432\u043e \u0438 \u0432\u043f\u0440\u0430\u0432\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0443\u0437\u0435\u043b. \u041a\u043b\u0430\u0432\u0438\u0448\u0438 \u00abHome\u00bb, \u00abEnd\u00bb, \u00abPage Up\u00bb \u0438 \u00abPage Down\u00bb \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443.
    \n
    \n\u0415\u0449\u0435 \u043e\u0434\u0438\u043d \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443 \u2014 \u0432\u0432\u0435\u0441\u0442\u0438 \u043f\u0435\u0440\u0432\u0443\u044e \u0431\u0443\u043a\u0432\u0443 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0433\u043e \u0443\u0437\u043b\u0430. \u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u0431\u0443\u043a\u0432\u0443 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440.", "Text_src": "There are several keyboard commands that can be used for tree navigation. The up and down arrow keys move the selection. The left and right arrows open and close the current node. The \"Home\", \"End\", \"Page Up\" and \"Page Down\" keys can be used to move quickly through the tree.<br />
    <br />
    Another way to move through the tree is to type the first letter of a visible node title. Hitting the letter again highlights to the next possibility." }, "format": "HEAD_PARA", "uid": "f16fe8dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0412\u044b\u0431\u043e\u0440", "Name_src": "Selection", "Text": "\u041c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0437\u043b\u043e\u0432, \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044f \u043d\u0430\u0436\u0430\u0442\u043e\u0439 \u043a\u043b\u0430\u0432\u0438\u0448\u0443 CTRL \u0438\u043b\u0438 SHIFT \u043f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u0437\u043b\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u044b \u0438\u0437 \u0432\u044b\u0431\u043e\u0440\u0430 \u043f\u0440\u0438 \u0443\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0438 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 CTRL. \u041f\u0440\u0438 \u0443\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0438 SHIFT \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0431\u043e\u0440 \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c \u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438. \u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b\u0448\u0438 \u0438\u043b\u0438 \u043b\u044e\u0431\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0441 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b.\n

    \n\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0412\u0438\u0434 > \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0432\u044b\u0431\u043e\u0440\u00bb \u0438 \u00ab\u0412\u0438\u0434 > \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u044b\u0431\u043e\u0440\u00bb \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439 \u0432\u044b\u0431\u043e\u0440\u0430, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443.", "Text_src": "Multiple nodes can be selected by holding down the CTRL or the SHIFT key when changing the active node. Individual nodes are added or removed from the selection when the CTRL key is held. The selection of all nodes between the old and new active nodes are toggled when SHIFT is held. The active node can be changed by using the mouse or by using any of the keyboard navigation methods.<br />
    <br />
    The \"View &gt; Previous Selection\" and \"View &gt; Next Selection\" commands can be used to toggle through a history of selections, allowing faster navigation through the tree." }, "format": "HEAD_PARA", "uid": "f16fe9e2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043e\u0438\u0441\u043a", "Name_src": "Searching", "Text": "\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430\u00bb \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0432 \u0434\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435. \u0412 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0432\u043e \u0432\u0441\u0435\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u0430 \u0438\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u0445 \u0443\u0437\u043b\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0432\u044b\u0431\u043e\u0440\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0446\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430. \u041f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \u043e\u043f\u0446\u0438\u0438 \"\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430\" \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u043e\u0438\u0441\u043a \u0443\u0437\u043b\u043e\u0432, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043b\u043e\u0432\u0430, \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u0432 \u043b\u044e\u0431\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0443\u0437\u043b\u0430. \u041f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \"\u041f\u043e\u043b\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430\" \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0439\u0434\u0435\u043d\u044b \u0443\u0437\u043b\u044b \u0441 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0441\u043b\u043e\u0432\u0430\u043c\u0438 [\u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043b\u043e\u0432, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0441\u043b\u043e\u0432, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438\u0441\u043a\u043e\u043c\u043e\u0435 \u043f\u043e\u043b\u043d\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043b\u043e\u0432, \u043e\u0442\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c\u0438, \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043e\u0442 \u0431\u0443\u043a\u0432], \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0435\u0441\u044f \u0432 \u043b\u044e\u0431\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0443\u0437\u043b\u0430. \u0412\u044b\u0431\u043e\u0440 \"\u041f\u043e\u043b\u043d\u0430\u044f \u0444\u0440\u0430\u0437\u0430\" \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u043e\u0438\u0441\u043a\u0443 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0444\u0440\u0430\u0437\u0435 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u043b\u043e\u0432. \u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0432\u044b\u0431\u043e\u0440 \"\u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435\" \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u043e\u0438\u0441\u043a \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 Python.\n

    \n\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u0423\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a\u00bb \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u0430\u0445 \u0438 \u043f\u043e\u043b\u044f\u0445 \u0443\u0437\u043b\u043e\u0432. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043b\u044f \u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u043c\u0443 \u0438\u043b\u0438 \u043c\u0435\u043d\u044c\u0448\u0435\u043c\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e, \u0438\u043b\u0438 \u0447\u0430\u0441\u0442\u0438 \u0438\u0441\u043a\u043e\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f. \u0410 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b True / False \u0434\u0430\u044e\u0442 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439. \u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u043e\u043b\u0435\u0439. \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u043e\u0438\u0441\u043a\u0430, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u00ab\u0438\u00bb \u0438\u043b\u0438 \u00ab\u0438\u043b\u0438\u00bb. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u00ab\u0412\u0441\u0435 \u0442\u0438\u043f\u044b\u00bb \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u043f\u043e\u043b\u044f\u043c \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432, \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f\u043e\u0432 \u0443\u0437\u043b\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0432 \u043e\u0434\u0438\u043d \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u0423\u0441\u043b\u043e\u0432\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043b\u043e\u0436\u043d\u044b\u043c \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432 \u0443\u0437\u043b\u043e\u0432, \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0445 \u044d\u0442\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044f [\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u043e\u0438\u0441\u043a \u043f\u043e False \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e].\n

    \n\u0422\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c \u0443\u0437\u043b\u043e\u0432. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u043d \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \"ctrl + /\". [\u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0432\u0438\u0448 \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0432\u043d\u0438\u0437\u0443 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0430\u043a\u0442\u0438\u0432\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0438\u0441\u043a\u043e\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f]. \u0417\u0430\u0442\u0435\u043c \u043f\u043e \u043c\u0435\u0440\u0435 \u0432\u0432\u043e\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u0449\u0443\u0442\u0441\u044f \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438. \u041a\u043b\u0430\u0432\u0438\u0448\u0438 F3 \u0438 \"shift + F3\" \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e.", "Text_src": "The \"Tools &gt; Find Text\" command will search for text within the tree structure. The dialog box has options for searching all of the node data or only the node titles. There are also options for how to interpret the search text. Key words will match nodes with the search words found anywhere in the node. Key full words will only match complete words anywhere in the node. Full phrase will only match the complete phrase in the proper sequence. Finally, the regular expression option will search using Python regular expressions.<br />
    <br />
    The \"Tools &gt; Conditional Find\" command will search in particular node types and node fields. Various comparison operators can be selected to exactly match, to match a greater or lesser value, or part of the value. And the True/False operators give the same result regardless of the values. In general, the value is interpreted using the edit format for special field types. Multiple rules can be added, connected with logical \"and\" or \"or\" operators. The \"All Types\" option makes fields from every type are available, so that multiple node types to be part of the same search. The condition will be false for node types that do not contain that field name.<br />
    <br />
    There is also a quick, incremental search of node titles. By default, it's bound to ctrl+/. Then, matching titles are found as the search string is typed. The F3 and shift+F3 keys can be used to go to the next or previous matches, respectively." }, "format": "HEAD_PARA", "uid": "f16feaf0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f", "Name_src": "Filtering", "Text": "\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0434\u0432\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0443\u0437\u043b\u043e\u0432: \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u0438\u043b\u044c\u0442\u0440\u00bb \u0438 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u0423\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u0444\u0438\u043b\u044c\u0442\u0440\u00bb. \u041e\u043d\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u043e\u0438\u0441\u043a\u0430, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043e\u043d\u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0432\u0441\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0435 \u0443\u0437\u043b\u044b \u0432 \u043f\u043b\u043e\u0441\u043a\u043e\u043c \u0441\u043f\u0438\u0441\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u0434\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u0435\u0433\u043e \u043f\u0430\u043d\u0435\u043b\u0438. \u0412 \u044d\u0442\u043e\u0439 \u0444\u043e\u0440\u043c\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0443\u0437\u043b\u044b \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u00bb, \u0447\u0442\u043e\u0431\u044b \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0432\u0438\u0434\u0435 \u0434\u0435\u0440\u0435\u0432\u0430.
    \n
    \n\u041f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0433\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u044b\u0445 \u043e\u043a\u043d\u0430\u0445 \u0438 \u0441\u043d\u043e\u0432\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u043e\u0435 \u0432\u0440\u0435\u043c\u044f.", "Text_src": "There are two filtering commands, \"Tools &gt; Text Filter\" and \"Tools &gt; Conditional Filter\". They work like the corresponding search commands above, except that they show all of the matching nodes in a flat list that replaces the tree view. The nodes can be selected and edited from this view. Use the \"End Filter\" button to restore the full tree view.<br />
    <br />
    Searches for Conditional Find and Conditional Filter can be saved in the dialog boxes and loaded again at another time." }, "format": "HEAD_PARA", "uid": "f16fec08a25a11e7b7c67054d2175f18" }, { "children": [ "f16fedfca25a11e7b7c67054d2175f18", "f16feef6a25a11e7b7c67054d2175f18", "f16feffaa25a11e7b7c67054d2175f18", "f16ff0f4a25a11e7b7c67054d2175f18", "f16ff1e4a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0422\u0438\u043f\u043e\u0432 \u0423\u0437\u043b\u043e\u0432", "Name_src": "Defining Node Types" }, "format": "HEADINGS", "uid": "f16fed0ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0421\u043f\u0438\u0441\u043e\u043a \u0422\u0438\u043f\u043e\u0432", "Name_src": "Type List", "Text": "\u00ab\u0421\u043f\u0438\u0441\u043e\u043a \u0442\u0438\u043f\u043e\u0432\u00bb \u2014 \u044d\u0442\u043e \u043f\u0435\u0440\u0432\u0430\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0422\u0438\u043f\u044b \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u0421\u043f\u0438\u0441\u043e\u043a \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043e\u043a, \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u0441\u043f\u0440\u0430\u0432\u0430. \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0442\u0438\u043f\u044b, \u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0442\u0438\u043f\u044b \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c.", "Text_src": "The \"Type List\" is the first tab of the \"Data > Configure Types Dialog\". The list of data types can be modified by the buttons on the right. New types can be added, and existing types can be copied, renamed or deleted." }, "format": "HEAD_PARA", "uid": "f16fedfca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u0430", "Name_src": "Type Config", "Text": "\u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u0430\u00bb \u2014 \u044d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u043e\u0432 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044b\u0431\u043e\u0440 \u0442\u0438\u043f\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0443\u0437\u043b\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e, \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 \u0441 \u044d\u0442\u0438\u043c \u0442\u0438\u043f\u043e\u043c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f. \u0415\u0441\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u00ab[\u041d\u0435\u0442]\u00bb, \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0443\u0437\u043b\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u0438\u0431\u043e \u0442\u0438\u043f \u0441\u0435\u0441\u0442\u0440\u0438\u043d\u0441\u043a\u0438\u0445 \u0443\u0437\u043b\u043e\u0432, \u043b\u0438\u0431\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445. \n

    \n\u041a\u043d\u043e\u043f\u043a\u0430 \u00ab\u0421\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a\u00bb \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u041a\u043d\u043e\u043f\u043a\u0430 \u00ab\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u00bb \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0437\u043d\u0430\u0447\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043b\u044f \u0437\u043d\u0430\u0447\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u00ab\u041d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u00bb, \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u043d\u0430\u0447\u043e\u043a \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f. \u0427\u0442\u043e\u0431\u044b \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u043a\u0438 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435, \u0432 \u043e\u043a\u043d\u0435 \u00ab\u041e\u0431\u0449\u0438\u0435 \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b\u00bb \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u00ab\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u043a\u0438 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435\u00bb.\n

    \n\u0412 \u044d\u0442\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043e\u043f\u0446\u0438\u0438 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0443\u0441\u0442\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u043c\u0435\u0436\u0434\u0443 \u0443\u0437\u043b\u0430\u043c\u0438, \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u0435\u0433\u043e\u0432 HTML \u043f\u0440\u0438 \u0432\u044b\u0432\u043e\u0434\u0435 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0430\u0440\u043a\u0435\u0440\u043e\u0432 \u0438\u043b\u0438 \u0442\u0430\u0431\u043b\u0438\u0446.", "Text_src": "\"Type Config\" is the second tab of the Configure Types Dialog. It contains a selection for the default child type. If set, this will be the initial type used for new children with this type of parent. If set to \"[None]\", children will default to either the type of their siblings or their parent.
    \n
    \nThe \"Change Icon\" button allows the selection of a custom tree icon for this data type. The \"Clear Select\" button on the icon dialog can be used to set the icon to \"None\", so that no icon will be displayed for this type. To avoid showing any tree icons, the \"Show icons in the tree view\" general option can be unset.
    \n
    \nThere are also options here for adding blanks lines between nodes, allowing HTML tags in the common format text, and changing the output to add bullets or tables." }, "format": "HEAD_PARA", "uid": "f16feef6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u0435\u0439", "Name_src": "Field List", "Text": "\u00ab\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u0435\u0439\u00bb \u2014 \u044d\u0442\u043e \u0442\u0440\u0435\u0442\u044c\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u043e\u0432 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u0421\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u0435\u0439 \u0432 \u0442\u0438\u043f\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043e\u043a \u0441\u043f\u0440\u0430\u0432\u0430. \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f, \u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c. \u0422\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0435 \u0443\u0437\u043b\u043e\u0432, \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043a\u043b\u044e\u0447\u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438.", "Text_src": "The \"Field List\" is the third tab of the Configure Types Dialog. The list of fields within a data type can be modified by using the buttons on the right. New fields can be added, and existing fields can be moved, renamed or deleted. Sort keys can also be defined to specify the fields that are compared when nodes are sorted." }, "format": "HEAD_PARA", "uid": "f16feffaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u041f\u043e\u043b\u044f", "Name_src": "Field Config", "Text": "\u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u041f\u043e\u043b\u044f\u00bb \u2014 \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u0430\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u043e\u0432 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0442\u0438\u043f \u043f\u043e\u043b\u044f \u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0435\u0433\u043e \u0432\u044b\u0432\u043e\u0434\u0430, \u0435\u0441\u043b\u0438 \u043e\u043d \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u043a \u043f\u043e\u043b\u044e. \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0438\u0439 \u0442\u0435\u043a\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c \u043f\u043e\u043b\u044f, \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0443\u0437\u043b\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0440\u043e\u043a \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435. \u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u0433\u043e\u0432 HTML \u0432 \u043f\u043e\u043b\u044f\u0445 \u0412\u044b\u0431\u043e\u0440, \u0410\u0432\u0442\u043e\u0412\u044b\u0431\u043e\u0440, \u041a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f, \u0410\u0432\u0442\u043e\u041a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u0438 \u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0433\u043e\u0432 HTML. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b (\u0443\u0433\u043b\u043e\u0432\u044b\u0435 \u0441\u043a\u043e\u0431\u043a\u0438 \u0438 \u043a\u0430\u0432\u044b\u0447\u043a\u0438), \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0438\u0441\u044c \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u043e\u043b\u044f.", "Text_src": "\"Field Config\" is the fourth tab of the Configure Types Dialog. The field type and its output format string can be set, if applicable to the field. Extra prefix and suffix text to be output with the field can also be set, and a default field value for new nodes can be entered. The number of lines displayed in the editor for the field can also be specified. Finally, an option to evaluate HTML tags can be set to recognize HTML tags in Choice, AutoChoice, Combination, AutoCombination and RegularExpression fields. If this is set, special characters (angled brackets and quotation marks) will need to be manually escaped to show up in the field text." }, "format": "HEAD_PARA", "uid": "f16ff0f4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0412\u044b\u0432\u043e\u0434", "Name_src": "Output", "Text": "\u00ab\u0412\u044b\u0432\u043e\u0434\u00bb \u2014 \u044d\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u043e\u0432 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u0412 \u043b\u0435\u0432\u043e\u0439 \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0435 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u044b [\u0438\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u0432 \u0443\u0437\u043b\u0435] \u043f\u043e\u043b\u044f. \u0412 \u043f\u0440\u0430\u0432\u043e\u0439 \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0430\u0442 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0443\u0437\u043b\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435) \u0438 \u0432\u044b\u0432\u043e\u0434\u0430 \u0443\u0437\u043b\u0430. \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c\u0438 \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 \u0441 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438. \u041f\u043e\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \"{* field_name *}\". \u041f\u043e\u043b\u044f, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 (\u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d \u0432\u044b\u0431\u043e\u0440 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u043f\u0440\u0438 \u0443\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0438 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 Ctrl \u0438\u043b\u0438 Shift \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441 \u0449\u0435\u043b\u0447\u043a\u043e\u043c \u043c\u044b\u0448\u0438), \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u043e\u043b\u0435 \u00ab\u0424\u043e\u0440\u043c\u0430\u0442 \u0412\u044b\u0432\u043e\u0434\u0430\u00bb \u0432 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043a\u0443\u0440\u0441\u043e\u0440\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043a\u0438 \u00ab>>\u00bb. \u0421\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043f\u043e\u043b\u0435 \u043f\u043e\u0434 \u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \"<<\".", "Text_src": "\"Output\" is the last tab of the Configure Types Dialog. The left half of the dialog shows the fields. The right half shows the formatting for the title (used for the node text in the tree view) and the node output. The formatting consists of text lines with embedded fields. The fields are shown as \"{*field_name*}\". The fields that are selected in the list (multiple fields can be selected by holding Ctrl or Shift keys while clicking) can be added to a format at the cursor position with the \">>\" keys. The field reference at the cursor can be removed with the \"<<\" keys." }, "format": "HEAD_PARA", "uid": "f16ff1e4a25a11e7b7c67054d2175f18" }, { "children": [ "f16ff3e2a25a11e7b7c67054d2175f18", "f16ff4dca25a11e7b7c67054d2175f18", "f16ff5f4a25a11e7b7c67054d2175f18", "f16ff7c0a25a11e7b7c67054d2175f18", "f16ff8f6a25a11e7b7c67054d2175f18", "f16ff9faa25a11e7b7c67054d2175f18", "f17005f8a25a11e7b7c67054d2175f18", "f1700710a25a11e7b7c67054d2175f18", "f16ffc02a25a11e7b7c67054d2175f18", "f16ffd06a25a11e7b7c67054d2175f18", "f16ffe14a25a11e7b7c67054d2175f18", "f16ffb08a25a11e7b7c67054d2175f18", "f16fff18a25a11e7b7c67054d2175f18", "f1700008a25a11e7b7c67054d2175f18", "f1700102a25a11e7b7c67054d2175f18", "f1700206a25a11e7b7c67054d2175f18", "f1700300a25a11e7b7c67054d2175f18", "f1700404a25a11e7b7c67054d2175f18", "f17004fea25a11e7b7c67054d2175f18", "f170081ea25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0422\u0438\u043f\u044b \u041f\u043e\u043b\u0435\u0439", "Name_src": "Field Types" }, "format": "HEADINGS", "uid": "f16ff2f2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u041f\u043e\u043b\u0435\u0439", "Name_src": "Field Options", "Text": "\u0422\u0438\u043f \u043f\u043e\u043b\u044f \u0438 \u0435\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e\u043b\u044f\u00bb \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u043e\u0432 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043d\u0438\u0436\u0435 \u0430\u0431\u0437\u0430\u0446\u0430\u0445 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u043e\u043b\u0435\u0439. \n
    \n
    \n\u0414\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u043e\u043b\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0435\u0435 \u0432\u044b\u0432\u043e\u0434\u0430. \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0445\u0441\u044f \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e\u00bb. \u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u043f\u043e\u043b\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0443, \u043f\u0440\u0438\u0432\u0435\u0434\u0443\u0442 \u043a \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044e \u0441\u0438\u043d\u0435\u0433\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u043b\u0435\u0432\u043e\u043c \u0443\u0433\u043b\u0443 \u043f\u043e\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043f\u0440\u0438 \u0432\u044b\u0432\u043e\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u043d\u0430 \u00ab#####\u00bb.", "Text_src": "The field type and options are set in the \"Field Config\" tab of the \"Data > Configure Types Dialog\". The many different field types are described in the paragraphs below.
    \n
    \nSeveral of the field types use a formatting string to define their output. For a list of available formatting characters, use the \"Format Help\" button. Entries in the data editor which do not match the format will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with \"#####\"." }, "format": "HEAD_PARA", "uid": "f16ff3e2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0422\u0435\u043a\u0441\u0442", "Name_src": "Text Type", "Text": "\u0422\u0438\u043f \u043f\u043e\u043b\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u2014 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435. \u041e\u043d\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c \u0442\u0438\u043f\u043e\u043c \u043f\u043e\u043b\u0435\u0439. \u042d\u0442\u0438 \u043f\u043e\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0444\u043e\u0440\u043c\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043f\u043e\u043b\u0435\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 \u043c\u0435\u043d\u044e \u00ab\u0424\u043e\u0440\u043c\u0430\u0442\u00bb (\u0430 \u0442\u0430\u043a\u0436\u0435 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u043c \u043c\u0435\u043d\u044e) \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0442\u0438\u043b\u0435\u0439 \u0448\u0440\u0438\u0444\u0442\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0438\u043b\u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043e\u043a. \u0412\u044b\u0441\u043e\u0442\u0430 \u043f\u043e\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u043e\u043a \u0442\u0435\u043a\u0441\u0442\u0430 [, \u043a\u043e\u0433\u0434\u0430 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u0432\u044b\u0441\u043e\u0442\u0443 \u043f\u043e\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f] \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043e\u043a\u043d\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0432\u044b\u0441\u043e\u0442\u0443 \u043f\u043e\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u044f\u0432\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e\u043b\u044f\u00bb.", "Text_src": "The default field type is a text field. It is the most commonly used field. These fields are edited using edit boxes in the data editor view. There are several commands in the Format menu (and also in the context menu) for setting the font style and adding external or internal links. The edit box height expands when re-displayed after adding several lines of text. The minimum edit box height can also be set explicitly in the \"Field Config\" tab." }, "format": "HEAD_PARA", "uid": "f16ff4dca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0422\u0435\u043a\u0441\u0442 \u0441 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u043e\u0439 HTML", "Name_src": "HTML Text Type", "Text": "\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 HTML-\u0442\u0435\u0433\u0438. \u0427\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c\u0438 \u0442\u0435\u0433\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \"<b> \u0436\u0438\u0440\u043d\u044b\u0439 </b>\", \"<u> \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u0435 </u>\", \"\u0440\u0430\u0437\u0440\u044b\u0432 \u0441\u0442\u0440\u043e\u043a\u0438 <br/>\", \"\u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043b\u0438\u043d\u0438\u044f <hr/>\" \u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0442\u0435\u0433\u0438 \u0448\u0440\u0438\u0444\u0442\u043e\u0432. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0431\u043b\u043e\u0447\u043d\u044b\u0445 \u0442\u0435\u0433\u043e\u0432. \u0412\u043e\u0437\u0432\u0440\u0430\u0442 \u043a\u0430\u0440\u0435\u0442\u043a\u0438 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0430 \u043d\u0435\u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u00ab<\u00bb, \u00ab>\u00bb \u0438 \"&\" \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f.", "Text_src": "This type allows simple HTML tags to be used in the text. Commonly used tags include \"<b>bold</b>\", \"<u>underline</u>\", \"line break<br/>\", \"horizontal line<hr/>\", and various font tags. Complex block tags should generally be avoided. Carriage returns are ignored, and non-escaped \"<\", \">\" and \"&\" symbols do not display. " }, "format": "HEAD_PARA", "uid": "f16ff5f4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041e\u0434\u043d\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0422\u0435\u043a\u0441\u0442", "Name_src": "One Line Text Type", "Text": "\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0434\u043b\u0438\u043d\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0439. \u0412 \u043d\u0435\u043c \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u043a\u0430\u0440\u0435\u0442\u043a\u0438 [\u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0441\u0442\u0440\u043e\u043a\u0438], \u043d\u043e \u043d\u0435 \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u043e\u0432 \u043e\u0434\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438.", "Text_src": "This type restricts the text length to a single line. It does not allow carriage returns but does not restrict line wrapping of a single long line." }, "format": "HEAD_PARA", "uid": "f16ff7c0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0435\u043a\u0441\u0442 \u0441 \u041c\u0435\u0436\u0434\u0443\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u043c\u0438 \u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430\u043c\u0438", "Name_src": "Spaced Text Type", "Text": "\u0423\u0437\u043b\u044b \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b. \u0414\u0440\u0443\u0433\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f. \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043f\u043e\u043b\u044f \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0448\u0440\u0438\u0444\u0442\u044b\u00bb, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0448\u0440\u0438\u0444\u0442 \u0441 \u043e\u0434\u0438\u043d\u0430\u0440\u043d\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u043c.", "Text_src": "This type holds plain text and preserves all spacing. Other formatting of the text is not permitted. It could be useful to use the \"Tools > Customize Fonts\" command to set the editor font to a mono-spaced font when using this field type." }, "format": "HEAD_PARA", "uid": "f16ff8f6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0427\u0438\u0441\u043b\u043e", "Name_src": "Number Type", "Text": "\u0412 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u043c \u0442\u0438\u043f\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432 \u043f\u043e\u043b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0447\u0438\u0441\u0435\u043b. \u0414\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0432\u044b\u0432\u043e\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u0438\u0437 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u00ab#\u00bb (\u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0446\u0438\u0444\u0440\u0430) \u0438 \u00ab0\u00bb (\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0446\u0438\u0444\u0440\u0430). \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0438\u0441\u043b\u043e \u043f\u0438, \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u00ab#. #\u00bb, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a \u00ab3.1\u00bb, \u0430 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u00ab00.00\u00bb \u043a\u0430\u043a \u00ab03.14\u00bb. \u041d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0446\u0438\u0444\u0440\u044b \u0441\u043b\u0435\u0432\u0430 \u043e\u0442 \u0434\u0435\u0441\u044f\u0442\u0438\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u043d\u0435 \u0443\u0441\u0435\u043a\u0430\u044e\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043d\u0435\u0432\u0435\u0440\u043d\u043e\u043c\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0443. \u041d\u043e \u0431\u0443\u0434\u044c\u0442\u0435 \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0435\u0441\u044f\u0442\u0438\u0447\u043d\u044b\u0445 \u0437\u043d\u0430\u043a\u043e\u0432 (\u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u043b\u0438 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445), \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u043e\u043a\u0440\u0443\u0433\u043b\u0435\u043d\u0438\u044f.\n
    \n
    \n\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0438\u043d\u0442\u0435\u0440\u043d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0441\u0438\u043c\u0432\u043e\u043b \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d \u043a\u0430\u043a \".\" \u0438\u043b\u0438 \",\". \u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f \u0442\u044b\u0441\u044f\u0447 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u00ab\\\u00bb \u0438\u043b\u0438 \u00ab\\.\u00bb. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043a\u0430\u043a \u00ab# \\, ### \\, ###. ##\u00bb \u0438\u043b\u0438 \u043a\u0430\u043a \u00ab# \\. ### \\. ###, ##\u00bb. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e\u00bb \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u043f\u043e\u043b\u044f.\n
    \n
    \n\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432, \u0432 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u043c \u0442\u0438\u043f\u0435 \u0444\u043e\u0440\u043c\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u0436\u0435 \u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043b\u044e\u0431\u0430\u044f \u043d\u043e\u0432\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0441 \u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e (\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0441\u0438\u043c\u0432\u043e\u043b \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u044f).", "Text_src": "In the number type, special characters in the format define the display of the numbers. The format uses a string of \"#\" (optional digit) and \"0\" (required digit) characters to define the output formatting. For example, pi formatted with \"#.#\" is \"3.1\" and formatted with \"00.00\" is \"03.14\". Regardless of the formatting, digits to the left of the decimal point are not truncated, since that would display an incorrect result. But use care to show enough decimal places (either optional or required) to avoid problems with round-off error.
    \n
    \nThe radix character can be specified as either \".\" or \",\" to handle internationalization. For use as a thousands separator, use \"\\,\" or \"\\.\". For example, a large number may be formatted as \"#\\,###\\,###.##\" or as \"#\\.###\\.###,##\". Press the \"Format Help\" button from the field format dialog for more formatting details.
    \n
    \nUnlike most other formats, the number type also uses the output format for display in the Data Editor. Of course, any new entry with a reasonable format is correctly interpreted (but the correct radix character must be used)." }, "format": "HEAD_PARA", "uid": "f16ff9faa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0422\u0438\u043f", "Name_src": "Boolean Type", "Text": "\u041f\u043e\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0434\u0432\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0432\u044b\u0431\u043e\u0440\u0430, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c \u0438\u0441\u0442\u0438\u043d\u0430 / \u043b\u043e\u0436\u044c. \u041c\u0435\u043d\u044e \u0441\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043f\u043e\u043b\u0435\u0439 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u00ab\u0434\u0430 / \u043d\u0435\u0442\u00bb, \u00ab\u0438\u0441\u0442\u0438\u043d\u0430 / \u043b\u043e\u0436\u044c\u00bb \u0438 \u00ab1/0\u00bb, \u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u0432\u0435\u0441\u0442\u0438 \u0441\u0432\u043e\u044e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043f\u0430\u0440\u0443 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u0432. \u041f\u043e\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043b\u0438\u0431\u043e \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435, \u043b\u0438\u0431\u043e \u0432 \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0430.", "Text_src": "This type gives two choices corresponding to true/false values. The format help menu includes typical values such as \"yes/no\", \"true/false\" and \"1/0\", but users can also enter their own word pair. The data editor boxes will accept either the currently set format or any of the typical values." }, "format": "HEAD_PARA", "uid": "f16ffb08a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0414\u0430\u0442\u0430", "Name_src": "Date Type", "Text": "\u0412 \u043f\u043e\u043b\u044f\u0445 \u0441 \u0442\u0438\u043f\u043e\u043c \u0434\u0430\u0442\u0430 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0432\u0441\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441 \"%\") \u0437\u0430\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u0430\u043a \u0438 \u0432 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u044f\u0445. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e\u00bb \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043f\u043e\u043b\u044f. \u041d\u0435\u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432\u044b\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c\u0438, \u043a\u0430\u043a \u043e\u043d\u0438 \u0435\u0441\u0442\u044c.\n
    \n
    \n\u0422\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b > \u0424\u043e\u0440\u043c\u0430\u0442\u044b \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb. \u042d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0439 \u0434\u0430\u0442\u044b \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u043d\u043e \u0432 \u0434\u0430\u0442\u0430\u0445 \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u043d\u044c\u2014\u043c\u0435\u0441\u044f\u0446\u2014\u0433\u043e\u0434. \u0422\u0430\u043a\u0436\u0435 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0444\u043e\u0440\u043c\u0430\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u043d\u0438 \u043d\u0435\u0434\u0435\u043b\u0438.\n
    \n
    \n\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u00ab\u0421\u0435\u0439\u0447\u0430\u0441\u00bb \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0434\u0430\u0442\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0437\u043b\u0430.", "Text_src": "In the date field type, special characters in the format (all starting with \"%\") are replaced by elements of the data, similar to number fields. Press the \"Format Help\" button from the field format dialog for formatting details. Non-special characters will be output as themselves.
    \n
    \nThere is also an edit format under \"Tools > General Options > Data Editor Formats\". This controls how date fields are displayed in the Data Editor view. Generally, entries in the data editor with various formats will be correctly interpreted regardless of this setting, but dates must use the correct day-month-year sequence. Also note that the date editor format does not support days of the week.
    \n
    \nA default initial field value of \"Now\" can be used to enter the date of node creation." }, "format": "HEAD_PARA", "uid": "f16ffc02a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0412\u0440\u0435\u043c\u044f", "Name_src": "Time Type", "Text": "\u0412 \u043f\u043e\u043b\u044f\u0445 \u0441 \u0442\u0438\u043f\u043e\u043c \u0432\u0440\u0435\u043c\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0432\u0441\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441 \"%\") \u0437\u0430\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u0430\u043a \u0438 \u0432 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u044f\u0445. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e\u00bb \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043f\u043e\u043b\u044f. \u041d\u0435\u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432\u044b\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c\u0438, \u043a\u0430\u043a \u043e\u043d\u0438 \u0435\u0441\u0442\u044c.\n
    \n
    \n\u0422\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b > \u0424\u043e\u0440\u043c\u0430\u0442\u044b \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb. \u042d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0439 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430.\n
    \n
    \n\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u00ab\u0421\u0435\u0439\u0447\u0430\u0441\u00bb \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0437\u043b\u0430.", "Text_src": "In the time field type, special characters in the format (all starting with \"%\") are replaced by elements of the data, similar to number fields. Press the \"Format Help\" button from the field format dialog for formatting details. Non-special characters will be output as themselves.
    \n
    \nThere is also an edit format under \"Tools > General Options > Data Editor Formats\". This controls how time fields are displayed in the Data Editor view. Generally, entries in the data editor with various formats will be correctly interpreted regardless of this setting.
    \n
    \nA default initial field value of \"Now\" can be used to enter the time of node creation." }, "format": "HEAD_PARA", "uid": "f16ffd06a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0414\u0430\u0442\u0430 \u0438 \u0412\u0440\u0435\u043c\u044f", "Name_src": "DateTime Type", "Text": "\u041f\u043e\u043b\u044f \u00ab\u0414\u0430\u0442\u0430 \u0438 \u0412\u0440\u0435\u043c\u044f\u00bb \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442 \u0434\u0430\u0442\u0443 \u0438 \u0432\u0440\u0435\u043c\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u043e\u043b\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u0434\u043b\u044f \u043e\u0442\u043c\u0435\u0442\u043e\u043a \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0432\u0441\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0441 \"%\") \u0437\u0430\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u0430\u043a \u0432 \u043f\u043e\u043b\u044f\u0445 \u0434\u0430\u0442\u044b \u0438 \u043f\u043e\u043b\u044f\u0445 \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e\u00bb \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043f\u043e\u043b\u044f. \u041d\u0435\u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432\u044b\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0442\u0430\u043a\u0438\u043c\u0438, \u043a\u0430\u043a \u043e\u043d\u0438 \u0435\u0441\u0442\u044c.\n
    \n
    \n\u041f\u0440\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u043e\u043b\u0435\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0442\u0438\u043f\u043e\u043c \u00ab\u0414\u0430\u0442\u0430 \u0438 \u0412\u0440\u0435\u043c\u044f\u00bb \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0434\u0430\u0442\u044b \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b > \u0424\u043e\u0440\u043c\u0430\u0442\u044b \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb. \u0417\u0430\u043f\u0438\u0441\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0434\u0430\u0442\u044b \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u043e\u043b\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u043c.\n
    \n
    \n\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u00ab\u0421\u0435\u0439\u0447\u0430\u0441\u00bb \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0434\u0430\u0442\u044b \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0437\u043b\u0430.", "Text_src": "The DateTime field combines dates and times into a single field that is useful for timestamps. Special characters in the format (all starting with \"%\") are replaced by elements of the data, as in date and time fields. Press the \"Format Help\" button from the field format dialog for formatting details. Non-special characters will be output as themselves.
    \n
    \nThe DateTime edit format is uses the date and time formats located in \"Tools > General Options > Data Editor Formats\". The date and time formats are combined, separated by a space character.
    \n
    \nA default initial field value of \"Now\" can be used to enter the date and time of node creation." }, "format": "HEAD_PARA", "uid": "f16ffe14a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0412\u044b\u0431\u043e\u0440", "Name_src": "Choice Type", "Text": "\u041f\u043e\u043b\u044f \u0441 \u0442\u0438\u043f\u043e\u043c \u0432\u044b\u0431\u043e\u0440 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u0437 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u043e\u043a\u043d\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430. \u0412 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u044e\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c \u00ab/\u00bb (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u00ab//\u00bb, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0438\u043c\u0432\u043e\u043b \u00ab/\u00bb \u0432 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0435). \u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0432\u044b\u0431\u043e\u0440\u0443, \u0432\u044b\u0437\u043e\u0432\u0443\u0442 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0438\u043d\u0435\u0433\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u043b\u0435\u0432\u043e\u043c \u0443\u0433\u043b\u0443 \u043f\u043e\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0430 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u043d\u0430 \u00ab#####\u00bb.", "Text_src": "The choice field type allows for the selection of text items from a pull-down edit list. The formatting strings for these types list the items separated with the \"/\" character (use \"//\" to get a literal \"/\" in an item). Entries in the data editor which do not match the choices will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with \"#####\"." }, "format": "HEAD_PARA", "uid": "f16fff18a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0410\u0432\u0442\u043e\u0412\u044b\u0431\u043e\u0440", "Name_src": "Auto Choice Type", "Text": "\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u043f\u043e\u043b\u044f \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u0435\u043d \u0442\u0438\u043f\u0443 \u0432\u044b\u0431\u043e\u0440\u0430, \u043d\u043e \u0431\u0435\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0430. \u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u043c\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0432\u0441\u0435\u0445 \u0440\u0430\u043d\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0412\u0441\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u043c\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0435 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.", "Text_src": "This field type is similar to the choice type, but without a format string. The entries in the pull-down menu are automatically generated from all previously used entries. Any entries that are typed will be available in the pull-down menu for future use. " }, "format": "HEAD_PARA", "uid": "f1700008a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u041a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f", "Name_src": "Combination Type", "Text": "\u041f\u043e \u0441\u0443\u0442\u0438, \u044d\u0442\u043e \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442 \u0442\u0438\u043f\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c [\u0438\u043d\u0430\u0447\u0435 \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0438\u0437 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432]. \u0417\u0430\u043f\u0438\u0441\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c \u00ab/\u00bb. \u0412 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u043c\u0441\u044f \u043c\u0435\u043d\u044e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0444\u043b\u0430\u0436\u043a\u0438 [\u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f] \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0443\u0437\u043b\u043e\u0432. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u044b\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043f\u044f\u0442\u0443\u044e \u0438 \u043f\u0440\u043e\u0431\u0435\u043b. \u042d\u0442\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u0430\u00bb \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0422\u0438\u043f\u044b \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435\u00bb, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f [\u0420\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0422\u0438\u043f\u0430 \u041a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f && \u0421\u043f\u0438\u0441\u043a\u043e\u0432 \u0414\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0423\u0437\u043b\u043e\u0432].", "Text_src": "This is basically the equivalent of the choice type with multiple selection. The formatting string entries are separated by the \"/\" character. The pull-down menu shows check-boxes that are checked for currently selected nodes. By default, the selected entries are output separated by a comma and a space. This can be changed in the \"Type Config\" tab of the \"Data > Configure Types Dialog\". Click the \"Show Advanced\" button to see the separator setting." }, "format": "HEAD_PARA", "uid": "f1700102a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0410\u0432\u0442\u043e\u041a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f", "Name_src": "Auto Combination Type", "Text": "\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u043f\u043e\u043b\u044f \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u0435\u043d \u0442\u0438\u043f\u0443 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f, \u043d\u043e \u0431\u0435\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0430. \u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u043c\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0432\u0441\u0435\u0445 \u0440\u0430\u043d\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0412\u0441\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u043c\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0435 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.", "Text_src": "This field type is similar to the combination type, but without a format string. The entries in the pull-down menu are automatically generated from all previously used entries. Any entries that are typed will be available in the pull-down menu for future use. " }, "format": "HEAD_PARA", "uid": "f1700206a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0412\u043d\u0435\u0448\u043d\u044f\u044f \u0413\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0430", "Name_src": "External Link Type", "Text": "\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b \u0441\u0441\u044b\u043b\u043e\u043a, \u0432\u043a\u043b\u044e\u0447\u0430\u044f http \u0438 https \u0434\u043b\u044f \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446, mailto \u0434\u043b\u044f \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0438 file \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432. \u0412\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0435 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0435 \u043e\u043a\u043d\u043e \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u0438\u043f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u0432\u0435\u0441\u0442\u0438 \u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438. \u0412 \u043f\u043e\u043b\u044f\u0445 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0432 [\u0441\u043a\u043e\u0431\u043a\u0430\u0445] \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438 \u0432 \u043e\u043a\u043d\u0435 \u0432\u044b\u0432\u043e\u0434\u0430. \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u00abfile\u00bb \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u043f\u0443\u0442\u0438 \u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043f\u0443\u0442\u0438.\n
    \n
    \n\u0415\u0441\u043b\u0438 \u0449\u0435\u043b\u043a\u043d\u0443\u0442\u044c \u043d\u0430 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0443 \u0432 \u043e\u043a\u043d\u0435 \u0432\u044b\u0432\u043e\u0434\u0430 \u0438\u043b\u0438 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u00ab\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0443\u00bb \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438 \u0432 \u043f\u043e\u043b\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u0430 \u0432 \u0432\u0435\u0431-\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 [\u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0444\u0430\u0439\u043b \u0432 Windows \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0441 \u0444\u0430\u0439\u043b\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c]. \u0412 Linux \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u044b \u00abBROWSER\u00bb \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u0438\u043f\u0430 \u00abmozilla% s\u00bb \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430.", "Text_src": "This type can support various link protocols, including http and https for web pages, mailto for email addresses and file for local files. A pull down dialog in the data editor allows the selection of the protocol type and the entry of an address and a display name. In the edit boxes, the display name shows up in [brackets], and it is used as the text of the link in the output view. The \"file\" protocol also provides a button to browse for a path and buttons to choose either absolute or relative path names.
    \n
    \nClicking on the link in the output view or choosing \"Open Link\" from the right-click context menu in the edit box will open the link in a web browser. In Linux, setting the \"BROWSER\" environment variable to a string like \"mozilla %s\" will result in the desired browser being used." }, "format": "HEAD_PARA", "uid": "f1700300a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0413\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0430", "Name_src": "Internal Link Type", "Text": "\u042d\u0442\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u044f\u0440\u043b\u044b\u043a\u0438 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 [\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043a] \u0443\u0437\u043b\u043e\u0432 \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0434\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b. \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443, \u0449\u0435\u043b\u043a\u043d\u0438\u0442\u0435 \u0441\u0442\u0440\u0435\u043b\u043a\u0443 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0443\u0437\u0435\u043b \u0432 \u0434\u0435\u0440\u0435\u0432\u0435. \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043e \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u0445 \u0441\u043a\u043e\u0431\u043a\u0430\u0445. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0438\u043c\u0435\u043d\u0438 \u044f\u0440\u043b\u044b\u043a\u0430 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0446\u0435\u043b\u0435\u0432\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438, \u043d\u043e \u043e\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e. \u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435 \u043c\u0435\u043d\u044e, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438\u043b\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u0446\u0435\u043b\u0435\u0432\u043e\u0433\u043e \u0443\u0437\u043b\u0430. \n
    \n
    \n\u0429\u0435\u043b\u0447\u043e\u043a \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0432 \u043e\u043a\u043d\u0435 \u0432\u044b\u0432\u043e\u0434\u0430 \u0432\u044b\u0431\u0435\u0440\u0435\u0442 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0443\u0437\u0435\u043b \u0432 \u0434\u0435\u0440\u0435\u0432\u0435.", "Text_src": "These links create shortcuts to select nodes elsewhere in the tree structure. To create a link, click the pull-down arrow and then select the target node in the tree view. The display name is shown in brackets. It is initially set to the target node title, but it can be edited. The right-click context menu can be used to clear the link or to select the target node.
    \n
    \nClicking the link in the output view will select the target node in the tree view." }, "format": "HEAD_PARA", "uid": "f1700404a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", "Name_src": "Picture Type", "Text": "\u042d\u0442\u0438 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0438 \u0441\u043b\u0443\u0436\u0430\u0442 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u043e\u043a\u043d\u043e \u0432\u044b\u0432\u043e\u0434\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442. \u0412 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u043c\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043a\u043d\u043e\u043f\u043a\u0430 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c [\u0441 \u0443\u0437\u043b\u043e\u043c]. \u0412 \u043e\u043a\u043d\u0435 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u044b\u0435 \u0438\u043b\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.", "Text_src": "These links add referenced pictures to the output view. A pull down dialog in the data editor has a button to browse for picture files to be linked. It also allows absolute or relative paths to be used and has a small image preview." }, "format": "HEAD_PARA", "uid": "f17004fea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0422\u0438\u043f", "Name_src": "Math Type", "Text": "\u0422\u0438\u043f\u044b \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0443\u0442\u0435\u043c \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0441\u0441\u044b\u043b\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f, \u043f\u043e\u043b\u044f \u0434\u0430\u0442, \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435, \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 / \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043e\u043b\u044f. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0437\u043b\u0430. \u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 [\u0438\u043d\u0430\u0447\u0435 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435], \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0435 [\u0438\u043d\u0430\u0447\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f] \u0438 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 [\u0438\u043d\u0430\u0447\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435] \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438 \u043c\u043e\u0433\u0443\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0447\u0438\u0441\u043b\u0430, \u0442\u0435\u043a\u0441\u0442, \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0434\u0430\u0442\u044b \u0438\u043b\u0438 \u0432\u0440\u0435\u043c\u044f.\n
    \n
    \n\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u0434\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043e\u043b\u044f, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0417\u0430\u0434\u0430\u0442\u044c \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u00bb \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e\u043b\u044f\u00bb \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0422\u0438\u043f\u044b \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u041e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0435 \u043e\u043a\u043d\u043e \u0441 \u043f\u043e\u043b\u044f\u043c\u0438 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u043d\u0430 \u043d\u0438\u0445 \u0441\u0441\u044b\u043b\u043e\u043a \u0441\u043b\u0435\u0432\u0430 \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0441\u043f\u0440\u0430\u0432\u0430. \u0412\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u00ab\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u0441\u044b\u043b\u043a\u0438\u00bb \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0441\u044b\u043b\u043a\u0438 \u2014 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0436\u0435 [\u0441\u0432\u043e\u0435\u0433\u043e] \u0443\u0437\u043b\u0430, \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e, \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e \u0438\u043b\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u0443\u0437\u043b\u0430. \u0412\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0435 \u043c\u0435\u043d\u044e \u00ab\u0422\u0438\u043f \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u00bb \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432 \u0432\u0438\u0434\u0435 \u0434\u0430\u0442\u044b, \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043b\u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b. \u0412\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0435 \u043c\u0435\u043d\u044e \u00ab\u0422\u0438\u043f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u00bb \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b. \u041a\u043d\u043e\u043f\u043a\u0438 \u0441\u043e \u0441\u0442\u0440\u0435\u043b\u043a\u043e\u0439 \u0432\u043d\u0438\u0437 \u043f\u043e\u0434 \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a \u0441\u0442\u0440\u043e\u043a\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u043d\u0438\u0436\u0435. \u0427\u0430\u0441\u0442\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u044b \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f.\n
    \n
    \n\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u043e\u043b\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u0430\u043a\u0443\u044e \u200b\u200b\u043a\u0430\u043a sum, max, min, mean \u0438\u043b\u0438 join. \u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u0435\u0439 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u0438\u043b\u0438 \u043d\u0430 \u043f\u043e\u043b\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432, \u043d\u043e \u043d\u0435 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043f\u043e\u043b\u044f \u0443\u0437\u043b\u043e\u0432 \u0441\u0432\u043e\u0435\u0433\u043e \u0436\u0435 \u0443\u0440\u043e\u0432\u043d\u044f [\u0438\u043d\u0430\u0447\u0435 \u0441\u0435\u0441\u0442\u0440\u0438\u043d\u0441\u043a\u0438\u0435 \u0443\u0437\u043b\u044b] \u043d\u0430 \u0441\u0435\u0431\u044f (\u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443). \u0421\u0441\u044b\u043b\u043a\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441\u0441\u044b\u043b\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u043e\u043b\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0438\u043b\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 \u0441 \u0442\u0430\u043a\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0443\u0437\u0435\u043b \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0442\u0438\u043f\u0430.\n
    \n
    \n\u0412 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0442\u0438\u043f\u0430 \u00ab\u0414\u0430\u0442\u0430\u00bb \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0434\u043d\u0435\u0439, \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0438\u0445 \u0441 1 \u044f\u043d\u0432\u0430\u0440\u044f 1970 \u0433., \u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u00ab\u0412\u0440\u0435\u043c\u044f\u00bb \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0441\u0435\u043a\u0443\u043d\u0434 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u043d\u043e\u0447\u0438. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u043e\u043b\u044f \u0434\u0430\u0442 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0438\u0445 \u0434\u043d\u0435\u0439, \u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043d\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0437 \u0434\u0430\u0442, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u0442\u044b. \u041f\u043e\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0438\u0445 \u0441\u0435\u043a\u0443\u043d\u0434, \u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0435\u043a\u0443\u043d\u0434 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0437 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0430\u0442\u044b \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0432\u0432\u0435\u0434\u0435\u043d\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u043f\u043e\u043b\u0435\u0439 ({* Now_Date *}, {* Now_Time *} \u0438 {* Now_Date_Time *}). \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0421\u0441\u044b\u043b\u043a\u0438\u00bb \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043e\u043a, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438.\n
    \n
    \n\u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 [\u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u044b \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432] \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u00abif\u00bb \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0439 \u043e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043f\u043e\u043b\u044f. \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u00ab\u0438\u0441\u0442\u0438\u043d\u043d\u043e\u0435_\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0435, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043b\u043e\u0436\u043d\u043e\u0435_\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u00bb. \u0421\u0430\u043c\u043e \u0441\u043e\u0431\u043e\u0439 \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0441\u0442\u0440\u043e\u043a\u0438 \u00ab\u0438\u0441\u0442\u0438\u043d\u043d\u043e\u0435_\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u00bb, \u00ab\u0443\u0441\u043b\u043e\u0432\u0438\u0435\u00bb \u0438 \u00ab\u043b\u043e\u0436\u043d\u043e\u0435_\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u00bb \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438 \u0438\u043b\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0432\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 (\u043f\u0440\u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438), \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0441\u043a\u043e\u0431\u043a\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0439 \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u042d\u0442\u0438 \u043a\u0440\u0443\u0433\u043b\u044b\u0435 \u0441\u043a\u043e\u0431\u043a\u0438 \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u0445.\n
    \n
    \n\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u00abjoin\u00bb \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 (\u0438\u043b\u0438 \u0438\u0437 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432). \u041f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u2014 \u044d\u0442\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043a\u0430\u0436\u0434\u044b\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0430. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u2014 \u044d\u0442\u043e \u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c.\n
    \n
    \n\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u043a\u043d\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u043e \u043e\u043d\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f. \u0427\u0442\u043e\u0431\u044b \u0441\u043a\u0440\u044b\u0442\u044c \u0438\u0445, \u0441\u043d\u0438\u043c\u0438\u0442\u0435 \u0444\u043b\u0430\u0436\u043e\u043a \u00ab\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u0432 \u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b > \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438\u00bb.\n
    \n
    \n\u0422\u0430\u043a\u0436\u0435 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0424\u0430\u0439\u043b > \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0443\u0441\u0442\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 \u043a\u0430\u043a \u043d\u043e\u043b\u0435\u0439. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0436\u043e\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e), \u043f\u0443\u0441\u0442\u043e\u0435 \u043f\u043e\u043b\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u043e\u043b\u0435, \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u043e\u043b\u044c (\u0434\u043b\u044f \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439) \u0438\u043b\u0438 \u043f\u0443\u0441\u0442\u043e\u0435 (\u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439). \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0436\u043e\u043a \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u043b\u044e\u0431\u044b\u0435 \u043f\u0443\u0441\u0442\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 [\u043d\u0430 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f] \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0443\u0442 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442, \u0431\u0443\u0434\u0443\u0442 \u043f\u0443\u0441\u0442\u044b\u043c\u0438.\n
    ", "Text_src": "Math field types are configured by defining equations. The equations can reference number fields, date fields, time fields, boolean fields, text fields and/or other math fields. The resulting values of math fields are automatically calculated for each node. Various mathematical, relational and string operators are available. The results can be numbers, text, boolean, dates or times.\n
    \n
    \nTo define a math field equation, press the \"Define Equation\" button in the \"Field Config\" tab of the \"Data > Configure Types Dialog\". This brings up a dialog with fields to reference on the left and math operators on the right. The \"Reference Level\" pull-down determines whether the reference is from the same node, the node's parent, the root node, or the node's children. The \"Result Type\" pull-down allows arithmetic, date, time, boolean or text results to be chosen. The \"Operator Type\" pull-down allows numeric, comparison or text operators to be shown in the operator list. The down-arrow buttons below the references and operators add the selected item to the equation text below. Portions of equations can also be typed directly in the equation text line editor.\n
    \n
    \nReferences to child nodes must be enclosed in a grouping function, such as sum, max, min, mean or join. A math field can contain a parent or child reference to itself, but not a same-level reference to itself (a circular reference). The references only contain the field name, so they will reference a parent or child field with that name even if it is a different node type.\n
    \n
    \nIn equations, date fields are represented by the number of days since January 1, 1970, and time fields are the number of seconds since midnight. So date fields can be subtracted to give the number of days elapsed, and numbers of days can be added to or subtracted from dates to result in new dates. Time fields can be subtracted to give the number of seconds elapsed, and numbers of seconds can be added to or subtracted from times to result in new times. \nAlso, special field names ({*Now_Date*}, {*Now_Time*} and {*Now_Date_Time*}) can be manually typed in equations to represent current dates and times. The \"Data->Regenerate References\" command may be needed to force re-evaluation of time-based references.\n
    \n
    \nThe \"if\" comparison operator can be used to make the result depend on the value of another field. The expression is written as \"true_value if condition else false_value\". Of course, the \"true_value\", \"condition\" and \"false_value\" strings must be replaced with valid fields or expressions. If this operator is inserted from the operator list (under comparisons), it will include parenthesis as placeholders. These parenthesis are optional in the equations.\n
    \n
    \nThe \"join\" text function is used to combine text from several other fields (or from child nodes). The first argument to the function is a separator string that is placed between each piece of text. The remaining argument(s) are the text to be joined.\n
    \n
    By default, math fields are shown in the data edit view, but they are read-only. To hide them, uncheck the \"Show math fields in the Data Edit View\" box under \"Tools > General Options > Features Available\".\n
    \n
    \nThere is also an option under \"File > Properties\" that toggles whether blank fields are treated as zeros. If checked (the default), a blank field that is referenced by a math field has a value of zero (for numeric operations) or blank (for text operations). If unchecked, any blank references also cause equations that reference them to be blank.\n
    " }, "format": "HEAD_PARA", "uid": "f17005f8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u041d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u044f", "Name_src": "Numbering Type", "Text": "\u042d\u0442\u043e\u0442 \u0442\u0438\u043f (\u043d\u0435 \u043f\u0443\u0442\u0430\u0442\u044c \u0441 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u043c \u0442\u0438\u043f\u043e\u043c \u0432\u044b\u0448\u0435) \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u044e\u00bb. \u041a\u043d\u043e\u043f\u043a\u0430 \u00ab\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e\u00bb \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb (\u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e\u043b\u044f\u00bb) \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0432\u044b\u0432\u043e\u0434\u0430. \u041e\u0434\u043d\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 [1\u2014i] \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0445\u0435\u043c\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 [\u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435]. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u00ab/\u00bb [1\u2014i./] \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043c\u0430\u043a\u0435\u0442 \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 \".\" \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043c\u0430\u043a\u0435\u0442\u0443 \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 \"2.3.5\". \n
    \n
    \n\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u043e\u043b\u044f \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u043d\u0438 \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u043a\u043d\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u0427\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0444\u043b\u0430\u0436\u043e\u043a \u00ab\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044f \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0432 \u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b > \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438\u00bb. \u041a\u043e\u0433\u0434\u0430 \u043e\u043d\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u043a\u043d\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u043d\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0438\u043b\u0435 [\u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0439] \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432, \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0432\u044b\u0432\u043e\u0434\u0430.", "Text_src": "This type (not to be confused with the number type above) provides fields that are automatically filled in with the \"Data > Update Numbering\" command. The \"Format Help\" button in the field format dialog shows the output format options. A single format level will result in a simple sequential numbering scheme. Use of the \"/\" level separator will result in an outline-type numbering with different sequences at different levels. Use of the \".\" section separator will result in a \"2.3.5\" type numbering scheme.\n
    \n
    \nSince numbering fields are automatically populated, by default they are not shown in the data edit view. To show them, check the \"Show numbering fields in the Data Edit View\" box under \"Tools > General Options > Features Available\". When they are shown in the data edit view, they show up in section numbering style, regardless of the output format." }, "format": "HEAD_PARA", "uid": "f1700710a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0438\u043f \u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435", "Name_src": "Regular Expression Type", "Text": "\u042d\u0442\u043e\u0442 \u0442\u0438\u043f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 [\u0432\u0432\u043e\u0434\u0438\u043c\u044b\u0445] \u0441\u0442\u0440\u043e\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0442\u0430\u043a, \u0447\u0442\u043e [\u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435] \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c [\u0432 \u043f\u043e\u043b\u0435 \u00ab\u0424\u043e\u0440\u043c\u0430\u0442 \u0412\u044b\u0432\u043e\u0434\u0430\u00bb \u0432\u043a\u043b\u0430\u0434\u043a\u0438 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u041f\u043e\u043b\u044f\u00bb \u043e\u043a\u043d\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0422\u0438\u043f\u044b \u0414\u0430\u043d\u043d\u044b\u0445\u00bb]. \u0414\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0432\u0432\u043e\u0434\u0430 \u043f\u043e\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 Python. \u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044e \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u0432\u044b\u0437\u043e\u0432\u0443\u0442 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0438\u043d\u0435\u0433\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u043b\u0435\u0432\u043e\u043c \u0443\u0433\u043b\u0443 \u043f\u043e\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0430 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u043d\u0430 \u00ab#####\u00bb.", "Text_src": "This type allows arbitrary format strings to be matched that restrict the data to a particular format. It uses Python regular expression syntax. Entries in the data editor which do not match the format string expression will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with \"#####\"." }, "format": "HEAD_PARA", "uid": "f170081ea25a11e7b7c67054d2175f18" }, { "children": [ "f1700a26a25a11e7b7c67054d2175f18", "f1700b34a25a11e7b7c67054d2175f18", "f1700c38a25a11e7b7c67054d2175f18", "f1700d3ca25a11e7b7c67054d2175f18", "f1700e40a25a11e7b7c67054d2175f18", "bbbf735ac24711e8b560d66a6ab671cb" ], "data": { "Name": "\u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0412\u044b\u0432\u043e\u0434\u0430 \u0432 \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u0445", "Name_src": "Output Formatting Details" }, "format": "HEADINGS", "uid": "f1700936a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0424\u043e\u0440\u043c\u0430\u0442\u0430 \u0412\u044b\u0432\u043e\u0434\u0430", "Name_src": "Output Format Examples", "Text": "\u042d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0432\u044b\u0432\u043e\u0434\u0430 \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u043a\u043d\u0438\u0433:
    \n
    \n\"{*Title*}\"
    \n(c) {*Copyright*}, Rating: {*Rating*}
    \n{*PlotDescription*}
    \n
    \n\u0418\u043c\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0432 \u0444\u0438\u0433\u0443\u0440\u043d\u044b\u0435 \u0441\u043a\u043e\u0431\u043a\u0438 \u0438 \u0437\u0432\u0435\u0437\u0434\u043e\u0447\u043a\u0438: {* *}. \u0417\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0444\u0430\u0439\u043b\u0430\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0438\u0437 \u043c\u0435\u043d\u044e \u00ab\u0424\u0430\u0439\u043b > \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u041f\u0440\u0438\u043c\u0435\u0440\u00bb.", "Text_src": "Here is an example of output formatting for a book list:
    \n
    \n\"{*Title*}\"
    \n(c) {*Copyright*}, Rating: {*Rating*}
    \n{*PlotDescription*}
    \n
    \nEach of the field names in enclosed in {* *}, curly brackets and asterisks. For more examples, see the sample files that can be opened using the \"File > Open Sample\" command." }, "format": "HEAD_PARA", "uid": "f1700a26a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0424\u043e\u0440\u043c\u0430\u0442\u044b \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430", "Name_src": "Title Formats", "Text": "\u041a\u043e\u0433\u0434\u0430 \u0443\u0437\u0435\u043b \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044f (\u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u0442\u0440\u043e\u043a \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u00ab\u0421\u043f\u0438\u0441\u043e\u043a \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432\u00bb). \u0415\u0441\u043b\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0441\u043b\u043e\u0436\u043d\u043e\u0435, \u043e\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0436\u0435\u043b\u0430\u0435\u043c\u044b\u0439 \u0432\u044b\u0432\u043e\u0434. \u0421\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043c\u0435\u0436\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 \u0431\u0435\u0437 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0445 \u0438\u0445, \u0435\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0443\u0437\u043b\u044b \u0432 \u0434\u0435\u0440\u0435\u0432\u0435.
    \n
    \n\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430.", "Text_src": "When a node in the tree is renamed, the program attempts to match the title formatting pattern to set the appropriate fields (the same title matching occurs when editing lines in the \"Title List\" view). If the title formatting is too complex, it may not correctly guess the intent. Things like adjacent fields with no characters separating them should be avoided unless you do not wish to rename nodes from the tree.
    \n
    \nIf the text data used for a tree view title has multiple lines, only the first line will be used as the title." }, "format": "HEAD_PARA", "uid": "f1700b34a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0435 \u0421\u0442\u0440\u043e\u043a\u0438 \u0412\u044b\u0432\u043e\u0434\u0430", "Name_src": "Skipped Output Lines", "Text": "\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u043f\u0443\u0441\u0442\u044b, \u0442\u043e \u044d\u0442\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 [\u043d\u0435 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0432\u044b\u0432\u043e\u0434\u0430] \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043d\u0438 \u043f\u0443\u0441\u0442\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u043d\u0438 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a \u0441\u0442\u0440\u043e\u043a\u0435 [\u0432\u044b\u0432\u043e\u0434\u0430] \u0431\u0435\u0437 \u043f\u043e\u043b\u0435\u0439 (\u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442). \u0422\u0430\u043a\u0436\u0435, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u0433\u043e\u043c <br/> \u0438\u043b\u0438 <hr/>, \u044d\u0442\u043e\u0442 \u0442\u0435\u0433 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0442\u0435\u0433 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f [\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0442\u0430\u043a\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u044d\u0442\u0438\u0445 \u0442\u0435\u0433\u043e\u0432 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430].", "Text_src": "If all of the fields in an output format line are empty for a given node, then the line is skipped. No blank line or embedded text will be output for that line. Note that this does not apply to a line without any fields (only embedded text). Also, when a line ending with a <br/> or an <hr/> tag is skipped, the ending tag is retained." }, "format": "HEAD_PARA", "uid": "f1700c38a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0422\u0435\u0433\u0438 HTML", "Name_src": "HTML Tags", "Text": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u00ab\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0435\u0433\u0438 HTML\u00bb \u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u0430\u00bb \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u043e\u0432 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043b\u044e\u0431\u044b\u0435 HTML-\u0442\u0435\u0433\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0435\u043a\u0441\u0442. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u043f\u0440\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u044b\u0432\u043e\u0434\u0430 \u0443\u0437\u043b\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0442\u0435\u0433\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f HTML.\n
    \n
    \n\u0427\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c\u0438 \u0442\u0435\u0433\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \"<b> \u0436\u0438\u0440\u043d\u044b\u0439 </b>\", \"<u> \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u0435 </u>\", \"\u0440\u0430\u0437\u0440\u044b\u0432 \u0441\u0442\u0440\u043e\u043a\u0438 <br/>\", \"\u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043b\u0438\u043d\u0438\u044f <hr/>\" \u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0442\u0435\u0433\u0438 \u0448\u0440\u0438\u0444\u0442\u043e\u0432. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0431\u043b\u043e\u0447\u043d\u044b\u0445 \u0442\u0435\u0433\u043e\u0432.", "Text_src": "By default, the \"Allow HTML rich text in formats\" option is unchecked in the \"Type Config\" tab of the Configure Types Dialog. So any HTML tags are treated as plain text. If the option is enabled, simple HTML formatting tags can be used in node output formats.
    \n
    \nCommonly used tags include \"<b>bold</b>\", \"<u>underline</u>\", \"line break<br/>\", \"horizontal line<hr/>\", and various font tags. Complex block tags should generally be avoided." }, "format": "HEAD_PARA", "uid": "f1700d3ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0414\u0440\u0443\u0433\u0438\u0435 \u041f\u043e\u043b\u044f", "Name_src": "Other Field References", "Text": "\u041a \u0432\u044b\u0432\u043e\u0434\u0443 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0432 \u0443\u0437\u043b\u0435. \u041d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u00bb \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0412\u044b\u0432\u043e\u0434\u00bb \u0432 \u0444\u043e\u0440\u043c\u0435 \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u0438\u0434\u0438\u043c\u044b\u043c \u0432\u044b\u0431\u043e\u0440 \u0443\u0440\u043e\u0432\u043d\u044f \u0441\u0441\u044b\u043b\u043a\u0438.\n
    \n
    \n\u0415\u0441\u043b\u0438 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u0441\u044b\u043b\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d \u043d\u0430 \u00abFile Info Reference\u00bb [\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0444\u0430\u0439\u043b\u0435], \u043a \u0432\u044b\u0432\u043e\u0434\u0443 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044f, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u0430. \u041a \u043d\u0438\u043c \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f File_Name [\u0418\u043c\u044f_\u0424\u0430\u0439\u043b\u0430], File_Path [\u041f\u0443\u0442\u044c_\u043a_\u0424\u0430\u0439\u043b\u0443], File_Size [\u0420\u0430\u0437\u043c\u0435\u0440_\u0424\u0430\u0439\u043b\u0430], File_ Mod_Date [\u0414\u0430\u0442\u0430_\u041c\u043e\u0434_\u0424\u0430\u0439\u043b\u0430] \u0438 File_ Mod_Time [\u0412\u0440\u0435\u043c\u044f_\u041c\u043e\u0434_\u0424\u0430\u0439\u043b\u0430]. \u042d\u0442\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \"{*! Field_name *}\" \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u0430.\n
    \n
    \n\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u043e\u043b\u044f \u0434\u043b\u044f Any Ancestor Reference [\u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432-\u043f\u0440\u0435\u0434\u043a\u043e\u0432] (Parent Reference [\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0443\u0437\u0435\u043b], Grandparent Reference [\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u041f\u0440\u0430\u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0443\u0437\u0435\u043b] \u0438 Great Grandparent Reference [\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u041f\u0440\u0430\u041f\u0440\u0430\u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0443\u0437\u0435\u043b]). \u0414\u043b\u044f \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0441\u044b\u043b\u043a\u0438. \u041f\u0440\u0438 \u0435\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u0438\u043c\u0435\u043d\u0430 \u043f\u043e\u043b\u0435\u0439, \u043d\u043e \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u043b\u044e\u0431\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u044f. \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u043e\u043b\u044f \u0438\u0437 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 \u0438 \u0443\u0437\u043b\u043e\u0432-\u043f\u0440\u0430\u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u0439 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \"{** field_name *}\" \u0438 \"{*** field_name *}\" \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u0449\u0438\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u0440\u0435\u0434\u043a\u043e\u0432, \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u043a \"{*? Field_name *}\", \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0435\u0440\u0443\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u043a\u0430 \u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u043b\u0435\u043c. \n
    \n
    \n\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b Child Reference [\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0443\u0437\u043b\u044b], \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u043a\u0430\u043a \u00ab{* & amp; field_name *}\u00bb. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u0432\u044b\u0432\u043e\u0434 [\u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432] \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0443\u0437\u043b\u043e\u0432. \u0414\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u043e\u0439-\u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u0435\u043c, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u0430\u00bb (\u043f\u0440\u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u043a\u0430\u0437\u0435 \u0444\u043e\u0440\u043c\u044b [\u043d\u0430\u0436\u0430\u0442\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0435 \u00ab\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u00bb]). \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u044f\u0442\u0430\u044f \u0438 \u043f\u0440\u043e\u0431\u0435\u043b, \u043d\u043e \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0430 <br/> \u0438\u043b\u0438 \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0435\u0449\u0435.\n
    \n
    \n\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u00ab\u041f\u043e\u0434\u0441\u0447\u0435\u0442 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432\u00bb [Child Count]. \u0412 \u044d\u0442\u043e\u043c \u043f\u043e\u043b\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u043f\u043e\u043b\u0435 \u00abLevel1\u00bb [\u0423\u0440\u043e\u0432\u0435\u043d\u044c1]), \u0432\u043d\u0443\u043a\u043e\u0432 (\u043f\u043e\u043b\u0435 \u00abLevel2\u00bb [\u0423\u0440\u043e\u0432\u0435\u043d\u044c2]) \u0438\u043b\u0438 \u043f\u0440\u0430\u0432\u043d\u0443\u043a\u043e\u0432 (\u043f\u043e\u043b\u0435 \u00abLevel3\u00bb [\u0423\u0440\u043e\u0432\u0435\u043d\u044c3]) \u0443\u0437\u043b\u0430. \u0412 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u043e\u043d\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a {* # Level1 *}.
    \n
    \n\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u044d\u0442\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0441\u043c. \u0432 \u0444\u0430\u0439\u043b\u0435 \u00absample_other_fields\u00bb (\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0424\u0430\u0439\u043b > \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u041f\u0440\u0438\u043c\u0435\u0440\u00bb).", "Text_src": "References to fields that are not contained within the node can be added to the output. Pushing the \"Show Advanced\" button on the \"Output\" tab of the configure dialog makes a reference level selection become visible.
    \n
    \nIf the reference level is changed to \"File Info Reference\", fields containing file meta-data can be added to the output. These include the file name, path, size, modified date and modified time. These special fields are shown as \"{*!field_name*}\" in the title and output format editors.
    \n
    \nThere are field references to various ancestor nodes (parents, grandparents, etc.). These require the data type of the reference to be specified. This selection determines the field names that are available, but the data from any type with a matching field name will be shown in the output. References to fields from parent and grandparent nodes are shown as \"{**field_name*}\" and \"{***field_name*}\", respectively. There are also general ancestor references, shown as \"{*?field_name*}\", that take data from the closest ancestor with a matching field.
    \n
    \nReferences to child nodes can also be added, shown as \"{*&field_name*}\". These also require that the child data type be specified. The child data becomes embedded in the parent output. The child data is delimited with a separator string defined on the \"Type Config\" tab (with show advanced active). The separator defaults to a comma and a space, but can be set to <br/> or anything else.
    \n
    \nFinally, a \"Child Count\" reference can be added. This field will show the number of children (\"Level1\" field) or grandchildren (\"Level2\" field) of a node. These are shown as {*#Level1*} in the format editors.
    \n
    \nFor examples of these fields, see the \"sample_other_fields\" file (by using the \"File > Open Sample\" command)." }, "format": "HEAD_PARA", "uid": "f1700e40a25a11e7b7c67054d2175f18" }, { "children": [ "f1701156a25a11e7b7c67054d2175f18", "f170125aa25a11e7b7c67054d2175f18", "f1701368a25a11e7b7c67054d2175f18", "aa6f6ca4bb0711e7bbf43417ebd53aeb" ], "data": { "Name": "\u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0422\u0438\u043f\u043e\u0432 \u0432 \u0414\u0435\u0442\u0430\u043b\u044f\u0445", "Name_src": "Type Format Details" }, "format": "HEADINGS", "uid": "f1700f58a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041e\u0431\u0449\u0438\u0435 \u0438 \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0435 \u0422\u0438\u043f\u044b", "Name_src": "Generic and Derived Types", "Text": "\u0422\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u043e\u0442 \u043e\u0431\u0449\u0435\u0433\u043e \u0442\u0438\u043f\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0442\u0438\u043f\u0430\u043c \u0441 \u0440\u0430\u0437\u043d\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0432\u044b\u0432\u043e\u0434\u0430 \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043d\u0430\u0431\u043e\u0440 \u043f\u043e\u043b\u0435\u0439. \u041b\u044e\u0431\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043f\u0438\u0441\u043a\u0435 \u043f\u043e\u043b\u0435\u0439 \u0438 \u0442\u0438\u043f\u043e\u0432 \u043f\u043e\u043b\u0435\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u044f\u0445 \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432. \u042d\u0442\u043e \u043d\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e.\n
    \n
    \n\u0415\u0441\u0442\u044c \u0434\u0432\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0442\u0438\u043f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u043c, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0438\u043f\u0430 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0421\u043f\u0438\u0441\u043e\u043a \u0442\u0438\u043f\u043e\u0432\u00bb \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb. \u041f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0442\u0438\u043f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u043c, \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u0430\u00bb \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 [\u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0448\u0435] \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430, \u0435\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.", "Text_src": "Data types can be set to derive their field settings from a generic type. This allows types with different output formatting to always use the same set of fields. Any changes to the generic's list of fields and field types are automatically reflected in the fields of all derived types. This does not apply to a field's output formatting, which can still be set independently.
    \n
    \nThere are two methods for creating derived types. First, a derived option can be selected when copying a type on the \"Type List\" tab of the \"Data > Configure Types Dialog\". Alternately, a generic type can be specified from the derived type's \"Type Config\" tab of the dialog if the advanced functions are shown." }, "format": "HEAD_PARA", "uid": "f1701156a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0423\u0441\u043b\u043e\u0432\u043d\u044b\u0435 \u0422\u0438\u043f\u044b", "Name_src": "Conditional Types", "Text": "\u0423\u0441\u043b\u043e\u0432\u043d\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0437\u043b\u0430. \u0423\u0441\u043b\u043e\u0432\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u0449\u0435\u043c\u0443 \u0442\u0438\u043f\u0443 \u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c \u0441 \u043d\u0438\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u043c \u0442\u0438\u043f\u0430\u043c. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u0432\u043e\u0434\u0430 \u0438\u043b\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u043a\u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0437\u043b\u0430. \n
    \n
    \n\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u043c\u0443 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c\u0443 \u043e\u043a\u043d\u0443 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043a\u0438 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u0430\u00bb \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0422\u0438\u043f\u043e\u0432 \u0414\u0430\u043d\u043d\u044b\u0445\", \u0435\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d \u043f\u043e\u043a\u0430\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a. \u041a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u043e\u043b\u0435, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f. \u0412 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0432\u0445\u043e\u0434\u044f\u0442 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e, \u0431\u043e\u043b\u044c\u0448\u0435, \u043c\u0435\u043d\u044c\u0448\u0435, [\u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u043e, \u043c\u0435\u043d\u044c\u0448\u0435 \u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u043e], \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441, \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0418\u0441\u0442\u0438\u043d\u0430 \u0438 \u041b\u043e\u0436\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0442\u0438\u043f \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e.\n
    \n
    \u0414\u043b\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u043f\u043e\u043b\u0435\u0439, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u0434\u0430\u0442\u044b, \u0432\u0440\u0435\u043c\u044f \u0438 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u0442\u043e\u043c \u0436\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0435, \u0447\u0442\u043e \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043e\u043a\u043d\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u00ab\u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u00bb, \u00ab\u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u00bb \u0438 \u00ab\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u00bb \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u0430\u0442\u0430 \u0438 \u0432\u0440\u0435\u043c\u044f \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u00ab\u0421\u0435\u0439\u0447\u0430\u0441\u00bb, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0434\u0430\u0442\u0430 \u0438 \u0432\u0440\u0435\u043c\u044f. \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0438\u00bb \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043e\u0441\u043d\u043e\u0432\u044b\u0432\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0441\u044b\u043b\u043e\u043a.\n
    \n
    \n\u041a\u043d\u043e\u043f\u043a\u0430 \u00ab\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u043e\u00bb \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u0443\u0441\u043b\u043e\u0432\u0438\u0439. \u0421\u0442\u0440\u043e\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u00ab\u0438\u00bb \u0438\u043b\u0438 \u00ab\u0438\u043b\u0438\u00bb. \u041a\u043d\u043e\u043f\u043a\u0430 \u00ab\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u043e\u00bb \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0443\u0441\u043b\u043e\u0432\u0438\u044f. \u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0430, \u043a\u043d\u043e\u043f\u043a\u0430 \u00ab\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u043e\u00bb \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0443\u0434\u0430\u043b\u0438\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u0435.\n
    \n
    \n\u041d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432 \u0441\u0435\u043c\u0435\u0439\u0441\u0442\u0432\u0435. \u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0443\u0437\u043b\u0430 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043d\u0438\u043a\u0430\u043a\u0438\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0432\u044b\u0431\u0435\u0440\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435, \u0430 \u043d\u0435 \u043b\u043e\u0436\u043d\u043e\u0435.\n
    \n
    \n\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u043c. \u0444\u0430\u0439\u043b \"sample_conditional_todo\" (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \"\u0424\u0430\u0439\u043b > \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u041f\u0440\u0438\u043c\u0435\u0440\").", "Text_src": "Conditional expressions can be used to automatically assign a data type based on each node's content. Conditions can be assigned only to a generic type and its associated derived types. This allows the automatic assignment of different output formatting or different icons depending on each node's field data.\n

    \nThe conditional dialog box is accessed from a button on the \"Type Config\" tab of the \"Data->Configure Types Dialog\" if the advanced functions are shown. Each line of the condition includes a field, an operator and a comparison value. The operators include equality, greater than, less than, starts with, ends with, and contains. There are also True and False operators that will toggle the type of all nodes simultaneously.\n

    \nFor special field types such as dates, times, and booleans, the comparison value should be entered in the same format that is used in the Data Editor window. In general, the starts with, ends with, and contains operators should not be used for these special fields, since the comparison is done using an internal data representation. Dates and times also support a special comparison value of \"Now\", which is always interpreted as the current date and time. The \"Data->Regenerate References\" command may be needed to force re-evaluation of time-based references.\n

    \nThe \"Add New Rule\" button is used to add additional condition lines. The lines can be joined with \"and\" or \"or\" operators. The \"Remove Rule\" button deletes the last condition line. If only a single line is present, the \"Remove Rule\" button completely removes the condition.\n

    \nConditions do not have to be set for all types in a family. If no conditions are true for a node, the program will select a blank condition rather than a false one.\n

    \nFor an example, see the \"sample_conditional_todo\" file (by using the \"File > Open Sample\" command)." }, "format": "HEAD_PARA", "uid": "f170125aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u0424\u043e\u0440\u043c\u0430\u0442\u044b", "Name_src": "Copying Formats", "Text": "\u0414\u0440\u0443\u0433\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 TreeLine. \u042d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0422\u0438\u043f\u044b \u0438\u0437 \u0424\u0430\u0439\u043b\u0430\u00bb. \u041f\u0440\u0438 \u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432\u0441\u0435 \u0442\u0438\u043f\u044b \u0438\u0437 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430. \u041b\u044e\u0431\u044b\u0435 \u0442\u0438\u043f\u044b \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0444\u0430\u0439\u043b\u0435 \u0441 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u043c\u0438 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f, \u043d\u043e \u0442\u0438\u043f\u044b \u0441 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f.", "Text_src": "Another method for changing data type formatting is to copy the formats from another TreeLine file. This is done with the \"Data > Copy Types from File\" command. All types from the chosen file are copied. Any types in the current file with matching names are overwritten, but types with unique names are retained." }, "format": "HEAD_PARA", "uid": "f1701368a25a11e7b7c67054d2175f18" }, { "children": [ "f170155ca25a11e7b7c67054d2175f18", "f1701660a25a11e7b7c67054d2175f18", "f1701764a25a11e7b7c67054d2175f18", "f1701868a25a11e7b7c67054d2175f18", "f170198aa25a11e7b7c67054d2175f18", "f1701a8ea25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0414\u0430\u043d\u043d\u044b\u043c\u0438 \u0414\u0435\u0440\u0435\u0432\u0430", "Name_src": "Tree Data Operations" }, "format": "HEADINGS", "uid": "f170146ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430", "Name_src": "Sorting", "Text": "\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0437\u043b\u044b\u00bb \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0437\u043b\u044b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0443\u0437\u043b\u043e\u0432 \u0438\u043b\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043f\u043e\u043b\u0435\u0439, \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0442\u0438\u043f\u0430 \u0443\u0437\u043b\u0430. \u041f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e\u043b\u044f\u00bb [\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c, \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a\u0430\u043a \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u043e\u043b\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u2014 \u0435\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0443 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c, \u0442\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0434\u043b\u044f \u0434\u0435\u0440\u0435\u0432\u0430 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0412\u044b\u0432\u043e\u0434\u00bb] \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u00ab\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb. \u041a\u043d\u043e\u043f\u043a\u0430 \u00ab\u041a\u043b\u044e\u0447\u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438\u00bb [\u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u00ab\u0421\u043f\u0438\u0441\u043e\u043a \u041f\u043e\u043b\u0435\u0439\u00bb] \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u0435\u0439, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0445 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438. \u041f\u043e\u043b\u044f \u0432\u044b\u0448\u0435 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438\u043c\u0435\u044e\u0442 \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u0438\u0439 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442. \u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f [\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432] \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435.", "Text_src": "The \"Data > Sort Nodes\" command can sort nodes based on either node titles or key fields predefined in the node type configuration. The predefined sort fields can be changed in the \"Field Config\" tab of the Configure Types Dialog. The \"Sort Keys\" button brings up a list of fields that define a sort key sequence. The fields higher in the sequence have a higher priority. The direction for each key field can be flipped." }, "format": "HEAD_PARA", "uid": "f170155ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u044f", "Name_src": "Numbering", "Text": "\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 > \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u044e\u00bb \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u043e\u043b\u0435\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043f\u043e\u043b\u044f \u2014 \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438. \u0424\u043e\u0440\u043c\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u043e\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0447\u0438\u0441\u0435\u043b \u0432 \u0432\u044b\u0432\u043e\u0434\u0435, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0447\u0438\u0441\u0435\u043b, \u043d\u043e\u043c\u0435\u0440\u043e\u0432 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0438\u043b\u0438 \u0441\u0445\u0435\u043c\u044b \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0441\u043c. \u0432 \u0422\u0438\u043f \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438.\n
    \n
    \n\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043f\u043e\u043b\u044f \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u043a\u043d\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0444\u043b\u0430\u0436\u043e\u043a \u00ab\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044f \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0432 \u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0414\u0430\u043d\u043d\u044b\u0445\u00bb \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b > \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0424\u0443\u043d\u043a\u0446\u0438\u0438\u00bb. \u041a\u043e\u0433\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u043d\u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0438\u043b\u0435 \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432, \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0432\u044b\u0432\u043e\u0434\u0430.", "Text_src": "The \"Data > Update Numbering\" command updates the contents of fields with a special numbering field type. The field's output format defines how the numbers are displayed in the output, including whether individual numbers, outline numbers or a section numbering scheme are shown. See the Numbering Field Type for more information.
    \n
    \nNote that numbering fields are not shown in the data edit view unless \"Show numbering fields in the Data Edit View\" is checked under \"Tools > General Options > Features Available\". When they are shown in the data edit view, they show up in section numbering style, regardless of the output format." }, "format": "HEAD_PARA", "uid": "f1701660a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u043e\u0438\u0441\u043a \u0438 \u0417\u0430\u043c\u0435\u043d\u0430", "Name_src": "Find and Replace", "Text": "\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041f\u043e\u0438\u0441\u043a \u0438 \u0417\u0430\u043c\u0435\u043d\u0430\u00bb \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 [\u0441\u0440\u0430\u0437\u0443] \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0443\u0437\u043b\u0430\u0445. \u0412 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u0437\u0430\u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0439 \u0442\u0435\u043a\u0441\u0442. \u041f\u043e\u0438\u0441\u043a \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0438 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0439, \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043d\u044b\u0445 \u0441\u043b\u043e\u0432\u0430\u0445 \u0438\u043b\u0438 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 Python [\u0441\u043c. \u041f\u043e\u0438\u0441\u043a]. \u041f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c \u0443\u0437\u043b\u0430 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u043b\u0435\u043c \u0443\u0437\u043b\u0430. \n
    \n
    \n\u0417\u0430\u043c\u0435\u043d\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u2014 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043e\u0449\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442. \u041f\u0440\u0438 \u043f\u043e\u0438\u0441\u043a\u0435 \". *\" \u0411\u0443\u0434\u0435\u0442 \u043d\u0430\u0439\u0434\u0435\u043d \u0432\u0435\u0441\u044c \u0442\u0435\u043a\u0441\u0442 \u0432 \u043f\u043e\u043b\u0435. \u0421\u0442\u0440\u043e\u043a\u0430 \u0437\u0430\u043c\u0435\u043d\u044b \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0438\u0437 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u043a\u043e\u0441\u043e\u0439 \u0447\u0435\u0440\u0442\u044b \u0438 \u0447\u0438\u0441\u043b\u0430. \u041e\u0431\u0440\u0430\u0442\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0437\u0430\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0433\u0440\u0443\u043f\u043f\u043e\u0439 \u0432 \u0441\u043a\u043e\u0431\u043a\u0430\u0445 \u0438\u0437 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u00ab\\2\u00bb \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043c\u0435\u043d\u0435\u043d \u0442\u0435\u043a\u0441\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 \u0438\u0437 \u0441\u043a\u043e\u0431\u043e\u043a. \"\\g<0>\" \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u043d\u044b \u0432\u0441\u0435\u0439 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u0440\u043e\u043a\u0438.", "Text_src": "The \"Tools > Find and Replace\" command can be used to change the text in several nodes. The search text and replacement text are entered. Searching can be based on any match, full words only, or a Python regular expression. The operation can optionally be restricted to a particular node type and to a particular node field.
    \n
    \nReplacement using regular expressions is quite powerful. Searching for \".*\" will match all of the text in the field. The replacement string can contain back references that consist of a backslash and a number. The back references get replaced with the corresponding parenthesized group from the match. For example, \"\\2\" will be replaced with the text that matched the second group of parenthesis. The \"\\g<0>\" back-reference can be used to substitute the entire matching string." }, "format": "HEAD_PARA", "uid": "f1701764a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u041f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f", "Name_src": "Spell Check", "Text": "\u0412 \u043c\u0435\u043d\u044e \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b\u00bb \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043e\u0440\u0444\u043e\u0433\u0440\u0430\u0444\u0438\u0438. \u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b (aspell, ispell \u0438\u043b\u0438 hunspell \u2014 \u0441\u043c. \u0420\u0430\u0437\u0434\u0435\u043b \u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f ). \u0415\u0441\u043b\u0438 \u0432 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0441\u043b\u043e\u0432\u0430 \u0441 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438, \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0441\u043b\u043e\u0432\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c, \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438\u043b\u0438 \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044f\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0437\u043b\u0430.", "Text_src": "There is a spell check command in the \"Tools\" menu. Use of this command requires an external program to be installed (either aspell, ispell or hunspell- see the System Requirements section). If there are any misspelled words in the selected branch, a dialog will allow the word to be ignored, added to the dictionary, replaced with a suggestion or edited. This will spell check the text in all data fields of each node." }, "format": "HEAD_PARA", "uid": "f1701868a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0423\u0437\u043b\u044b", "Name_src": "Cloned Nodes", "Text": "\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u0434\u0435\u0440\u0435\u0432\u0430. \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0432\u043e \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445. \u041a\u043e\u0433\u0434\u0430 \u0432\u044b\u0431\u0440\u0430\u043d \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b, \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0443\u0437\u043b\u044b-\u043f\u0440\u0435\u0434\u043a\u0438, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u0439. \u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u0431\u0443\u0434\u0435\u0442 \u0447\u0435\u0440\u043d\u044b\u043c (\u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u043e\u0439), \u043d\u043e \u043f\u043e \u0435\u0433\u043e \u0435\u0433\u043e \u043a\u043b\u043e\u043d\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0449\u0435\u043b\u043a\u043d\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0438\u0445 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435.\n
    \n
    \n\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043f\u0443\u0442\u0435\u043c \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0443\u0437\u043b\u043e\u0432 \u0438\u043b\u0438 \u0432\u0435\u0442\u0432\u0435\u0439, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0437 \u043c\u0435\u043d\u044e \u00ab\u041f\u0440\u0430\u0432\u043a\u0430\u00bb \u0434\u043b\u044f \u0438\u0445 \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0432 \u0434\u0440\u0443\u0433\u043e\u0435 \u043c\u0435\u0441\u0442\u043e [\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u0432\u0441\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442, \u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0438\u0435 \u0443\u0437\u043b\u044b\u00bb, \u0441\u043c. \u043d\u0438\u0436\u0435]. \u0421\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043a\u043b\u043e\u043d \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c, \u0443\u0434\u0430\u043b\u0438\u0432 \u0443\u0437\u043b\u044b \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 & gt; \u041e\u0442\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u043a\u043b\u043e\u043d\u044b\u00bb, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0443\u0437\u043b\u044b.
    \n
    \n\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0414\u0430\u043d\u043d\u044b\u0435 & gt; \u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0438\u0435 \u0443\u0437\u043b\u044b\u00bb. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0432\u0441\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b\u0435 \u0443\u0437\u043b\u044b \u0432 \u0434\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0432 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b. [\u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b \u2014 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u0439 \u0443\u0437\u0435\u043b, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u00ab\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0438\u0435 \u0443\u0437\u043b\u044b\u00bb].\n
    \n
    \n\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f\u043c\u0438 \u0441\u043c. \u0432 \u0444\u0430\u0439\u043b\u0435 \u00absample_genealogy\u00bb (\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0424\u0430\u0439\u043b> \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u041f\u0440\u0438\u043c\u0435\u0440\u00bb).", "Text_src": "Cloned nodes are used to duplicate sections of the tree. Editing their data or child structure in one location changes all locations. When a cloned node is selected, multiple lines are shown in the Breadcrumb view, showing ancestor nodes that have multiple parents. The selected node will appear black (not a link), but its clones can be clicked to select their location in the tree view.
    \n
    \nCloned nodes are created by copying nodes or branches and then using the special paste clone commands found in the \"Edit\" menu to paste them elsewhere. The clone link can be removed by deleting the nodes or by using the \"Data > Detach Clones\" command to convert them back to regular nodes.
    \n
    \nCloned nodes can also be created automatically by using the \"Data > Clone All Matched Nodes\" command. This will convert all identical nodes in the tree structure into cloned nodes.
    \n
    \nFor an example of cloned nodes with multiple parents, see the \"sample_genealogy\" file (by using the \"File > Open Sample\" command)." }, "format": "HEAD_PARA", "uid": "f170198aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438", "Name_src": "Category-Based Arrangement", "Text": "\u041c\u0435\u043d\u044e \u00ab\u0414\u0430\u043d\u043d\u044b\u0435\u00bb \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f\u043c. \u042d\u0442\u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u0443\u0437\u043b\u043e\u0432 \u043d\u0438\u0436\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0443\u0437\u043b\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435. \n
    \n
    \n\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438\u00bb \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0430\u043c \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u0434\u043d\u043e \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043e\u0431\u0449\u0438\u043c\u0438 \u0434\u043b\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432. \u042d\u0442\u0438 \u043f\u043e\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439, \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u044f \u0438\u0445 \u043f\u043e \u043e\u0431\u0449\u0438\u043c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f\u043c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043a\u043d\u0438\u0433 \u0432\u044b\u0431\u043e\u0440 \u043f\u043e\u043b\u0435\u0439 \u00abauthor_first_name\u00bb \u0438 \u00abauthor_last_name\u00bb \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0434\u0435\u0440\u0435\u0432\u0430 \u0441 \u043a\u043d\u0438\u0433\u0430\u043c\u0438 \u0432 \u043d\u043e\u0432\u044b\u0445 \u0443\u0437\u043b\u0430\u0445 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u0440\u0430. \n
    \n
    \n\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0421\u0432\u0435\u0441\u0442\u0438 \u0432 \u043e\u0434\u0438\u043d \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043f\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438\u00bb \u043f\u043e\u0447\u0442\u0438 \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043f\u043e\u043b\u043e\u0436\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u00ab\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438\u00bb. \u0414\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u043b\u044e\u0431\u044b\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0443\u0437\u043b\u044b \u0441 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u043f\u043e\u043b\u044f \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u043d\u0438\u0445 [\u0432\u043d\u0443\u0447\u0430\u0442\u044b\u0445 \u0443\u0437\u043b\u043e\u0432] \u0441\u0432\u043e\u0438\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u0443\u0437\u043b\u0430\u043c. \u041e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044f \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043f\u043e\u043b\u0435\u0439, \u043d\u043e \u044d\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u0430, \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0443\u0437\u043b\u044b \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043a \u0440\u0430\u0437\u043d\u044b\u043c \u0442\u0438\u043f\u0430\u043c \u0441 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043f\u043e\u043b\u0435\u0439.\n
    \n
    \n\u0422\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u041f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u0443\u0440\u043e\u0432\u043d\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439\u00bb, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u0435\u043d\u044f\u0435\u0442 \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0438 \u0432\u043d\u0443\u0447\u0430\u0442\u044b\u0439 \u0443\u0437\u043b\u044b \u043f\u043e\u0434 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u0443\u0437\u043b\u043e\u043c. \u0414\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0443\u0437\u0435\u043b \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438 \u043f\u043e\u0434 \u043d\u0438\u043c \u0431\u0443\u0434\u0435\u0442 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0438\u0437 \u043d\u0438\u0445. \u041b\u044e\u0431\u044b\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043a\u043b\u043e\u043d\u044b \u0432\u043d\u0443\u043a\u043e\u0432 \u0441\u0442\u0430\u043d\u0443\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438.", "Text_src": "The \"Data\" menu contains commands for arranging and flattening the data by category. These methods are used to automatically add and remove levels of nodes below the current node in the tree.\n
    \n
    \nThe \"Add Category Level\" command allows you to select one or more of the fields that the child nodes have in common. These fields are used to create new parent nodes for the children, grouping them by common categories. For example, in a list of books, picking the \"author_first_name\" and \"author_last_name\" fields will result in a tree with the books under new nodes for each unique author.\n
    \n
    \nThe \"Flatten by Category\" command is almost the opposite of \"Add Category Level\". It eliminates any descendant nodes with children, transferring their data fields to their children. It will rename fields instead of overwriting data with the same field names, but this command is most useful when the children and parents are different types with unique field names.\n
    \n
    \nThere is also a \"Swap Category Levels\" command that will swap the child and grandchild nodes beneath a selected node. A child node with multiple nodes under it will become cloned under each one. Any existing grandchild clones will become individual nodes with multiple children." }, "format": "HEAD_PARA", "uid": "f1701a8ea25a11e7b7c67054d2175f18" }, { "children": [ "fd0fe3dd69dc11ebab13001fd026534b", "0a0d866469dd11eb9819001fd026534b", "12aaf67e69dd11eb9d47001fd026534b" ], "data": { "Name": "\u041f\u0435\u0447\u0430\u0442\u044c", "Name_src": "Printing" }, "format": "HEADINGS", "uid": "f1701caaa25a11e7b7c67054d2175f18" }, { "children": [ "f170216ea25a11e7b7c67054d2175f18", "f1702272a25a11e7b7c67054d2175f18", "f170236ca25a11e7b7c67054d2175f18", "f1702470a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432", "Name_src": "File Handling" }, "format": "HEADINGS", "uid": "f170207ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0421\u0436\u0430\u0442\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432", "Name_src": "File Compression", "Text": "\u0424\u0430\u0439\u043b TreeLine \u0438\u043c\u0435\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 JSON. \u0412 \u043d\u0435\u043c \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0436\u0430\u0442\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 (\u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 gzip) \u0434\u043b\u044f \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0438 \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u0436\u0430\u0442\u044b \u043b\u0438\u0431\u043e \u0438\u0437 \u043c\u0435\u043d\u044e \u00ab\u0424\u0430\u0439\u043b > \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u00bb, \u043b\u0438\u0431\u043e \u0438\u0437 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u0438\u043f\u043e\u0432 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u00ab\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a\u00bb [\u043f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \u0442\u0438\u043f\u0430 \u0444\u0430\u0439\u043b\u0430].", "Text_src": "A TreeLine file is in a JSON text format. There are options to compress the files (gzip format) to save storage space. Individual files can be set to compressed mode from either \"File > Properties\" or from the file type pull-down in the save-as dialog." }, "format": "HEAD_PARA", "uid": "f170216ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432", "Name_src": "File Encryption", "Text": "\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043e\u043f\u0446\u0438\u044f \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 TreeLine \u0434\u043b\u044f \u0438\u0445 \u0437\u0430\u0449\u0438\u0442\u044b \u043e\u0442 \u043d\u0435\u0441\u0430\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u0430\u0440\u043e\u043b\u0435\u043c. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u044b \u043b\u0438\u0431\u043e \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u043d\u044e \u00ab\u0424\u0430\u0439\u043b> \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u00bb, \u043b\u0438\u0431\u043e \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u043c\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0435 \u0442\u0438\u043f\u043e\u0432 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435 \u00ab\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a\u00bb. \u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0445\u044d\u0448-\u0444\u0443\u043d\u043a\u0446\u0438\u044e SHA \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0448\u0438\u0444\u0440\u0430 \u2014 \u044d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438.", "Text_src": "There is a file encryption option to password protect TreeLine files. Individual files can be set to encrypted mode from either \"File > Properties\" or from the file type pull-down in the save-as dialog. The encryption uses an SHA hash function as a stream cipher - it should be fairly secure." }, "format": "HEAD_PARA", "uid": "f1702272a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0410\u0432\u0442\u043e\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435", "Name_src": "Auto-Save", "Text": "\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0430\u0432\u0442\u043e\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043d\u0435\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u0438\u043c\u0432\u043e\u043b\u0430 \u00ab~\u00bb \u043a \u0438\u043c\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u0430. \u0424\u0430\u0439\u043b\u044b \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0445 \u043a\u043e\u043f\u0438\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0444\u0430\u0439\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430 TreeLine \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u0437 \u043e\u0448\u0438\u0431\u043e\u043a. \u0412\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0430\u0432\u0442\u043e\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u00ab\u041e\u0431\u0449\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445\u00bb. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0443\u043b\u0435\u0432\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430 \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e.", "Text_src": "An auto-save feature can store unsaved files with a \"~\" appended to the file name. The backup files are automatically removed when the file is saved or TreeLine exits cleanly. The auto-save time interval is set in the general options. Setting the interval to zero disables this feature." }, "format": "HEAD_PARA", "uid": "f170236ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0414\u0435\u0440\u0435\u0432\u0430", "Name_src": "Saved Tree States", "Text": "\u041f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 TreeLine \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0443\u0437\u043b\u043e\u0432. \u042d\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 TreeLine \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0432 \u043e\u043a\u043d\u0435 \u00ab\u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b\u00bb.", "Text_src": "When opening a recently used file, TreeLine will restore the states of open and selected nodes. This information is stored in the user's TreeLine configuration files. If desired, this feature can be disabled with a general option." }, "format": "HEAD_PARA", "uid": "f1702470a25a11e7b7c67054d2175f18" }, { "children": [ "f170265aa25a11e7b7c67054d2175f18", "f170275ea25a11e7b7c67054d2175f18", "f1702b46a25a11e7b7c67054d2175f18", "95547c38b97411e7a42a3417ebd53aeb", "f1702858a25a11e7b7c67054d2175f18", "f1702952a25a11e7b7c67054d2175f18", "f1702a42a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442 \u0424\u0430\u0439\u043b\u043e\u0432", "Name_src": "File Import" }, "format": "HEADINGS", "uid": "f170256aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041e\u0431\u0449\u0438\u0435 \u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f", "Name_src": "General Information", "Text": "\u0424\u0430\u0439\u043b\u044b TreeLine \u0438\u043c\u0435\u044e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 JSON. \u0424\u0430\u0439\u043b\u044b \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0424\u0430\u0439\u043b > \u0418\u043c\u043f\u043e\u0440\u0442\u00bb, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0435 \u043e\u043a\u043d\u043e, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0435\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u0438\u043f \u0438\u043c\u043f\u043e\u0440\u0442\u0430. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u044d\u0442\u043e\u0433\u043e \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u00ab\u0424\u0430\u0439\u043b > \u041e\u0442\u043a\u0440\u044b\u0442\u044c\u00bb \u043d\u0430 \u0444\u0430\u0439\u043b \u0441 \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c \u043e\u0442 TreeLine \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c.", "Text_src": "A TreeLine file is in a specific JSON text format. Other types of files can be imported using the \"File > Import\" command, which will show a dialog box where the type of import can be selected. Alternatively, using the \"File > Open\" command with a non-TreeLine file will also show this dialog." }, "format": "HEAD_PARA", "uid": "f170265aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442 \u0422\u0435\u043a\u0441\u0442\u0430", "Name_src": "Text Import", "Text": "\u0414\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432. \u0422\u0435\u043a\u0441\u0442 \u0441 \u043e\u0442\u0441\u0442\u0443\u043f\u0430\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0430\u0431\u0443\u043b\u044f\u0446\u0438\u0439 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0443\u0437\u043b\u0430 \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 \u0441\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439, \u043e\u0441\u043d\u043e\u0432\u044b\u0432\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0430\u0431\u0443\u043b\u044f\u0446\u0438\u0439 \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0439.\n
    \n
    \n\u0412 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445, \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u044f\u0442\u044b\u043c\u0438 (CSV) \u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445, \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0445 \u0442\u0430\u0431\u0443\u043b\u044f\u0446\u0438\u044f\u043c\u0438, \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043c\u0435\u043d \u043f\u043e\u043b\u0435\u0439, \u0437\u0430\u0442\u0435\u043c \u043a\u0430\u0436\u0434\u0430\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0443\u0437\u043b\u043e\u043c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u044f, \u0432\u0437\u044f\u0442\u044b\u043c\u0438 \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0442\u043e\u043b\u0431\u0446\u0430. \u0418\u043c\u043f\u043e\u0440\u0442 CSV \u0441 \u043d\u043e\u043c\u0435\u0440\u0430\u043c\u0438 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0434\u0435\u0440\u0435\u0432\u043e \u0438\u0437 \u043d\u043e\u043c\u0435\u0440\u043e\u0432 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u0432 \u043f\u0435\u0440\u0432\u043e\u043c \u0441\u0442\u043e\u043b\u0431\u0446\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f. \n
    \n
    \n\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430, \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0443\u0437\u043b\u0443 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443, \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u043b\u043e\u0441\u043a\u043e\u0435 [\u043e\u0434\u043d\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u043e\u0435] \u0434\u0435\u0440\u0435\u0432\u043e, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0443\u0437\u043b\u043e\u0432.\n
    \n
    \n\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u0430\u0431\u0437\u0430\u0446\u0430\u043c\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0443\u0437\u043b\u044b \u0441 \u043f\u043e\u043b\u044f\u043c\u0438, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u043c\u0438 \u0434\u043b\u0438\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0430, \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438.", "Text_src": "Several different text formats can be selected for import. Tab indented text creates a node title from each line in the file, structured based on the number of tabs before each line.
    \n
    \nThe comma-delimited (CSV) and the tab delimited text tables use the first line as a header row to create field names, then each additional row becomes a node with field data taken from each column. The CSV import with level numbers creates a tree structure from level numbers in the first column that are incremented to show child relationships.
    \n
    \nThe plain text, one node per line import creates a flat tree of node titles.
    \n
    \nFinally, the plain text paragraph import creates long text nodes from text separated by blank lines." }, "format": "HEAD_PARA", "uid": "f170275ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442 \u0444\u0430\u0439\u043b\u043e\u0432 Treepad", "Name_src": "Treepad Import", "Text": "\u0424\u0430\u0439\u043b\u044b \u0438\u0437 \u0443\u0441\u043b\u043e\u0432\u043d\u043e-\u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b Treepad \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0443\u0437\u043b\u044b Treepad.", "Text_src": "Files from the Treepad shareware program can be imported. Only Treepad text nodes are supported." }, "format": "HEAD_PARA", "uid": "f1702858a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442 XML", "Name_src": "XML Import", "Text": "TreeLine \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b XML \u043e\u0431\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430 [\u0438\u043d\u0430\u0447\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 XML]. \u042d\u0442\u043e \u043d\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0443\u0442\u0438\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u2014 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 XML \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0443\u0437\u043b\u043e\u043c, \u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 XML \u2014 \u043f\u043e\u043b\u0435\u043c. \u0422\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 XML \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u044f \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u00abElement_Data\u00bb. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 TreeLine \u043a\u0430\u043a \u0441 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432 XML.", "Text_src": "TreeLine will import and export generic XML files. These routines do not have much intelligence - each XML element becomes a node and each XML attribute becomes a field. XML text content become fields named \"Element_Data\". This lets TreeLine function as a crude XML editor." }, "format": "HEAD_PARA", "uid": "f1702952a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442 ODF ", "Name_src": "ODF Import", "Text": "TreeLine \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432 (ODF) \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u043a\u0430\u043a Apache OpenOffice \u0438 LibreOffice. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0443\u0437\u043b\u043e\u0432 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u043d\u044b\u0445 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435 \u0441\u0442\u0438\u043b\u0435\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432. \u041b\u044e\u0431\u043e\u0439 \u0442\u0435\u043a\u0441\u0442 \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0443\u0437\u043b\u0443 \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430. \u0424\u0438\u043b\u044c\u0442\u0440 \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439. \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0430 \u0442\u0430\u043a\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u0430\u043a \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043d\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f.", "Text_src": "TreeLine will import Open Document Format (ODF) text documents, from applications such as Apache OpenOffice and LibreOffice. The node structure is formed based on the heading styles assigned in the document. Any text under each heading is assigned to that heading's node. The import filter is intended for simple text outlines only. No formatting is maintained, and objects such as tables and pictures are not imported." }, "format": "HEAD_PARA", "uid": "f1702a42a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043c\u043f\u043e\u0440\u0442 \u0417\u0430\u043a\u043b\u0430\u0434\u043e\u043a", "Name_src": "Bookmarks Import", "Text": "TreeLine \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0444\u0430\u0439\u043b\u044b \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a \u043a\u0430\u043a \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 Mozilla HTML (\u0431\u0440\u0430\u0443\u0437\u0435\u0440 Firefox), \u0442\u0430\u043a \u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 XBEL (\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b Konqueror, Galeon \u0438 Elinks). \u041a\u0430\u0436\u0434\u0430\u044f \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0443\u0437\u043b\u043e\u043c, \u0438\u043c\u0435\u044e\u0449\u0438\u043c \u0438\u043c\u044f \u0438 \u043f\u043e\u043b\u0435 \u0441 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u043e\u0439. \u0418\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a, \u0442\u0430\u043a\u0430\u044f \u043a\u0430\u043a \u0434\u0430\u0442\u044b \u043f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u044f \u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0438\u043a\u043e\u043d\u043a\u0438, \u043d\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0444\u0430\u0439\u043b sample_bookmarks (\u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0424\u0430\u0439\u043b > \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u041f\u0440\u0438\u043c\u0435\u0440\u00bb).", "Text_src": "TreeLine will import bookmark files in both the Mozilla HTML format (Firefox browser) and the XBEL format (Konqueror, Galeon and Elinks browsers). Each bookmark becomes a node with a name and a link field. Some information in the files, such as visited dates and icon references, is not imported. For an example, see the \"sample_bookmarks\" file (by using the \"File > Open Sample\" command).
    " }, "format": "HEAD_PARA", "uid": "f1702b46a25a11e7b7c67054d2175f18" }, { "children": [ "f1702d4ea25a11e7b7c67054d2175f18", "f1702e52a25a11e7b7c67054d2175f18", "f1702f60a25a11e7b7c67054d2175f18", "65289b36b97611e783eb3417ebd53aeb", "f1703064a25a11e7b7c67054d2175f18", "f170315ea25a11e7b7c67054d2175f18", "f1703262a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0424\u0430\u0439\u043b\u043e\u0432", "Name_src": "File Export" }, "format": "HEADINGS", "uid": "f1702c4aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041e\u0431\u0449\u0438\u0435 \u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f", "Name_src": "General Information", "Text": "\u0424\u0430\u0439\u043b\u044b \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0424\u0430\u0439\u043b > \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u00bb. \u041f\u0440\u0438 \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0435 \u043e\u043a\u043d\u043e \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430.", "Text_src": "Files are exported using the \"File > Export\" command. This will show a dialog box of available export types and options." }, "format": "HEAD_PARA", "uid": "f1702d4ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 HTML", "Name_src": "HTML Export", "Text": "\u041f\u043e\u0434\u0442\u0438\u043f\u044b \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0432 HTML \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u043e\u0434\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0439 \u0438\u043b\u0438 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 HTML. \u041e\u0434\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0439 \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u0432\u043e\u0434\u0430 \u0441 \u043e\u0442\u0441\u0442\u0443\u043f\u0430\u043c\u0438. \u041f\u0430\u043d\u0435\u043b\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0441\u043b\u0435\u0432\u0430 \u0441 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u043c\u0435\u0442\u043a\u0438 [\u044f\u043a\u043e\u0440\u044f] \u0432 \u043f\u043e\u0437\u0438\u0446\u0438\u044f\u0445 \u0443\u0437\u043b\u043e\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439.\n
    \n
    \n\u041f\u0440\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u0432 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0439 HTML \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0434\u043d\u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430. \u0412 \u0444\u0430\u0439\u043b\u044b \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043f\u0430\u043d\u0435\u043b\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0441\u043b\u0435\u0432\u0430 \u0441 \u0433\u0438\u043f\u0435\u0440\u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441 \u0441\u0435\u0441\u0442\u0440\u0438\u043d\u0441\u043a\u0438\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438, \u0443\u0437\u043b\u0430\u043c\u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u0439 \u0438 \u0441\u0435\u0441\u0442\u0440\u0438\u043d\u0441\u043a\u0438\u0435 \u0443\u0437\u043b\u044b \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u0439.\n
    \n
    \n\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0439 HTML \u0442\u0430\u0431\u043b\u0438\u0446 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0444\u0430\u0439\u043b\u0435 HTML \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043d\u0430\u0431\u043e\u0440\u0430 \u0441\u0435\u0441\u0442\u0440\u0438\u043d\u0441\u043a\u0438\u0445 \u0443\u0437\u043b\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432.\n
    \n
    \n\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0414\u0435\u0440\u0435\u0432\u043e HTML \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Javascript \u0438 CSS \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. \u0423\u0437\u043b\u044b \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0438 \u0441\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c, \u0430 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430. \u041f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \u043f\u0435\u0440\u0432\u043e\u0439 \u0444\u043e\u0440\u043c\u044b \u0442\u0430\u043a\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0441 \u0438\u043c\u0435\u044e\u0449\u0438\u043c\u0441\u044f \u0444\u0430\u0439\u043b\u043e\u043c TreeLine. \u042d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0435 (\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f). \u0412 \u0444\u0430\u0439\u043b\u0435 HTML \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043e\u0442 \u0444\u0430\u0439\u043b\u0430 TreeLine \u043a \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c\u0443 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0443 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u0430 \u0441\u0432\u044f\u0437\u044c \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u0414\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b TreeLine (\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f).\n
    \n
    \n\u0412\u0442\u043e\u0440\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0432 \u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0414\u0435\u0440\u0435\u0432\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b (\u0441\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438), \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0438\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0435\u0431-\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430. \u0412 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043e\u043d\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u043f\u0435\u0440\u0432\u0430\u044f \u0444\u043e\u0440\u043c\u0430.", "Text_src": "The HTML export subtypes can export to a single page or to multiple pages. The single page export contains all of the indented output. A navigation pane on the left with links to anchors at node positions is optional.
    \n
    \nThe multiple HTML pages export has one web page per node. It includes a navigation pane on the left with links to the pages with sibling, parent and aunt/uncle nodes.
    \n
    \nMultiple HTML data tables export creates a table in each HTML file that contains the data for a set of siblings, as well as links to the parent and child pages.
    \n
    \nThe Live Tree HTML export uses Javascript and CSS to create an interactive view. Nodes in the tree can be expanded and collapsed, and a separate pane shows the output for all descendants of the selected node. The first form of this export creates separate files that are linked to the existing TreeLine file. These files are intended for use on a web server (browser security usually prevents local access). The HTML file stores the relative path from the TreeLine file to the initial export directory, so this relationship needs to be maintained on the web server. Only the TreeLine file needs to be replaced to update the data (re-export is not required).
    \n
    \nThe second form of Live Tree export creates a single file (with embedded data) that can be accessed from a local web browser. It appears the same as the first form on the browser." }, "format": "HEAD_PARA", "uid": "f1702e52a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u0422\u0435\u043a\u0441\u0442", "Name_src": "Text Export", "Text": "\u0414\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432 \u0442\u0430\u0431\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432, \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u044f\u0442\u044b\u043c\u0438 (CSV) \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0442\u0430\u0431\u0443\u043b\u044f\u0446\u0438\u044f\u043c\u0438. \u042d\u0442\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u0430.\n
    \n
    \n\u0418\u043c\u0435\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u043d\u0435\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u0435\u0441\u044c \u0432\u044b\u0432\u043e\u0434 \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u0431\u0435\u0437 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.", "Text_src": "Data can be exported to tabbed title text, comma-delimited (CSV) tables and tab-delimited tables. These formats are the same as the corresponding import formats.\n
    \n
    \nThere is also an unformatted text export the dumps all of the output into a text file without preserving the tree structure." }, "format": "HEAD_PARA", "uid": "f1702f60a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 XML", "Name_src": "XML Export", "Text": "TreeLine \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0444\u0430\u0439\u043b\u044b XML \u043e\u0431\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430 [\u0438\u043d\u0430\u0447\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 XML]. \u042d\u0442\u043e \u043d\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0443\u0442\u0438\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u2014 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 XML \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0443\u0437\u043b\u043e\u043c, \u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 XML \u2014 \u043f\u043e\u043b\u0435\u043c, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u0435\u0439 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u00abElement_Data\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0442\u0435\u043a\u0441\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 TreeLine \u043a\u0430\u043a \u0441 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432 XML.", "Text_src": "TreeLine will import and export generic XML files. These routines do not have much intelligence - each node becomes an XML element and each field becomes an XML attribute, except for fields named \"Element_Data\" that become the element's text. This lets TreeLine function as a crude XML editor." }, "format": "HEAD_PARA", "uid": "f1703064a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 ODF", "Name_src": "ODF Export", "Text": "\u041f\u0440\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 (ODF), \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Apache OpenOffice \u0438 LibreOffice, TreeLine \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443. \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0438\u043b\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435. \u041b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432\u044b\u0432\u043e\u0434\u0430 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0437\u043b\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u043f\u043e\u0434 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c. \u0424\u0438\u043b\u044c\u0442\u0440 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430. \u041b\u044e\u0431\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 HTML \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f, \u0430 \u0442\u0430\u043a\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u0430\u043a \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f.", "Text_src": "TreeLine will export an outline to an Open Document Format (ODF) text document, compatible with Apache OpenOffice and LibreOffice. The title of each node is assigned a heading style at the appropriate level. Any other text in the output of each node becomes normal text under the heading. The export filter is intended for simple text outlines only. Any HTML formatting is stripped, and objects such as tables and pictures are not supported." }, "format": "HEAD_PARA", "uid": "f170315ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0417\u0430\u043a\u043b\u0430\u0434\u043e\u043a", "Name_src": "Bookmarks Export", "Text": "TreeLine \u043c\u043e\u0436\u0435\u0442 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a \u043a\u0430\u043a \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 Mozilla HTML (\u0431\u0440\u0430\u0443\u0437\u0435\u0440 Firefox), \u0442\u0430\u043a \u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 XBEL (\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b Konqueror, Galeon \u0438 Elinks). TreeLine \u0438\u0449\u0435\u0442 \u043f\u043e\u043b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0443\u0437\u043b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u043e\u0439.", "Text_src": "TreeLine will export bookmark files in both the Mozilla HTML format (Firefox browser) and the XBEL format (Konqueror, Galeon and Elinks browsers). TreeLine will look for a link field in each node that becomes the target of the bookmark." }, "format": "HEAD_PARA", "uid": "f1703262a25a11e7b7c67054d2175f18" }, { "children": [ "f1703442a25a11e7b7c67054d2175f18", "f1703546a25a11e7b7c67054d2175f18", "f170364aa25a11e7b7c67054d2175f18", "f1703744a25a11e7b7c67054d2175f18", "9ff09734dc9011ea887bac675dac20af", "f1703848a25a11e7b7c67054d2175f18", "7e9b3b88c24511e896c7d66a6ab671cb" ], "data": { "Name": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438", "Name_src": "Customizations" }, "format": "HEADINGS", "uid": "f170335ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b", "Name_src": "Options", "Text": "\u041f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 TreeLine \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0432 \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041e\u0431\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b\u00bb. \u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0438\u0437 \u044d\u0442\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445 \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430.", "Text_src": "TreeLine's behavior can be modified with several settings available in \"Tools > General Options\". Most of these options are covered elsewhere in this document." }, "format": "HEAD_PARA", "uid": "f1703442a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0413\u043e\u0440\u044f\u0447\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438", "Name_src": "Keyboard Shortcuts", "Text": "\u0421\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448 [\u0433\u043e\u0440\u044f\u0447\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438] \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0433\u043e\u0440\u044f\u0447\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438\u00bb. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e, \u0432\u044b\u0431\u0440\u0430\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043f\u043e\u043b\u0435, \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043b\u0430\u0432\u0438\u0448.", "Text_src": "Keyboard shortcuts can be customized by using the \"Tools > Set Keyboard Shortcuts\" command. Simply type the new key sequence with the appropriate field selected." }, "format": "HEAD_PARA", "uid": "f1703546a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041f\u0430\u043d\u0435\u043b\u0438 \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432", "Name_src": "Toolbars", "Text": "\u0412 \u043c\u0435\u043d\u044e \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432\u00bb \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0430\u043d\u0435\u043b\u0435\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u041c\u043e\u0436\u043d\u043e \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u043d\u0435\u043b\u0435\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445.", "Text_src": "An editor to customize the toolbars is available from \"Tools > Customize Toolbars\". The number of toolbars can be set, and the buttons on each can be defined." }, "format": "HEAD_PARA", "uid": "f170364aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0428\u0440\u0438\u0444\u0442\u044b", "Name_src": "Fonts", "Text": "\u0428\u0440\u0438\u0444\u0442, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043c\u0435\u043d\u044e \u00ab\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b > \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0448\u0440\u0438\u0444\u0442\u044b\u00bb. \u0422\u0430\u043a\u0436\u0435 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0448\u0440\u0438\u0444\u0442\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u043f\u0430\u043d\u0435\u043b\u044f\u0445 \u0434\u0435\u0440\u0435\u0432\u0430, \u0432\u044b\u0432\u043e\u0434\u0430 \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430.", "Text_src": "The default font used in the application can be set using the \"Tools > Customize Fonts\" menu. There are also options to specify fonts used in the tree views, the output view and the editor views." }, "format": "HEAD_PARA", "uid": "f1703744a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0418\u043a\u043e\u043d\u043a\u0438 \u0414\u0435\u0440\u0435\u0432\u0430", "Name_src": "Tree Icons", "Text": "\u0412 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441 \u0438\u043a\u043e\u043d\u043a\u0430\u043c\u0438 (\u00ab~/.treeline-x.x/icons\u00bb \u0432 Linux, \u00ab\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438\\<\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c >\\AppData\\roaming\\bellz\\treeline-x.x\\icons\u00bb \u0432 Windows). \u0424\u0430\u0439\u043b\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 (PNG \u0438\u043b\u0438 BMP), \u043f\u043e\u043c\u0435\u0449\u0435\u043d\u043d\u044b\u0435 \u0432 \u044d\u0442\u043e\u0442 \u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043a\u043e\u043d\u043e\u043a \u0434\u0435\u0440\u0435\u0432\u0430.", "Text_src": "There is an icons directory in the user configuration directory (\"~/.treeline-x.x/icons\" on Linux, \"Users\\<user>\\AppData\\roaming\\bellz\\treeline-x.x\\icons\" on Windows). Image files (PNG or BMP) placed into this directory are available for use as tree icons." }, "format": "HEAD_PARA", "uid": "f1703848a25a11e7b7c67054d2175f18" }, { "children": [ "b5fe698830e111ebbc097054d2175f18", "7ffeb66ddc8711ea9a87ac675dac20af", "194b0533e5d811e9b5fea44cc8e97404", "db25cd62481e11e989f27054d2175f18", "800a0971305111e991cda44cc8e97404", "9c08f39ee80311e8a510a44cc8e97404", "6610203fd2c111e8b033d66a6ab671cb", "67e95a5bbbf611e891f7a44cc8e97404", "e8e10d33a14311e88e24a44cc8e97404", "4bc47248786711e8a8bfa44cc8e97404", "95a6e90a333f11e89efed66a6ab671cb", "6df9a0c5ba3b11e78e7e3417ebd53aeb", "f1703e7ea25a11e7b7c67054d2175f18", "f1704752a25a11e7b7c67054d2175f18", "f170527ea25a11e7b7c67054d2175f18", "f170652aa25a11e7b7c67054d2175f18", "f1706be2a25a11e7b7c67054d2175f18", "f170748ea25a11e7b7c67054d2175f18", "f1708032a25a11e7b7c67054d2175f18", "f1708ae6a25a11e7b7c67054d2175f18", "f170ab34a25a11e7b7c67054d2175f18", "f170c1aaa25a11e7b7c67054d2175f18", "f170e900a25a11e7b7c67054d2175f18", "f170fddca25a11e7b7c67054d2175f18", "f1710e58a25a11e7b7c67054d2175f18", "f1711f24a25a11e7b7c67054d2175f18" ], "data": { "Name": "\u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439", "Name_src": "Revision History" }, "format": "HEADINGS", "uid": "f1703d8ea25a11e7b7c67054d2175f18" }, { "children": [ "f1703f8ca25a11e7b7c67054d2175f18", "f170427aa25a11e7b7c67054d2175f18" ], "data": { "Name": "March 26, 2017 - Release 2.1.2 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1703e7ea25a11e7b7c67054d2175f18" }, { "children": [ "f170407ca25a11e7b7c67054d2175f18", "f1704176a25a11e7b7c67054d2175f18" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "f1703f8ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It may contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) should probably be used for critical work." }, "format": "BULLETS", "uid": "f170407ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations have not yet been updated." }, "format": "BULLETS", "uid": "f1704176a25a11e7b7c67054d2175f18" }, { "children": [ "f1704360a25a11e7b7c67054d2175f18", "f170445aa25a11e7b7c67054d2175f18", "f1704554a25a11e7b7c67054d2175f18", "f170464ea25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170427aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "DateTime output", "Text": "Fix problems formatting DateTime fields in output views." }, "format": "BULLETS", "uid": "f1704360a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Internal links", "Text": "Fix dialog issues with clicking on targets when creating inline internal links." }, "format": "BULLETS", "uid": "f170445aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data view tabbing", "Text": "Fix a regression that prevented using the tab key to cycle between data edit view items." }, "format": "BULLETS", "uid": "f1704554a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Autosave restore", "Text": "Avoid opening two windows when restoring an auto-saved backup file." }, "format": "BULLETS", "uid": "f170464ea25a11e7b7c67054d2175f18" }, { "children": [ "f1704842a25a11e7b7c67054d2175f18", "f1704b30a25a11e7b7c67054d2175f18", "f1704d1aa25a11e7b7c67054d2175f18" ], "data": { "Name": "March 12, 2017 - Release 2.1.1 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1704752a25a11e7b7c67054d2175f18" }, { "children": [ "f1704928a25a11e7b7c67054d2175f18", "f1704a2ca25a11e7b7c67054d2175f18" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "f1704842a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It may contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) should probably be used for critical work." }, "format": "BULLETS", "uid": "f1704928a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations have not yet been updated." }, "format": "BULLETS", "uid": "f1704a2ca25a11e7b7c67054d2175f18" }, { "children": [ "f1704c20a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f1704b30a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Windows binary", "Text": "The Windows binary is now built using Python 3.6 and PyQt 5.8." }, "format": "BULLETS", "uid": "f1704c20a25a11e7b7c67054d2175f18" }, { "children": [ "f1704f54a25a11e7b7c67054d2175f18", "f170506ca25a11e7b7c67054d2175f18", "f1705166a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1704d1aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Set icon crash", "Text": "Fix a crash when changing the icon on the Type Config page of the Configure Data Types dialog box." }, "format": "BULLETS", "uid": "f1704f54a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Type list issues", "Text": "Fix inconsistent type selections on the Type List page of the Configure Data Types dialog box." }, "format": "BULLETS", "uid": "f170506ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Window placement", "Text": "Fix issues with restoring the placement of the TreeLine window in some multiple monitor setups." }, "format": "BULLETS", "uid": "f1705166a25a11e7b7c67054d2175f18" }, { "children": [ "f170536ea25a11e7b7c67054d2175f18", "f170565ca25a11e7b7c67054d2175f18", "f170603ea25a11e7b7c67054d2175f18", "f1706228a25a11e7b7c67054d2175f18" ], "data": { "Name": "February 20, 2017 - Release 2.1.0 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170527ea25a11e7b7c67054d2175f18" }, { "children": [ "f170545ea25a11e7b7c67054d2175f18", "f1705558a25a11e7b7c67054d2175f18" ], "data": { "Name": "Notes" }, "format": "BULLET_HEADING", "uid": "f170536ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unstable snapshot", "Text": "This is an unstable development snapshot of TreeLine. It probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) should probably be used for critical work." }, "format": "BULLETS", "uid": "f170545ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Translations", "Text": "The GUI and documentation translations have not yet been updated." }, "format": "BULLETS", "uid": "f1705558a25a11e7b7c67054d2175f18" }, { "children": [ "f170574ca25a11e7b7c67054d2175f18", "f1705850a25a11e7b7c67054d2175f18", "f1705954a25a11e7b7c67054d2175f18", "f1705a4ea25a11e7b7c67054d2175f18", "f1705b48a25a11e7b7c67054d2175f18", "f1705c4ca25a11e7b7c67054d2175f18", "f1705d46a25a11e7b7c67054d2175f18", "f1705e40a25a11e7b7c67054d2175f18", "f1705f3aa25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170565ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Port to Qt5", "Text": "TreeLine has been ported from the Qt4 library to the Qt5 library. The system requirements have been updated to Python 3.4 or higher, PyQt 5.4 or higher and Qt 5.4 or higher." }, "format": "BULLETS", "uid": "f170574ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Cloned nodes", "Text": "Cloned nodes that can duplicate sections of the tree have been added. Editing their data or child structure in one location changes all locations. They are created by copying nodes and then using the \"Edit->Paste Cloned Node\" command to paste them elsewhere. The clone link can be removed by deleting the nodes or by cutting them and pasting them back using the regular paste command." }, "format": "BULLETS", "uid": "f1705850a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "DateTime field", "Text": "Added a new DateTime field that combines dates and times into a single field that is useful for timestamps. The editor format is a combination of the date and time formats from the general options, separated by a space." }, "format": "BULLETS", "uid": "f1705954a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML in choice fields", "Text": "Added an option to allow HTML tags in Choice, AutoChoice, Combination, AutoCombination and RegularExpression fields. The control is in the Field Config tab of the Configure Data Types dialog. This option is disabled by default. If enabled, special characters (angled brackets and quotation marks) will need to be escaped to show up in text." }, "format": "BULLETS", "uid": "f1705a4ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved conditional rules", "Text": "Saved rules for Conditional Find and Conditional Filter commands are listed directly in the dialog boxes, making them easier to load and save." }, "format": "BULLETS", "uid": "f1705b48a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "CSV import/export", "Text": "Added comma-delimited (CSV) table import and export, similar to existing tab-delimited table import and export. The export only handles data from a single level of child nodes." }, "format": "BULLETS", "uid": "f1705c4ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Incremental title search", "Text": "Added a quick, incremental search of node titles. By default, it's bound to ctrl+/. Then, matching titles are found as the search string is typed. The F3 and shift+F3 keys can be used to go to the next or previous matches, respectively." }, "format": "BULLETS", "uid": "f1705d46a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Multiple field selection", "Text": "Multiple fields can now be selected in the Output page of the Configuration dialog, so several fields can be added to the formats simultaneously." }, "format": "BULLETS", "uid": "f1705e40a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Print settings", "Text": "A pull-down selector for printers has been added to the Print Setup dialog. This enables TreeLine to verify that the page size and margin settings are supported by the current printer." }, "format": "BULLETS", "uid": "f1705f3aa25a11e7b7c67054d2175f18" }, { "children": [ "f170612ea25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f170603ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "SpacedText Field special characters", "Text": "The SpacedText Field now allows special HTML characters (angled brackets and quotation marks) without requiring them to be manually escaped." }, "format": "BULLETS", "uid": "f170612ea25a11e7b7c67054d2175f18" }, { "children": [ "f170630ea25a11e7b7c67054d2175f18", "f1706426a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1706228a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Printed page splits", "Text": "The code that splits content into pages when printing has been improved. It now handles very long nodes better." }, "format": "BULLETS", "uid": "f170630ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Formatted field title edits", "Text": "When formatted fields (dates, times, etc.) are used in node titles, editing the titles in the tree or in the Title List pane will now work if the edit and output formats are similar." }, "format": "BULLETS", "uid": "f1706426a25a11e7b7c67054d2175f18" }, { "children": [ "f1706610a25a11e7b7c67054d2175f18", "f1706804a25a11e7b7c67054d2175f18" ], "data": { "Name": "October 3, 2015 - Release 2.0.2 (new stable release)" }, "format": "HEADINGS", "uid": "f170652aa25a11e7b7c67054d2175f18" }, { "children": [ "f1706700a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1706610a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data edit regression", "Text": "Fixed a major regression in 2.0.1 that broke data editors for most specialized field types (number, math, boolean, choice, etc.)" }, "format": "BULLETS", "uid": "f1706700a25a11e7b7c67054d2175f18" }, { "children": [ "f17068f4a25a11e7b7c67054d2175f18", "f17069e4a25a11e7b7c67054d2175f18", "f1706ae8a25a11e7b7c67054d2175f18" ], "data": { "Name": "Compatibility Notes" }, "format": "BULLET_HEADING", "uid": "f1706804a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File format", "Text": "There are some file format changes between TreeLine 1.4.x and this version of TreeLine." }, "format": "BULLETS", "uid": "f17068f4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File conversion", "Text": "Older files opened in this version are automatically converted when saved." }, "format": "BULLETS", "uid": "f17069e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File compatibility", "Text": "Files saved in this version may not be fully compatible with TreeLine 1.4.x." }, "format": "BULLETS", "uid": "f1706ae8a25a11e7b7c67054d2175f18" }, { "children": [ "f1706cd2a25a11e7b7c67054d2175f18", "f1706fb6a25a11e7b7c67054d2175f18" ], "data": { "Name": "September 26, 2015 - Release 2.0.1 (new stable release)" }, "format": "HEADINGS", "uid": "f1706be2a25a11e7b7c67054d2175f18" }, { "children": [ "f1706db8a25a11e7b7c67054d2175f18", "f1706ebca25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f1706cd2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Plugin options", "Text": "Added methods to the plugin interface that allow general program options to be queried and changed." }, "format": "BULLETS", "uid": "f1706db8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Table import errors", "Text": "Improve text table import error messages by including the line number where the problem is found." }, "format": "BULLETS", "uid": "f1706ebca25a11e7b7c67054d2175f18" }, { "children": [ "f170709ca25a11e7b7c67054d2175f18", "f1707196a25a11e7b7c67054d2175f18", "f1707290a25a11e7b7c67054d2175f18", "f1707380a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1706fb6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data edit undo", "Text": "Reduce the amount of work that a single undo command removes from editors in the data edit view." }, "format": "BULLETS", "uid": "f170709ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Configuration changes", "Text": "Fixed a bug that prevented setting the unique ID reference field on a newly created data type." }, "format": "BULLETS", "uid": "f1707196a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Legacy newline convert", "Text": "Preserve hard newlines in text fields when converting TreeLine 1.4.x files to this version." }, "format": "BULLETS", "uid": "f1707290a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Indent expand status", "Text": "Fix problems preserving expand/collapse node states when indenting and unindenting nodes." }, "format": "BULLETS", "uid": "f1707380a25a11e7b7c67054d2175f18" }, { "children": [ "f1707592a25a11e7b7c67054d2175f18", "f1707c5ea25a11e7b7c67054d2175f18" ], "data": { "Name": "May 17, 2015 - Release 2.0.0 (new stable release)" }, "format": "HEADINGS", "uid": "f170748ea25a11e7b7c67054d2175f18" }, { "children": [ "f1707682a25a11e7b7c67054d2175f18", "f170777ca25a11e7b7c67054d2175f18", "f1707876a25a11e7b7c67054d2175f18", "f1707966a25a11e7b7c67054d2175f18", "f1707a60a25a11e7b7c67054d2175f18", "f1707b5aa25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f1707592a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Treepad import update", "Text": "Modified the Treepad file import to use SpacedText fields to more closely match Treepad formatting." }, "format": "BULLETS", "uid": "f1707682a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Treepad export", "Text": "An optional plugin was written that can export files to the Treepad text file format." }, "format": "BULLETS", "uid": "f170777ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "New icon", "Text": "The TreeLine icon was replaced with a new one. Thanks to David Reimer for contributing the artwork." }, "format": "BULLETS", "uid": "f1707876a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Translation updates", "Text": "The German and Portuguese GUI translations were updated." }, "format": "BULLETS", "uid": "f1707966a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sample file updates", "Text": "Updated the long text sample file to include the SpacedText field type, and added a conditional equation to the math sample file." }, "format": "BULLETS", "uid": "f1707a60a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Documentation update", "Text": "Updated the Math Field section of the documentation." }, "format": "BULLETS", "uid": "f1707b5aa25a11e7b7c67054d2175f18" }, { "children": [ "f1707d44a25a11e7b7c67054d2175f18", "f1707e3ea25a11e7b7c67054d2175f18", "f1707f38a25a11e7b7c67054d2175f18" ], "data": { "Name": "Compatibility Notes" }, "format": "BULLET_HEADING", "uid": "f1707c5ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File format", "Text": "There are some file format changes between TreeLine 1.4.x and this version of TreeLine." }, "format": "BULLETS", "uid": "f1707d44a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File conversion", "Text": "Older files opened in this version are automatically converted when saved." }, "format": "BULLETS", "uid": "f1707e3ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File compatibility", "Text": "Files saved in this version may not be fully compatible with TreeLine 1.4.x." }, "format": "BULLETS", "uid": "f1707f38a25a11e7b7c67054d2175f18" }, { "children": [ "f1708118a25a11e7b7c67054d2175f18", "f17083fca25a11e7b7c67054d2175f18", "f1708802a25a11e7b7c67054d2175f18" ], "data": { "Name": "March 29, 2015 - Release 1.9.7 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1708032a25a11e7b7c67054d2175f18" }, { "children": [ "f1708208a25a11e7b7c67054d2175f18", "f1708302a25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f1708118a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field conditions", "Text": "Added comparison operators and conditional if statements to math field equations. The operators can be used with a new boolean result type, or as a part of numeric, date, time or text expressions." }, "format": "BULLETS", "uid": "f1708208a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field text operations", "Text": "Text operators were made available in math field equations, and the result type can be set to text. This allows math fields to combine text from other fields, replace sub-strings and change capitalization." }, "format": "BULLETS", "uid": "f1708302a25a11e7b7c67054d2175f18" }, { "children": [ "f17084eca25a11e7b7c67054d2175f18", "f17085f0a25a11e7b7c67054d2175f18", "f17086fea25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f17083fca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved status bar message", "Text": "Added a \"file saved\" status bar message." }, "format": "BULLETS", "uid": "f17084eca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "German translation", "Text": "Added a German GUI translation." }, "format": "BULLETS", "uid": "f17085f0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Portuguese translation", "Text": "Updated the Portuguese GUI translation." }, "format": "BULLETS", "uid": "f17086fea25a11e7b7c67054d2175f18" }, { "children": [ "f17088e8a25a11e7b7c67054d2175f18", "f17089e2a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f1708802a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Combination editor", "Text": "Fixed a focus problem that made Combination and AutoCombination field editor pull-downs unusable." }, "format": "BULLETS", "uid": "f17088e8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Choice editor", "Text": "Fixed a focus problem that made the pull-downs in choice and boolean field editors unusable on Linux." }, "format": "BULLETS", "uid": "f17089e2a25a11e7b7c67054d2175f18" }, { "children": [ "f1708bcca25a11e7b7c67054d2175f18", "f17097aca25a11e7b7c67054d2175f18", "f170a2eca25a11e7b7c67054d2175f18" ], "data": { "Name": "March 10, 2015 - Release 1.9.6 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1708ae6a25a11e7b7c67054d2175f18" }, { "children": [ "f1708cbca25a11e7b7c67054d2175f18", "f1708db6a25a11e7b7c67054d2175f18", "f1708ea6a25a11e7b7c67054d2175f18", "f1708faaa25a11e7b7c67054d2175f18", "f17090aea25a11e7b7c67054d2175f18", "f17091e4a25a11e7b7c67054d2175f18", "f17092dea25a11e7b7c67054d2175f18", "f1709644a25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f1708bcca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "OneLineText field", "Text": "Added a new OneLineText field type that restricts the text length to a single line." }, "format": "BULLETS", "uid": "f1708cbca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "All Types conditional test", "Text": "Added an All Types option to the conditional find and filter commands. This allows multiple node types to be found or filtered at the same time. The fields from every type are available for use in conditions. The conditions give a false result for all node types that do not contain that field name." }, "format": "BULLETS", "uid": "f1708db6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field dates and times", "Text": "Added support for date and time calculations using math fields. Math equation result types can be set to numeric, date or time output. Date fields can be subtracted to give the number of days elapsed, and numbers of days can be added to or subtracted from dates, resulting in new dates. Time fields can be subtracted to give the number of seconds elapsed, and numbers of seconds can be added to or subtracted from times, resulting in new times." }, "format": "BULLETS", "uid": "f1708ea6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field root references", "Text": "In math fields, added an equation reference level to reference fields in the root node. This provides a place for \"constant\" field values that can be referenced from any node but only need to be changed in one location." }, "format": "BULLETS", "uid": "f1708faaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Plugin interface", "Text": "Support was added for plugin extension modules. Most of the interface methods from TreeLine 1.4.x were duplicated to ease porting of old plugins. Of course, old plugins must be ported from Python 2.x to Python 3.x, and there are multi-window implementation differences. New interfaces allow the creation of new field types and the execution of any menu command. Sample plugins are available on the TreeLine download page." }, "format": "BULLETS", "uid": "f17090aea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Automatic HTML tags", "Text": "Added text formatting and link commands for HTML fields that add tags to the HTML content." }, "format": "BULLETS", "uid": "f17091e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Open in folder", "Text": "An open in folder command was added to external link field editors to open the directory in a file manager." }, "format": "BULLETS", "uid": "f17092dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Select All command", "Text": "Added the Select All command to global menus with a different default shortcut key (ctrl-L) to avoid conflicts with the add child shortcut." }, "format": "BULLETS", "uid": "f1709644a25a11e7b7c67054d2175f18" }, { "children": [ "f170989ca25a11e7b7c67054d2175f18", "f170998ca25a11e7b7c67054d2175f18", "f1709a7ca25a11e7b7c67054d2175f18", "f1709b8aa25a11e7b7c67054d2175f18", "f1709c7aa25a11e7b7c67054d2175f18", "f1709d6aa25a11e7b7c67054d2175f18", "f1709e50a25a11e7b7c67054d2175f18", "f1709f40a25a11e7b7c67054d2175f18", "f170a026a25a11e7b7c67054d2175f18", "f170a116a25a11e7b7c67054d2175f18", "f170a206a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f17097aca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data edit view focus", "Text": "Improved the focus handling for data edit view edit boxes. This eliminates the blue outline for boxes in inactive data edit views. It also makes tab-to-focus more predictable, including fully selecting single-line field types when they receive tab focus." }, "format": "BULLETS", "uid": "f170989ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Data editor resize", "Text": "Data edit boxes are now automatically resized when editing is complete and the focus moves to another row." }, "format": "BULLETS", "uid": "f170998ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Drag external links", "Text": "Allow files to be drag & dropped on data edit boxes to create external links." }, "format": "BULLETS", "uid": "f1709a7ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Stay-on-top dialogs", "Text": "Small, non-modal dialogs, such as those for sorting, numbering, finding and filtering, have been set to stay on top, so they won't be obscured by TreeLine windows." }, "format": "BULLETS", "uid": "f1709b8aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Opening external links", "Text": "Made opening associated programs from external file links more consistent, especially in Linux." }, "format": "BULLETS", "uid": "f1709c7aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Copy types from file", "Text": "The copy types from file command now supports encrypted and compressed files." }, "format": "BULLETS", "uid": "f1709d6aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Wait cursors", "Text": "Added wait cursors to TreeLine operations that could be time consuming." }, "format": "BULLETS", "uid": "f1709e50a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Context menus", "Text": "Improved the consistency of context menus and shortcut commands used in edit boxes." }, "format": "BULLETS", "uid": "f1709f40a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Portuguese translation", "Text": "Added a nearly complete Portuguese GUI translation." }, "format": "BULLETS", "uid": "f170a026a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sample file languages", "Text": "Added support for sample TreeLine files to be provided in alternate languages." }, "format": "BULLETS", "uid": "f170a116a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Documentation translation", "Text": "Prepared the help file for translation into other languages," }, "format": "BULLETS", "uid": "f170a206a25a11e7b7c67054d2175f18" }, { "children": [ "f170a3d2a25a11e7b7c67054d2175f18", "f170a4b8a25a11e7b7c67054d2175f18", "f170a5a8a25a11e7b7c67054d2175f18", "f170a698a25a11e7b7c67054d2175f18", "f170a77ea25a11e7b7c67054d2175f18", "f170a86ea25a11e7b7c67054d2175f18", "f170a95ea25a11e7b7c67054d2175f18", "f170aa44a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170a2eca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Duplicate unique IDs", "Text": "Corrupted TreeLine files with the same unique ID assigned to multiple nodes no longer fail to open. The user is warned that unique IDs have been updated, which could break some internal links." }, "format": "BULLETS", "uid": "f170a3d2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional field list", "Text": "Fixed missing fields in the pull-down list in the conditional find and filter dialog boxes when a rule was re-used after a node type change. " }, "format": "BULLETS", "uid": "f170a4b8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field missing references", "Text": "Fixed problems with math fields that reference non-existing fields in parent or child nodes." }, "format": "BULLETS", "uid": "f170a5a8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field type updates", "Text": "Made math fields update properly after node type changes." }, "format": "BULLETS", "uid": "f170a698a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Rename bullet/table fields", "Text": "Fixed inconsistent updates after renaming fields used with bulleted or tabled output." }, "format": "BULLETS", "uid": "f170a77ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Copying descendants", "Text": "Made node copy-paste and drag-and-drop work when the initial selection includes both parent and child nodes. " }, "format": "BULLETS", "uid": "f170a86ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Tabbed text import", "Text": "When importing a tabbed text file with multiple top-level nodes, create a single higher-level node to prevent failure." }, "format": "BULLETS", "uid": "f170a95ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Custom toolbar dialog", "Text": "Fixed the availability of the move up button in the customize toolbar dialog when the second command in the list is selected." }, "format": "BULLETS", "uid": "f170aa44a25a11e7b7c67054d2175f18" }, { "children": [ "f170ac38a25a11e7b7c67054d2175f18", "f170afeea25a11e7b7c67054d2175f18", "f170b836a25a11e7b7c67054d2175f18" ], "data": { "Name": "December 31, 2014 - Release 1.9.5 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170ab34a25a11e7b7c67054d2175f18" }, { "children": [ "f170ad1ea25a11e7b7c67054d2175f18", "f170ae0ea25a11e7b7c67054d2175f18", "f170aefea25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170ac38a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Math field type", "Text": "Added a math field type that is configured by defining an equation. The field value is automatically calculated based on references to numerical values in other nodes. See the \"sample_math_fields\" file for a usage example." }, "format": "BULLETS", "uid": "f170ad1ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Clear formatting", "Text": "Added a Clear Formatting command that removes font changes and links from data editor text." }, "format": "BULLETS", "uid": "f170ae0ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "GUI Translations", "Text": "Made source code changes necessary to support user interface translations into other languages. The actual translation work remains to be done." }, "format": "BULLETS", "uid": "f170aefea25a11e7b7c67054d2175f18" }, { "children": [ "f170b0caa25a11e7b7c67054d2175f18", "f170b1baa25a11e7b7c67054d2175f18", "f170b2aaa25a11e7b7c67054d2175f18", "f170b390a25a11e7b7c67054d2175f18", "f170b480a25a11e7b7c67054d2175f18", "f170b570a25a11e7b7c67054d2175f18", "f170b656a25a11e7b7c67054d2175f18", "f170b746a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f170afeea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Combination field scroll bars", "Text": "Add scroll bars to the pull-down editors for combination fields with many entries." }, "format": "BULLETS", "uid": "f170b0caa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "External link truncation", "Text": "Reduce the truncation of external link URLs when generating default display names." }, "format": "BULLETS", "uid": "f170b1baa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "File newlines", "Text": "Use Unix-style newlines for saved TreeLine files to keep files consistent across platforms." }, "format": "BULLETS", "uid": "f170b2aaa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML panes", "Text": "Update the CSS code in exported HTML with navigation panes to improve the appearance in some browsers." }, "format": "BULLETS", "uid": "f170b390a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Undo optimization", "Text": "Optimize some undo information to reduce the amount of data in memory." }, "format": "BULLETS", "uid": "f170b480a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Move sample files", "Text": "Move sample files into a separate directory to avoid future translation conflicts." }, "format": "BULLETS", "uid": "f170b570a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Installer clarification", "Text": "Clarify a Linux installer error message when checking for the Python 3 version of PyQt." }, "format": "BULLETS", "uid": "f170b656a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Include MSVC files", "Text": "Include MSVCR DLL files in the Windows installer." }, "format": "BULLETS", "uid": "f170b746a25a11e7b7c67054d2175f18" }, { "children": [ "f170b91ca25a11e7b7c67054d2175f18", "f170ba0ca25a11e7b7c67054d2175f18", "f170baf2a25a11e7b7c67054d2175f18", "f170bbeca25a11e7b7c67054d2175f18", "f170bcf0a25a11e7b7c67054d2175f18", "f170bde0a25a11e7b7c67054d2175f18", "f170bed0a25a11e7b7c67054d2175f18", "f170bfc0a25a11e7b7c67054d2175f18", "f170c0a6a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170b836a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Applying config dialog settings", "Text": "Fix problems applying multiple configuration changes while the Configure Data Types dialog box remains open." }, "format": "BULLETS", "uid": "f170b91ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Title list line split", "Text": "In the Title List editor, splitting a title into two lines now creates a new node without losing the children and parameters of the original node." }, "format": "BULLETS", "uid": "f170ba0ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Title list undo", "Text": "Fix the undo command in the Title List View so that deleted lines/nodes are properly restored. " }, "format": "BULLETS", "uid": "f170baf2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Sorting by fields", "Text": "When sorting nodes by fields, properly handle a reverse direction." }, "format": "BULLETS", "uid": "f170bbeca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Find and replace", "Text": "Fix problems with the find and replace command when a particular node type is specified." }, "format": "BULLETS", "uid": "f170bcf0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional types", "Text": "Fix problems defining conditional types from the Configure Data Types dialog box." }, "format": "BULLETS", "uid": "f170bde0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Apply font sizes", "Text": "Correctly apply font size formatting to selections with mixed font sizes." }, "format": "BULLETS", "uid": "f170bed0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Editor height", "Text": "Fix the height of long text field editors with customized data editor fonts." }, "format": "BULLETS", "uid": "f170bfc0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Base 64 image export", "Text": "Fix HTML export of Base 64 images." }, "format": "BULLETS", "uid": "f170c0a6a25a11e7b7c67054d2175f18" }, { "children": [ "f170c286a25a11e7b7c67054d2175f18", "f170e068a25a11e7b7c67054d2175f18", "f170e46ea25a11e7b7c67054d2175f18" ], "data": { "Name": "March 8, 2014 - Release 1.9.4 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170c1aaa25a11e7b7c67054d2175f18" }, { "children": [ "f170d8d4a25a11e7b7c67054d2175f18", "f170d9d8a25a11e7b7c67054d2175f18", "f170dac8a25a11e7b7c67054d2175f18", "f170dbb8a25a11e7b7c67054d2175f18", "f170dca8a25a11e7b7c67054d2175f18", "f170dd98a25a11e7b7c67054d2175f18", "f170de88a25a11e7b7c67054d2175f18", "f170df6ea25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170c286a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Documentation", "Text": "Created new documentation, including a TreeLine file with details and a text file with basic usage instructions. Both are accessible from the help menu." }, "format": "BULLETS", "uid": "f170d8d4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Font settings", "Text": "Added customizing of default fonts used in the tree, output and editor views." }, "format": "BULLETS", "uid": "f170d9d8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spaced text field", "Text": "Added a new SpacedText field type that holds plain text and preserves all spacing." }, "format": "BULLETS", "uid": "f170dac8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Combination editor", "Text": "Combination and auto combination field types now use a simpler checkbox style pull-down editor." }, "format": "BULLETS", "uid": "f170dbb8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Autosave option", "Text": "An autosave option was added." }, "format": "BULLETS", "uid": "f170dca8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unique ID output", "Text": "A unique ID reference field was added to the file info fields to allow node unique IDs to be included in output formats." }, "format": "BULLETS", "uid": "f170dd98a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Paste plain text", "Text": "A plain text paste command was added to paste non-formatted text to data editors." }, "format": "BULLETS", "uid": "f170de88a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Indent option", "Text": "Added an option to set the child indent offset amount." }, "format": "BULLETS", "uid": "f170df6ea25a11e7b7c67054d2175f18" }, { "children": [ "f170e162a25a11e7b7c67054d2175f18", "f170e252a25a11e7b7c67054d2175f18", "f170e36aa25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f170e068a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Print preview size", "Text": "The last size and position of the print preview window are remembered and restored." }, "format": "BULLETS", "uid": "f170e162a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Page breaks in nodes", "Text": "When printing, nodes with long text content are split between pages." }, "format": "BULLETS", "uid": "f170e252a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Export relative links", "Text": "In multiple page HTML exports, relative links in the content are adjusted based on the directory depth." }, "format": "BULLETS", "uid": "f170e36aa25a11e7b7c67054d2175f18" }, { "children": [ "f170e54aa25a11e7b7c67054d2175f18", "f170e63aa25a11e7b7c67054d2175f18", "f170e720a25a11e7b7c67054d2175f18", "f170e810a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170e46ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Blank nodes", "Text": "Fixed problems outputting completely blank nodes." }, "format": "BULLETS", "uid": "f170e54aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional rules", "Text": "Problems with the contains and true/false conditional rules were fixed." }, "format": "BULLETS", "uid": "f170e63aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Link dialogs", "Text": "Fixed issues displaying several editor link dialogs in quick succession." }, "format": "BULLETS", "uid": "f170e720a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Output config cursor", "Text": "In the configure data types dialog, the output format cursor no longer moves when switching to other field references." }, "format": "BULLETS", "uid": "f170e810a25a11e7b7c67054d2175f18" }, { "children": [ "f170e9dca25a11e7b7c67054d2175f18", "f170f12aa25a11e7b7c67054d2175f18", "f170f846a25a11e7b7c67054d2175f18" ], "data": { "Name": "January 19, 2014 - Release 1.9.3 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170e900a25a11e7b7c67054d2175f18" }, { "children": [ "f170eac2a25a11e7b7c67054d2175f18", "f170eba8a25a11e7b7c67054d2175f18", "f170ec8ea25a11e7b7c67054d2175f18", "f170ed74a25a11e7b7c67054d2175f18", "f170ee5aa25a11e7b7c67054d2175f18", "f170ef4aa25a11e7b7c67054d2175f18", "f170f030a25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170e9dca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Keyboard shortcuts", "Text": "Added controls in the Tools menu for customizing TreeLine's keyboard shortcuts." }, "format": "BULLETS", "uid": "f170eac2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Toolbars", "Text": "Controls for customizing TreeLine's toolbar buttons were added to the Tools menu." }, "format": "BULLETS", "uid": "f170eba8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional search", "Text": "New dialogs were created for conditional finding and filtering of nodes. Specific conditions can be applied to individual types and fields, and the conditions can be saved." }, "format": "BULLETS", "uid": "f170ec8ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Find and replace", "Text": "Find and replace functionality was added to search and change nodes' text data. The search can be limited to specific types and fields." }, "format": "BULLETS", "uid": "f170ed74a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Table output", "Text": "A new option for output data in tables was added to the Type Config pane of the Configure Data Types dialog. Each line of the output format becomes a column. Any text at the start of the format line that is followed by a colon becomes a table heading." }, "format": "BULLETS", "uid": "f170ee5aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Bullet output", "Text": "An option to add bullets to the output of child nodes was added to the Type Config pane of the Configure Data Types dialog." }, "format": "BULLETS", "uid": "f170ef4aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Toggle selections", "Text": "Added View > Previous Selection and Next Selection commands to step through the node selection history." }, "format": "BULLETS", "uid": "f170f030a25a11e7b7c67054d2175f18" }, { "children": [ "f170f210a25a11e7b7c67054d2175f18", "f170f2f6a25a11e7b7c67054d2175f18", "f170f418a25a11e7b7c67054d2175f18", "f170f4fea25a11e7b7c67054d2175f18", "f170f5e4a25a11e7b7c67054d2175f18", "f170f6d4a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f170f12aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Drop to reorder", "Text": "Nodes can now be reordered by dragging and dropping them between sibling nodes." }, "format": "BULLETS", "uid": "f170f210a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Date entry formats", "Text": "The keyboard entry of dates and times into fields was made more flexible by allowing entries such as 4-digit years that don't exactly match the entry format." }, "format": "BULLETS", "uid": "f170f2f6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Default link names", "Text": "Any text selection is now used as the default name for links inserted into text fields." }, "format": "BULLETS", "uid": "f170f418a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Anchor links", "Text": "Links to local named anchors in a node's HTML text content now work if they don't conflict with any node unique IDs." }, "format": "BULLETS", "uid": "f170f4fea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Line spacing", "Text": "Line spacing in output views was made more consistent." }, "format": "BULLETS", "uid": "f170f5e4a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved states", "Text": "Improved the efficiency of restoring node open/close states when opening files." }, "format": "BULLETS", "uid": "f170f6d4a25a11e7b7c67054d2175f18" }, { "children": [ "f170f936a25a11e7b7c67054d2175f18", "f170fa1ca25a11e7b7c67054d2175f18", "f170fb0ca25a11e7b7c67054d2175f18", "f170fbf2a25a11e7b7c67054d2175f18", "f170fce2a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f170f846a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Paste font sizes", "Text": "Errors when pasting text with varying font sizes into data editors were fixed." }, "format": "BULLETS", "uid": "f170f936a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional data types", "Text": "Various issues with conditional data types were fixed, including problems with pasting conditional nodes and prompt updating when the types change." }, "format": "BULLETS", "uid": "f170fa1ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Drag undo", "Text": "Problems with undoing the dragging and dropping of a node were fixed." }, "format": "BULLETS", "uid": "f170fb0ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Expand branches", "Text": "Fix the extremely slow operation of the View > Expand Full Branch and Collapse Full Branch commands." }, "format": "BULLETS", "uid": "f170fbf2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Printed lines", "Text": "Fix improperly placed branch lines in printed output." }, "format": "BULLETS", "uid": "f170fce2a25a11e7b7c67054d2175f18" }, { "children": [ "f170fec2a25a11e7b7c67054d2175f18", "f171053ea25a11e7b7c67054d2175f18", "f17108e0a25a11e7b7c67054d2175f18" ], "data": { "Name": "October 22, 2013 - Release 1.9.2 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f170fddca25a11e7b7c67054d2175f18" }, { "children": [ "f170ffa8a25a11e7b7c67054d2175f18", "f171008ea25a11e7b7c67054d2175f18", "f171017ea25a11e7b7c67054d2175f18", "f1710264a25a11e7b7c67054d2175f18", "f171034aa25a11e7b7c67054d2175f18", "f1710430a25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f170fec2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Spell check", "Text": "Added a spell check tool. This requires either aspell, ispell or hunspell to be installed." }, "format": "BULLETS", "uid": "f170ffa8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Numbering field type", "Text": "Included a node numbering field type with several formatting options. An update numbering command fills in the sequence." }, "format": "BULLETS", "uid": "f171008ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Add category level", "Text": "Added a command to add a category level based on a subset of data fields." }, "format": "BULLETS", "uid": "f171017ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Flatten by category", "Text": "Added a flatten by category command to combine parent fields into child nodes." }, "format": "BULLETS", "uid": "f1710264a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Flatten by link", "Text": "A new flatten by link command flattens the structure and provides internal links to the former parent nodes." }, "format": "BULLETS", "uid": "f171034aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Arrange by link", "Text": "An arrange by link command restores the structure based on parent internal links." }, "format": "BULLETS", "uid": "f1710430a25a11e7b7c67054d2175f18" }, { "children": [ "f171061aa25a11e7b7c67054d2175f18", "f171070aa25a11e7b7c67054d2175f18", "f17107f0a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f171053ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "URL drag-and-drop", "Text": "Allow file URL drag-and-drop on active external link data edit widgets." }, "format": "BULLETS", "uid": "f171061aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Share directory", "Text": "Change the Linux installer to use the 'share' directory in place of 'lib' for python files." }, "format": "BULLETS", "uid": "f171070aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Windows binary", "Text": "Update the Windows binary to use version 3.3 of Python." }, "format": "BULLETS", "uid": "f17107f0a25a11e7b7c67054d2175f18" }, { "children": [ "f17109bca25a11e7b7c67054d2175f18", "f1710aa2a25a11e7b7c67054d2175f18", "f1710b88a25a11e7b7c67054d2175f18", "f1710c78a25a11e7b7c67054d2175f18", "f1710d68a25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f17108e0a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Output line sequence", "Text": "Fix out of sequence output lines when output formats are longer than ten lines." }, "format": "BULLETS", "uid": "f17109bca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Node indenting", "Text": "Fix problems with unique IDs and internal links when indenting and unindenting nodes." }, "format": "BULLETS", "uid": "f1710aa2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Widget focus problems", "Text": "Avoid widget focus problems when editing data on conditional types." }, "format": "BULLETS", "uid": "f1710b88a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Format cursor position", "Text": "Maintain the output format cursor position when changing fields in the configure dialog." }, "format": "BULLETS", "uid": "f1710c78a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "XML import", "Text": "Fix importing of generic XML documents that have nodes with no data." }, "format": "BULLETS", "uid": "f1710d68a25a11e7b7c67054d2175f18" }, { "children": [ "f1710f48a25a11e7b7c67054d2175f18", "f17118a8a25a11e7b7c67054d2175f18" ], "data": { "Name": "May 2, 2013 - Release 1.9.1 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1710e58a25a11e7b7c67054d2175f18" }, { "children": [ "f171102ea25a11e7b7c67054d2175f18", "f171111ea25a11e7b7c67054d2175f18", "f171120ea25a11e7b7c67054d2175f18", "f17112fea25a11e7b7c67054d2175f18", "f17113eea25a11e7b7c67054d2175f18", "f17114dea25a11e7b7c67054d2175f18", "f17115d8a25a11e7b7c67054d2175f18", "f17116c8a25a11e7b7c67054d2175f18", "f17117b8a25a11e7b7c67054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "f1710f48a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Compression and encryption", "Text": "Added TreeLine file compression and file encryption, controlled from a File > Properties dialog box." }, "format": "BULLETS", "uid": "f171102ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Restore tree states", "Text": "Tree node open/close states are restored for recent files." }, "format": "BULLETS", "uid": "f171111ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Derived data types", "Text": "Added derived data types that keep the field list of their generic type." }, "format": "BULLETS", "uid": "f171120ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Conditional type setting", "Text": "Added conditional type setting that changes icons or output format based on field contents." }, "format": "BULLETS", "uid": "f17112fea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Other field references", "Text": "Other field references (file info, ancestors, children) can be used in node output formats and in print headers & footers." }, "format": "BULLETS", "uid": "f17113eea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "HTML file export", "Text": "Added an HTML file export to a single file with a navigation pane on the side." }, "format": "BULLETS", "uid": "f17114dea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Embedded blank lines", "Text": "Allow embedded blank lines in non-HTML node output formats." }, "format": "BULLETS", "uid": "f17115d8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Separator config option", "Text": "Added an output separator config option for combination fields and child references." }, "format": "BULLETS", "uid": "f17116c8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "First day of week option", "Text": "Add an option to set the first day of the week for calendar widgets." }, "format": "BULLETS", "uid": "f17117b8a25a11e7b7c67054d2175f18" }, { "children": [ "f1711998a25a11e7b7c67054d2175f18", "f1711a88a25a11e7b7c67054d2175f18", "f1711b6ea25a11e7b7c67054d2175f18", "f1711c54a25a11e7b7c67054d2175f18", "f1711d44a25a11e7b7c67054d2175f18", "f1711e2aa25a11e7b7c67054d2175f18" ], "data": { "Name": "Bug Fixes" }, "format": "BULLET_HEADING", "uid": "f17118a8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Drag multiple nodes", "Text": "Fixed problems with pasting or dragging multiple nodes." }, "format": "BULLETS", "uid": "f1711998a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Remove fields from multi-line output formats", "Text": "Made removing fields from multi-line output formats work properly." }, "format": "BULLETS", "uid": "f1711a88a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Prevent duplicate unique IDs", "Text": "Prevent duplicate unique IDs from being created after undoing the deletion of a branch." }, "format": "BULLETS", "uid": "f1711b6ea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Fixed non-text nodes sorting", "Text": "Fixed node sorting of non-text nodes (numbers, dates, times, etc.)" }, "format": "BULLETS", "uid": "f1711c54a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Calendar widgets", "Text": "Avoid placing calendar widgets partially off screen if near the bottom." }, "format": "BULLETS", "uid": "f1711d44a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Automatic cell height", "Text": "Limit the automatic height increases for text edit cells to avoid confusing double scroll bars." }, "format": "BULLETS", "uid": "f1711e2aa25a11e7b7c67054d2175f18" }, { "children": [ "f171200aa25a11e7b7c67054d2175f18" ], "data": { "Name": "February 6, 2013 - Release 1.9.0 (unstable development snapshot)" }, "format": "HEADINGS", "uid": "f1711f24a25a11e7b7c67054d2175f18" }, { "children": [ "f17120e6a25a11e7b7c67054d2175f18", "f17121d6a25a11e7b7c67054d2175f18", "f17122c6a25a11e7b7c67054d2175f18", "f17123aca25a11e7b7c67054d2175f18", "f171249ca25a11e7b7c67054d2175f18", "f171258ca25a11e7b7c67054d2175f18", "f1712690a25a11e7b7c67054d2175f18", "f1712776a25a11e7b7c67054d2175f18", "f1712866a25a11e7b7c67054d2175f18", "f1712960a25a11e7b7c67054d2175f18", "f1712a46a25a11e7b7c67054d2175f18", "f1712b36a25a11e7b7c67054d2175f18", "f1712c1ca25a11e7b7c67054d2175f18", "f1712d02a25a11e7b7c67054d2175f18", "f1712df2a25a11e7b7c67054d2175f18", "f1712ed8a25a11e7b7c67054d2175f18", "f1712fbea25a11e7b7c67054d2175f18", "f1713194a25a11e7b7c67054d2175f18", "f1713284a25a11e7b7c67054d2175f18", "f171336aa25a11e7b7c67054d2175f18" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f171200aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Full Python 3 rewrite", "Text": "TreeLine has been fully rewritten using Python 3." }, "format": "BULLETS", "uid": "f17120e6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Direct model-view and ElementTree", "Text": "Improved performance due to direct use of model-view classes for views and ElementTree for input/output." }, "format": "BULLETS", "uid": "f17121d6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Table based data editor pane", "Text": "A table based data editor pane (much faster)." }, "format": "BULLETS", "uid": "f17122c6a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "WYSIWYG data editor view.", "Text": "WYSIWYG formatting in the data editor view." }, "format": "BULLETS", "uid": "f17123aca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Real-time window updates ", "Text": "Real-time updates of the same file shown in multiple windows." }, "format": "BULLETS", "uid": "f171249ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Improved printing", "Text": "Improved printing and print preview performance." }, "format": "BULLETS", "uid": "f171258ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saves print options", "Text": "Saves print options with the TreeLine file." }, "format": "BULLETS", "uid": "f1712690a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Built-in PDF", "Text": "Built-in print to PDF function." }, "format": "BULLETS", "uid": "f1712776a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Searching options.", "Text": "More searching options." }, "format": "BULLETS", "uid": "f1712866a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Filtering command", "Text": "A filtering command shows matches in a simple list." }, "format": "BULLETS", "uid": "f1712960a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Saved sorting parameters", "Text": "Sorting parameters can be saved with each data type." }, "format": "BULLETS", "uid": "f1712a46a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Basic text field type", "Text": "The basic text field type allows formatting, preserves line breaks and allows HTML restricted characters." }, "format": "BULLETS", "uid": "f1712b36a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Calendar widget", "Text": "A calendar widget can be used for editing date fields." }, "format": "BULLETS", "uid": "f1712c1ca25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Easy internal links", "Text": "Internal link fields and inline internal links are easier to use." }, "format": "BULLETS", "uid": "f1712d02a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Unified external links", "Text": "An external link type supports http, https, file and mailto protocols." }, "format": "BULLETS", "uid": "f1712df2a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Support relative paths", "Text": "Relative paths are supported for external links and pictures." }, "format": "BULLETS", "uid": "f1712ed8a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Regular expression field type", "Text": "A regular expression field type can match patterns (phone numbers, email addresses, etc.)" }, "format": "BULLETS", "uid": "f1712fbea25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Node IDs automatically generated", "Text": "Unique node IDs are automatically generated and updated." }, "format": "BULLETS", "uid": "f1713194a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "New windows installer", "Text": "A new windows installer allows a single-user, non-administrator install." }, "format": "BULLETS", "uid": "f1713284a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Portable installs", "Text": "Includes better support for portable installs." }, "format": "BULLETS", "uid": "f171336aa25a11e7b7c67054d2175f18" }, { "children": [ "f171354aa25a11e7b7c67054d2175f18", "f1713644a25a11e7b7c67054d2175f18", "f171372aa25a11e7b7c67054d2175f18" ], "data": { "Name": "\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u044b", "Name_src": "Contacts" }, "format": "HEADINGS", "uid": "f1713464a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u0421\u043f\u0438\u0441\u043e\u043a \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438", "Name_src": "Mailing list", "Text": "\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u0442\u044c \u0432\u0441\u0435 \u0438 \u0432\u0441\u044f \u043e TreeLine. \u042d\u0442\u043e \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 (\u043e\u0442 \u0434\u043e\u0440\u043e\u0436\u043d\u044b\u0445 \u043a\u0430\u0440\u0442 \u0434\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043f\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c \u0438 \u0431\u0435\u0442\u0430-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f), \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043e \u0432\u044b\u043f\u0443\u0441\u043a\u0430\u0445, \u043e\u0442\u0447\u0435\u0442\u043e\u0432 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0438 \u043e\u0431\u0449\u0438\u0445 \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 (\u043e\u0442 \u043d\u043e\u0432\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u043e \u0441\u043e\u0432\u0435\u0442\u043e\u0432, \u043f\u0440\u0438\u0435\u043c\u043e\u0432 \u0438 \u043e\u0431\u0440\u0430\u0437\u0446\u043e\u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438). \n
    \n
    \n\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 lists.sourceforge.net/lists/listinfo/treeline-users", "Text_src": "There is a low-volume mailing list for users to discuss anything and everything about TreeLine. This is the place for development discussions (from roadmaps to feature suggestions to beta testing), release announcements, bug reports, and general user discussions (from new uses to tips & tricks to configuration samples).
    \n
    \nTo subscribe, go to lists.sourceforge.net/lists/listinfo/treeline-users
    \n" }, "format": "HEAD_PARA", "uid": "f171354aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Email", "Name_src": "Email", "Text": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u0441\u043e \u043c\u043d\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u0435: doug101 \u041a\u041e\u041c\u041c\u0415\u0420\u0427\u0415\u0421\u041a\u041e\u0415 AT bellz \u0422\u041e\u0427\u041a\u0410 org", "Text_src": "If you do not wish to subscribe to the mailing list, I can be contacted by email at: doug101 AT bellz DOT org " }, "format": "HEAD_PARA", "uid": "f1713644a25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f", "Name_src": "Updates", "Text": "\u042f \u043f\u0440\u0438\u0437\u043d\u0430\u0442\u0435\u043b\u0435\u043d \u0437\u0430 \u043b\u044e\u0431\u044b\u0435 \u043e\u0442\u0437\u044b\u0432\u044b, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0437\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e \u043b\u044e\u0431\u044b\u0445 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u0432\u0430\u043c\u0438 \u043e\u0448\u0438\u0431\u043a\u0430\u0445. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443: treeline.bellz.org.", "Text_src": "I welcome any feedback, including reports of any bugs you find. Also, you can periodically check back to treeline.bellz.org for any updates." }, "format": "HEAD_PARA", "uid": "f171372aa25a11e7b7c67054d2175f18" }, { "children": [], "data": { "Name": "Network drive issues", "Text": "Work around bugs when using files located on some types of Windows network drives." }, "format": "BULLETS", "uid": "f2a0c0a1dc8d11ea8921ac675dac20af" }, { "children": [], "data": { "Name": "Error handling", "Text": "Error handling has been improved. For most errors, a dialog box is shown with debugging information that can be copied into an email." }, "format": "BULLETS", "uid": "f5983b38bb0411e795e13417ebd53aeb" }, { "children": [ "42fb4166305a11e99fd7a44cc8e97404", "014e1392305b11e9ab99a44cc8e97404", "46f3d0a4305e11e9892fa44cc8e97404", "f7bbd90a305111e98209a44cc8e97404", "221ca8f0305911e99f3fa44cc8e97404", "2c9ba0c832ed11e9bf7f7054d2175f18", "2d4430dc305711e9a33aa44cc8e97404", "1b73aaf4305811e98bb7a44cc8e97404" ], "data": { "Name": "New Features" }, "format": "BULLET_HEADING", "uid": "f7bbd909305111e9be43a44cc8e97404" }, { "children": [], "data": { "Name": "Regenerate references command", "Text": "A new Regenerate References command was added to the Data menu. It forces updates to all conditional types and math fields. It should only be necessary for comparisons to current dates/times or for externally modified data." }, "format": "BULLETS", "uid": "f7bbd90a305111e98209a44cc8e97404" }, { "children": [], "data": { "Name": "XML export", "Text": "Fixed problems with generic XML export from multiple root nodes." }, "format": "BULLETS", "uid": "f817e5b6334a11e89349d66a6ab671cb" }, { "children": [], "data": { "Name": "Spanish translation", "Text": "Added a Spanish GUI translation (thanks to Diego)." }, "format": "BULLETS", "uid": "f966db0cc23f11e8b80fd66a6ab671cb" }, { "children": [], "data": { "Name": "Printing empty branches", "Text": "Fix an error caused by attempting to print an empty branch." }, "format": "BULLETS", "uid": "fcc1b718e5df11e9a7f9a44cc8e97404" }, { "children": [], "data": { "Name": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u041f\u0435\u0447\u0430\u0442\u0438", "Name_src": "Print Setup", "Text": "\u0414\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u043e\u0435 \u043e\u043a\u043d\u043e \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0435\u0447\u0430\u0442\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0447\u0435\u0442\u044b\u0440\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0438. \u041f\u0435\u0440\u0432\u0430\u044f, \u00ab\u041e\u0431\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u00bb, \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043a\u0430\u043a\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0434\u0435\u0440\u0435\u0432\u0430 \u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c, \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0443\u0437\u043b\u044b \u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0442\u044c \u043b\u0438 \u0440\u0430\u0437\u0440\u044b\u0432\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043c\u0435\u0436\u0434\u0443 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u0438 \u0435\u0433\u043e \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u0443\u0437\u043b\u0430\u043c\u0438. \u0412 \u043d\u0435\u043c \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043f\u0435\u0447\u0430\u0442\u0438, \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0447\u043d\u043e\u0439 \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043f\u0435\u0447\u0430\u0442\u0438. \u0412\u0442\u043e\u0440\u0430\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u00ab\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b\u00bb \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0431\u0443\u043c\u0430\u0433\u0438, \u043e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043f\u043e\u043b\u0435\u0439 \u0438 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u0422\u0440\u0435\u0442\u044c\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 [\u00ab\u0412\u044b\u0431\u043e\u0440 \u0448\u0440\u0438\u0444\u0442\u0430\u00bb] \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0448\u0440\u0438\u0444\u0442 \u0434\u043b\u044f \u043f\u0435\u0447\u0430\u0442\u0438. \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430, \u00ab\u0412\u0435\u0440\u0445\u043d\u0438\u0439/\u043d\u0438\u0436\u043d\u0438\u0439 \u043a\u043e\u043b\u043e\u043d\u0442\u0438\u0442\u0443\u043b\u00bb, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u0430\u043f\u043e\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438\u0445 \u0432 \u0432\u0435\u0440\u0445\u043d\u0438\u0435 \u0438 \u043d\u0438\u0436\u043d\u0438\u0435 \u043a\u043e\u043b\u043e\u043d\u0442\u0438\u0442\u0443\u043b\u044b.", "Text_src": "The dialog for print setup contains four tabs. The first, General Options, includes settings for what part of the tree to print, whether to include lines to child nodes and whether to allow page breaks between a parent an its first child node. It also has place to set the printer queue, to make pagination and print previews more accurate. The second tab, Page Setup, includes paper size, orientation, margins and columns. The third tab selects the font for printing. The last tab, Header/Footer, defines text and file data meta-fields for inclusion in headers and footers." }, "format": "HEAD_PARA", "uid": "fd0fe3dd69dc11ebab13001fd026534b" }, { "children": [ "6a6067d4482011e989f27054d2175f18", "b398d8ee482211e989f27054d2175f18", "ff3f7da6481e11e989f27054d2175f18" ], "data": { "Name": "Updates" }, "format": "BULLET_HEADING", "uid": "ff3f7c98481e11e989f27054d2175f18" }, { "children": [], "data": { "Name": "Translations", "Text": "Updated German and Spanish GUI translations (thanks to Maria Seliger and Diego)." }, "format": "BULLETS", "uid": "ff3f7da6481e11e989f27054d2175f18" } ], "properties": { "tlversion": "3.2.1", "topnodes": [ "f16f7d90a25a11e7b7c67054d2175f18" ] } }TreeLine-3.2.1/docs/000077500000000000000000000000001506556630100141635ustar00rootroot00000000000000TreeLine-3.2.1/docs/CNAME000066400000000000000000000000221506556630100147230ustar00rootroot00000000000000treeline.bellz.orgTreeLine-3.2.1/docs/default.css000066400000000000000000000026641506556630100163310ustar00rootroot00000000000000/* bellz.org style sheet */ body { background: #033; color: white; } a { color: #0f9; text-decoration: none; } a:hover { text-decoration: underline; } hr { height: 4px; } h1 { text-align: center; border-top: thick double #ccc; padding: .3em; margin: 1em 0 0; clear: both; } h2 { border-top: thin solid #ccc; padding: .3em 0 0; margin: 1em 0 0; } ul { margin-left: 0; } li { list-style-type: square; padding: .2em 0; margin-left: 2em; } img { border: 0; } .interior { margin: 0 auto; width: 90%; } .title { margin: 0; padding: 4px 0; float: left; } .title h1 { font-size: 4em; margin: 0; padding: 0; } .toplinks { float: right; text-align: right; } .toplinks p { margin: 0; padding: 0; } .navigation { clear: both; line-height: 3em; margin: 0; padding: 0; } .navigation a { background: #366; margin-right: 3px; padding: .4em .4em; } .navigation a:hover { background: #099; text-decoration: none; } .current-nav { background: #366; margin-right: 3px; padding: .4em .4em 1em; } .content { background: #366; margin: 0 0 2em; padding: .5em 1.5em; zoom: 1; /* fixes IE layout bug */ /* height: 1%; /* fixes IE layout bug */ } .centered { text-align: center; } .smallimage { float: left; margin: 0 1em; } .clearer { clear: both; } TreeLine-3.2.1/docs/download.html000066400000000000000000000107111506556630100166600ustar00rootroot00000000000000 TreeLine - Downloads
    TreeLine

    TreeLine Downloads

    Linux

    On a Linux system that has the libraries noted on the requirements page, all that is needed is the source code (with an installer script).

    Alternately, TreeLine packages are available from the repositories in many popular distrobutions.

    Also, please read about the installation and use of TreeLine.

    Windows

    Multiple windows installers are available.

    The source code for the libraries used to build the Windows binaries is available upon request.

    Also, please read about the installation and use of TreeLine.

    Older Versions

    Previous versions of TreeLine are available from SourceForge.

    TreeLine-3.2.1/docs/favicon.png000066400000000000000000000045251506556630100163240ustar00rootroot00000000000000‰PNG  IHDR00Wù‡sBIT|dˆ pHYsÅʼnÖïtEXtSoftwarewww.inkscape.org›î<ÒIDATh�½š{pÔÕÇ?÷÷ÛG6›Ý¼7!H ѦSσxãÓ»ØQ÷¬A^ž»�…%·S’9‡4‡�pì,'Nïæ“¦ jÞ€&c:}E¨¬¼x³‹¾gÛŸ‹JóÅŽ¸{¤`n2’§Ã ûÒO…üô2Ò~6½ÉšƒËtºn5ƒ•k¹xÂM–öÚzkx£ú>mÛ¬“«Š‹‡æíc¢¿ÒšŒ`÷”<1Oœh‘•ªÂ'VzÁþV¶ÔüŽM¯s:tr„ A^z½ÑNzú;‡È;|Ü;w;“3gY„D²ù‹'xçóGuò‰þJš·UqYû 2C½oÕ¯,2Sø¤é-žÙ»˜ã;GϘé�t‰…t²[/y“ sMMI (ÏYÀñÎ� y°¯… w¥YÖ‰!5š ‹Í*÷Ÿz�?ú.}Ñ`JD⸴èff\7ª6×”?–p$Žm'þd˜#Ã!‹“FV´õÖð·#·"¥fhäs�á̳Ü|®*{`´ÜÉ(,ŸþbØÖÔªåHóF»f“@áHéæã�Ó;«“U•ÜÁ’²Ud§ ø+‘´÷Öp¤åöœ|‰SÁjʲ¯ Øÿµ19Pä›NEÞ޵¿—�m}×n!(õmR—ôôwðÐÖ Ä´HB¶¤l7|å)ÛÎë»÷ƒ”LɺtÌìmx…µ‡W$ʹž~»¸ÖRß1RðßÎí:òéÎl¾Yþ«¤OÉœ=Z®¦9ù;Buœ7$"?ÊHAMç.]¹"o n5c\È¥‚lO1>w�Nv:ô¥¥¾Á�ΰ^9•µ|¼‘å.Ò•»ûš,u )”Q硼íbZ?1¢Hq†Ï[6�?K7—ãéUQ… Uqëè5Yj`p oçI¢õ À@x³šÃ¬>Ÿ|-Ÿ‰Zz7L3×1¤P¨çße\e3¸p(*N'ås®ÆŸ7�W¸© c"©F b2úU+³%?à€ñqCŠÚë?cïýE§¢j)ó¿ÿB1:^PVÉ”ÊÔÚ1Ä«/dЋCgaäVT ¬/$C$UÑaÎÒ;MÉÇ1©B³�¦O?Í?êE•NœZNÕƒÃåNÎÈ$…¤þˆ¥ƒ?o¢­¹Ø¥^êm‰²;¿ÕRWç€×�KÈ¡?…†£A<ÎLÛÍ�H+“ð8=öÏ'=±N4÷Ðx½y–ºº¡s92 W¸æ³ÇR ;º$C]÷>]9'½ÄRW׳@pAö×u G[ÞMÞ£Ù$°sÀ¦®#TGuë¿t²©9Ö¯›†¡›ž�®¼»á¥¤×JaýÄjºBY¡1x”>þ61mhCóºr¸0w¡eƒ•…7èRâL_3ë«oCb=jf+Šm �¨«ëÚÇovVðć39¬ÖÕ-œr§íqÞÐsÀ[nxTú¸q=ëÿÄšÐh×ÑP…ƒ–³Ÿä%Y—ñ�©Û¶5]Œ¿óÕg —ŠÒl»w/3FÙ4…F'ß;Õ R–=�ŸÏÞ„C±_ÆMð¹òù鬿'^Êsª˜7ùVK#B1Ù‰mR(¾KÇ‘æðãsÈO/cù´g¹gîvà šÁp˜‹£,û îžók¯à–™«G=Q‡æQjéõƒÊ—˜à›F®§$%ý8@`º³”f_ΣUÇP…¥ŸƒÍ°&n�é�k홚£G¬/œ�”<`:‰íÎ:ã �Š€†s5d¶ i}”°ÝäFÓ/4(l;wK&$mRÿ\Žº.$[5ÆÛã`ÊDd�q‚TÙ¨Š£Höœ‹!Å,ßíˆ�OvMÉŸ*šÊ}¶—Ô>ÛeYg¶í|åqª·½NWKýX»�U0¸”æŠ�ê[å+VØ·2"ÒbÿÛ/ä¦÷äAúç_¿s&•S±àF¦/ZŽ?`þþ9RðrI�ØÃ62­‡ÛT/¥ò­,Žp°‹·ŸZIk½ñÎ0t¡±·ÑÙpœ]ëŸf÷k¿§¤²ŠŠª¥ø“�é 3PLA™á;Ù5Äí‰~†×œh‘ŠÂÆT>·žØ¿…ÍÏý’žÓýÒý¹x2sðdäàñçpÃàµîG·¬'ì ·«�Pw=Ý„‚�hш©m ˜Ë—ÝËŒ«nÑ¥ �|Ô¯qýÔB‘¸cšÿÕÀÇ HVZ‘o¯ÿŒ¦ãÉ.º€Ìüb¼Ygêo@q„ƒ]œio »µ-Ú�‚¬ÂòK§æŽ¼,ƒüÂö¯Ãq²]ÎÑ$O ¬tþ�°W‘<89 L¿c']¤O6ËRá:)¸RÂÄÁojçíï64 É8Ø49GTÛ5øùMë:MØí²IEND®B`‚TreeLine-3.2.1/docs/feature.html000066400000000000000000000160011506556630100165020ustar00rootroot00000000000000 TreeLine - Features
    TreeLine

    TreeLine Features

      General
    • Stores almost any type of information, including plain text, rich text, HTML, numbers, dates, times, booleans, URLs, etc.
    • The tree structure helps keep things organized.
    • Each node can have several fields that form a mini-database.
    • Several node types, with different sets of fields, can be included in one file.
    • The node format, including fields, output lines, formatting and tree-view icon, can be defined for each node type.
      Views
    • The left-hand view shows an indented, expandable list of titles
    • The right-hand view can show one of three views - for showing output, editing node data and editing node titles.
    • The right-hand view is normally split to show data from the parent node and its children.
    • If multiple nodes are selected, the right-hand view shows all of their data.
    • The output view can be set to show indented output from all descendant nodes.
    • An upper breadcrumb view shows titles of the selected node's ancestors; the titles can be clicked to select them in the tree.
      Navigation
    • Find commands can search node data for text matches or for more specific rules.
    • Filtering commands show only matching nodes in a flat left-hand view.
    • Previous and next selection commands toggle selections to quickly move between parts of the tree.
      Formatting
    • The dialog for data type configuration has several tabs to easily set all type, field and output parameters.
    • Each tree node can be set to a type format independently.
    • Formatting information can be copied from another TreeLine file.
      File Handling
    • Undo and redo commands are available for all modifying operations.
    • TreeLine files use a JSON format, with options for automatically compressing or encrypting the files.
    • Document templates for new files are preformatted to cover basic needs.
    • The formatted output can be printed with parent/child lines, headers and footers.
      File Import and Export
    • The data can be exported to single or multiple HTML files with optional navigation panes.
    • A live tree HTML export creates an interactive view with expandable nodes and a descendant output pane.
    • Plain text, tab-indented text and delimited table files can be imported and exported.
    • Files from older versions of TreeLine (2.x and 1.x) can be imported and exported.
    • Mozilla and XBEL format bookmark files can be imported and exported.
    • Generic XML files can be imported and exported, allowing TreeLine to function as a crude XML editor.
    • ODF text documents can be imported and exported as outlines.
      Linking
    • Internal link fields select a linked node when clicked.
    • External link fields can be used to open URLs in web browsers.
    • Both internal and external links can be embedded into text fields.
    • Nodes that are duplicated by cloning show up as separate clickable paths in the upper breadcrumb view.
      Data Manipulation
    • Nodes can be sorted by title or by predefined key fields.
    • Math fields can be defined that automatically calculate their contents based on numerical values in other nodes.
    • Numbering fields can be defined and automatically updated.
    • A node's icon and output format can be changed conditionally based on its data.
    • Cloned nodes (the same nodes with multiple parents/locations) can be created using special paste commands or by automatically matching identical nodes.
    • Text data can be spell checked (requires an external program - see the System Requirements section).
    • Data can be automatically re-arranged using categories from data fields.
      Customization
    • There are many options for customizing both general and file-based attributes.
    • There are editors for keyboard shortcuts and toolbar commands.
    • Fonts used in the GUI, editors and output views can be customized.
    • The user interface is available in simplified Chinese, English, German, Russian and Spanish. Translations into other languages are TBD.
    TreeLine-3.2.1/docs/index.html000066400000000000000000005303611506556630100161700ustar00rootroot00000000000000 TreeLine - News
    TreeLine

    What is TreeLine?

    Do you have lots of sticky notes lying around with various useful information jotted down? Or many lists of books, movies, website logins, personal contacts, or things to do? Can you find them when you need them? Well, I often couldn't. So here's my answer.

    Some would call TreeLine an Outliner, others would call it a PIM. Basically, it just stores almost any kind of information. A tree structure makes it easy to keep things organized. And each node in the tree can contain several fields, forming a mini-database. The output format for each node can be defined, and the output can be shown on the screen, printed, or exported to html.

    A source code repository is available at GitHub.

    There is a low-volume email list for users to discuss TreeLine. To subscribe, go to this page.

    News

    September 27, 2025 - Release 3.2.1 (stable release)

      Updates:
    • Added an easily selectable light-colored theme option.
      Bug Fixes:
    • Fixed errors that occurred when dragging and dropping nodes and files.
    • An error setting some page sizes for printing was fixed.
    • Fixed the appearance of the print preview when a dark theme is being used.
    • Fixed the appearance of the time edit widget when used with a dark theme.
    • A problem with the option to minimize to the system tray was fixed.

    August 30, 2025 - Release 3.2.0 (stable release)

      New Features:
    • Made extensive updates to port TreeLine to the Qt6 and PyQt6 libraries.
    • Added a word count function for math field types.
      Updates:
    • Removed deprecated string escapes used when formatting numbers.
      Bug Fixes:
    • Fixed errors closing a window if the same file is open in another window.
    • Fixed a problem with the filter view when the tree icon is set to none.
    • Improved the handling of multi-line text in generic XML import.

    June 3, 2023 - Release 3.1.6 (stable release)

      Updates:
    • Detect external file modifications by checking the file's last modified time just prior to saving.
    • Preserve the choices in the field format when switching between Choice and Combination field types.
      Bug Fixes:
    • Fix a bug that prevented child type limits from being set back to all types.
    • Preserve the modified status of the config dialog when switching between windows displaying different files.
    • Fix problems occurring when the escape key is used to close various non-modal dialogs.
    • Avoid a traceback error message when attempting to import a CSV file with a bad header row.
    • Fix a bug using child count fields in live HTML exports.

    September 10, 2022 - Release 3.1.5 (stable release)

      New Features:
    • Add a command for strike-through font formatting.
      Updates:
    • For better visibility, increase the width of tree structure lines in printed and PDF output files.
    • Update the libraries used to build the Windows binaries to Python 3.10 and Qt/PyQt 5.15. Note that this eliminates support for Windows 7.
    • Add a Russian translation of the GUI and the help files (thanks to Andrew Trofimov).
    • Update the German GUI translation (thanks to Karsten).
      Bug Fixes:
    • Fix a bug preventing a second-try password entry from opening an encrypted file.
    • Add fallbacks to UTF-8 encoding if the OS encoding fails on import and export.
    • Avoid a crash when bad field name modifiers are in a math field equation.

    November 28, 2020 - Release 3.1.4 (stable release)

      Bug Fixes:
    • Fix an incompatibility with the new Python 3.9 version under Linux or running from source.
    • Avoid an error message when a window is closed with the focus on a dialog box.
    • Fix a problem recalculating root references in field equations.

    August 16, 2020 - Release 3.1.3 (stable release)

      New Features:
    • Add a more flexible tool for customizing GUI colors.
    • Add an Insert Date command that adds a timestamp to text field edit boxes.
    • Evaluate math expressions contained in fields that are referenced by math field equations.
    • Add support for German outline numbering using double letters in some levels (thanks to Teresa M).
      Updates:
    • Update math field equation restrictions to work with Python 3.8.
    • References to a macOS port on MacPorts were added to the System Requirements and Installation documentation.
    • Update the libraries used to build the Windows binaries to Python 3.8 and Qt/PyQt 5.14.
      Bug Fixes:
    • Make the Add Child command available after filtering has ended.
    • Avoid an application error when a Find and Replace command causes fields to contain invalid data.
    • Perform a more complete recalculation of math fields after certain operations.
    • Fix problems opening files that contain circular reference errors in math fields.
    • Avoid problems with empty parameters in the font dialogs.
    • Fix a bug in Data Edit views when no fields are visible due to hidden numbering or math fields.
    • Properly update multiple windows after drag and drop tree changes.
    • Fix issues with restoring window geometry with multiple monitors and changing configurations.
    • Work around bugs when using files located on some types of Windows network drives.
    • Fix problems detecting existing TreeLine sessions when opening files (mostly in Linux).

    October 6, 2019 - Release 3.1.2 (stable release)

      New Features:
    • Add a simplified Chinese GUI translation (thanks to Qu Ray for translating).
    • Add a general option to extend the height of data editors with long text content. The default setting (limit the height to the window size) is unchanged. The new option uses the view scroll bars to access the full text length.
      Updates:
    • Restore the cursor and scroll positions of data editors when the editors are re-created after focus changes.
    • Add an asterisk after the file name in the title bar if a file has been modified.
    • Change lettered outline numbering sequences to match standards. The sequences change from ...Y, Z, AA, AB, AC... to ...Y, Z, AA, BB, CC...
      Bug Fixes:
    • Fix a bug that truncated plain text exports after the first line.
    • Enable the title list view's select in tree context menu to be used on new child nodes.
    • Modify dark mode colors to make tool tips visible.
    • Fix error due to character encoding when importing files from Treepad.
    • Fix an error caused by attempting to print an empty branch.

    March 17, 2019 - Release 3.1.1 (stable release)

      Updates:
    • Added many Show Configuration Structure data fields to show detailed settings for type formats and field formats.
    • Added support for finding and replacing empty data fields using the search and replace command.
    • Updated German and Spanish GUI translations (thanks to Maria Seliger and Diego).
      Bug Fixes:
    • Fix printing problems when using the dark theme.
    • Fix incorrect numbering updates in some situations with mixed node types.
    • Fix problems defining a math field equation on a recently copied data type.
    • Eliminate a problem defining math field equations that include child count references.
    • Fix a minor bug affecting default directories for save-as and export commands when there is not already a file name set.

    February 20, 2019 - Release 3.1.0 (beta release)

      Notes:
    • This is a beta release of TreeLine. Some new features have not been extensively tested, but major bugs are unlikely. Testing and bug reports are appreciated, but those with very critical work should consider using the stable release (TreeLine 3.0.x).
    • GUI translations are available in German and Spanish, but they still require minor updates to cover recent changes. Volunteers are also needed to update or create translations in additional languages.
      New Features:
    • A Select in Tree command was added to the Title List's right-click context menu. It selects the node corresponding to the current line in the Title List editor. This makes it easier to edit or add children to an item.
    • A minimize to system tray option was added to General Options (under Features Available). If enabled, it adds a TreeLine system tray icon to toggle application display and hides the taskbar entry when TreeLine is minimized.
    • An optional dark color theme was added to General Options (under Appearances).
    • A new Regenerate References command was added to the Data menu. It forces updates to all conditional types and math fields. It should only be necessary for comparisons to current dates/times or for externally modified data.
    • Added support for current date and time references to math fields. Special field names ({*Now_Date*}, {*Now_Time*} and {*Now_Date_Time*}) must be manually typed in equations.
    • A new Show Configuration Structure command was added to the Data menu. This opens a read-only visualization of complex type structures as another TreeLine file.
    • An indent (pretty print) output option was added to General Options (under Features Available). This makes saved TreeLine JSON files easier for humans to read at the expense of somewhat larger file sizes.
    • The Evaluate HTML tags control was enabled for date, time, boolean and math fields. This allows HTML tags to be evaluated or ignored in more field types.
      Updates:
    • The top root node is now selected at file open if there is not a recent selection state to restore. Previously these files opened with no selection, which could cause confusion.
    • Non-editable math fields in the Data Edit view show as gray when the mouse hovers over them.
    • Some unnecessary libraries were eliminated from the Windows installer to reduce download sizes and installed space requirements.
      Bug Fixes:
    • Fixed the truncation of node titles that are generated from the first line of HTML Text fields.
    • Some redundant newline characters were removed from text storage in TreeLine files.

    November 17, 2018 - Release 3.0.3 (stable release)

      Bug Fixes:
    • Fixed an error when adding child count fields to the output format.
    • Problems with writing config files in Windows portable installations were fixed.
    • Improved error handling after failing to read or write config files.
    • In the Windows installer, improve the deletion of files from older versions and avoid problems if installing into a directory shared with other applications.

    October 20, 2018 - Release 3.0.2 (stable release)

      Updates:
    • Upgraded the Windows binary from Python 3.6 to Python 3.7.
      Bug Fixes:
    • Fixed nonfunctional printing commands under Windows by building the Windows binary using PyInstaller rather than cx_Freeze.
    • Multiple issues with printing long nodes were fixed.
    • Fixed problems saving files when the blanks as zeros property was changed for math fields.

    September 29, 2018 - Release 3.0.1 (stable release)

      Updates:
    • Added a Spanish GUI translation (thanks to Diego).
    • Added a read-only text box to the Help > About dialog to allow copying of the version and library information.
      Bug Fixes:
    • Fixed a problem opening old TreeLine files that had format changes in File Info fields.
    • TreeLine files with invalid child references can now be opened. A warning message is given about the missing child nodes in the corrupt file.
    • The Sort command now properly sorts multiple root nodes when sorting the entire tree.
    • Now forces references to AM/PM in time field formats to be output regardless of system locale settings.
    • Data from fields that were removed from the configuration is now purged when a file is saved. This avoids missing matches in the Clone All Matched Nodes command.
    • Fixed various errors when applying advanced clone and category commands from the Data menu to complex node structures.
    • Fixed some problems with using the Undo command after complex operations.
    • Fix an error caused by attempting to use the Edit > Cut command when there is only one node.

    August 19, 2018 - Release 3.0.0 (new stable release)

      Notes:
    • This is the first stable release of a major TreeLine rewrite. It includes all of the new features shown below in the 2.1.x and 2.9.x development series.
    • TreeLine files now use a JSON format in place of the old XML format. This provides more flexibility for structuring new features like cloned nodes and multiple root nodes. A new file extension (".trln) helps to distinguish files with the new format. Import and export filters are provided for older TreeLine version 2.x and 1.x files. The older files can be opened using the standard "File > Open" command.
    • A GUI translations is available in German. All other translations are out of date and have not been included. Volunteers are needed to update translations in several languages.
      New Features:
    • The default font for the application can now be set in Tools > Customize Fonts. This is useful for enlarging fonts on some systems with high screen resolutions. Options still exist to individually specify tree view, output view and editor fonts.
      Updates:
    • The Windows binary is now built using updated libraries (Qt 5.11 and PyQt 5.11).

    June 30, 2018 - Release 2.9.2 (unstable development snapshot)

      Notes:
    • This is a development snapshot of TreeLine that should be considered a release candidate for an upcoming stable release. Many bugs have been fixed. User testing and bug reports are appreciated.
    • This is a major rewrite of TreeLine. Once it becomes fully stable, it will be released as TreeLine version 3.0.0.
    • A GUI translations is available in German. All other translations are out of date and have not been included. Volunteers are needed to update translations in several languages.
      Updates:
    • The German GUI translation was updated (thanks to Maria Seliger).
    • The expand/collapse status of nearby nodes is maintained while editing the node structure. This includes adding, deleting, moving and indenting nodes.
    • The expanded/collapsed and selected tree states are now saved even if changes were discarded in the previous session.
    • A click on a tree node to restore tree focus no longer starts editing the node title.
    • The enter key now selects a tree node after the first title letter(s) are typed to make it current (shown with a box around the title).
      Bug Fixes:
    • Several errors occurring when deleting or removing nodes have been fixed. These include problems when the mouse is pre-highlighting descendant nodes and when nodes to be deleted are selected in a separate window.
    • Fixed node title editing errors caused by moving the mouse to a data edit box with the title edit still active.
    • Fixed errors occurring when field types are changed after initial default values have been set.

    March 31, 2018 - Release 2.9.1 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of TreeLine. It has improved but could still contain bugs. Testing and bug reports are appreciated, but those with very critical work should consider using the stable release (TreeLine 2.0.x).
    • This is a major rewrite of TreeLine. Once it becomes more stable, it will be released as TreeLine version 3.0.0. The 2.1.x unstable series is being discontinued (no stable 2.2.0 release is planned).
    • The GUI and documentation translations are out of date and have not been included. Volunteers are needed to update translations in several languages.
      New Features:
    • A new HTML export uses Javascript and CSS to create a live tree view. Nodes in the tree can be expanded and collapsed, and a separate pane shows the output for all descendants of the selected node. One form of this export creates separate files that are linked to the existing TreeLine file. These files are intended for use on a web server (browser security usually prevents local access). Only the TreeLine file needs to be replaced to update the data (re-export is not required). The second form creates a single file (with embedded data) that can be accessed from a local web browser.
    • New forms of CSV table text imports and exports can work with multiple levels of child nodes, preserving the tree structure. The first column of the table includes a level number that is incremented for child relationships.
    • Added a custom time select dialog box for editing Time and TimeDate fields.
    • A new general option controls whether inaccessible files are removed from the recent file list at startup. The files are removed by default, but this can be changed to avoid losing listings of files stored on removable drives.
      Bug Fixes:
    • Fix errors shown when using copy commands after closing TreeLine windows.
    • Fixed problems with copy / paste and drag / drop on nodes with conditional type settings.
    • Avoid problems showing the tree view after closing a filter command that found no matches.
    • Fixed issues on Windows with pull-down combo boxes not working after repeatedly showing some dialogs (mostly find and filter dialogs).
    • Fixed problems with generic XML export from multiple root nodes.
    • Fixed problems with number field formatting when using a "," radix with exponents.
    • Avoid issues resolving relative paths between different Windows drive letters in external link fields.
    • Fixed problems with advanced ancestor field output references in some tree locations.
    • Properly update the right-hand views after using a new window command.
    • Avoid problems running data category-based commands on selections without any child nodes.
    • Fixed minor spacing issues for tables shown in output views and HTML exports.

    January 28, 2018 - Release 2.9.0 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of TreeLine. It could contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) is recommended for critical work.
    • This is a major rewrite of TreeLine. Once it becomes more stable, it will be released as TreeLine version 3.0.0. The 2.1.x unstable series is being discontinued (no stable 2.2.0 release is planned).
    • The GUI and documentation translations are out of date and have not been included. Volunteers are needed to update translations in several languages.
      New Features:
    • TreeLine files now uses a new JSON format in place of the old XML format. This provides more flexibility for structuring new features like cloned nodes and multiple root nodes. A new file extension (".trln) helps to distinguish these files.
    • Import and export filters are provided for older TreeLine version 2.x and 1.x files. The older files can be opened using the standard "File > Open" command.
    • Multiple top-level (root) nodes are now permitted. When no nodes are selected in the tree (by clicking on a blank area or Ctrl clicking to unselect), the right-hand view will show information about all of the top-level nodes.
    • A new breadcrumb view pane above the other panes shows a sequence of ancestor titles for a selected node. The ancestors can be clicked to select them. For cloned nodes, multiple lines provide links to each instance's ancestor sequence.
    • By default, the edit boxes in the data edit view now activate when the mouse hovers over them. This eliminates the need to click to activate them. This feature can be disabled in general options if desired.
    • When a file is opened in an existing window, the window is now reused (not just replaced) to eliminate flashing.
    • Cloned nodes now have a more native and efficient implementation. This allows the same nodes to have multiple parents. The new breadcrumb view shows a list of clones for the selected node that can be clicked to select the other instances.
    • New paste commands have been added for adding nodes before and after siblings. There are also multiple paste commands for adding clones of nodes.
    • Cloned nodes can be created automatically from all identical nodes by using the "Data > Clone All Matched Nodes" command.
    • The new "Data > Detach Clones" command converts cloned nodes in selected branches back into independent nodes.
    • A new "Swap Category Levels" command swaps child and grandchild nodes beneath a selected node. A child node with multiple nodes under it will become cloned under each one. Any existing grandchild clones will become individual nodes with multiple children.
    • Child node types that are available to be set can be limited. A new pull-down list of child type limits is in the "Type Config" tab of the configuration dialog if the advanced functions are shown.
    • The Date, Time and DateTime fields have new format strings that enable extra text to be added to the date output.
    • To improve efficiency, user visible node unique IDs that depend on the node's data have been removed.
    • Error handling has been improved. For most errors, a dialog box is shown with debugging information that can be copied into an email.
    • Added a desktop specification file to the Linux installer for desktop environment menu support.

    March 26, 2017 - Release 2.1.2 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of TreeLine. It may contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 2.0.x) should probably be used for critical work.
    • The GUI and documentation translations have not yet been updated.
      Bug Fixes:
    • Fix problems formatting DateTime fields in output views.
    • Fix dialog issues with clicking on targets when creating inline internal links.
    • Fix a regression that prevented using the tab key to cycle between data edit view items.
    • Avoid opening two windows when restoring an auto-saved backup file.

    March 12, 2017 - Release 2.1.1 (unstable development snapshot)

      Updates:
    • The Windows binary is now built using Python 3.6 and PyQt 5.8.
      Bug Fixes:
    • Fix a crash when changing the icon on the Type Config page of the Configure Data Types dialog box.
    • Fix inconsistent type selections on the Type List page of the Configure Data Types dialog box.
    • Fix issues with restoring the placement of the TreeLine window in some multiple monitor setups.

    February 20, 2017 - Release 2.1.0 (unstable development snapshot)

      New Features:
    • TreeLine has been ported from the Qt4 library to the Qt5 library. The system requirements have been updated to Python 3.4 or higher, PyQt 5.4 or higher and Qt 5.4 or higher.
    • Cloned nodes that can duplicate sections of the tree have been added. Editing their data or child structure in one location changes all locations. They are created by copying nodes and then using the "Edit->Paste Cloned Node" command to paste them elsewhere. The clone link can be removed by deleting the nodes or by cutting them and pasting them back using the regular paste command.
    • Added a new DateTime field that combines dates and times into a single field that is useful for timestamps. The editor format is a combination of the date and time formats from the general options, separated by a space.
    • Added an option to allow HTML tags in Choice, AutoChoice, Combination, AutoCombination and RegularExpression fields. The control is in the Field Config tab of the Configure Data Types dialog. This option is disabled by default. If enabled, special characters (angled brackets and quotation marks) will need to be escaped to show up in text.
    • Saved rules for Conditional Find and Conditional Filter commands are listed directly in the dialog boxes, making them easier to load and save.
    • Added comma-delimited (CSV) table import and export, similar to existing tab-delimited table import and export. The export only handles data from a single level of child nodes.
    • Added a quick, incremental search of node titles. By default, it's bound to ctrl+/. Then, matching titles are found as the search string is typed. The F3 and shift+F3 keys can be used to go to the next or previous matches, respectively.
    • Multiple fields can now be selected in the Output page of the Configuration dialog, so several fields can be added to the formats simultaneously.
    • A pull-down selector for printers has been added to the Print Setup dialog. This enables TreeLine to verify that the page size and margin settings are supported by the current printer.
      Updates:
    • The SpacedText Field now allows special HTML characters (angled brackets and quotation marks) without requiring them to be manually escaped.
      Bug Fixes:
    • The code that splits content into pages when printing has been improved. It now handles very long nodes better.
    • When formatted fields (dates, times, etc.) are used in node titles, editing the titles in the tree or in the Title List pane will now work if the edit and output formats are similar.

    October 3, 2015 - Release 2.0.2 (new stable release)

      Bug Fixes:
    • Fixed a major regression in 2.0.1 that broke data editors for most specialized field types (number, math, boolean, choice, etc.)
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    September 26, 2015 - Release 2.0.1 (new stable release)

      Updates:
    • Added methods to the plugin interface that allow general program options to be queried and changed.
    • Improve text table import error messages by including the line number where the problem is found.
      Bug Fixes:
    • Reduce the amount of work that a single undo command removes from editors in the data edit view.
    • Fixed a bug that prevented setting the unique ID reference field on a newly created data type.
    • Preserve hard newlines in text fields when converting TreeLine 1.4.x files to this version.
    • Fix problems preserving expand/collapse node states when indenting and unindenting nodes.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    May 17, 2015 - Release 2.0.0 (new stable release)

      Updates:
    • Modified the Treepad file import to use SpacedText fields to more closely match Treepad formatting.
    • An optional plugin was written that can export files to the Treepad text file format.
    • The TreeLine icon was replaced with a new one. Thanks to David Reimer for contributing the artwork.
    • The German and Portuguese GUI translations were updated.
    • Updated the long text sample file to include the SpacedText field type, and added a conditional equation to the math sample file.
    • Updated the Math Field section of the documentation.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    March 29, 2015 - Release 1.9.7 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of a full rewrite of TreeLine. It is nearly ready for a stable release, but it could still contain bugs. Testing and bug reports are appreciated.
    • The GUI and documentation translations are not yet complete.
      New Features:
    • Added comparison operators and conditional if statements to math field equations. The operators can be used with a new boolean result type, or as a part of numeric, date, time or text expressions.
    • Text operators were made available in math field equations, and the result type can be set to text. This allows math fields to combine text from other fields, replace substrings and change capitalization.
      Updates:
    • Added a "file saved" status bar message.
    • Added a German GUI translation.
    • Updated the Portuguese GUI translation.
      Bug Fixes:
    • Fixed a focus problem that made Combination and AutoCombination field editor pull-downs unusable.
    • Fixed a focus problem that made the pull-downs in choice and boolean field editors unusable on Linux.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    March 10, 2015 - Release 1.9.6 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of a full rewrite of TreeLine. It could still contain bugs. Testing and bug reports are appreciated.
    • The GUI and documentation translations are not yet complete.
      New Features:
    • Added a new OneLineText field type that restricts the text length to a single line.
    • Added an All Types option to the conditional find and filter commands. This allows multiple node types to be found or filtered at the same time. The fields from every type are available for use in conditions. The conditions give a false result for all node types that do not contain that field name.
    • Added support for date and time calculations using math fields. Math equation result types can be set to numeric, date or time output. Date fields can be subtracted to give the number of days elapsed, and numbers of days can be added to or subtracted from dates, resulting in new dates. Time fields can be subtracted to give the number of seconds elapsed, and numbers of seconds can be added to or subtracted from times, resulting in new times.
    • In math fields, added an equation reference level to reference fields in the root node. This provides a place for "constant" field values that can be referenced from any node but only need to be changed in one location.
    • Support was added for plugin extension modules. Most of the interface methods from TreeLine 1.4.x were duplicated to ease porting of old plugins. Of course, old plugins must be ported from Python 2.x to Python 3.x, and there are multi-window implementation differences. New interfaces allow the creation of new field types and the execution of any menu command. Sample plugins are available on the TreeLine download page.
    • Added text formatting and link commands for HTML fields that add tags to the HTML content.
    • An open in folder command was added to external link field editors to open the directory in a file manager.
    • Added the Select All command to global menus with a different default shortcut key (ctrl-L) to avoid conflicts with the add child shortcut.
      Updates:
    • Improved the focus handling for data edit view edit boxes. This eliminates the blue outline for boxes in inactive data edit views. It also makes tab-to-focus more predictable, including fully selecting single-line field types when they receive tab focus.
    • Data edit boxes are now automatically resized when editing is complete and the focus moves to another row.
    • Allow files to be drag & dropped on data edit boxes to create external links.
    • Small, non-modal dialogs, such as those for sorting, numbering, finding and filtering, have been set to stay on top, so they won't be obscured by TreeLine windows.
    • Made opening associated programs from external file links more consistent, especially in Linux.
    • The copy types from file command now supports encrypted and compressed files.
    • Added wait cursors to TreeLine operations that could be time consuming.
    • Improved the consistency of context menus and shortcut commands used in edit boxes.
    • Added a nearly complete Portuguese GUI translation.
    • Added support for sample TreeLine files to be provided in alternate languages.
    • Prepared the help file for translation into other languages,
      Bug Fixes:
    • Corrupted TreeLine files with the same unique ID assigned to multiple nodes no longer fail to open. The user is warned that unique IDs have been updated, which could break some internal links.
    • Fixed missing fields in the pull-down list in the conditional find and filter dialog boxes when a rule was re-used after a node type change.
    • Fixed problems with math fields that reference non-existing fields in parent or child nodes.
    • Made math fields update properly after node type changes.
    • Fixed inconsistent updates after renaming fields used with bulleted or tabled output.
    • Made node copy-paste and drag-and-drop work when the initial selection includes both parent and child nodes.
    • When importing a tabbed text file with multiple top-level nodes, create a single higher-level node to prevent failure.
    • Fixed the availability of the move up button in the customize toolbar dialog when the second command in the list is selected.
      Missing Features (not implemented yet):
    • Language translations for the GUI and documentation.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    December 31, 2014 - Release 1.9.5 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of a full rewrite of TreeLine. It is not yet complete and could contain bugs. Testing and bug reports are appreciated.
    • The GUI and documentation translations have not yet been done.
      New Features:
    • Added a math field type that is configured by defining an equation. The field value is automatically calculated based on references to numerical values in other nodes. See the "sample_math_fields" file for a usage example.
    • Added a Clear Formatting command that removes font changes and links from data editor text.
    • Made source code changes necessary to support user interface translations into other languages. The actual translation work remains to be done.
      Updates:
    • Add scroll bars to the pull-down editors for combination fields with many entries.
    • Reduce the truncation of external link URLs when generating default display names.
    • Use Unix-style newlines for saved TreeLine files to keep files consistent across platforms.
    • Update the CSS code in exported HTML with navigation panes to improve the appearance in some browsers.
    • Optimize some undo information to reduce the amount of data in memory.
    • Move sample files into a separate directory to avoid future translation conflicts.
    • Clarify a Linux installer error message when checking for the Python 3 version of PyQt.
    • Include MSVCR DLL files in the Windows installer.
      Bug Fixes:
    • Fix problems applying multiple configuration changes while the Configure Data Types dialog box remains open.
    • In the Title List editor, splitting a title into two lines now creates a new node without losing the children and parameters of the original node.
    • Fix the undo command in the Title List View so that deleted lines/nodes are properly restored.
    • When sorting nodes by fields, properly handle a reverse direction.
    • Fix problems with the find and replace command when a particular node type is specified.
    • Fix problems defining conditional types from the Configure Data Types dialog box.
    • Correctly apply font size formatting to selections with mixed font sizes.
    • Fix the height of long text field editors with customized data editor fonts.
    • Fix HTML export of Base 64 images.
      Missing Features (not implemented yet):
    • Support for plugin extension modules.
    • Language translations for the GUI and documentation.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    March 8, 2014 - Release 1.9.4 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of a full rewrite of TreeLine. It is not yet complete and could contain bugs. Testing and bug reports are appreciated.
    • The GUI and documentation translations have not yet been done.
      New Features:
    • Created new documentation, including a TreeLine file with details and a text file with basic usage instructions. Both are accessible from the help menu.
    • Added customizing of default fonts used in the tree, output and editor views.
    • Added a new SpacedText field type that holds plain text and preserves all spacing.
    • Combination and auto combination field types now use a simpler checkbox style pull-down editor.
    • An autosave option was added.
    • A unique ID reference field was added to the file info fields to allow node unique IDs to be included in output formats.
    • A plain text paste command was added to paste non-formatted text to data editors.
    • Added an option to set the child indent offset amount.
      Updates:
    • The last size and position of the print preview window are remembered and restored.
    • When printing, nodes with long text content are split between pages.
    • In multiple page HTML exports, relative links in the content are adjusted based on the directory depth.
      Bug Fixes:
    • Fixed problems outputting completely blank nodes.
    • Problems with the contains and true/false conditional rules were fixed.
    • Fixed issues displaying several editor link dialogs in quick succession.
    • In the configure data types dialog, the output format cursor no longer moves when switching to other field references.
      Missing Features (not implemented yet):
    • Support for plugin extension modules.
    • Language translations for the GUI and documentation.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    January 19, 2014 - Release 1.9.3 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of a full rewrite of TreeLine. It is not feature complete and probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.4.x) should be used for critical work.
    • The documentation is not included yet. It needs to be updated to cover the new features.
    • The GUI and documentation translations have not yet been done.
      New Features:
    • Added controls in the Tools menu for customizing TreeLine's keyboard shortcuts.
    • Controls for customizing TreeLine's toolbar buttons were added to the Tools menu.
    • New dialogs were created for conditional finding and filtering of nodes. Specific conditions can be applied to individual types and fields, and the conditions can be saved.
    • Find and replace functionality was added to search and change nodes' text data. The search can be limited to specific types and fields.
    • A new option for output data in tables was added to the Type Config pane of the Configure Data Types dialog. Each line of the output format becomes a column. Any text at the start of the format line that is followed by a colon becomes a table heading.
    • An option to add bullets to the output of child nodes was added to the Type Config pane of the Configure Data Types dialog.
    • Added View > Previous Selection and Next Selection commands to step through the node selection history.
      Updates:
    • Nodes can now be reordered by dragging and dropping them between sibling nodes.
    • The keyboard entry of dates and times into fields was made more flexible by allowing entries such as 4-digit years that don't exactly match the entry format.
    • Any text selection is now used as the default name for links inserted into text fields.
    • Links to local named anchors in a node's HTML text content now work if they don't conflict with any node unique IDs.
    • Line spacing in output views was made more consistent.
    • Improved the efficiency of restoring node open/close states when opening files.
      Bug Fixes:
    • Errors when pasting text with varying font sizes into data editors were fixed.
    • Various issues with conditional data types were fixed, including problems with pasting conditional nodes and prompt updating when the types change.
    • Problems with undoing the dragging and dropping of a node were fixed.
    • Fix the extremely slow operation of the View > Expand Full Branch and Collapse Full Branch commands.
    • Fix improperly placed branch lines in printed output.
      Missing Features (not implemented yet):
    • Plugin support.
    • Language translations.
    • Help documentation.
    • Font appearance options for views.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    October 22, 2013 - Release 1.9.2 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of a full rewrite of TreeLine. It is not feature complete and probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.4.x) should be used for critical work.
    • The documentation is not included yet. It needs to be updated to cover the new features.
    • The GUI and documentation translations have not yet been done.
      New Features:
    • Added a spell check tool. This requires either aspell, ispell or hunspell to be installed.
    • Included a node numbering field type with several formatting options. An update numbering command fills in the sequence.
    • Added a command to add a category level based on a subset of data fields.
    • Added a flatten by category command to combine parent fields into child nodes.
    • A new flatten by link command flattens the structure and provides internal links to the former parent nodes.
    • An arrange by link command restores the structure based on parent internal links.
      Updates:
    • Allow file URL drag-and-drop on active external link data edit widgets.
    • Change the Linux installer to use the 'share' directory in place of 'lib' for python files.
    • Update the Windows binary to use version 3.3 of Python.
      Bug Fixes:
    • Fix out of sequence output lines when output formats are longer than ten lines.
    • Fix problems with unique IDs and internal links when indenting and unindenting nodes.
    • Avoid widget focus problems when editing data on conditional types.
    • Maintain the output format cursor position when changing fields in the configure dialog.
    • Fix importing of generic XML documents that have nodes with no data.
      Missing Features (not implemented yet):
    • Plugin support.
    • Language translations.
    • Help documentation.
    • Font appearance options for views.
    • Previous/next selection history commands.
    • Customized keyboard shortcuts.
    • Customized toolbars.
    • Prefix/suffix sibling tags for HTML tables, bullets, etc.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be fully compatible with TreeLine 1.4.x.

    May 2, 2013 - Release 1.9.1 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of a full rewrite of TreeLine. It is not feature complete and probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.4.x) should be used for critical work.
    • The documentation is not included yet. It needs to be updated to cover the new features.
    • The GUI and documentation translations have not yet been done.
      Updates:
    • Added TreeLine file compression and file encryption, controlled from a File > Properties dialog box.
    • Tree node open/close states are restored for recent files.
    • Added derived data types that keep the field list of their generic type.
    • Added conditional type setting that changes icons or output format based on field contents.
    • Other field references (file info, ancestors, children) can be used in node output formats and in print headers & footers.
    • Added an HTML file export to a single file with a navigation pane on the side.
    • Allow embedded blank lines in non-HTML node output formats.
    • Added an output separator config option for combination fields and child references.
    • Add an option to set the first day of the week for calendar widgets.
      Bug Fixes:
    • Fixed problems with pasting or dragging multiple nodes.
    • Made removing fields from multi-line output formats work properly.
    • Prevent duplicate unique IDs from being created after undoing the deletion of a branch.
    • Fixed node sorting of non-text nodes (numbers, dates, times, etc.)
    • Avoid placing calendar widgets partially off screen if near the bottom.
    • Limit the automatic height increases for text edit cells to avoid confusing double scroll bars.
      Missing Features (not implemented yet):
    • Plugin support.
    • Language translations.
    • Help documentation.
    • Spell checking.
    • Font appearance options for views.
    • Previous/next selection history commands.
    • Customized keyboard shortcuts.
    • Customized toolbars.
    • Automatic node numbering.
    • Prefix/suffix sibling tags for HTML tables, bullets, etc.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be compatible with TreeLine 1.4.x.

    February 6, 2013 - Release 1.9.0 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot of a full rewrite of TreeLine. It is far from feature complete and probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.4.x) should be used for critical work.
    • The documentation is not included yet. It needs to be updated to cover the new features.
    • The GUI and documentation translations have not yet been done.
      Major New Features:
    • TreeLine has been fully rewritten using Python 3.
    • Improved performance due to direct use of model-view classes for views and ElementTree for input/output.
    • A table based data editor pane (much faster).
    • WYSIWYG formatting in the data editor view.
    • Real-time updates of the same file shown in multiple windows.
    • Improved printing and print preview performance.
    • Saves print options with the TreeLine file.
    • Built-in print to PDF function.
    • More searching options.
    • A filtering command shows matches in a simple list.
    • Sorting parameters can be saved with each data type.
    • The basic text field type allows formatting, preserves line breaks and allows HTML restricted characters.
    • A calendar widget can be used for editing date fields.
    • Internal link fields and inline internal links are easier to use.
    • An external link type supports http, https, file and mailto protocols.
    • Relative paths are supported for external links and pictures.
    • A regular expression field type can match patterns (phone numbers, email addresses, etc.)
    • Unique node IDs are automatically generated and updated.
    • A new windows installer allows a single-user, non-administrator install.
    • Includes better support for portable installs.
      Missing Features (not implemented yet):
    • File compression and file encryption.
    • Plugin support.
    • Language translations.
    • Help documentation.
    • Saving of tree open/close states.
    • Spell checking.
    • Font appearance options for views.
    • Previous/next selection history commands.
    • Customized keyboard shortcuts.
    • Customized toolbars.
    • Generic and derived data types.
    • Conditional type setting.
    • Automatic node numbering.
    • Other field references (file info, ancestors, children).
    • Prefix/suffix sibling tags for HTML tables, bullets, etc.
      Compatibility Notes:
    • There are some file format changes between TreeLine 1.4.x and this version of TreeLine.
    • Older files opened in this version are automatically converted when saved.
    • Files saved in this version may not be compatible with TreeLine 1.4.x.

    November 11 2011 - Release 1.4.1 (stable release)

      Bug Fixes:
    • Fixed failures due to bad internal references when opening encrypted files in multiple windows.
    • Avoid corruption of user option settings after attempting to automatically open an imported file as the last file used.
    • Fix problems with imported files when the user sets new files to be encrypted by default.
    • Prompt the user for a password when copying types from an encrypted TreeLine file.

    April 14, 2011 - Release 1.4.0 (new stable release)

      Notes:
    • This is a new stable release, ending the 1.3.x development series.
    • This release is available in English, French and German, although the French documentation is not completely up to date. Volunteers to do additional translations are welcome.
      Updates:
    • The file browser used for editing path-based fields now remembers the previously used directory.
    • Added icons for the New Window and Close Window commands so they can be added to toolbars.
      Bug Fixes:
    • Fixed a bug that could keep the column control from being enabled during HTML export.
      Major New Features Since 1.2.x:
    • Different files can be open in multiple TreeLine windows within the same TreeLine session. This is controlled with commands in the new "Window" menu.
    • The "Window->New Window" command creates a new window with views of the same TreeLine file. Changes in either window are saved in the same document.
    • Starting TreeLine (from a shortcut, file association or command line) will activate an existing TreeLine session if it is already running.
    • An "Add internal link" context menu has been added to text boxes in the data editor. It prompts for another node to be clicked with the mouse, then an inline internal link is added with that node's reference information.
    • Added an "HTML directory pages" export option. This will export a directory structure with an HTML file for every node. A navigation pane on the left side of each page contains links to nearby nodes.
    • New dialog buttons will restore the default configuration when customizing toolbars or shortcuts.
    • A new text search function has been added to the help viewer.

    January 5, 2011 - Release 1.3.5 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It may contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.2.x) should be used for critical work.
      Updates:
    • Incorporated some minor code clean-ups (thanks to Erik Wegner for identifying them).
    • The Windows binary is now based on the Python 2.7, Qt 4.7 and PyQt 4.8 libraries.
      Bug Fixes:
    • Fixed incorrect sorting by type with siblings of mixed types.
    • Fixed problems showing child lines in print previews if the lines option was changed with the preview open.
    • Really disable click-to-rename if the general option is unselected.

    September 22, 2010 - Release 1.3.4 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It may contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.2.x) should be used for critical work.
      Updates:
    • Added ico and gif as valid tree icon types.
    • The French GUI translation has been updated, but the documentation translation is still out of date.
    • Minor updates have been made to the German GUI translation.
      Bug Fixes:
    • The list of windows in the Window menu is now properly updated after saving a file with a new name.
    • Fixed a bug that could cause spell checks to hang.

    June 24, 2010 - Release 1.3.3 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It may contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.2.x) should be used for critical work.
    • German is the only GUI and documentation translation that has been updated so far.
      New Features:
    • A new text search function has been added to the help viewer.
    • The keyboard shortcuts for scrolling the right-hand views (Ctrl+Page Up and Ctrl+Page Down) now cycle through the Data Editor view pages if there is no more room to scroll
      Updates:
    • The Linux system requirements have been updated to indicate that Qt 4.4 or higher is now required.
    • The Windows installer now sets the sample and readme documents to read-only status.
    • The German GUI and documentation translation has been updated.
      Bug Fixes:
    • The cascading of new windows has been fixed. It now references the current position of the previous window, and it avoids cascading windows off of the screen.
    • The Data Editor widgets are now sized correctly when TreeLine is started in Data Editor mode.
    • The spell checker and the Linux installation script have been updated to avoid subprocess command depreciation warnings.

    May 14, 2010 - Release 1.3.2 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It may contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.2.x) should be used for critical work.
    • The GUI and documentation translations have not yet been updated.
      Updates:
    • Updated the ReadMe file to cover the new features added during this development cycle.
      Bug Fixes:
    • Fixed a major bug that prevented files from being saved at the "Save Changes?" dialog when closing a modified file.

    April 8, 2010 - Release 1.3.1 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It may contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.2.x) should be used for critical work.
    • The documentation has not yet been updated to cover the new features.
    • The GUI and documentation translations have not yet been updated.
      New Features:
    • Added a menu command that updates another window containing the same file (without waiting for a focus change). This command also has a keyboard shortcut (Ctrl+W).
    • A menu option has been added to hide the status bar. There is also a new general option to hide it at startup. A hidden status bar is automatically shown temporarily for important messages.
    • A new button on the toolbar editing dialog will restore the default toolbar configuration.
    • A new button on the keyboard shortcuts editing dialog will restore the default shortcut configuration.
      Updates:
    • Portability on Windows has been improved. A "treeline.ini" config file in TreeLine's "lib" directory will be used if it's present and there are no config files in the user's application data directory.
    • The Change Selected Data command has been updated to use Data Editor formats for dates and times.
    • An alternate TreeLine executable file (treeline_dos.exe) has been added to make batch command-line operations work from Windows.
    • Additional plugin methods have been added for handling files and languages.
      Bug Fixes:
    • Fixed a problem spell checking with older versions of aspell when Unicode characters were present.

    October 14, 2009 - Release 1.3.0 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is not feature complete and probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.2.x) should be used for critical work.
    • The documentation has not yet been updated to cover the new features.
    • The GUI and documentation translations have not yet been updated.
      New Features:
    • Multiple TreeLine windows with different files can be open within the same TreeLine session. The "Open files in new windows" general option controls whether new windows are used when opening or creating files.
    • A "Window" menu has been added with commands to create new windows, close windows, or select from a list of current windows.
    • The "Window->New Window" command creates a new window with views of the same TreeLine file. Changes in either window are saved in the same document. This can be used to work in different sections of the file simultaneously. For performance reasons, the non-active window does not show the changes made in the active window until the non-active window is focused.
    • Starting TreeLine (from a shortcut, file association or command line) will activate an existing TreeLine session if it is already running. A new window will be opened if an unopened file was specified by file association or in the command line.
    • An "Add internal link" context menu has been added to text boxes in the data editor. It prompts for another node to be clicked with the mouse, then an inline internal link is added with that node's reference information.
    • Added an "HTML directory pages" export option. This will export to a directory structure with an HTML file for every node. A navigation pane on the left side of each page contains links to the node's parent, uncles and children.
      Updates:
    • The general options dialog has been split into three columns for better viewing on small, wide displays.
    • Additional export commands and export options have been added to the plugin interface.
    • To avoid a problem on the Mac platform, when TreeLine is run for the first time, it lets the OS determine the window position.

    October 12, 2009 - Release 1.2.4 (stable release)

      Bug Fixes:
    • Added a work-around for a bug in PyQt 4.6's clipboard support that can prevent TreeLine from starting.
    • Prevent an uncommanded horizontal scrolling to the left of the tree view when changing the selection.

    May 5, 2009 - Release 1.2.3 (stable release)

      Updates:
    • A new build has been created for use on the Windows 98 operating system. This fixes problems that made TreeLine 1.2.2 unusable on Windows 98.
    • Data copied to the Windows clipboard is now preserved after exiting from TreeLine.
      Bug Fixes:
    • Fixed a bug on Windows that showed an error message at program exit if the copy command had been used during the session.
    • In an HTML directories export, characters that are illegal in directory names are now correctly removed.

    January 8, 2009 - Release 1.2.2 (stable release)

      Updates:
    • Added German translations of the GUI and the ReadMe file.
    • Added a few missing strings to the translation files.
    • Substituted some imported modules to avoid deprecation warnings in Python 2.6. Note that Python 2.3 is no longer supported.
    • The windows binary has been updated to use Python 2.6, and the installer has been tweaked to reduce DLL conflicts.
      Bug Fixes:
    • Fixed problems using the tab key to change focus from the tree to the data editor.
    • ID numbers are now properly assigned to new nodes with UniqueID fields in the title.
    • Fixed problems creating nodes with child count fields in the titles.

    November 4, 2008 - Release 1.2.1 (stable release)

      Bug Fixes:
    • Fix the loss of entered text when the renaming of a node is ended by a command that changes the selected node.
    • Problems with opening files with Unicode file names from the command line or from a file association have been fixed.
    • Fixed problems with JPEG and GIF image support in the Windows binary build.
    • When commands change the tree view, it no longer scrolls vertically unless the current node is not visible.
    • Fixed problems with files set to both compressed and encrypted modes. But note that compressing an encrypted file still does not significantly reduce its size.
    • Problems on the Macintosh platform with detecting the text encoding and with setting the default theme have been fixed.

    June 17, 2008 - Release 1.2.0 (new stable release)

      Notes:
    • This is a new stable release, ending the 1.1.x development series.
    • This release is only available in English and French. The 1.0.2 release is still available, including German, Portuguese, Russian and Spanish translations. Volunteers to update the translations are welcome.
      Updates:
    • The French translations of the GUI and the ReadMe file have been updated.
      Bug Fixes:
    • When restoring an auto-saved backup file, TreeLine no longer replaces a the main file with the backup if the backup is not a valid TreeLine file.
    • Fixed a minor bug in the Configure Data Types dialog caused by unselecting a field in the Output pane.
      Major New Features Since 1.0.x:
    • TreeLine was extensively rewritten to port it to the Qt4 library (previous versions used Qt3.x on Linux and Qt2.3 on Windows). Benefits include updated widgets and removal of the non-commercial license exception in Windows.
    • Preformatted templates have been added for new TreeLine documents. User-created templates can also be added.
    • The content of right-hand views varies based on the selection and other options. A single selection still shows panes with the parent and its children, but a multiple selection will show all of the selected nodes in a single pane. Also, the Data Output view can optionally show an indented view of all descendants, and the Data Editor view splits the display into pages to speed up display.
    • More commands can make use of a multiple selection instead of just using the single active node. Also, an option can set the sequence of showing and exporting multiple selections to either tree order or selection order.
    • There is a tab on the left-hand view for a flat node list showing the selected nodes and all of their descendants. It is most useful for showing the results of filtering. There is a conditional filter for specific rules and a text filter that searches all fields for a string.
    • Several dialogs have been reworked for usability. The Configure Data Types and Print Options dialogs use tabs for better organization. The Configure dialog also has initially hidden advanced features and is now modeless, so it can be left open while applying configuration changes. The Sort, Export and Print Preview dialogs have also been updated.
    • Navigation through the tree is simplified by new commands that step through the selection history. Also, search strings are now highlighted in the Data Output view for text searches.
    • New dialogs have been added to customize keyboard shortcuts and tool bar buttons. There is also a directory for user-defined tree icons.
    • New file import and export options convert between an outline and an Open Document Format (ODF) text document, compatible with OpenOffice.org and KWord. Formatting is not maintained.
    • A Unique ID field type has been added that is automatically loaded with unique numbers. It is useful for link references.

    January 15, 2008 - Release 1.1.10 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is nearly ready to become a stable release, but it could still contain bugs. Testing and bug reports are appreciated.
    • The French translation of the GUI is the only one completed so far. None of the documentation translations have been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages may not be available yet for these libraries in some distributions.
    • If you've installed previous development releases, it is recommended that you delete the old configuration file ("~/.treeline-1.1/treelinerc" on Linux, "Documents and Settings\<login>\Application Data\bellz\treeline-1.1\treeline.ini" on Windows) before running this release.
      Updates:
    • Exporting to HTML directories has been improved. The file names are generated from the reference field (were from the first field). Internal links to nodes now work properly in the exported files.
    • When saving a new file, the Save-As dialog now defaults to the top directory in the recent file list.
    • A translation of the GUI in French is now available. The i18n installation file is a separate download.
    • The ReadMe documentation file has been updated to clarify certain usage issues.
      Bug Fixes:
    • The other controls in the configuration dialog are updated immediately when setting a data type to be derived from a generic.
    • A recent file list bug that affected the httpload plugin has been fixed. Also, a library need by the plugin (urllib) has been added to the Windows installation.
    • An error message about removing a status bar widget has been eliminated.
    • An error on a Mac when setting the language encoding has been fixed.
    • Various issues with file paths containing Unicode characters have been fixed.

    June 13, 2007 - Release 1.1.9 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It could contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.x) should be used for critical work.
    • The translations of the GUI and of the documentation have not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
    • If you've installed previous development releases, it is recommended that you delete the old configuration file ("~/.treeline-1.1/treelinerc" on Linux, "Documents and Settings\<login>\Application Data\bellz\treeline-1.1\treeline.ini" on Windows) before running this release.
      Updates:
    • Initially select the top filtering result in the flat view to avoid issues with a blank selection.
    • Avoid entering rename mode when clicking on a multiple selection in the flat view.
    • Maintain the size of the type icon dialog during a session.
    • Remove the redundant printing units option from the general options dialog.
    • Extensively update the ReadMe documentation to match the current feature set.
    • Add a new file template for TODO lists.
      Bug Fixes:
    • Fix incorrect internal references in groups of pasted nodes.
    • Abort a tree rename operation if the new name does not match the title format.
    • Correctly add a field to the generic type when numbering a derived type.
    • Properly update the pull-down choices for a choice or combination field after a configuration change.
    • Enable the conditional type button immediately after defining a type as derived.
    • Remove the page number field from the available file reference fields in the main configuration settings.
    • Properly update the Data menu after starting a filtering operation.
    • Fix an error due to a missing system language setting.
    • Properly handle a file open error due to an unknown field type.

    June 1, 2007 - Release 1.0.2 (stable bug-fix release)

      Updates:
    • The environment variable LC_MESSAGES is now checked before the LANG variable to determine the user's preferred language.
      Bug Fixes:
    • Problems with automatically adding a new field to derived data types when using the Data->Numbering and the Data->Flatten... commands have been fixed.
    • Fixed a crash at file open if the file's owner is not found in a Linux machine's user password database.

    May 22, 2007 - Release 1.1.8 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.x) should be used for critical work.
    • The documentation and GUI translations have not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
    • If you've installed previous development releases, it is recommended that you delete the old configuration file ("~/.treeline-1.1/treelinerc" on Linux, "Documents and Settings\<login>\Application Data\bellz\treeline-1.1\treeline.ini" on Windows) before running this release.
      Updates:
    • Translation of ODF text documents has been added to the command line batch processing options.
    • The environment variable LC_MESSAGES is now checked before the LANG variable to determine the user's preferred language.
      Bug Fixes:
    • Problems writing the options file when there are Unicode characters in the username have been fixed.
    • Various minor bugs in Unicode handling have been fixed.

    May 3, 2007 - Release 1.1.7 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is not feature complete and probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.x) should be used for critical work.
    • The documentation and GUI translations have not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
    • If you've installed previous development releases, it is recommended that you delete the old configuration file ("~/.treeline-1.1/treelinerc" on Linux, "Documents and Settings\<login>\Application Data\bellz\treeline-1.1\treeline.ini" on Windows) before running this release.
      New Features:
    • Preformatted templates have been added. The File->New command brings up a dialog with a list of available templates. The dialog is also shown at startup if the recent file list is empty. Default templates are installed into TreeLine library directories. New templates can be added to a user templates directory in the user settings location. Template file names consist of a number for sorting, a language code and the name of the template.
      Updates:
    • The Save As dialog in Windows is now the native dialog.
      Bug Fixes:
    • Problems exporting to an ODF text document when blank fields are encountered have been fixed.
    • Added appropriate error messages to the Linux installer if some installer files are not found.

    April 17, 2007 - Release 1.1.6 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is not feature complete and probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.x) should be used for critical work.
    • The documentation and GUI translations have not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
    • If you've installed previous development releases, it is recommended that you delete the old configuration file ("~/.treeline-1.1/treelinerc" on Linux, "Documents and Settings\<login>\Application Data\bellz\treeline-1.1\treeline.ini" on Windows) before running this release.
      New Features:
    • A new command (View->Show Output Descendants) toggles the Data Output child view from showing only child nodes to showing an indented view of all descendant nodes. A button was added to the default toolbar for this command. Also, a new general option can make the descendant view the default at startup.
    • A new file export option converts an outline to an Open Document Format (ODF) text document, compatible with OpenOffice.org and KWord. The title of each node is assigned a heading style at the appropriate level. Any other text in the output of each node becomes normal text under the heading. Any HTML formatting is stripped.
    • ODF text documents can be imported. The node structure is based on the heading styles assigned in the document. Any text under each heading is assigned to that heading's node. Formatting is not maintained.
      Updates:
    • New commands were added to the Data Editor context menus that open the Configure Data Types dialog with the editor's type and/or field already selected.
    • Keyboard shortcuts were added for the commands that add HTML tags in the Data Editor. Icons were also added to these commands, so the toolbar editor can be used to place them on a toolbar if desired.
    • The interface for writing plugin modules was improved by adding interfaces to the keyboard shortcut editor and the toolbar editor. Also, a plugin interface to get the plugin's directory was added.
    • Any default text for new fields is added when a node's data type is changed (not just to a new node), as long as there isn't already data in a field with the same name.
      Bug Fixes:
    • Fixed a problem with the automatic opening of the last file used if there are no valid recent files.
    • Fixed a crash at file open if the file's owner is not found in a Linux machine's user password database.
    • Issues with the display of text have been fixed if the Qt library being used is version 4.2.3 or greater (the Windows build now uses 4.2.3). These issues showed up when scroll bars were shown and could hide the right edge of the text or the last line.
    • Multiple issues with dragging or pasting nodes between sessions of TreeLine were fixed.
    • If the Configure Data Types dialog is open, it is properly updated after the use of the undo command.
    • The find dialog is properly focused when repeatedly shown.
    • Fixed problems occurring when attempting to print an empty branch or an empty selection.
    • Fixed problems with the export of HTML directories. It now removes illegal characters from directory names created from field contents.
    • Auto choice fields are now properly updated after configuration changes.
    • A missing help menu was added to the Unique ID field format editor.

    March 8, 2007 - Release 1.0.1 (stable bug-fix release)

      Updates:
    • A Russian translation of the GUI and ReadMe file has been added. As a result, there are now six supported languages (English, French, German, Portuguese, Russian and Spanish).
      Bug Fixes:
    • Fixed a problem using drag & drop on a node with a conditional type.
    • Avoid problems caused by using the Edit->Cut command with the root node included in the selection.
    • The importing of files with bad Unicode characters has been improved.

    February 22, 2007 - Release 1.1.5 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is not feature complete and probably contains bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.0) should be used for critical work.
    • The documentation and GUI translations have not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
    • If you've installed previous development releases, it is recommended that you delete the old configuration file ("~/.treeline-1.1/treelinerc" on Linux, "Documents and Settings\<login>\Application Data\bellz\treeline-1.1\treeline.ini" on Windows) before running this release.
      New Features:
    • A Unique ID field type has been added. The field is automatically loaded with unique numbers. Initially, the field's format string is set to the desired first number in the series, with optional leading zeros and optional leading or trailing characters. All nodes of the data type will get an automatically assigned ID. The field format string will always show the next available number, which will be given to the next new node of that type.
    • The node sorting commands have been consolidated into a single new dialog. This provides more options for selecting what to sort (all nodes, branches, children or siblings) and how (by types and fields or by titles).
    • An option has been added to the numbering dialog to only number nodes where the number field already exists. This allows node types in the branch that do not have the number field to be skipped.
      Updates:
    • The tree view no longer scrolls horizontally when the selection is changed.
    • The focus behavior of the Data Editor view has been tweaked to allow easier tabbing between widgets.
    • Clicking on a selected node to rename it is now disabled when multiple nodes are selected. This avoids initiating a rename when the intent was to modify a multiple selection.
    • The Insert Sibling Before command has been added to the node right-click context menu for consistency.
    • The Spell Check dialog is no longer hidden and re-shown between each misspelled word, resulting in smoother operation.
    • The Output tab of the Configure Data Types dialog has been adjusted to avoid changing the dialog size when toggling the advanced options.
    • The fonts in the Print Options dialog are sorted case insensitively, and the size of the dialog is fixed regardless of the selected font.
      Bug Fixes:
    • Fixed a crash when opening a file with the flat view shown.
    • Fixed problems occurring when the number of toolbars was set to zero.
    • Fixed undo operations for Numbering, data Add Category Level and Arrange by Reference commands.
    • Fixed problems with undo and delete commands issued while a node is being renamed.
    • Fixed problems with renaming data types and fields in the Configure Data Types dialog.
    • Avoid adding duplicate types to Other Field References in the advanced Output tab of the Configure Data Types dialog.
    • No longer allow the Edit Cut command to operate if the root node is selected.
    • Fixed a freeze of the spell checker on some platforms.
    • An empty rectangle that was sometimes shown on the status line at the bottom of the main window has been removed.
    • An occasional problem with the import of generic XML was fixed.
    • The importing of files with bad Unicode characters has been improved.
    • The restoring of tree states when opening a file has been made more robust.
    • Fixed several other minor tracebacks that can show up in a terminal or log file.

    January 18, 2007 - Release 1.1.4 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is not feature complete and is sure to contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.0) should be used for critical work.
    • The documentation and GUI translations have not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
      New Features:
    • Previous and Next Selection commands have been added to the View menu. These commands step through a history of tree selections for quicker navigation.
    • When using the Find command with the Data Output view visible, the search string occurrences are highlighted in the output. Note: in Linux, this feature requires Qt v4.2 or greater and PyQt v4.1 or greater.
    • An icons directory has been added to the user configuration directory ("~/.treeline-1.1/icons" on Linux, "Documents and Settings\<user>\Application Data\bellz\treeline-1.1\icons" on Windows). Image files (PNG or BMP) placed into this directory are available for use as tree icons.
    • "Move First" and "Move Last" commands have been added to the Edit menu. These commands move a child node to be the first or last child of its parent.
      Updates:
    • Horizontal scrolling of the tree view when the contents are wide is now supported.
    • The non-interactive command line options have been ported from the stable version. These options allow batch processing of file imports and exports.
    • Support for plugin extension modules has been ported from the stable version. The interfaces to TreeLine functions are unchanged, but existing plugins will need to be ported to the Qt4 library. An updated version of the httpLoad plugin is available.
    • A plugins directory has been added to the user configuration directory. This allows plugin installation without elevated privileges.
    • The code required to support GUI translations has been ported from the stable version, but the actual translations have not yet been updated.
      Bug Fixes:
    • The problem with cut/copy/paste operations in Windows that produced an error message at application exit was fixed.
    • Fixed several problems with the undo of changes to the Data Type Configuration.
    • A bug that could sometimes add an extra node during renaming in the Tree View has been fixed.
    • Problems encountered when typing a replacement word during spell check have been fixed.
    • A spell check language setting in File Options that is not available on the system is now ignored.

    December 21, 2006 - Release 1.1.3 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is not feature complete and is sure to contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.0) should be used for any critical work.
    • Some features from the stable release are not yet implemented here. These include command line options, plugin support and translation support. Also, the documentation has not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
    • One known bug in the Windows version produces an error message at application exit if cut/copy/paste operations were done during the session.
      New Features:
    • A new built-in editor for keyboard shortcuts has been added to the Tools menu. It has two tabs: one for menu commands and one for other commands. Simply press the desired key combination to change the shortcut in the selected entry. In general, printable characters without Ctrl or Alt modifiers should not be used for shortcuts. Although the editor will accept them, they may not work properly when certain widgets are focused.
    • A dialog to customize the tool bars has been added. It is accessed from the Tools menu. This allows the user to select small or large icons, define the number of tool bars, and define the commands included in each tool bar.
      Updates:
    • The saving of node open/close states for recently opened files has been ported from the stable version.
    • The restoring of splitter sizes and the active right-hand tab from the previous session has been ported from the stable version.
    • The TreeLine configuration files now include a version number (.treeline-1.1 on Linux, treeline-1.1.ini on Windows) to avoid incompatibility issues with previous versions.
    • The default non-menu keyboard shortcuts have been changed to control-key sequences that function regardless of the focused widget.
    • The incremental node title search has been ported from the stable version. The default keyboard shortcut is now Ctrl+/.
    • The option to add a node when pressing the enter key has been ported from the stable version.
      Bug Fixes:
    • Searching for nodes with the flat view active now only finds nodes actually present in the flat view.
    • Problems with drag & drop of nodes with Unicode content were fixed.
    • The Icon Selection dialog under Configure Data Types now scrolls to the currently selected icon when opened.

    November 22, 2006 - Release 1.1.2 (unstable development snapshot)

      Notes:
    • All of the notes listed for Version 1.1.1 still apply.
      Bug Fixes:
    • Fixed a serious bug that caused TreeLine to crash when using a pull-down combo box on a field in the Data Editor view.

    November 21, 2006 - Release 1.1.1 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is not feature complete and is sure to contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.0) should be used for any critical work.
    • Several features from the stable release are not yet implemented here. These include keyboard shortcuts for non-menu items, command line options, plugin support and translation support. Also, restoring of tree node open/close states, window split locations and active tabs are not yet available. And the documentation has not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
    • One known bug in the Windows version produces an error message at application exit if cut/copy/paste operations were done during the session.
      New Features:
    • Printing functionality has been added to the development series. It now includes options to print the entire tree, the selected branches, or just the selected nodes.
    • A new Print Options dialog box is tabbed to give easier access to all of the options. There are buttons that give a more logical progression from the options to the print preview and to the print dialog.
      Updates:
    • The buttons at the bottom of the Configure Data Types dialog have been changed to OK/Apply/Reset/Cancel. This can reduce the number of mouse clicks.
    • The Configure Data Types dialog now defaults to the selected node's type when it is shown.
    • On Windows, the TreeLine.ini file has been moved from the installation directory to a location under the "Documents and Settings" folder. This avoids problems on multi-user systems and for users with limited access rights.
      Bug Fixes:
    • The Configure Data Types dialog now updates properly after copying types from another file, adding numbering, and rearranging by category and reference.
    • Various problems with node drag & drop that could result in inadvertent drops were fixed.
    • A bug that caused the right-hand view splitter to reset to even sizes was fixed.
    • Problems with saving changes to the format of file information fields were fixed.
    • Issues with some internal links and pictures in the help viewer were fixed.

    September 15, 2006 - Translation Updates

      Notes:
    • Spanish and Portuguese translations of the GUI and ReadMe file have been added for the stable version of TreeLine. A typo in the German translation was also fixed. The French translation remains unchanged.
    • The httpload plugin has been updated with French, German, Spanish and Portuguese translations.

    September 12, 2006 - Release 1.1.0 (unstable development snapshot)

      Notes:
    • This is an unstable development snapshot. It is not feature complete and is sure to contain bugs. Testing and bug reports are appreciated, but the stable release (TreeLine 1.0.0) should be used for any critical work.
    • Several features from the stable release are not yet implemented here. These include printing, keyboard shortcuts for non-menu items, command line options, plugin support and translation support. Also, restoring of tree node open/close states, window split locations and active tabs are not yet available. And the documentation has not been updated.
    • On Linux, running TreeLine requires Qt version 4.1 or higher and PyQt version 4.0 or higher. Binary packages are not yet available for these libraries in some distributions.
    • One known bug in the Windows version produces an error message at application exit if cut/copy/paste operations were done during the session.
      New Features:
    • TreeLine was ported to the Qt4 library. This involved a major rewrite of the code. The previous versions used Qt3.x on Linux and Qt2.3 on Windows. Benefits include updated widgets and removal of the non-commercial license exception in Windows.
    • The Configure Data Types dialog uses tabs for better organization. Many tabs contain advanced features that can be shown if desired. The dialog is also modeless, so it can be left open while applying configuration changes.
    • The content of the right-hand view varies based on the kinds of nodes selected. With a single parent node selected, it splits the view, showing the parent and its children (same as version 1.0.0). With a multiple selection or with a childless node selected, it shows all of the selected nodes in a single pane.
    • A general option sets the sequence for multiple selection to either tree order or selected order. When nodes are selected with control-click under the selected order option, they show in the right-hand view in the order they were picked. This sequence also applies to copy and export commands.
    • More commands make use of a multiple selection instead of just using the single active node. For example, the paste command will add duplicate children under each selected destination node.
    • The export command includes options to export the entire tree, the selected branches, or just the selected nodes.
    • In order to render the Data Editor right-hand view faster, there is a general option to set the number of "pages" initially shown. By default, only one page is shown. Buttons allow toggling to the next page or all pages.
    • There is a tab on the left-hand view to show a flat node list. It shows the initially selected nodes and all of their descendants. It is probably most useful when using filtering commands.
    • A conditional filter selects nodes based on rules for specific data types and fields, and a text filter selects based on finding the given text in any field. Both filters show their results in the tabbed "Flat View" and remain in effect until removed.
    • In the advanced mode, a child count field reference can be added to the output configuration. It shows the number of children at a specified descendant level.

    July 6, 2006 - Release 1.0.0

      Updates:
    • A new version numbering system is being introduced. This release is 1.0.0, to better indicate its stability. The 1.1.x series will be started soon for less stable development releases.
    • The German translation of the ReadMe file has been updated.
      Bug Fixes:
    • Fixed a problem with duplicate nodes showing up when pasting multiple nodes on Windows.
    • Deriving types from other derived types is no longer allowed, since it did not function properly.
    • A problem with saving an encrypted file in the German version of TreeLine has been fixed.

    February 16, 2006 - Release 0.14.1

      Updates:
    • Exported XSLT files now support field prefixes and suffixes. Thanks to Roland Meister for supplying patches.
    • Added functions to the plugin interface to allow plugins to open and close nodes.
      Bug Fixes:
    • Fixed a problem with displaying output from fields with non-ASCII characters in their names.
    • Auto save now works properly with encrypted files.
      Notes:
    • The French and German UI translation files and the French ReadMe files have been updated, but the German ReadMe files are not complete (but still usable). Updated files will be made available soon.

    December 20, 2005 - Release 0.14.0

      New Features:
    • Data types can be set to derive their field settings from a generic type. This allows types with different output formatting to always use the same field data. Any changes to the generic's list of fields and field types are automatically reflected in the fields of all derived types. A derived option can be selected when copying a type, or a generic type can be specified from the derived type's "Advanced Configuration" dialog box.
    • Conditional expressions can be used to automatically assign a data type based on each node's content. Conditions are assigned to a generic type and its associated derived types. This allows the automatic assignment of different output formatting or different icons depending on each node's field data. Conditions are specified from each type's "Advanced Configuration" dialog box. Conditions do not have to be set for all types in a family, since, if no conditions are true for a node, the program will select a blank condition over a false one. In addition, conditions that are always "True" or "False" are available to toggle the output format of all nodes of a certain type simultaneously by modifying the condition.
    • By default, the spell check uses dictionaries for the current operating system language. A new option under "Tools->File Options" can be used to specify an alternate two-letter language code for the current TreeLine file. This only works with aspell and with the appropriate aspell dictionaries available.
    • A new menu item, "File->Open Sample", is a shortcut to the directory containing sample template files.
    • A new menu item, "Help->Help Contents", directly opens the "Using TreeLine" section of the ReadMe file.
      Updates:
    • When changing a node's type, if the result would have been a blank title, TreeLine now adjusts the new title fields to maintain the original title text.
    • Picture links with relative paths now resolve their reference based on the directory containing the current TreeLine file.
    • When applying a font tag in the editor view, the selection is maintained. This allows multiple tags to be applied.
    • HTML tags in field prefixes and suffixes are now removed in node titles.
    • Exported HTML has been made somewhat more compliant with standards.
    • A new option on the windows installer toggles the writing of installation directory and uninstall information to the registry. When this and other options are disabled, TreeLine can be installed without modifying the registry.
    • Four more sample files have been included. These files provide examples of using TreeLine's features and can be used as templates.
    • The ReadMe file has been updated with descriptions of the sample files, with more internal links, and with screenshots.
      Bug Fixes:
    • A problem with saving reference field settings for unused node types was fixed.
    • Formats copied from another file are now available immediately.
    • Node titles from HTML-enabled fields that contain escaped characters (<, >, &) are now properly displayed.
    • Fixed some minor bugs concerning setting the default field value for new nodes.
    • A problem with exporting HTML directories with very recent versions of the PyQt library was fixed.
    • When displaying child data in node output, extra separators between blank entries are no longer shown.
      Notes:
    • The French and German UI translation files have been updated, but the French and German ReadMe files are not complete (but still usable). Updated files will be made available soon.

    November 4, 2005 - German Translation Update

      Notes:
    • Updated German translations are now available on the download page.

    November 1, 2005 - Release 0.13.1

      New Features:
    • The number of recently used files listed in the File menu can be set using a new general option. Note that this also controls how many files have their tree states (open/closed nodes, etc.) saved.
      Updates:
    • TreeLine now sets the interface language using the LANG environment variable (if set) before falling back to other locale settings. This allows the operating system's locale settings to be overridden.
      Bug Fixes:
    • Problems starting TreeLine when the locale's LANG variable ends with "@euro" have been fixed.
    • Problems with the display of the rename edit box when creating new nodes in a long, scrolled tree view have been fixed.
      Notes:
    • The French translation files have been updated, but the German files are not complete (but still usable). Updated files will be made available soon.

    August 29, 2005 - Release 0.13.0

      New Features:
    • The TreeLine user interface and documentation have been internationalized. Currently, translations are available for French and German. Volunteers to translate into additional languages are welcome.
    • Number formats can be internationalized. Periods and commas are supported as radix characters, and commas, periods or spaces can be set as thousands separators.
    • A new general option can set printing units to either inches or centimeters.
    • An external editor can be invoked from a Data Editor text field context menu. The EDITOR environment variable can be used to specify the editor to start, or, if the variable doesn't exist, TreeLine will prompt for an executable to set as the default.
      Updates:
    • The general option for a number editing format has been removed. Instead, the output format is displayed in the editor. Of course, any new entry with a reasonable format is correctly interpreted (but the correct radix character must be used).
    • Handling of spaces in filenames for the linking fields have been improved. Paths with spaces selected in the file browser are properly quoted (Windows) or escaped (Linux).
    • Page Up/Down commands in the Data Output view now leave a one-line overlap.
    • A Ctrl-C interrupt in a terminal is now ignored.
      Bug Fixes:
    • A dummy field has been added to imported bookmark separator formats to avoid configuration problems.
    • Paths in links to XSLT files are now properly handled when not in the same directory as the XML file.
    • Format text is now immediately updated when renaming fields.
    • Problems with undo after complex data changes have been fixed.
    • Errors due to having ASCII control characters in TreeLine text have been fixed.
    • Problems with spell check of unicode characters have been fixed.

    May 4, 2005 - Release 0.12.0

      New Features:
    • A new AutoChoice field type provides pull-down selection of previously used entries. Any new entries are automatically added to the pull-down.
    • A new ExecuteLink field type runs an external program when its link is clicked. The command to run is given by the text of the field. Or the field's prefix may contain the program name, so that the field's text is used for arguments or file names. There is also a general option to disable these links when security is a concern.
    • A button that brings up a file browsing dialog has been added to the editor for Path, ExecuteLink and Picture field types.
    • Link fields can display alternate text in place of the target URL. This is done by specifying an alternate text field in the Advanced Field Format dialog.
    • Fields from child nodes can be embedded in their parent's output. Select a child reference from the Other Fields dialog. The child data is delimited with a separator string defined as a file option.
    • A new file option allows the removal of line breaks from each output line. This allows other HTML tags to be used to separate the output lines.
    • A "contains" rule to check for substrings has been added to the rules for node filtering and selective type changes.
    • The right-hand view that was previously used is now selected automatically on startup. This can be disabled using the general restore window geometry option.
      Updates:
    • Toolbar and tree icons are loaded from individual PNG files instead of from an XPM file. This improves icon quality.
    • Some features from the dialogs for data types and fields have been moved to advanced dialogs for simplicity.
    • Unicode characters are accepted for first-letter tree searches.
    • All calls to the eval() function have been replaced for improved security. Thanks to Roland Meister for providing patches.
    • The HTML version of the ReadMe file is now exported from the TreeLine version.
    • Spaces are permitted in Linux command line arguments.
    • Qt command line options are supported.
    • There have been several minor improvements to the plugin module interface.
      Bug Fixes:
    • A serious problem with deleting the last child under the root item has been fixed.
    • Some keyboard shortcuts for incremental searching have been fixed.
    • Open nodes are restored more consistently when opening files.
    • A font issue on early versions of Qt3 has been fixed.
    • The search for dtd files linked from XML files has been disabled to eliminate errors.
    • Visibility problems with long unbroken text lines in data editors have been fixed in Qt3.

    February 16, 2005 - Release 0.11.1

      Bug Fixes:
    • Fixed a compatibility issue in the toolbar code that would prevent TreeLine from starting when PyQt was built against the newest versions of the sip library (versions 4.2rc1 and 4.2rc2).
    • Problems with editing the data of combination field types have been fixed.
    • A bug in the plugin interface for setting field formats has been fixed.

    February 4, 2005 - Release 0.11.0

      New Features:
    • Icons have been added to the tree view. The icon assigned to each data type can be changed from the Configure Data Types dialog box. There are several generic icons available within TreeLine, and plugin modules can be written to add additional ones. A general option to disable the tree icons has also been added.
    • A command has been added to the data menu to copy type formatting from another TreeLine file. All types from the chosen file are copied. Any types in the current file with a matching name are overwritten, but types with unique names are retained.
    • Functions to import and export generic XML files have been added. These routines do not have much intelligence - each XML element becomes a node and each XML attribute becomes a field. This lets TreeLine function as a crude XML editor.
    • An editor height parameter has been added to text fields. This allows the number of lines in the data editor to be set for each field in each data type. As a result, the LongText field type becomes redundant and has been removed.
    • A field parameter has been added for fields that are required to be filled. Fields with this parameter set are marked with an asterisk in the data editor view.
    • Another field parameter has been added to allow certain fields to be hidden in the data editor view.
      Updates:
    • A fair amount of TreeLine code has been rewritten to improve efficiency and to ease future changes. Users should see improved speed with large files, especially noticeable when repainting during editing.
    • TreeLine now requires Python Version 2.3 or higher on Linux systems. The previous version of TreeLine will remain available for those stuck with older versions of Python.
    • HTML tags are now stripped from node titles in the left-hand tree view if the fields are set to output HTML rich text.
    • The plugin extension module interface has been expanded. Several added functions deal with node and field formatting. There is also a new callback trigger called whenever a node's data is modified.
    • A user plugin directory can now be specified in the configuration file. This allows plugins to be installed without root/administrator access.
    • An option has been added to the Linux installer to allow a different documentation directory to be specified.
      Bug Fixes:
    • Fixed a drag-and-drop bug that wouldn't allow nodes to be moved instead of copied in the Linux version.
    • Fixed the output of fields that include dashes and periods in their names.
    • A problem retaining the font setting for edit views has been fixed.
    • A rare startup failure due to problems with the encryption engine has been fixed.
    • A rare problem with foreign language encodings has been fixed.

    November 8, 2004 - Release 0.10.2

      Bug Fixes:
    • Fixed a major bug that could prevent new nodes that contain date or time fields from being created.

    October 28, 2004 - Release 0.10.1

      Bug Fixes:
    • Fixed a major bug that caused TreeLine to hang when attempting to open a recent file that no longer exists. This bug also caused startup failures if automatic opening was enabled with nonexistent files.
    • A bug in the plugin interface's getRootNode function was fixed.
    • Fixed a problem with file encryption on 64-bit systems.

    October 15, 2004 - Release 0.10.0

      New Features:
    • One of the fields in a data type can be tagged as a reference field in the field-type dialog box. It defaults to the first field. This field is now used as the reference for the arrange and flatten by reference commands. It is also used by the new internal link feature, described below.
    • There is a new internal link field type. It creates a clickable link in the Data Output window that selects the next node with matching text in its reference field. If link or reference fields contain multiple lines, each line is treated as a separate link or reference, respectively. If desired, the same field can be used as both the link and reference fields, so that clicking on a keyword in one node's field selects the next node that also has that keyword. If exported to HTML, the internal links function as links to page anchors, but, in cases with duplicate references, they only find the uppermost reference on the page instead of the next one.
    • File encryption has been added as an option to password protect TreeLine files. Individual files can be set to encrypted mode from either "Tools->File Options" or from the save-as dialog. There is also a general option to set the default for new files. The encryption uses the SHA hash function as a stream cipher - it should be fairly secure.
    • A default initial field value can now be specified for a field type. Any new nodes get this value for the given data field when they are created. Also, in date and time fields, an initial value of "Now" can be used to get a time-stamp of node creation.
    • An interface to plugin extension modules has been added to TreeLine. This allows extensions to be written by various coders that provide functionality needed by a few users without adding bloat to the main application. Currently available plugins are listed on the "Downloads" page of the TreeLine web site. The plugins are installed by copying their Python file (*.py) to the plugins directory ("<prefix>/lib/treeline/plugins/" on Linux or "TreeLine\lib\plugins\" on Windows). A list of loaded plugins can be found using the "Help->About Plugins" command. Information about writing plugins can be found in the "plugininterface.py" file in the TreeLine source code.
    • Options have been added under "Tools->General Options" to set the fonts used for the tree view and for the right-pane editor views.
    • When printing, TreeLine will now avoid breaking pages between a parent and its first child. This behavior can be disabled by changing the "Keep first child with parent" print option.
      Updates:
    • Unicode text handling has been improved. Unicode can now be used in TreeLine file names, node data type names and field names. Also, imported and exported text files now use the proper encoding based on the system's locale settings.
    • A new sample TreeLine file with internal link fields has been added to the documentation.
      Bug Fixes:
    • An occasional problem bringing up the field-type dialog for file-info fields was fixed.
    • Avoid showing an oddly-named internal file-info data type in the dialogs after the file-info format is changed.
    • The option to restore the view state when opening recently used files now works more consistently.

    September 16, 2004 - Release 0.9.1

      Updates:
    • Unicode text is now supported without requiring modifications of the Python sitecustomize file. The sitecustomize change has been eliminated from the installer.
    • The compressed ".trl.gz" extension has been added to the file open filter.
    • Information about the new TreeLine mailing list has been added to the documentation.
      Bug Fixes:
    • A bug that prevented XSLT file export under Linux has been fixed.
    • Special characters in bookmark URL's are now properly escaped during export to XBEL format.

    September 9, 2004 - New Mailing List

    A mailing list has been created for users to discuss anything and everything about TreeLine. This is the place for development discussions (from roadmaps to feature suggestions to beta testing), release announcements, bug reports, and general user discussions (from new uses to tips & tricks to configuration samples).

    To subscribe, go to this page. I expect this to be a low-volume mailing list.

    September 1, 2004 - Release 0.9.0

      New Features:
    • Import and export of bookmarks in both the Mozilla HTML format (Mozilla, Firefox and Netscape browsers) and the XBEL format (Konqueror, Galeon and Elinks browsers) have been added.
    • An new option exports a portion of a tree to another TreeLine file.
    • Command line options have been added to allow non-interactive file importing and exporting. This allows automated runs to be scheduled. For more details, run "treeline -h" from the command line. If using a windows binary, output is supressed, so it must be directed to a log file ("treeline -h > log.txt").
    • Options have been added to work with compressed TreeLine files. Individual files can be set to compressed mode from either "Tools->File Options" or from the save-as dialog. There is also a general option to set the default for new files. Thanks to Mathieu Girard for contributing code.
    • A field reference to show data from any ancestor node has been added. The closest one with a matching field is used.
    • Fields containing file meta-data have been added. These include file name, path, size, and modified time.
    • Headers and footers for printing have been added. They can contain the file meta-data mentioned above. The headers and footers can also be shown in exported HTML files.
    • HTML character formatting tags can be automatically added to text using a new data editor context menu. Available tags include bold, italics, underline, size and color. Note that the fields must be set to display HTML content for this to be effective.
    • A new general option makes new fields default to HTML content. This allows for easier display of HTML formatting. This option is not enabled by default, since it does not preserve carriage returns and does not show non-escaped "<", ">" and "&" symbols.
    • When opening a recently used file, TreeLine will now restore the states of open and selected nodes. If desired, this feature can be disabled with a new general option. Thanks to Jan Hustak for contributing this code.
    • The toolbar has been split into two separate bars (general commands and node commands) that can be shown and moved independently. Again, thanks to Jan Hustak for contributing this code.
    • A new auto-save feature stores unsaved files with a "~" appended to the name. The backup files are automatically removed when the file is saved or TreeLine exits cleanly. The auto-save time interval is set in the general options.
    • New key bindings, set to Shift+Page-Up and Shift+Page-Down by default, scroll the current right-hand child view.
    • The XSL export command now prompts for the name of an optional style sheet (css). This name is stored in the TreeLine file as the default for future exports.
      Updates:
    • There have been some general improvements to the handling of imported and exported files.
    • File option settings can now be restored with undo/redo commands.
    • The README documentation files have been revised to be more organized and readable.
    • More sample files are provided. See the "sample_*.trl" files in the "doc" directory of the installation.
    • The Linux install script now includes an option for a temporary build root directory.
      Bug Fixes:
    • The up-arrow key binding did not work as expected in a deeply nested tree.
    • Some problems with auto-completion on data editor combo boxes have been fixed.
    • Problems in windows with some option spin boxes accepting new values have been fixed.
    • Fixed a compatibility issue with older versions of Python.

    June 23, 2004 - Release 0.8.1

      Bug Fixes:
    • Fixed crashes that sometimes occurred when switching focus or views after renaming a new or existing node.
    • Fixed a compatibility issue with older versions of Qt (3.0.x).

    June 3, 2004 - Release 0.8.0

      New Features:
    • Added undo and redo commands and an option for the number of undo levels that are stored.
    • Added the ability to show parent and grandparent data within a node's formatted output.
      Updates:
    • When changing node types with the menu, check marks now show the current type(s).
      Bug Fixes:
    • Fixed crashes caused by right-clicking in the edit area or using the Alt-Tab key combination when renaming a node title.
    • Fixed problems occurring when several similar data type names were defined.
    • A rare problem with the installation script choking on image thumbnail directories was fixed.

    May 18, 2004 - Release 0.7.3

      New Features:
    • Spell checking of the tree data has been implemented. This feature requires an external program, either aspell or ispell (see the System Requirements section).
      Updates:
    • The size and position of the print preview window are now saved.
    • Added an option for including only open descendants when exporting tabbed title text.

    April 1, 2004 - Release 0.7.2

      Updates:
    • For faster keyboard navigation, the left arrow key now closes the selected node's parent if the selected node has no children or is already closed.
      Bug Fixes:
    • Some tree item drag-and-drop bugs have been fixed.
    • Problems when some dialogs were closed using the escape key have been fixed.
    • Fixed some rare Linux install script problems with some systems.

    March 9, 2004 - Release 0.7.1

      Updates:
    • The open file dialog now uses the directory of the most recently opened file as its initial directory.
    • To improve performance, some unnecessary refreshes of the right-hand view were eliminated.
      Bug Fixes:
    • Fixed problems with repeated uses of the search dialog command and the command to set the types of descendants.
    • Fixed problems with the data editor view in the mode that does not show children.

    March 2, 2004 - Release 0.7.0

      New Features:
    • Added prefix and suffix tag formatting for groups of siblings. These tags allow output to be formatted in tables or with bullets. See the "sample_table.trl" file for an example of table formatting.
    • The size and position of the window and its splitters are now saved at exit. A new option will disable this feature if desired.
    • An import filter has been added to open Treepad files (text nodes only).
    • An install program has been added for windows.
      Bug Fixes:
    • Fixed Linux install script problems with certain versions of Python.
    • Fixed some text exports where improper end-of-line characters were used on windows.

    November 19, 2003 - Release 0.6.2

      Updates:
    • Cursor changes were added to indicate time-consuming operations.
      Bug Fixes:
    • Eliminated inadvertent scrolling of the tree view when editing in the right-hand view.
    • Fixed problems encountered when the Linux install script attempted to delete old TreeLine directories under certain versions of Python.

    November 7, 2003 - Release 0.6.1

      New Features:
    • Incremental searching has been improved by adding keyboard commands to repeat the search forward (F3 by default) and backward (Shift-F3 by default).
    • The sorting commands now contain options for reverse sorting.
    • The importing of text files has been improved. Imports of plain text were added, with items for each line or each paragraph. A prompt for the type of text file was also added.
    • A new option setting avoids going into title renaming mode when adding a new node. This also keeps the selection unchanged as nodes are added.
    • Dragging files to the TreeLine window in order to open them is now supported.
      Updates:
    • The rename command was added to the tree context menu.
    • The right view now scrolls to the top when the item selected in the tree view changes.
    • When opening the configure types dialog, the current tree item's type is initially selected.
    • A TreeLine formatted version of the ReadMe file has been added.
    • An install script was added for Linux and Unix systems.
    • The windows build now uses Python version 2.3 and PyQt version 3.8.
      Bug Fixes:
    • Keyboard commands are disabled during tree rename operations to avoid unpredictable results.
    • The right views now update properly when the parent of the selected tree item is closed.
    • Problems involving copying with multiple nodes selected were fixed.
    • Problems with drag-and-drop on some Linux systems were fixed.

    September 16, 2003 - Release 0.6.0

      New Features:
    • The three right views are now divided into upper sections for the selection's data and lower sections for the data from the selection's children. View commands can be used to hide the display of children if desired.
    • Keyboard shortcuts can be customized by editing the TreeLine configuration file ("~/.treeline" on Linux, "treeline.ini" on windows). Any configuration files from previous versions should be deleted when installing TreeLine 0.6.0.
    • A new command will quickly set a node's data type.
    • Parent nodes will automatically open and close when found with the two search methods, by typing the first letter and with the "next sibling" keyboard command. This behavior can be disabled with a new general option.
    • Typing a lowercase letter will move forward through the visible tree items that start with that letter. An uppercase letter will move backward.
    • Tree items (including those not visible) can be incrementally searched by typing "/" followed by the search string.
    • The Find dialog box is now modeless (the program may be operated while the dialog is open).
    • A "Choice" field type has been added that allows selection from a user-defined list of strings.
    • A "Combination" field type has been added that allows selection of several items from a user-defined list of strings.
    • Several linking field types have been added, including "URL", "Path", "Email", and "Picture". Clicking on a "URL" or "Path" in the output window will open the link in an external browser. The "Picture" fields are shown on in the output window for certain image formats.
    • Pull-down editors have been added for the "Choice", "Combination", "Date", "Time", and "Boolean" field types.
    • A font selection for the data output view has been added to the general options.
    • New printing options include setting the print font and setting a default page size.
      Updates:
    • Configuration information is properly saved for unused node data types.
    • TreeLine is now more keyboard-friendly in many ways.
    • Window captions now put the file name first.
      Bug Fixes:
    • Fixed problems with data edit view resizing (on Qt3 only).
    • Fixed file corruption problems caused by the use of HTML characters in the field format's prefix and suffix areas.

    March 14, 2003 - Release 0.5.0

      New Features:
    • When configuring node data types, a default type for that type's new children can be set.
    • An added form of HTML export creates a directory structure with a separate page for each parent node.
      Updates:
    • A shortcut (Ctrl-B) has been added to the command to insert a sibling node.
    • Icon files have been added to the distribution files.

    August 26, 2002 - Release 0.4.2

      Bug Fixes:
    • Fixed another (oops) incompatablity problem with Python 2.1.x. This change is also not needed when using Python 2.2 or higher.

    August 23, 2002 - Release 0.4.1

      Bug Fixes:
    • Fixed an incompatablity problem with Python versions 2.1.x. This change is not needed when using Python 2.2 or higher.

    August 22, 2002 - Release 0.4.0

      New Features:
    • Data fields can be formatted as specific types, including short and long text, numbers, dates, times, and boolean values.
    • Individual fields can be specified as plain text or HTML. Line breaks are preserved in plain text mode.
    • Text prefixes and suffixes can be assigned to fields. The extra text does not display for blank fields.
    • Options for spaces between nodes and allowing HTML in formats are saved with the file instead of being global options.
    • Node titles are truncated after the first line of text data.
    • Node types can be set conditionally.
    • A new option allows the number of lines in a long text edit field to be set.
    • Missing fields can be updated from a separate file by matching unique values of the first data field.
      Bug Fixes:
    • Clicking on an unselected current item no longer initiates title renaming.
    • Rare problems with opening or pasting content with complex text strings were fixed.

    May 28, 2002 - Release 0.3.4a

      Bug Fixes:
    • A fix of the Windows binary only. Fixes major problems by upgrading the library version to PyQt 3.2.4.

    May 15, 2002 - Release 0.3.4

      Updates:
    • TreeLine has been ported to Qt 3. It now works with both Qt 2.x and 3.x using the same source code.
    • The binaries for windows have been updated to Python 2.2 and PyQt 3.2 (but are still using Qt 2.3 Non-commercial).
      Bug Fixes:
    • A selection bug that caused problems with the up/down and indent/unindent commands has been fixed.
    • Errors in the initial user preference file were fixed.

    March 19, 2002 - Website Update

      This website now looks a little better. Hopefully, it's more user-friendly, too.
      Stay tuned - I'll soon be porting these programs to use PyQt with Qt 3.0.

    March 6, 2002 - Release 0.3.3

      New Features:
    • Multiple nodes in the tree can now be selected using the shift and control keys - most commands will operate on multiple nodes.
    • A new command will copy node titles as text, not just as XML.
    • Options have been added to print and export only nodes which are open in the tree.
    • A new option allows the numbering command to start with a number greater than one.
    • A tool to remove the XSLT reference from a file has been added.
      Updates:
    • The command to arrange a tree by reference has been made more robust.
    • Errors when opening files are now handled better.
      Bug Fixes:
    • The export of Unicode characters to HTML has been fixed.
    • A problem with the set data types dialog under Python 2.2 has been fixed.

    January 7, 2002 - Release 0.3.2

      New Features:
    • Unicode is now supported in both data and format strings, allowing the entry of foreign text and symbols (note that there is an extra step in the Linux installation to enable this feature).
    • A new sort command allows all nodes of a given type to be sorted.
    • A preference setting now controls the initial state of the right-hand view.
      Bug Fixes:
    • Fixed crashes caused by tool-bar use while renaming a node.
    • Occasional problems with deleting or renaming fields have been fixed.
    • Fixed crashes resulting from very large data edit views.

    December 12, 2001 - Release 0.3.1

      New Features:
    • Parent/child lines can now be added to printouts for better tree visualization.
    • An option was added to compress the format into a single line of output.
      Bug Fixes:
    • Problems with sorting full branches were fixed.
    • Fixed improper indentation on an HTML export file.

    November 27, 2001 - Release 0.3.0

      New Features:
    • Added filtering of descendant nodes.
    • Added a data node numbering feature with both outline and section styles.
    • Added a feature to export the format to an XSLT file.
    • Added table of contents links to the help file.
      Updates:
    • Improved the handling and editing of long data strings.
    • Improved the handling of HTML tags in data formats.
    • Improved XML parser error handling.

    October 23, 2001 - Release 0.2.1

      Bug Fixes:
    • Fixed a major bug that caused errors when new node types were created.

    October 17, 2001 - Release 0.2.0

      New Features:
    • TreeLine has been extensively rewritten to include database field information in each node.
    • The file format is now XML.
    • Added additional views in the right-hand pane.
    • Added options for data formatting and manipulation.
    • Added more file import and export options, including HTML export.
    TreeLine-3.2.1/docs/install.html000066400000000000000000000057251506556630100165300ustar00rootroot00000000000000 TreeLine - Installation
    TreeLine

    TreeLine Installation

    Linux

    Extract the source files from the treeline tar file, then change to the "TreeLine" directory in a terminal. For a basic installation, simply execute the following command as root: "python install.py"

    If your distribution defaults to Python 2.x, you may need to substitute "python3" for "python" in these commands.

    To see all install options, use: "python install.py -h"

    To install TreeLine with a different prefix (the default is "/usr/local"), use: "python install.py -p /prefix/path"

    To skip dependency checks, use: "python install.py -x"

    Windows

    To install for all users, execute the "TreeLine-x.x.x-install-all.exe" file. Administrator permissions are required.

    To install for a single user (administrator rights are not required), execute the "TreeLine-x.x.x-install-user.exe" file.

    For a portable install, execute the "TreeLine-x.x.x-install-user.exe" file. The file association, shortcuts and uninstaller tasks should be unchecked. When TreeLine starts and prompts for the config file location, choose the program directory option.

    To use TreeLine's spell checker, an external program (aspell, ispell or hunspell) must be installed.

    macOS

    See MacPorts for a third-party port to macOS.

    TreeLine-3.2.1/docs/logo.png000066400000000000000000000070321506556630100156330ustar00rootroot00000000000000‰PNG  IHDR~P sRGB®ÎébKGD33`¾�  pHYs  šœtIMEØ 9#0ð@tEXtCommentCreated with GIMPW� uIDATxÚí]-l\Ù>;r †ØRÆ` fL"Ùp¤Z•Ç  *� k­Šº•P¶ÅEÁ«•5`´d�gÀ��AãJ­”÷€ 2À²` Þ>Í‹ýæÍ=÷œ{î¹ï�O Iì¼sÿ¾û�ûóÝÏààà0 Cg°Qû·»«Cwq5Çý<çxÁ~{Ð/þHa¾(þ`á'¶>8ÚÈ·Œ±ÚÄ£µAïñ:ŒA`š»ÿ<çxÁ~;Æx�äxbeꃫ�|ÊH-«`[õj+Ú`è2¶ûGŽƒ—;;Æ|;Öx律­®6’,c„¶2â7BŽÄ··#�W 1R'ÇXmáCþ—ÉkÊÑSÓ‘ †É?”PŠ9ñ´MùSbl©òßp® ñȈÀÐM�^MpŠ›k¼4}{•ºm ·„eðö`v³úgöãlªlVäÚF?x÷¾¹Œ!ʰ­Üˆ´YT¸ÁÐUÔ‘M“Pâ/ç×øßnɎ׷—~¿wòÔï÷þù7æl£?K«#ß²rãj0»©YêYÕ‘ †®ât†#ÎìøÂCI7e막„C,“¼8tÿY‰6 YÖ@}¹§²# )@b Ï<ÿŽ P[—‘„ Þ'Û²mäšuIN2DôÔu$ƒAV‘蝹cN¡Ô¤¦'yüº¹¸‰39¾tTýmtÁ°¬¤,s]ÓF‘ÁÐiâ¿Áý¼”Pš/’¿´º\—‘¬"^êÄÉ>í÷1mäšu…*kÅoëû†.cUš/!”Ví-¬#-“bh¼Nõsµ‘ËÄŸÂú~eë%¸Á � ¤Ú�!”ªä¯I]6�䀯êÇ´u}_ÓŠIe류¦ 1TÒ'�8á¢øc*L|¡&ǃÏWÿGa'~ BÀa[žãÿ¸°[»ƒOš_ẼóÀ³Óâ†kÝX�pBîtæOîR“ã‹C€/ÞÅo#®²ž_Ó'³$þiþ°ÃØm]ƒá!$üX(„«={ç$Þ'Û…ê¿?Asµ¥|Êúf†øtswšÊß`0ཡĹWG!=ÉS‚˜zÑFœe ý‡ÄŸüíâ–Á–\SsrlZ²÷kÞu›¼mDUûزž_‹5Cý \å²�]Ü2˜â‰¥_åÇ5)QIHúq˜—‡¯¿“m#î².¾x¾ë÷»È‡c6VþË4g˜ñ6ú?©ÿ{®I…£Á MíSH—ë6ñE %‡Pû 'ûKâçj#*·`Ëšßúk@´(#ƒAk¿ö%]-›Œ\Ä;Íp?�qíäâm{*ŽÇÈ?ç®þÅ  ¢ˆmÌæéMFŽÉñ,Ã+àòh§äÅ-.!p–ñµ·ùoˆóþ1´Bp]"¢ *Î�Õ³ ÷{ã@vKo#ic¶ãÿþdzÓŠ_Û•vƒ� -Ælš'%.\ntN�Jx•O׌ÙÖô#yÅ/Õ ¹nîͨcRI•�Š«y7ãטÅrÖ)eòáZâýÇ—âÑGõߟ0ºjÌ&Jü±•Ñî ü9â�• �‹@\ëvO qúű߮ğb›âÅ­óëbL•õ�ߢÇ#|¦PEŒÙÖô£žÚÆ×Ží~Ñ1÷űգ¡%+YGC‹_Ãú¾–³ëœ«¥ƒ@vWí¤Lx’·p<Cü{‘M¬b(Êr"x¾víoOÙä‚%ÏTã7c6¹É±ÜX­fÒ9ò„…|¥�Ù"ô#YÅßoÿñ0m%lÊß_Y¦¬ö©¤ÇýâÕ|±TýØ¥›�­åwµ³EÀ†êN¸ M›/MÊŒ«ä·ëÏ—d2ÍÃw6-t<x5igü™Š³=ļòNv“÷h�]ʪ} ËÙýHŽøc_isž“]ñÿ|¸]¦¤“, ù/MÄ߯øÍ˜�wr¼O¼ÕMÞ ’øË%ÍÆlAˆ}?JSñ7Íh1ÏÖîl}ÚÙªùky�ZJ5~3f£gR¼¯�?Ö¿+8¥�Ù¾üZ̃¿ þ5þØ–µš6¹v¶Šï¾þ5ÀQ·!‘jüfÌ&'JꈷºÉ‹õï9VnÌ6‹c;ÓS[!>ÊH³¢üãÏþö›öªýuj)åøÍ˜-þäH9ÚÉ­öµï©¨!~)c6í òø‘?ù§ÞÙRŽ_óÃ+«�¢1[ñRŽvjUü-gdŽsJít§ *?øëóö•mq¤¿ö¸ÛhÌVÊÑNî¬+õ%Wvâ�}¥]Â2—¥},ÇÀÒR¶uÄ‘jüY¬³¹oÕ3ë,ùK³µ^ñǾɦñí`®%-eó]£N5~3fãŸ×ou¹‡[õwÀ˜­Š�à�PÒ˜�ëûëÁÖUß•¬ÛP*£iЦÌ,vÐoV˜œû&»~'ÚŽ˜”£�”Œ•[œeþ«Ë^„#âám™c+#ŸM®uäò|·P£Íâv`,Õ¢l¿žLeЗ¹(t–U.Iåxò—|ñªÛ4ãk׌O‹1ñr(ßR�Vc¶�›\ÙÀÛKÿãe¿?�íl±žªL5þØY¬ïz2%u|³•}rt%Þê&/çÑNê©*ì”3ÄM𘠿Æ{§›ûKÝ x{ÙŽ²Yüº²Øm¡E÷×Ë1äÏmÌæ‚XG;9…@vÇ×G<ÈŸg©G³1÷Ì/í¹Ïù½á¦_JJYOL9þ˜Æl¾cŠëÐÀxè·ì#19VcÂú÷`³®eå¾€æ±ì–ø5³qâhÈ«Â( [6Jg a6—rü·šN�4�Ïĸª-Æ£"›mC!ŒÙ\PÝä=ËdV¸„ÀÎÀWÇüñ�Μë2Å/aÌÖtºbwÀŸzKž¦¦Ä¾ä™jüZ�Ù†[ü$×ôÿù.c†&bÊӌ܊?ÁwFxÖøÛj̶;(Èb<”[o�Q·XòìBü±³X-§Gf)RÄûþǵþ�þ=’B@°7’¨)c¶�ÿó;[ê<:gÙ¸.¼`”sÊñk5f“<:ìkÃ!å¿Äq´³CÆl2Äß%c¶£Q˜AÏY6î5E—õÄ”ã��ÅNò"Ó 5¦¨ã XnôiÙ0e™e¾XÖSøtGY•¨}€�Ç9S3fóõþøí>^iœ_Ëû‚Äèh©Æ¯!î’ÔbŒ)Œ8™æËsõ!&GL=ùŒaLÖ»¬Œ W�ÙF›~¤ðÆqvNÅt®mñk1f«#QâwçQsÚÊÖ•ø%²ØÅ÷´·V Ýñ�]âo“1ÛýÕ®±Dõâà‹wzTgŒÓ#)Ç/ѯó[0¼Ä㛼ğ¢1[¹”Šl¸‰;…òdà—;ÅYbͪ3uÕœr¦’Ý�Á›üy-R3f[¥(KŸï©‡÷Ç_~¥»l©·MÊjß`à"ÿ(Äßvc¶+â/ùU§³Å!~Î,ö,ƒAùó^àJ͘­ir)ßô|{‰÷ñ9Ùxý]ܲù>*S‚òÐv›âçÌb�GÉÚøñÆ.]ñ·É˜ÍEõû*5՝ɨl<Ä/¤ê†î�p�o�?5c6—óÔåZ¿�Ï÷É~q¼3FÙ¸Þõ!ÿ¶Å¿cV ­ÄïtOüm1fs¹DUý/yê[¶œñ䆯[‚áú¾OÅ]Í ‡<_Õ²·nC×YªñWÛÕ`0Å_ƒùâá—2f[õ}Ie6Í ’˜x^½oRý±ËFEÊñ—íšb¦eè^p둸ô‘·:‚‘L“J’¡ú©e‹•‰µ!þ:ò7T?ýÍ¿süÕ.eÌ&ñ} ùÿý=¿ê×P6ŸL¬-ñ—äo· ZÁô‚›ÿ®r€ÇºÒîû}.»__òw±rˆ]·ÔÔ2åø§9@ÿ§F0�`zŽô388øÁjÓ`0ºƒÿS¯7+öIEND®B`‚TreeLine-3.2.1/docs/require.html000066400000000000000000000061131506556630100165260ustar00rootroot00000000000000 TreeLine - Requirements
    TreeLine

    Legal Issues

    TreeLine 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. See the LICENSE file provided with this program for more information.

    System Requirements

    Linux

      The stable version of TreeLine (3.0.x) requires the following libraries and programs:
    • Python (Version 3.9 or higher)
    • Qt (Version 6.4 or higher)
    • PyQt (Version 6.4 or higher)
    • If spell checking capability is desired, either the aspell, ispell or hunspell are required

    The above versions of Qt and PyQt are recommended to minimize bugs. Somewhat older versions of Qt and PyQt are still mostly functional. To install with older libraries, use the "-x" option to skip dependency checking.

    Windows

    Should run on any computer running Windows 10 or 11.

    If spell checking capability is desired, an external program is required. Either aspell, ispell or hunspell must be installed.

    macOS

    Due to a lack of Macs for testing, TreeLine on macOS is not formally supported.

    There is a third-party port available on MacPorts.

    TreeLine-3.2.1/docs/scrnsht.html000066400000000000000000000031411506556630100165340ustar00rootroot00000000000000 TreeLine - Screenshots
    TreeLine

    TreeLine Screenshots

    With data output in the right view



    With data editor in the right view

    TreeLine-3.2.1/docs/treeline.png000066400000000000000000001070331506556630100165040ustar00rootroot00000000000000‰PNG  IHDRù–äÀvÅPLTE ƒ  )ú( $  #2"—$*"$"%0 +<&(&*9ÿ'-3#.=,-+2O:#.’*3>@?(4D131Ý 06=4¶ù796/:J*.ÿ>A3>N59š²?@>;AH7BR,?¨"BÀ;FV@HOFHE3P/Yo@¤/0DMYNPM)\WJS_MT[2b5TVSIKÿNXe"cŒ>`€9j:[]Z+f°«GIX`m~T]°[ah0oa_a^/qQC`Þ€~ceb\\ÿ‡cK<|9bkwDzDƒñfcÿ€¶.|§lnk<~i3{®‡ÊUr«mu‚tvsppÿ��&�Ê“tb=“20‹ÂMŽM{}z,�Íz€ˆ3Žð$˜ÂM“wPŠÙ{ƒ”¯{@A¢*˜áµvu…‡„l…úA™·€…Á‚‚ÿ„‹’I™Îf“±À‚1v�¹Œ�‹"º^¢[…�¤°Ö?§ë”–“Á¿ƒš¬‘˜Ÿy¬Dšœ™µ”•g«±]­Å˜–ÿq´Ar¥òu¯qg«Ùž �Ì™KŸ£¦z°›™¥·“¢ÿEÍ$¤¦£‡ªá‹±Á‚¼`©«¨‚¶Ö›°ÓÒ¨mŒ¼…­¯¬v»é©«ý¬¬õqÌ[°²¯Ù¬a¨´Å¯´¸¿À³µ²Ñ²y;è%”Ä”aÛX·¹¶Ô³³º¼¹ŸÊžº¿Ãò¹Q•ÉîyâD±ÆÄº¿ÿ·ÄÑÀÿ«ÉáÁÃÙÄÇÃ�âLèÁ�®ÑªëÄpÅÊÍ–àŒÉÌȳÏ÷ÔÊÃÈÎÖžæsÍÐÌ­ß›ÍÍý½Ù¸ÐÔÆÒÔÑ¿ÚîÕ×ÔÔÖéÍÚç†ú{ÖÚÞ˜ûXÚÜÙ±ó…ÝßÜÁïž¶ò¯ûá{àâßßàþÑæôÝäîùßÏâåáÓîÆåçäçéæùé©ßëýçëîÎòÿãíõüòìïëîðíìñúíóáðòïñôððôùðöëþû�ûôìôöóóöýõøôøú÷ÿÿÀúüùüþûýÿüÜ‚ÚâtRNS@æØfbKGDˆH pHYsuu¹cQ2tIMEâ�Ñ¥tEXtCommentCreated with GIMPW� IDATxÚì½ œ[Wyè[mz¶d¹Uƒ%ŽJçdj®ì WÔj¹QqÊ ˜�#E¡XÜPG §iÄ#î‰(7ºäˆ6€uM@I•´“Щ]ÈT�ˆl¥Ô(5T–ÝéT´c»B:3øJÆ2·²„Öï|kíµ¶öÞÚš‡ç¥­ïg�¤½×~ÿ÷·¿µö÷ø¹Ÿû¹Ÿ'ò‹\¸ô�¼r-ãþs ¿øðÄi.\úJæOéʪLž=}zâá_�ð1�SøÏc/Ì�\üÁw¦çæ^x¬3™ —u–Sk=ùàÏÿÜÏ?Œe þ?vƒÿƒAþìâÜÙÏÐÉ\¸¬»L­ùd ÿÿ ñð7ßyðó3ÿæÁσ֧“·Š<¸Ìù²I‹-ª]pE;up�Æ×äÈûP&VsòÕ‡4ù0ùø OÀÿssŸÇúþ"Qü?˜;“Žìw9°ghhÇ®îÆr@ú¼í@wÃ�;ïêšø¦Nîù0aç^<{øÍz‹êÉ0nv`Ÿ´Ø"Í:e;¡³ô›”rìÐ>õš‡©èoo§´¡KÝý>’ ùÛ¾}ûöëLÖk½Oåäû#ûáüìßG>Ô˜üƒ@ŽÂÿ¹ïïÿølòÌ}þÏææ`Òcú\îÚytz~zbï]ä÷²—|N=¼³«åö6Úy—fÚmCûîê5{ ¡‰á†OíÕYTO†Oí{ó�{ÂèèÎÅ›Ée;¡³´rÿܵ!Ú«ZÓí´íÑÛ=8ûßÔãÈû]ŽÊG½¡Î98º`k|‚ˆìUN¾+ŒŠûîºk_…¥õ¨±�–ÇàÿÜ_üwÒ¯> òÅÿ>7G'÷µ �B³SÓhæQãÊ•+{ásúT�½ë®½ÃÃ{Þ|ûÄ×ÿÍ{†÷ÞuèÈ=té<Ú?|Û];‡ß4*qûv²ßÃlGè'>{ðaÂÜΑ±Fý-Óë»w“<½÷6Õä­w¢�DÐή•‹�•¨ß ä¿õ6�ûá?�zîôÇ㟻xñ·Þ87“ÞÖç2ÔB�=C·Þ¶}%‚Áû‡áóh` M M¡ùi4¿ƒ}b²C§†÷´ç'N5÷ìÁ Ÿj£«óA˜SiÏãùð¾‚Ð~<ó6B>¾¥È“åu!4?�šÓ0qž8} �Â-áTƒ9G‡YËíÆ0ƒú–æ�fìÞ¨´ê¥çOML£©ítÿ¤_C·aò‡Éaï!ûONÞztGØÁ©8°ˆòÈä½ío¹_ú>…°Î‡Ë¦šÜ«5V|tZïÙƒW"Ÿ2õ[�ü_ÃrþÏ}ñ/æ0ù¿õ‘¹¹ï€µC'÷µ ÀG§vî�Ë ÒÞ.}¶öïÄN¡û„k?�¦^9¼MìÜ>´‡,½¬‰í¿£C;(¡í€™ äïùµ�ûÚ;Øä!y]¶Ï¢‰íGQ&N¿&Þ׆ïWvl?¥h ä¿“j;^ svì$Íè²Q²;Kï¸uhÇÞ}m´CšÅ~ÝJȇ=»uïþýû÷ÜŠwr&—tlGØ'&7WYgoûûºRð #&ÌžSSêɽZ£aÅG§5#_Õ“+Èø?÷gÎÍ�•Èÿüççæèäþ–áþ£WáŠÂeŽìß¿ëüОƒ¨½3Zr8„¦Ø'\{tuÇ®×î˜E¨91üÚ�uØÑ·Âœ=»öP>vîxֆ׌ɿõÖGAy²ÉòºXN§�(B&‰ AËhÓሢ%&è12�ÎÁ+”ŒìÄåÒ ˜‰¹Jf½–ýÚEÈÇÇ|~&Ç�ÉßIŽ`˜íû$äãQ›9Üß—•‚·kxphxx—jò­CTÔ­‡Ð�âCž¼ÀŸ†{v*&ò_ rþÏýãƒß äþÁÌÍÁ¤»^Ûç²kçÐÐv Œ<Ú‡†oy-ù|e í?€¦·EGÙ'\û) k×ðÐþÐ4zxhßþ=»€ÞýCXcîÜõZÆÇ毓gƒÃòdy]ùù0Tðþ½ÐRj0¡h ×mѵûÑìvò7ëüh“á�P.íGÓ;wÍdÖ0ûµk“�zïÁƒ÷î"'“Ovp×0Ûy‡ð©V›¹«¿¯ëù&¿kò�tÿ©'òDØô ~'ù#4�“ë.�»à?Ø8%Jþfæææ`Ò›wõ¹ì@§"aP÷„üa˜ŸS��B­�;j(rÿU´Ÿ}âk?·È¾èþ}( VÅ�aÀìTx/žsË.xÕ˜ü]·ì…yòdy]JòwÌ·CûüSûpËðø 5•-çÑÄQl‹@wsjÁÍädÍd'TK<�b��gía¿nÁä“]»exxøéÈäß²‹íû„mOOMÁ§òÈØÌ[úûºÞ%ššêšÌÈWObc;CÊÉÃ÷ó·Üèß?L&¨oò_{ È›à?q^ ÖþF'÷µ M5àH'†nÁäß ˆ�åÔ¾›oÆãaµàû¤êuj_ w v`p‡a^[º'n¹EÅ^5&h(œßÞ!_^�¿�‘O&³·¼qÿUTœP´¼ù@ MÓ Í)ü¸ÀÍØ²SÒN¨–†�C`Ãí‘fÉ¿¶còµ'È¿Y:º#{o¤ŸR—PkÔç×UÞÐP÷dfí¨' ©§ÓÉÃ÷7Çbòk�ü_Æ_nƒÿO0ò ¿Æ�{&ýZ¿“óÐö`ðÀ‘mß~#™²�>T˜³}¨ó oÞ¾}èæí;÷ì€ù¤=L€ÒœüÅÿ‡¶K'È?Þ>ý°´¨4Y±.²yâ+·K-oÂæ—¢%LØŽ'ܼwûöWNCÇ7c?¤Mã�P/ û¸cˆÍº‘ýÚ35‹B7jOÙy餹Yþ”NÅ�ê#c3û[n[ÅÉ7ßx³âƒBý˘ü›An…ÿ»NÎÍ]üÈ'?òÆ7~dìâÉ]0éµ7o¹qm:zôèý¿4<´Ô5Ò–7êomhâêôUèg܈›±ŠV½–VÈNØ¡ý7.íÐn\Õ¶þrëN&PòoÙ…ÿÜò™³g‰ÉsñìÙÏÜB¦Ü8ÀòKÛ·ÿÒê­mïÃGÃû·ëýX²l_ÕêkÙµ†“ Ô„ü_Ⲃ¹ÕÿÁeý…�_­Vk\¸ Žñœ|.œ|.\8ù\¸ (ùy¡Vó—°’‘D-â\ò&ˆÒZ�%µF+^Òiè¹~ÿ²7¸ŒóÉeÉ·@R¥ð—܇›2ùÙx-'èµJÔj3†âÒȇ͊#¡Šü[o�D*I"K$_:žåß7.‚lÂXO/¶p£j%"µHa¹äû<5|¢òœü &?\.—« *;ŸšTdò{pêíË!?RÉÇ,îÅɯÁ¶Mqº‹K!_>ù°—D~̌۹}K8‘)¡R›1+J|9ù›�üˆÒÚ‰ÚDgN÷R�Ä-¢_²vì‹%£måµÄù¥Q“Ù_©UFsȯÌFo©›|ø“å· –PMZ#ýÞ%&r»…,F÷L­6fiÂnÖ!Š^ÝË­<>§%m[_Á)¸`gÜF|€>ƒÉ¢yˆTÄñZmVH+NFÒêî¾M*Bªó8á�…Ì„�ØrvDp�úÙŽÂz †P-/V{‘OÏ ÞŒ90bóV8£Fþ˜)] Ù«úäç…±JÐ@È×Õù£[“?ê,æm¡ZÔ’+¹€ü€£PîV¥Òf­°ÉL5%¦¤5ÒïúäÇÌ™²Ç{¯„M%Lœ+X­¤ôWÌZyÌùZÕìœÉ‰#é’#T«DJe¯K÷‰1 G¶)OC^¨Ì˜Mð¡=!Î`ÍɉÁä[ 5¿·Vµ+c‚Ÿí(œ&üP‹¸zê|zfùÎJÕàŒ®+ù‚Ñ8ÂÈwcƒÇ”Õ^*hbtÖB.¬ ¿j‹bò1»Q{ÍÂJ½T3ÂÏŒYP§dxC�5zC=ÈwÁ¾ E¼5kçöæu¬r<¬•oÀ ‹»±.öȽyòSB¹æªNƒ%ó:2Ýì]5{f þ„%òÙq{--VHw�î(Ü0¾°©ÚmC’Ó)ùôÌòãpß[9£ëJ~(Ÿ/0òGLV«Õ4©½Tî|>?SócÅm_€üZÌ W¼d€>_ÊX‰�õ`(• °J«±ÚKç§œ³è—ÖH¿ë“?…?BÆ?Šï˜0&®à1Ú"]ä“ãa­<ø>2c³¾„]`‚ÙÌfCE·—`�ä…‚ê4x‚¾ˆ?ÜÍnR,šª%cÑ�•ȇu§,µ„Ÿ?ÛQ˜cÏ;2Ý["§3cȳ3CÈÇ7�ÀÝ0kÇêÙ%•é– „+•×'¿j*t>(Ä,è|1­ßÃ…?°ó-‘j Œc²Fú}©:iL(èÞR²Î×�™�•”uÉ:É �â4D\ö\Âmíj[@ë×F‚¦š’ü4þé‘u>|µÔü¡ÒÓÚ¡g†�wKœëü ´óÍ©êl¬ª7¶S®åÄ\-&ÙùåîA L~-.Jv~ÁvþH¹6Ší|g¾VHèŒíÈØ\þ¼Ñ/­‘~×'?jÎJv~‚Ùù±™ZZ(ö°ó¥VZòñáòG"Ý[É ˜?åiÈ –ZIìf·æ0Âê|F·Šüª5KøÙŽÖ"‚§–œ½Çvè™!ä�ÌG¸�¿�c;1»`öt‘OÔg`¦ÓGßdŒbF‡üÚÛñMdlÇæ ‘±‹` é » d.«L~� —Áù-.\Gä7¹páäsáäsáÂÉçÂ¥�$›JtI*ËÉç²åÁ/êÈÊÐW�ßàÂ¥?ÀŸé@%ëÔ’ŸjáL.b9{öüÉùU:„sd�çt×7=‹¥8½&çnþ´vJ�H�æ¹Ty¡µ]xö¥Ç/uMž=ùÂéNãck¾pL}êóÚKξãu'¯çèN}æ³ ÄäX¯Oõ Éõb>_¬/}FƒïW:ˆ0ú‰Õ$¿ÕÂÿdòÛµ/Ÿ¹úgŸÑN‡‡ÐL!ŸËe3é‚ÎQ¹<{ùÒ¹s:ë›ÅÕÝ®^ͯɹžêº¡^8‡å…î¦3…Bvl2•+JúëºtüÙÃGŽ?pâÌUõôÓÇN�:5}jj“ñ³ªyªóZòøõOç ¯ø•ž¹ž£{æÄ±gN<óÌÓDŽÓ΀iDúƒü+™x,1‹§+K�!‘DY}ò5 ùèÚåóúZþäÅËOÔÔàWëùä Ù·R2¯G>¦ûò¹«:èOð×�ü«SÊ�½HÞgœy¡Kä3™t>ŸŸ„}ð}ôÙgŸ=þè³�Vïÿ±SÓ³Ó SWÇþè�N÷Þ™Y‡WWÇ¿ã¯xÇë^·ðóõsŸëüí¨öÏ2y Kçvž–¦2�ÿÂjžÒøFý»ßéõÐlüà/«ðO¹D¢p¥Ù¬ÏŒÇ‹K›ÁÈ?ùI*'×€|�µƒÉG׿Î�=yl¶³Ð3Ï< ròäµË—OžT{±\K%$ò‹É¤<¹€:ÿô±“'O¿ \#À¿|õ”rš¼ ìi2¥šËéT&“J©×§X�‘??¥‚ñÜU,çNtÑ�J§Ç“Éäx:�Ö]cƒè?þ€j‡üù«Ød›>Ýø£·¾õ‰ÞÖάé«ã_÷ŠWÜðŠ.v¡â`>÷×ý9öW!?ü)¹ž:öÔ±cO=¥:…�Ÿþ°qú©§Ô·„öô,Y þð_ÿæ»ÿÚ ýýÃ÷¿óßÏÔ»¬%&+µZ©T«UÓ1å­!Í(43ð‚”üO¾‚Ê'ÑzX;ýk—_~ù˜‚üÿøÇ'ž¹ “/_~D…þÌl5—©�… q]òKO;wqúäɓǴ&Þ) þ¥ù)ý]M3“z§9“,V@fÇsõÉŸ=5�ï"ÿâ™gž8}zZK~:�"2«³Æ �~ôE”¿¢Á§¦¯^��™jœ~ëÁfokgÖ!X,—Ž?I®êB¸} Ëç>G>”-^|ñG؀æÎáÇUFÍ�^|±ñX:‡ïý�ßyªÇ陜ìÚædP!“ºä¿øÃ¿ü§ê£à¿ÿR:ä§³¥R l�dZ±4›‘WÏP�¿¦:_ÇÚ!¦þßiÈ?q–ÜŸy摊v¡Xª_!ŽpåtL�üö±g~|éÒ¥3ZòsS-ÿâüÑ©©B÷‚•D ô“‰ÄX"�Í“Dq!ò§¦§ÕöÇ9¸m/Ÿkc9§šC˜/�Å¢ù½ï¡g”°Ö¨®"º8?÷ÓÄ"'}Ö1â÷ù¢Ý:þ™×ÝðÉ« ’ÿÈ¢&ÿ‡}°±>ñ�|âO©Àÿá‹xÆ>øÁ| ù“¯þO]èOþÂ{oÿ "·ÿ‚ KþwÿùŸøâ‹ºèÿè‡ßÿgø÷ÍÉnòëñìÌ téxx&ïXôdÆÌLÐWÍP�¿Vv>ëH5ñ?&”üÿ»¿þ·¿þóŠ<È?)= øÂ¾ðÀ�òŒz~&�;·éɱx,2.O. ¶Âù?8~žgNž=VWÈTþâìçΞ={n å¬vÁJ<‰yLL^©«%™,”+¥T<•š«Õ»·HeâôéSê)ùÄØ¿xâ´b†D¾äÕ”Ÿé^ãñ÷½ï¡;/ÖO9~üÈCW;Ë}&Ѐ߼:QïÕy-:\äSÒñŠV�SWº—UÌÇþw*S6h¼ø#‚~} ä[ßšîÌðôb£~eÏ™šÖ==“¯þ‹·ý§IíF'ý÷Ýýwß}ß«•ó ~ÿëÿüOÿòü‹`ëkåßýþ7¿ûýþúW—‹-XŒçrE„êye,ËË `F6ƒj^°ùõˆ–|è`4ä_¾rùì¿ýí¿ýý_Õ”ä?€-ý'¿ðä>úÑ7|¨³º\� ëLŽ'±ð˜ùÓzòøK ÏhÈŸŸŸ=qæÌ™—Žæô·NOhŒEcñ±±X,’Òì<_�³[-¥¢ccÑb¹Ü}…æ¹óÎcSw=6­Yò .&û—žyFyÉ;äײé®c¸ø&ˆ—ì�ÎrXçù­ö©|÷yV�×¢ÃMO$ÖñJ‚#B~aòëû߈¨ÀòøC@¿^ÿÀÅò”<ãGdF£^ÿíßù�{ï÷žÒ[#€÷Ý¿Ñ}íÅ‚öõo~ó/¿û—ßïBÀØÿ¦.ùùD&Ïð­$♎ÒLP3$­˜¡&ÿ«ÆòÕ5 _-1÷—/þÝßÿÿÿ¿ýÕßÉ“Ÿüñ³/]lþø8pÿ¾w¿æ5 †s¹R»Q«”Š3…dH�üÙ=ùÒ‰]äOÌÏŸ~öÑGÂ2==ÝEþl¡I$¢É|ŸËr\^°FîÇt8ƒ{-‰vmqþC:ýÈ�z¢KKä_–ä„òŠcÉK/úê¹®c˜Èß™zý„dîÈ2ÿB~söáÓ‹œôY‡—-sQMðÈÿU"Zòÿå_^üþOúüÿ«CþO¿�çò|]ò1ø Úo×A߃µ¾zºbÁ/~å+ß|þÁ¯<ߘæ9U½ïùç÷ùç¿ò•uÉOÍÈš[M~Jžžßò5ÖVù׿ ù®$ÿ�Ö�_:þ…�¾¸Íë+›-–È€~6“Ð%¿õ�œ¹pá‰cçTä½8â£ï“äôüé¨Î‰�%â‘ìe%Ö^¤+É(öäˆEò] ~žHǽÿŒFé¿»q�‘F1#‰…u†u¬�yPú�>æ(ý‡”·ÌôcSÐÁ�xì‰äÿóï Z;òôU}òÿõÓ?Ñ·v~õWõÐñûüŸþô[D:GúS@ÿû/‚‚èiíL¾ú_Å~÷}·ëj}í³@IþƒŸ~äwÙšz±Zæ¾?ý»0÷퓵nk'66º½³|:ëh˜�{ky<3¡˜±AÖNµÛ×®U°µó÷5ùOþøø³_òßähVavgò³E~:Ô#�~ë/ž{â‰ï©”ðcÇŽ�ãé _À£¥ÇŽEtNt1‹Ç£‘X4Ž—´‡QKFâгÈW»|ä‘úé;¹zçºs¾7ù/hÉg'^‡üK@þGºóÈ£xPÿ!ÕJO%ŽNLÏïÏÿö¿ýûÂÖ#ÿ»JÀ•äWŸü�ý/²¨ÐƒŸý…ÎÇè¿xúøÀo«Ì y�“¯þâw¾ñEPí¯~5td»Ñÿ…Éž�Ÿ/½ýwï~ûÛßJwuMª™w½ýÁßxûƒwë�_‹���W°A“ûµÃ™1žHøªëE¾ÆÚa=Üÿ·ï)z¸O>yæÒÜ™—^zò ŸüäïøŒbÉL*+iüt*¦OþÅÓŸùƒÏ|æXHÙo�ò˜—‰ïäÉ£zÏù,˜4 ÑðØl­®ƒ~T~gÁcw~èNx¼ÜùBýCª§Lý‰c /ÌIÒM>�Ö,èé|ütúèG߇Ñ?¢Àö…'$�ú½¿úûߊK²vºÉE"‘Ê¿~÷ùOñ?Ð!ÿW1ó˜µÒñ_~ Ÿ˜: *òò//¾@L�G}T‡|ÕàeמNNÖ ÿmïzû»B)�>9Fÿ7àŸùõtŒÉ*BئLL*&3&ªªgt‘þ«_=¿öÖN›ÞbÿñwÊ‹'À#;ó/NŸ=yò§¦“2¶“šLF ]òa©sçÎýáßþÅC½r’dý§Oë’¥‡Ã‘D®\Ó9@_¾bÁÓ/`µ ÿ‘gº—:}Aù zÆsUI z×ü 3Ì=¢Äö…éÏžî ?³�µCÆóë_ùú׿òéOÿ¥’|‹¤ðu"ÏëlúsÄΛçsªÕcKç§9ò¶êOþäON«§ÿ4OfüéÓO�ê5ôµdQ’ÿ®à=úàcôïyWäžwé‘_ML¦ÓéZ þL&ŠŠKÙcFù_];¿ËÚa¢"ÿIâ„0;}zjâØ; Ê œ˜”ÈO&Ã~=òÛW¡Ç|ñÒÅ‹ýÿè˜ §.NKÛi·N_œÈê_¡Z¹T*UªúGR+Wë½G5ï<­ÕùÒv)ùJs= Û±lE’¼Þ/>DÔþû>ª2v°Ç½ƒ0ú¸€µðãñüú?ýÓ?}ýùç¿« ?ŸIÃÙ«üä'ÿúõýè'º=Ü�uþvpÿüÿ“?ýÓ?…ÿ�ûøÉŒOt™A«Aþ·Bã_ OVzp•¹'™¾'¥C~½œHfˆ$ÕµÔŸ±^:_cí´ÚL”äŸx„ʇ@žP{R–1½ý:}ú&ø·ßé3׋óø×®NOë«.�ÜùˆÆÎ—FSuÈ'ïos]ä+åÒüñ‡>úÐC�¾¤\%öXx‚~ÿÞŸÿ¿ÁÞ;Ó�¿àúMzÎЕ) ž™:*kç[d†dê¨f¬‚”³¥Ùl¹'X¹B%W¸¢7«’Š�ONŽÇ'‹Õ%ÎXc;ÿ –Tÿc2ì &Ǧä©Wj¥Ô®,]ÊŠ´ÿí#Gs¦ç‰`—¯‰+«/óÏ<2­3ùÔ팵½r=Öwîø™Ç/¨&�~ëÁ†|ê¾—8­š©>¯²àúëÿÑó?YÆÑ�ú£Ot×Îø¯TžZÕsZ#ÿzέáú³ÊùL&Wì&§×Œ^^Ê+Ù{-ùpí�+\V[øy]‰$tSV›|.\úOzÅd­ù<á—>•^q¸<¯&—-.ÝÜ <£,.œ|.\–Kþ$.ƒ#<ß—Á®ó¹ ¼ÎŸD\¸ Špò¹pò9ù\8ù\¸pò¹páäsáÂÉçÂ…“Ï… 'Ÿ N>.[�üÇïX¥]øêîuÙŒ¾øBœN>!ÿü{¶mÛý8º¼ iò|¹éS+Dr7¬ä=s ‘¿*›±ÇoÓ]�©,g€“OÈ¿ãŽó×^~È?íÚ5 É›Ú×^ÞöÜ É¼}~÷û$56³òãFC‰_xN¾–ü›¾J¦ù¬És7á´ñ·woÛý2<îØ¶û9‚dûýw\{n÷¶›W®±¥Oþ—úFüË»·Ýqµï؆?Ðå÷lÛý©Ýº›¹öþm7}¸Í6ó2<4Þ¿øf€ü‚C4Ž¢–Û(ºŠ-‚§è�ÛE[Zjã 8°‰4‹Ö ¶vfĈÉOÛÄBuŸÉl!WŒ$8ƒDþ{v?w¾‹üöËÛ¾�ÎoûêµÇ·]kïþÔµoo{�¼vÇ×|»ü²r�nW´¢KþùÝï¬oz¹ýøntíË×®½´90}þ¦Ýz›A¾ãòùÝŸb›�[âÚ6@ª^ IDATä»C¨•A­X½á«&^nÇŒ ”4¦ÛEZ¸Î� ÛÊY*¨8KÈ7ø›ã¢»R4f‘ÏU-ÙÃ(î@¨ 68ƒDþµO�Êý¶dçX6À·½§-Ù»Ÿ{¨Dïÿ0ü¼ãým„¶=~Y½F—Á`pFÊ:vþîó’RGÒ]uºpß Çwëm†Ìzn7ÛÌï?¿”Íùß,ýQ¤OkßLBvT1dQÞ˜jI=ÜC!ÞEb?P]˜AA/§cÐÆv®}jÛµËÛ^>þ²l†œ¿ãÃèÃØÚ¸ãqb–êôø6ðËwl»ãe-’˜ÊpM£ó_¾ Úí¾i÷îÝÛ¾ÝþÔî›nÚvíÚ¶Ëo�Í\ÃkyÛ t¼±Á´Øf€üÒ¨ÑGí Íl14A{›-Â$rÄå&6¸ \~„bÑS‘¬˜jÎ!ä × ðÉò„�•òù ð_ÖÚù�ßÔ­ó¿é<}Jt#i æºì|¬Üï�ú_Þ=:ÿšJç«7ÓÑùt3èÛÛÎ/º©‡›ʱ‘ Ø5Í¢ó�áŽÎÏD“I0b}_uû5ä3��ÆíYS›Ó1Päøåk—?Œu¾‚üvûüw`¼Míü—‰�œž¿öÜ5†nI{0¯×ý¶í«ØÎG—Ÿkc¼a+øº¶{·Þf  @í|¼ôÜ<./º ?QA9¡v#04s&°ñ “hÒ”A’�ïw–Ëå¢8VH·ZÞ.ò}®¶óQˈ \‰|0ó±ù¢$àx æ«�±�/KÃ�ŸÚ ?ÈÄŽB…c;dp�½]»c÷ïËðù©Ýº›!c;רf>¼McíèoÈ÷›D[Õ]#®X;›+`‡‹Ù2¶Ó2ŽþÝÙÑè®jɯ�šÌbÿ2ŽÁ³v¸páäsáÂÉçÂ…“Ï… 'Ÿ N>.œ|.\8ù\¸pò¹páäsáÂÉçÂ…“Ï… 'Ÿ N>.«O>.Y-ˆŠäÂëárYI5´ÿ¸pòA í?.œ|.\x ôþ|æ\6µðQÍ%I µÛ-�f£Q¯×%òÛ\6±pò—E>€¯ Ÿ?û6¯pòWD>?/›ö=–ùW?ùú×ÜðúO^姇“?PäŸ}÷Þð†×ÜpŽšs[šüD‚“¿eÉ¿ún,oxà 7¼®£õ³NAt¤ÐNe)ñ ‚-1`ä'¼Þ'«’ÿÉwüË_þòDZÖÿ$kÖ2†jÕd�YšÍ¦T²Áïm5âBi Èð1úœü­Iþ»ßýño_8óåwc¥Ïš‘ ó cyIÿ(üÓ…-FOȰ‹Ž!?kIÒz$[Œ|> ÏÉßšä¿áÝéÒ¥ocòo�u¾Å3Yí"¿•«(a.4¼n4+Œ·"¦:�Ÿ6§Y=ÞÃÕ^�±/ÉÍ»?þ…—^ú²Š|4ë· ®"ØùF£”‹ÛùC‘ÄôeC-Œ­Û2‡ÌYÄê‘ ù¼ãÖ ÿõ ô?þqþë”MË.'3—J¥Óùíœ9!•Qò|¸"ÈlÂ_h=N¾,¼ã&èá¾æ ox7Öìôp%#ߨeç{}DçW:?e—å¸Éà�¯[�±´ˆŽª´¸¶cÔíl¹ˆÉ”`õ[Fè&U…2‡r£È¿úú^óÌý ¿"�jÎ ͢˥"ßÛjfÍa·€�ïBE!IíüŠ-„h=’-H¾ÚoG&_·cÀQlg¥¡�®zŒQ!Ñ Xü�qc‹ÕcôŠ89“F>:ûúˆ(ÞdUG-‚É[V‘f>©.’Æv&í¢#KÆvJÖ0­G²•$™VŠ–|ÝzŒÆ´¼tW=ƨîR“q†ÕæJÁÉuF9“G>ºúÉ×��ϽT’^PçëÕcl:–KW=ƨ±*E¬cÛœ. 5~¦7�|.½ÉïÝÃí®ÇØÑùÝõäËõþ�›ŸhNþ¦"_·cÀ1KíüîzŒJòY=Ƭɞà'š“¿©È×­ÇØ б�zŒJòåzŒ6±ÉO4'ó�Ï…“ÏÉçÂÉçäsÙ*ät¬'pÉ_f¬V °Ð\o˜“Ïes�¯«e7Œ=\Ó(ù=b·8ù�×½úÂ]™û…|½X-d�¶Šß‚äëÇnqòªGšË]™7€ü±Q"cª¦z±Zäõex¡VÐbôÕQÁ)š|M„]]>J¾&vkÆ…G¾1ù•‘ ³‰æÈ!¿/¼²+mõJtþX7øº±ZÄeÅáA(è,7<~THµÊ#!Ô¶…Z)A&_»Õ¶[i1 ä“×–bÕò[�ü+Q‡Å\ÙÜY²£!T1„QQl[3(nÈ‘YøÄÚKQ§flí˜#6Á_r ®: èÄ/‚QÀ‡­¦HÌ!‡ÕÛ¢K‰ÛE[šº7«<žÃæà ÇzÖÎXøú±Z`çFÀ”1fàrš¥‹âFY±…�[¶ó•±[9<ËçG^¿»%#›ÅEkAòS^Ñ�h¡Y±U±˜à£  '¬nÌ;Ü>k�†ùvîvÉ©™�ï¬�Ž\Ýf�Øk­mNò%E‚ÌîVËÁ\¡±$�évq†¹7+=žQÖotFëœìë¶óÇ´àëÇj�ÎÏš³¨a°Úl6c»âµZL”´cäe�¯ŒÝJÚà#äA^Ó~SŸq Îìf'?b±‡%SÇ’IŒ:òÀ;({ÄŒy‡ö¨)âñ}aêÔLÈŸ”tDØ‹Xp�3J–i 2§à©êW¸B»¥yÔÕMéñ ÒJ¸ÅÑg{õz¸z±ZÄ·o”’�Œú(î@Y|÷(ìüNì–¬óù:Í�}³“¼)ɼ ùcÁfÖ’±yà½(V,uó¬ ¡˜qY,b€:5òsRo?êF, 3â"A*°ªHH£��.…ÅA>˜{³ÒËLÐ<€VqTS'V‹�ß0N‚�?‹JI䣆Óv~ylG»…íü è*o¸åq·‰ŠlzòQ5N>'Ÿ 'Ÿ“Ïeë“ß ˜DÚœ|.C~\üÆß÷^"†�$ß ÷¼ÀY<ò ßðßvûí·¿÷ö¥‹(-JÓPßDäGšMî-°ÅÉëž”ø¬òü·½×c`íƒè·–I~ÚÚ”äód˜[Ÿü.ßeÔ6ü�¬òÝß�É�¶J ‹{™äûŒ¶MI¾ÙìLq–¶8ù]èG~ý/î“È¿Ïñ6ÓòÄŸ'gÈ07ìoU74Q^ ÖÂäÓ$󊨬†°½4Y¢@>�âPÆ]l`×ä'³…��ã0mqòµèc+ÿn þÝ¿î7È)T¥$«¶ Á¢ä·aJZ�ȧIæQYqcË íâ–bÝ äÓ(eÜņp-2¶ãr˜‹ü±Û¿ÈŒÇí²™OÉw˜;>%?klÇ}e’ùNT–Ë�b{(J�ˆDq(ã.60„kò=œü³v ñÅ/þñßr»×BZ�ÏB°(ù,X‹è|’d^•Uã¨)JÑ[5@�Fq(=70„«7ù�x©2¦ÁêáÞûjÐ÷·ÿúí·ûîV„˜òó† Óùa/BE•ÎgIæ;QY!ƒÉdÜÈ –|ȧQꈣ áZ€|§(�XK.[˜ü®¡Ã}w�UʵZ51(®>Û±ºå¬´¥Žü*;Ÿ&™WDeÙƒår9)Tâ# äòi‡‚ü� áâïp›ü. Ù ¿~ß7Šå+©÷“ñxþϧc;(`u†éØÎh�X;R’ùº••HP…=Œ‚vWȧQʺ:ÂÅÉçä«¥ñ9M†W¿÷o KÍšæŽlÆ3ÅÉçäwI9ñ Þ%ñSA“Â,'ŸË– 3‰ö1ÄÉç2häo^áäsò9ùœ|N>'ŸËà’Ïc²¸ &ù“Åe@É_zL–µ÷ü…«jqò¹l0ùˈÉÒ©Ÿ%“2d8ù\6ùˈɚíI¾Õè[�ü'ŸKŸ‘¿Œ˜¬ðˆ6"‹‘Ÿâb¡¨kÔnKuªjÅí¢³ˆkãŒXQÐ,BkV‡6ääsÙ8ò—“Uwz4Y2ù>w˘ÀY†3(i‘«j¥ÌÙ6®6gv5QÎRAÅY¹ŽÔ�“Ï¥Èï“%šç¬&"‹‘�ÃOü. ߉�¥«ªåÁ�-¦dN"”7¦ðフF�rò¹ô�µÓ+&+\r5YŒ|r˜1Tˆÿ1J,PËa¶Ùl¦´�sˆžŠ²ꮩËÉç²q=Ü…b²�&"‹‘ïL&“!Ì€fUµÜÔÍ™V{ªºýÊr8œ|.Iþ’c²ùšˆ,J~Ù�,—ËAhVU ì|t%Ñ&äÒ­–ׯ,‡ÃÉ粑äwI¯˜,B¾6"K"?Lž !Ç€fUµvWÛÁägGD£»ª,‡ÃÉçÒWä_GLÖæN>'¿K–“ÅÉç²…Èáäsò9ùœ|N>'Ÿ 'Ÿ“Ïe°Èç1Y\“üAŽÉâ²ie�ëdu¢²¬‹'6çú�|.›XÖ#&+æ’Ÿ•îo”,…¿B£!NþÆIºë'ÿúb²dò0†:5²8ù\ú�üåÅdIµ°fŒ‚ÅŽ¼~§%g%Η¢-�­Z‹­‘5#†F¬aD‹™#vÑ k [ÈóÃrX½­–PæäsY_ò—“Åja�ï5—ˆuŸ4¦ÛÅü�Â’Œ©FÖ ØªÉe™’’® ¾„ø ®iL«…%‘–x§ÔÂ7Z «‘EJD¸â;?ä#u³��g?‘=5#68ù\®�|v×4&‹ÕÂR‘ßÑù´V#K�|¼@ë|J~Èåo²¸¬/ùˋɢµ°Ð¤­Õ!Ò”A’�O a‘ö´F#?àë�·€�ï’B?À’âäsY_ò»dá˜,©j¹D‹L>ŠÙil‡ÂBŠYŒü‚]ôv”<Û¡?‘ËÜæäs¹>ò‰U"#b²|‘‰�“¿%ÈOx½‰U"­{LÖ¬8³¹È÷†9v}B>€�Ñ_-ò×W‚Bõùö¼/†Æ:9àÆ ÁïI>î½WŒÈZä0®7ù|@s’¿A²ò-­FL(rò7Q÷ÞÕ�Cüí-(Ë"þãrÒoÀ)â×z)»èÈIžœü­Hþo+Êä'ªé ù­¸!�XB]¯1Ûò;Ѭ0ÞŠ˜êDç7ã(Qç0nvòßú*&o94ˆäw½lç ‘NrE¯§-‡ñû<õÌà²ÈË«¾ôû¿‘Wqò¥¯uŸ§“P׋Q7fÉÛ9W„“¿±äëûí\ùüw‚ÜóÎ^·µsâé-E>jš'¹Îï/I¦•² ä¿å? 4>!ÿ®Wá ¿ œœyvq–Í�éü8rx �ï÷tn‚°CN¨ë5æ°�_’ÄÎø8…8:·z:_²uˆÊó!äÃÿ3Ï.¾à‘ —ß»id)äÓ<è„ü+bJ;¶3iY$yfpÙèqée‘ÿÚ�UMûMÙØùµw;Ÿ’øÌ¥ 'îý½.�ÀŸ†�#÷Þ{è¸ôË™ãgž¾ϹpáȽ'ž¾÷Ù3'.]8ü4þuï¡.ÿ½C éáþ¸?–ð·mkp¾¶&ùúoé¡òóÀ«>(ë|Âò!`öÈ¡C'ÎÀÇá{Ÿ½pèÞã€ýáCdA úé ðt>LÈ¿tnŒã‡ŽHíÃ}qâø½pCÜ»IÈç²uÉÇè«ÁË;eòAåKãù”üLW¾$}‚2ÇúœÊÓg`Æ ÿ¾€|˜SàÜ ¸Ý‘3`-ÍpâäsYcòï}Ë[º­|IÞy€ÞTç>Aì–ã`Ì\>_¸:ýrÇr¹¦Î™ðK'ˆÎú½I.&íûCŽ�{�“Ïe£ÉïêßÞó›ï”äÀ=¿|¯’|܇½tø6o."ƺJç¹·Ä¥ ëÃ'NÈä_ äß{IÒù÷?�§rò¹ôù¿ÏgOœ8sæÌSŸevÐ:tæÈ¡#‡1ïOŸ8tè8�áС#ØŽ?søXþ‡°ñäґø#pâЉ§á¦p“Es��Ë\8#5ßpYˆü�g¥h'Ï·Ó‰ñOÔF��Ö^[ºž¶ò7[›’| ÿßòÖW½ê­÷*ùîb™ãPX¾ ì˜|Snœ“"é ñ!'N°"»'g ø›3äg…ò ÓLr¨ ‘ÉrF9X½– šÅ%¤âå²Näk½”�|œ ‚fŽ“¼Ô4äÚ¨a›Áäc2�ö¤<-ðP°d�Ý’G–,Ë$W!7båRæl;<‚r– *Îrˆû”üCÜŠ²ùb±,B(mV‘?ꬖì† &ß�);�Š)I¢3ˆFCk02+¶Y&9ù± e”óàÕ›fòÆT‹#¼äóÓ³Ôó¦Õù,ß¡Fç×FÍÖ ¬ ´ Î�¹£“ž¸"«�¼’QÎa¶Ùl¦4Š9DO…_Œ¾&ß`0Èß¶8ùØÎg:_cç¾](*˜L¢`&v~YÇÎGEÑ«›}¡nò¥Œrny´´êösˆû™|ÃÿýµŸ$î¶ÕÉ�í4srÇèxeÓk¶Q¡PM3¨Q.—ƒN°Ñ…±ºèO˜¤V2¶ƒs%ZÄ"ràÄÒ”|ÚÃeåÀÎGWíBºÕòròû�|È÷ð}‹“_7_a™ã*&:žïĉI”4 vš‘1¬Ï»;ãù2žï…þA@hÉä³.Ë(—°‹f/ÊŽˆFw•CÜïäú?CË#¿“2­ê;\wvéÞ�Œrœü•é|døÚÏ$“ŸÁ¿y“2m”ßÎÆd”ã䯎ÎÿêIþ¦IÊ´AäoPF9Nþêèü…ÈG›$)÷Õää¯DçoÞ¤Lœ|NþJt~GÑËvþ&IÊ´8ùQ÷ò׺�Î2zû׳iNþÚ�çëèü.ò7MR¦ÈÏ:Ñ‘ÒÅOs-èñÊrÉ/ ‹“sqÎ7�üÿõk’Î7&“$eêM~˪U“i=ò[‹�¿ gþÈosòûŽ|dø/€¾ágÃ×¾ö5ò7]R¦ÞäÏê?¿hMÉ�õ¨Ëkó’ŠÖ u�Q©û &K”öÞU•±�EÚ‚Ü.n£è*j{ûH(! ƒÅ’'7^¾î3™ƒ-ØÖ¨hO³MK•·¹Có‘OÐÇÜÿìgÚ—Y›2)Ó:ßâ™ÄïU£B¬±È�õ¨!Õ±vÂîf;Û$:ŸõÞYelê€L[àõÅê hmMoŸ’/ë|²¼ÏU-Ùð­X;!ÖØ¦±ÎçÍF>FßðþgI´¯q7_R¦ìüY¿U%uµ†3ÜðO™üÖÚ’µÃ,9V›: ÓTJÒZ~]äãåEòÌ@Qìô鈳Mcò¹CóÆ‘� y*[í¼iÆvÊ.§dl %ÖY'?ùÍ ÕhòYï]®Œ-9 ÓX+mf‹¡©ííw‘Æ7ô�3F°v`‚'Ì6Mì|îмqä#ÃÖpP^ʨ昑‘/ë|·zl§`M¨u>«ŒV¶ÀÈŽTP “¯ÖùÆX]Œe¸·ÎGÜ¡yÉßÂçMAþl°Ð,º\Œ|ÖY'?Y=U@U ǯ°Þ;#Ÿ: ÓHrä `òÕ½}gÅjJ ò}®ZÇί²MãÊÛÜ¡™“¿ÖäWG-‚É[fäËc;ø'ë¢Ç¬¢9€;ôb„õÞåÊØ’2m�Ç�\#®&_ÝÛÏ�8ÜØ¶żL~}ÔdHc;¶Î°®¼Íš7lTspb²¸pòàPLN¾Šü�‰ÉâÂÉW“¿Ä˜,³4�ÍÞÀûT/üK:n*½]¹ÖÐs‹“ÏÉ_ºÎï“e0öøÒȯGT«%ãu:äë:�%<% 'ŸËêü®È”V=Ò ÄZ�|�ô _ßiŒ“Ïeƒu¾^L–�E-ÚS@~Øjô5e¯+L>Í"I­šjDòÅò\‚c±å‘Òi µG]Wh2JN>—¾ÑùrLÖ¤¡P1ÆÛic ™•ª#ȼ®0ùÔ‰K&_J5ÙÑùælÓ;ŠØòHá4æny<-–Œ²˜j$8ù\úBç3˜D1ŒÙDÈEæ‰L¡oà1ùÔ‰K&¿“jR"?€]wåå±0§1—k´-'£ä=\.B~ï˜,s+è€h³ÙÌ!dÎ ”˜×&Ÿe‘däwîÉv~Æ*/O…8�¥îƒ”Œ’“Ïe#È_4&‹%ëÖù'®…Èk†0‰ÓXÄ‚}Ò¥d”œ|.ëOþb1Y'Ò‰·šé¢ÚίR;;qé��}±ùly¤r [K,%'ŸË�¿HL–œS4‚qŽÇvF›²×Û‘œ¸tÈǾXŒ|¶Ú|á6œüõ�ÉòJ®$§6K™m�XÕ‰¯)ùÔÚ‰¯(�ªä ä#éPeé–%â ·MÔl “Ò³F_}MÈß¼á6œüõ�ÉŠ#ù6ÕÐ,e¶ÙÕÔ$¾V‘¶—”PHä#[ˆ‘¯ÈÒ­%ßàodÁ :Ë �ÿú«n-ÖÃÝ”á6œüõ�ÉšES¤c›’ÚÄ×Jòƒ#¤‚B"ß`ä+²tw‘ ;Ç�fÌk7¶³)Ãm8ùë“ÒNiÂ)K™Mz„ªÄ× ò1¡€JOç+²twY;ðÇo¬°´±½väoÆpNþúÆdIìF§,e6 Q$¾VêüŒ)…TPòó`绣ø†!ƒ@4K·>ùȘ[³QM%ù›+܆“¿¾1YáñJ#.dˆÕÊRfchâ넉’_h6›mÉÎOSJ(¤±«›ÔIh8Ê,ÝøžÒ!?èœE¥äš“¿¹Âm8ùë“•pˆä¥ΩÍRfchâkªÛkd<>JÇvÒÆ´ 2ž?‚Çók.»3èPfénËÚ]E~+hláµ#dõÃm8ù}“åήh³9÷zœ·  Âm8ù¼NÖRÏ>qCþZ„Ûpòy�¬Ee,¥î«ÉÉI˲”f9ùœ|N>B!ùÍS0ÌÏÔ “¿Õb² ¿n®±V3}Ëê³ðk}ÔhÄ#2n8Ø)Ü*¸J�•â'kˆ�Un%ò·\LÖäG=�f.êYIá"…Èç¬íðpGšÍ&B³B¢6êì´öÚÒõ´ÕÇ©ÜZäo­˜¬ÈwãWgq»hK#–ï¦bJÂM`GäU36‹€ú’ì}�²†Â.§ùY¡…|F„FÃÌ{¹ n-ê›Ì\œUÞ¬\ú•üë�Ér¨_¶Æ]}M>v*HÓíâ ñÕé"ßÐFn³Ù ­Hif“|p!»Ô2ŒÝ.ì–<²d™÷r…܈ù&Sgµ7+—¾Õù½ëd ®¥‘_ÄÖqa\ÛàºÝìׂ|1 J�vrÓfù£ÎjÉnh d¶rÈ�‡äm²«q@: Î  U¬ÁȬØVz/“Ç‚ä›L]œÕÞ¬\ú^çwU £·µ ò»¥¯ÈÇ:ŸyÎkt~mÔl ¥ €}O�s%F'=øÙ¦ðç‘fßdæâ¬òfåÒ÷:_¯NBuŸÉl‘Ë\ÇÅîý.;dzŠ~ ¿àM¾&1X,yLDÊ.b|j÷ùØÎg:_cç¾éãÍ$v~YÇÎGEÑ«›±_›–|É7¹ãâ¬ðf岉t¾¸‡Ç=\` „;äƒ %Ÿj… @~ªU I:ÈŸÆ[S�™Á×ZµäG€öISa;ߣã•M{¬ÙF…B5aÌ F¼T� ÐB«û€~ꎊE±b©›qØ–&ß2{¢$?×IÒË^ bò‰Ó��—Ëh�:, ò©4sá䯌üU©“Õ-m�Ñs�‹® hÖRì|ù>Ìt™‘Ÿ×$qNX4äƒ�_¡¡ÖèŠ9É ›Ô}Y‚£Ètuå[îA>KÒKgÏ2�_�¯"Ÿù�ùÔ š¹ŽpòW¨ó{Äd¡ŠÏ,Ø‚‹{�êV—JŽH£ÐkìKá^…¢Y‹�í¨È7f[~§œ:9üõvAêÒFòµŒ}TÑÃÅc;båL ”4Lâ—ØB5 ÀKc çC]ù–{�Ï’ôÒÙ’ÿ‡ì|E­=B>ó‘ì|ìÍ\G8ù«¤ó5‘)u›3[/øÓ*E.ÿY”üÕønw©‘]Z‘U(šµØx¾]M~À)²±L~ÅkRë€Y°øëŠ.ÏÇ�߀ͰC›¦º¸î‰·†Ô�A“†4Òæ[îA>KÒËfcÿ¢c;Jò™ßÛ¡‰ž©ë'•t¾¶Bœ… Öß�tØÎψ™ü@¦^ ›¬ ⪈1jç“zlúE³ÕÚ8ùœüu‹É’ÇóãV§_ií°bVŒü‚]ô*Ò Hc;2ùA» :qžŽ°UmÊA\qõ’†ézÍRTkãäsò7kL–y�zŸ«W4‹“ÏÉ_:úë“eÎmÀyãäsòB]”9ù\ú�ü-|Þ8ùœ|N>N¾®¥³åc²¸pòàPLN¾Šü�‰ÉâÂÉW“¿þu²š†Å\/¯;÷'Ÿ“¿t�¿vu²!鹟ž’…“ÏÉ_#�¿úu²#ɹŸ8ùœüMU' m1#†F¬ÄÝÍd‰2ò—œû‰“ÏÉßTu²ùR‹C•Å"Š[Šu·†üÅs?S�'Ÿ“¿æ:ŸÈ*ÖÉŠã¼a-g…}îsŒüåå~Zwò㮕$@A+[˜“¿æãùk\'‹¶`žÇ8™R�‘¿ìÜO+!Ÿ˜pm\ì vÌ’Yh-4£tÙuà…~¹èwuOk\…ì)œü5'ÍëdÑrœUˆÒÚùKÎý´bòö\³î"¿¥K¾¾Ú¶G[¥D÷ݨXã*dOáäo`LÖ*ÕÉ¢-ùñ‘ò©Çv–˜ûiUÈ÷J‰Áýèg³lƤ+ÝÉšÒ!ŸZ;Qà•æE–ïל!Cbg’T÷Å‘:Ycg?TÙSh–N~?‘¿öu²h 9Î*hwE”ãùKÎý´RòI·=bŒäÛTC³lƸ+ÝÉšÒE~Ø^’ó"wžT¶#?ìn¶³MÍSD•=…fiYÿºØœüEÐï£:Y+­´³h7îM‘Žm"w¥å¬)Zòƒ#ÐÑay‘;ä;Œüˆ#§±v�&{ ÍÒÂ¥¿Èï¯:YkN>Bí„�&œ²lÆäá"gMÑ�/ˆx8•åEÖÓùÍ Õhë’/=çX–NuŸ‘ßWu²Ö�|’+sʲÓh1š5E«ó3¦’ó"ËäçÁÎwGñ C�¬‰ÈGƺ/ÉßÂç­‹üðx¥2Èïd3ÆäÓ¬) %¿}ï¶dç§�)9/²<¶cu“tZ ‡¥ ¨j#kì‘=…fiáÂÉß8òQ°Çq÷]Œ°lƘ|š5…êö1ý¢tl'mL³¼È´_.ŽàñüšË{Ì*šÒ{dO¡YZ¸ôÕ¨&�ÉRŠ;»¢­¯^öN>�ÉZWò¹ ù<&‹Ë€’¿â:Y�À^o 'Ÿ“¿ž1Y̹k©äûñ BK#¿G ×Êßïsò9ùË×ùÚjAÔ¹kÉä{ñHà2Èï–µ%?$ß–A>ÐÂÉï“E�»XX.ZeK³LÉ,4«à]>J¾Tç{á®1»€WÖ#†kMɯ›kòfnH_|V†¯��ø ÜðÔ‚{²ì6JŠ•âQIkˆ¿ƒ�¯rî¢aQIcº]œaU°hhVÛj¥ù Çp¥òí¬˜éõrŸ®È�*JY¸h±ÆH ߯Èç¬qåRw[pcDR*ò½¶t=mõq*·¾Îg=PìÜÅ¢ÜÄV`QhhVÿtSòq„Ue 1\¾ðb1\kB>Ž  .)¼@z¼aòM°c¸¬­›ù×”äg |ä†<.pî3"4f©F€øú´ð¬ªPf¥U.Ï\ú”üž1YHrîbaQäí¼\‹:+'qd?%ßS*•Ú‹Äpe\‹X(†kÍÈ·ÀÝ%=¸èahÈ7´‘Ûlv¦ºÈ§EÎá¡`É »%�,Yö�ª�›B:+æ¨vyæÒŸä÷ŽÉ’.w„…Eit¾tû¹xTÖÎÂ1\–XA¿`�®5#l4z¥Í*òG�`¡(™-„„œ–ü€4úê ¢ÑPŌ̊míC*kncÕ@‹9ª]ž¹ô#ù ÅdÉÎ]RXÔ¤ ÌóV‹ݶ%@kìü…b¸¿YèL.õ¦:ßAí{�ί�š­A£4Áì­óc®Äè¤÷̵;lO͈ ¹˜£Êå™K_’¿@LsîbaQ1› Û¡¡Yy‡Ã=ªÛY0†+aszñ Qï®5µó™Îרù„oú^ÍìiçÃýë�Õ;P÷‡¼ÁQe©G…Ë3—þ$¿Ïb²Ö�|\²Nzp¢1:^Ù´ÇšmT(TÆ jÄKÕ<åP³b˜i"泌è$JšûB §(à¬(äu¶¡.Ç£àñ| Ï÷Bÿ €»(ù¬‡ Ýt3ž/sTŠäÒÇä#ÃÖpP^Œüå¿Ã]ŽÏ²/À¡Ýtäoáó¶n~;³â ?ùœüÁ#?(ù¹ß\äó˜,.I>�Éâ2°äó˜¬ë­M¤Yãè�aA›¡3e³kq4CŽ$'¿ù+ŽÉb�<‡^ÞUA+ϯ³ ò—^›ˆ¬È)X?¥l ¡U$ß1Ö³Ó@S1ëÍ[¼8 'é:¿GLªøÌ‚-¸d¯á}w“u ¢#…b®®J‹¾?ˆiÈ÷Gâ£kFþ’kaÉÄÃjò Ú¸›ÖÊÈ7zmœ¥bîÚ'ò[]_8ùË×ùšÈ”ºÍ™­ü饮Ë#iΖ1T«&Ó “�àšÆ¥õ$ɵ‰$#ä‡3”|)b†FÖD]^[È'î äå—6ö†Î‘-Kä‡Mfáã,ÂÈlg® dm4á²$4]OÈîí$|&nÑ$¤…-FOEšO /OsâsÌVE÷ˆ“¿˜Î×F#ZšÊÒ¹'/4>vZ ÑH!•âªF#\šF>Œ‚Å._š„[¥�Lø8¼—€C¶(sëAþⵉ”äÓ¬iŒ|Y5¤ˆµ“A(/6%m¬Š½¡sh¢er^|ͼ1Å<™‘±€X˜YM¸¬$ßT$|–Ü¢‰ÎO˜ ¯[šO /¯ Ÿ®Ší'é:ŸÄd¹èe ç¾$ÔPÛœf§ÕB-‰cWÅt¾Å3‰ßÜ�O³$Ü:䛳Mï¨Ì\&?“^3ò—Y›hLm툰´´"_˜¬“ß~’ãš&ö†Î¡‰– Ç¢9¨'3&Ÿ¹|“µ©.wR1³8u‹&äc¿»²¡&Ï'Ë+ȧ«Rî'i:ŸÈHH=úጢ”E¾B ½`>ö”|4ë· ðŒ äÓÆ, ·žÎ'![Ë®‡u=ä/³6‘†ü ,Ýd‘5x%¤‡ë"KºÓÍéÄÞÐ94Ñ2æ3qËžÌ@> óÁkS'\î$'T&|ù$ò‰y%äåžÙ›ùlUl�8ù=Æó{Åd1�ÏÎ=àë ÈW¨4j¤¾,®ÊÓ!)»œ„|ùÐ$Ü:äÓØ®åÖÃZ‰�¿ÄÚDò%k‡FÖÈäg-):£‰½éÌÁ‰–:Ÿy2+u>^›*ár‡|eÂg –éü è|ù,³3Öù9ÕqòuÉï“Åì|vî«Â¬˜W^¡”PÖÓù„#Õù9ÙèwP’Ÿ_­ìò‹�í,±6Q»™°â‘ ¹‡[ KÓÈ™|d³Sc[{CçÐDË’�ߢv>ödfv>ó!kS%\î�¯LøŒÝ¢IH�ì|EÝF²<Íì,ÙùdUl�8ùºè÷ŽÉªÛ\dl‡�{ävÙ;W(QA9¡*uí’J;6Xh].4ikÉ�Yn¸*¿^%ùË®‡u½ãùK®M”­G=\,~YÓ!?$�&öFšC-+Çv$OfL¾<¶ƒ×¦J¸Ü!_™ð‡Âà�¢c;Jòifg:¶CVE÷ˆ“ß}ý˜,6žÏÎ=Š“79ô´úMä¢a¡qU”üê¨E0y˨å-ò5 I¸áªäÌM=ò—[ë:ÈבUx�w,—~ ½c²Âáõ‹¨�ÉÇq~N‰|~E""袌|ZYDK¾çb¨©Ãñ¸µÃÉß°˜¬1s DN˜�Càjù,ŠN&WȪHä³ð+âïNeäÓÊ"]ÖüJêpŽ¢ÓŽí`K†…_iÈ'Qt´²‹sÒ�¯ ÇãÖ'Ãb²¤ñüD'ÎÆv:ä“–¸WÄ ¿Ò�/EÑI•EÚ²vW‘¯ ÇãÖ'KÅd‘Ê"9÷º�7nípò@ýb²Ö¾²ÈÊ­M:¾…=/¸lfò×/&k*‹,`ít\2\K#ŸŒGƵ *Fd-rB·ù[ø¼©²ŽÈ.­e�ß-œ|Nþf ?¥ÑùÒPmÝg2[¤ã^Çåªý.;ÎkK“œ¢É×”òckGJ™Ë|18ù[‚ü-“Õ±v”.>WµdwÈ·TP`TN>\HµÊ#!Iç“wRÊ\ê‹ÑŒ£D�ºÉɸ˜,â’1†pó¸½C~�äµU&Ž»eòYúDê‹Áe‹�?Xu²ˆKF£Ž³»fŒò¥Lo,ùpÅkµ˜2ù,e.{±Áe‹�¿Ô˜,m¹�Àr {Ãý@¾díP�öB?¶C>K><êkàÜ€³Z�ÏÉßb:¿gLæÚ>¶8ùí E°ôB"E_W»0ÐJÈ÷¹jØÎO[êÈß!Ÿ%v‡QÃé y‹]rÊ\NþVÕùÚÈQ,/�ü°-×,ôÒèíf3g¨5›¨ŸÈ¯�šÌ�€Õî�Ï’çG.œ–{\ౚ2—“¿Uu¾–|›×Oȧ5Ï0ùQk‘]¢Ë'‘ï¥F�P"7ÃŒ±*1/àLÌrI,ºüÆ�Ï…“¿�ΗmEa“Okžùa{‰]µm¡VJ���#ù¶‚|C•ÅbùRI,´µâ’Xœ|Nþªë|É0°!Ÿ�Y;¾0�©ÈAWYì£ï¦Ê>îMù0Ë9Ö­óÉÐ! ÚÚ˜.N>#¿wL– •„ ŸÖ<›Ä’ƒ®’¸~Š_Ûi'„tÇÚARÁ2 ùtè�mqò¹l(ù ÄdÙpÌ �OkžÍˆSJºÊšõ¯g}ƒ2Î 4ºùa÷:ž7N>'¿ú ÄdùeAc5Ïè´1Å‚®Ú¶*R;?<^iÄ… rFPQì�Ÿ0é‘Ï‚¶ÖŸü�ü  †9aƒNþB1Y8Î<`c5Ï0Ðicš]å÷¨D~Â! ¸DhnÄáövÈ—µ»Š|¶üº“_7×X«Š™ÆÁû¬ülª�I9C·”+®ì6‘àI&8ZÌjs*·ùk“åÎnøyS’Uäe¶X$EÊÜùœ•¢nLw„ÄW")ù^[ºž¶ò‘ü-FþÀÔÉÂÉ#PÜ.ÚÒ´H²Ô=Áä›’pØ¥jÊDjJò³¤ðgÎ�ŸZÈg„¾L˜y,7òP`Ùã`õNxœÍ¢5Ã!îwò¥NNû�4¦ÛÅš1HC¾¡�Üf³3ÕE~È.µ ã´*vKY²Ìc™U÷¥ÙãRæl;<‚r– *Îrˆûžü-|Þ”äCG¹i'7mV‘?ꬖì†Jf !!§%? E/:ƒh4T±#³b[ë±L³ÇyðêM3ycŠ×Eää÷•Îg¹ 5:¿6j¶�´wì­óc®Ä褻òh}x¤ìq³Íf3¥QÌ!z*übô5ùT' ÛùLçkì|Â7�K÷{Úù¨(úcu³/ÔM¾”=Î-�–VÝ<„¥¯É¤˜,œkÒ”AØÎwǤ武=Öl£B¡š0fP#^ªÆèš6+†™&’_HxÈØö¯³ˆEäÀÎý”|ÚÃeÙãÀÎGWíBºÕòròû�ü�‰Éª›¯ ³ ¶4ª˜èx¾h%QÒ,`ÿ¤†Spâ\ª`¨Ë/$ðx¾…Œç{¡Z2ù¬‡K³Ç¡„]4{QvD4º«â~'ј,_hK�¿üw¸Ëy!á ph7�Î_,&+¥@Pz`YÉÖWVeÙ䯥¬}ö8Nþ†Åd©¥ÕlFÚ:ZÝ‚M€ÖÖ'²Çqò×?& ¬fEkYIq�=•Ò0yNÁYñ ö|g’ßiÉ‘zYRîeÅ+Ð1›hŽl%�Ïekè|uL&Ÿ†YÑZV òY&¯9WwZ­€[1 W\q5åºZ�W bÕò+,‰ÅÉç䯺Î'"Çdò¥0+U-+B>KÉ�#®Â0!gVM"õ²X�•Î+Pc¤¶þ=ÜÅdrDý{¥®7š�}Výtu R1Û�(©S€Î:ÄEúð%�“¿xL±vvpTײ"ä³4LØ_[h©œD†ÿX]­Î+ÐŒKpf×™|{WaëÞä�b:㺯a##‚ÒksÌ`ìñå�/WBŸcL9ö¦9°èË„zdàÉ_BLV‡|u-+µÎï�¯œDÈg:¿ó ¡&õ XGò£‹tȵä÷è–�{Uä[ZõˆP\ù²hÉ_–¯�©°ùž%sÝTò—“¥ _UËŠ�ÏÒ0)ÈWN"䳺Zò+ÐF¢A¼‚×—|é½-í~k2¤\ñˆö�´öŠ ¢Å‡­šs9êµÛRl~B~8Cɇ?B²î1Š#uòêËïGe�Iôº£fcXNÜÌ*^Ãé,8D㨔«…-FOï‡ÝKœF¤®ów&ûCGØDò3ÛÙLùÒÁ� FX1’$¢nŸ`ËEL&Xµ×çÁQ #�ÑDò—“¥ _UËJÛ¡i˜ä+'Iõ²h]-ùhÝ)’@>ë~k2¤ø\õ¢È�—Û1cCÒù@>͹+)iQ“OËÜaò' …°»ÙÎ6+BµMäð]i¥aÝþFV(Ê+¡¯átºC¨•‘t~Â\hxÝÐ6ßaò"y.Qg¶?Òˆ›ˆÅX�gvÈgÇt>�ˆ ‰VÀâoŒ Ê(ä”ÈÇ#NcÖ66ˆä¯o�¬õ>o*ò£Ñ!›bš )¸»È ²feòiþͨ\†šŠ|ÙÎ7‰Ð�Œ8ˆ莠I+Ê „Þ\OÏ)'nf¯T�o–Y;؇®l¨‘¶-À9 ­œú;³ý‘F”�yg;䳃cäÓ ¼eRÄ[œ!ÃM¡Lȇ¯yìŠñ$ù“eãrÕ¬û­Î�R7Tb¬cf‹0ÉÈg9—YùF=òÍeì¡Ó ZM�6J8�7Ä| åu«W‚A5B¯˜�OŒ!/õ üAd‘Òo1gº?Òˆ›(ë|if‡|vp”|6 ÁžÅøìÅGfÌòᙜ …Å=˜äJL–dí0µ¨É�"ð¨ ôÁAu['»tþäËFPÁš@Mc̦óÙºÕ+‘zø)¡<Ët~t>!?kIÑÕQg¶?Òˆ€[a�ùlæ:?'÷­eò}Ø»ÌÈÏÛý}ydÊj‘Ϻߚ )>jŒŒ œ©�’†IIy;Ÿä\V’ßjúGq¥-e¶[@Ul.ûìN¬±}ulç³u«W &*('T¥\Ͱó]lÈf§^Ôß™î ùlg;䳃ëØùd@BE¾1ÛòS;ßH½]Èpò·>ù¬û­É�R󌸂`íl®€}좗ŒíH9—•äW½€ª‡ ³Šfüâ.cÀAìe�Ñ8*¯[³Õo"=~R;DÇvÈjB²×³äïL÷‡�ЉÌÚ¡;«Û¡Çȧ*òN‘�í`ò+^“è˜@ò(&k]¤$¬èåtܱÖ;è o®+Èc²6ùíÀІIŽ('ŸÇdmBò›‚m%ÉãR‚«ÅÉï¿:YÒ¸™^è‘9·´­-ÑWk%‡ûjn1ݵ1Y¨ê7 –ÑBOòå X«C~‹®.¶’²Bœ|Nþòu¾&2¥nse®ÌF‚=É—+`­’Îo6›¦ñf³ÍÉçäohLVØÂ<©“­Œ%9gIs¤,Éæˆ]ô¶d‡*sÄ&øKNÁUgm©[�ï¢NY´X–6¥ +¨E—âäsò×7&ËÅœ¼©«Œ%9g©Èw–*ö˜ìPevVŠFG®î ³¶Ô- ÈÇÃv±A‹eu% ”È— j±¥–UP‹“ÏÉ_‰Î'2¶IÊdr²wâ¬2uÎR’Ÿ$I&™C•yRª öÒ¶Ì- ȯ 3(èeŲºPR�O j]—3'Ÿ“¿Tò{Æda�ß*GìÌŠUÆ¢ÎYJò¥´KÌ¡ ÿ¤NËR[æ…í|¸=¬“r±,mJ‰|©ÄÄu9Sqò9ùK$¿wLVÈ‚õqÜ.ëüNe,ìœÕM>s¨R�/µenQ˜üq{ÖÔVËR' T’]ÎTœ|NþÑï“U·¹²õ’ßÎü Xe,æœÕE>s¨R�OÛR·(L~ë¶w¶>Ê{Aß¿ÛÜiIEï„ÓGaêp( ‰@£�ýÐ( ‡À¬¹ fƒ%Áa0µA`ÈâØä‡!4=yΜ—ö´¼/ì./3bh),ûa:g:ßÎ%bX–h@ÔŠ‘ÿ­b*$É¿ýýš,²¬Xz òù¢JLÆ’ÅY;äË‚*…|±¯(‹bYÍ S�óaY¢etˆ‘ÿ�b*$É¿ý¿ÖdÝp ’�䟱VÖ IDAT�þ‹h²Ð�ü$ú¯¡ÉBCò_çsCò‘|$ Éßé & í…ÈGMÚË’�š¬ ,(šÅo>5ÑeíïÉ¿H“õm» mub×ãUý mÀ±Þ Ln—ç2Þú䛨ßS¶—åvË¢©;çIÇäX¥ùK“¤gÈùßúüš¬ÏBŠM…]uèfJ¦®îÈrá7W7Üæ~Ѩ- ˜(6e:§mõ¼]Ù•u!Û;¦+<ú…ä¯3¹ÑzZ�•=á�“ä7…Ç/›Qç¬�XŽUBòï×ç'”)ËfŸ‘_É-FŸNí¿¦Á{j´Œæl=(ŠÖKÈodÆÛéE’Ú/moô}¤Ã¼<ú…äK¹ TG�ì;ï'Ì~Ⱦüm2ï¦ gxOÜ–©Û¬;‚%úI[žëT¶dš3Rôèm¬†ÚòX|_\íðÎÊb+’G>?A¾˜ШºL†: 2¬[ÓÖ”^¹•/e‚¿`ù©j)NGI÷l=ÛpW‘•ìÉÍ{mKy{½™Œvø6Ög¢¡ ³ênºÄ¿iòèRÆ›q#?&· ɇ~Âì‡ì;,Ú&ƒÏ�„3rÞ‘ôùÅl—½U+ï�Lûþg¶N–FËÿÅZ+ä‹ÎÊbë¶CºkäüÞ|>ƒD�?ƒf«Í,iCy>/RjrÌqKë‡Ìøíõ¦’�|~ÓlN †¨¹³`´œ…ÈJÂÅ{m yV‚|¾�ù|J¾ìŽm|ßmÇŽ.ô`¢÷Én¶ž ¿&¿E²ï°h› äGÂ9ûB’¿©gYëzë}IÞ?¶SàåÜñ–Ç*ù¼³òÎV´;òùaôA�œ@ŸíN† Á‚ö“°Î ó©T�õ§V‡g´’|ÒÉ)zr0b‹Y ¸DßU!Ïâ¯g˜f�ïº £J¾ì”jõ™øK=ºÐƒ‰fÜ'ÉßñùÀµï0ôdq~(œ‘óŽšQfgíô«8ÅY–ÒvÊ•ÀÕ–Çj´CX¯Á�­hDþAMÖ Ÿ¿úLw™øD2xËÖ¶ù”ï®>ØhŸ‚|)²p‰^ÛRžÅ^o¸X|±]3D%_vÇ–åÐÑÑåC¢÷Iòeœ?�oª­�¯öÉ…3IŸÏ6ibÑ—ý—!åÊÆÂç’‹›ù…Ò}äÖdíÄù›0Î7XœŸáäKfÚÙ%YÄÉg}W#Ÿ/DV.á×£â|%ÚÛæIŸ#Ÿ]êÁx3î“ä3¹Í´:Øò¦©ä+}‡�|ø² á ‰æIòkÃõªfn‰å.W®4or.�óÛ"Îg §¹�|µ!2ÚŸ‘L“E¶Kíc ¹�Õˆçv6-ƒøM£9_S‚|Á \£ä»"Û×ø·Ütô!�óç"Î"+ ïµ-äY;q>lc}¶)ù²;¶B¾<ºxH4ã>}%Kæó;é\U�vÔ¾Ãðæ ›²ÎD¹��|ÏÑ�ý†[�´QÞ’IÖÍ{ï¡ËÆYq…NŽÓ‹‘¯6DFû;ò�i²Ø虣§öäóõlKtÆ̬óÙ|“’ÿfóSB×5ؼÌm-Ìíp‘•„‹÷Úò¬�ÜÛ}¶!·#Ta ùòèò¡úÉÜÎOر[ãb|Ïä¿Îœ¬ß&íÎÉGM’ÿ¢ä£& íEÉâÏ ÉGò‘|R‹Ð<Ì©¿<ù/¤ÉZ[á«¥µá7*i r°ë2\;&¤ÀjEI?g˜¥UtPH^¥ë˜‚&ò_I“ÕR®¿æÅ5‡f²ôPŽ:ƒrûB“ÕŠ¶Ú󩫤ÜK™Áz�® •ÏEþËh² p•¡ã™!�ð[×HªG`Þ,)DÚºéðæˆ�êk“¹î“ŠIH¹!«F75VÖãÃE«•þ)ë““cÐî’ü›h².øGÇwíä�í;w�0$?KÎw„|»OHϳ"ë‚bäk)XVŽL“jtªîð=P˜áØb�dÕèR̯­ÖXé�¨@Þ €vŸ>ÿ€&ë�Þ·¼ä3B­RÇÑSùEðòô‹9ð ÃhWV�6ýwì)5QZ µ@{È—²±�¼nwØ��oŒ+ïX1ò˹ÕÂÑ6¤7šÖu–¢7£ù`5þåÌyô�_¦½æÜbU£pZ°¨ÚÈ;cÐîÛç'”)o¶ï�ÌîòGzo³h/.y1§u¶âJšæ}€|! 2µÍÀŸ |¾¬)Jøü¯²•öLþ@¾ìS)#Ž|~;ß-¿á4µS;×ÿ06arr,Ú}ûüòjðÊUz°^¢#®¸‚FH³>Œz6Ý7DŠ+â´e´Ã·1Å`$ÊÁJռ㊠�K¬ÊºIƒ Âu^RÎ'^‡+'�‚è£X ׉8_úüDœÏøaW‘þÅC³¯|HaœOfFµ½¶ �(I~½ä•ÕúäøX´GñùL“EÉ&©÷Dð*}þD÷†àÀ¹â pÒ¬­N>�™Ø (®òù6æó)ùRêW¢¯PãÃà¤Ä*æó…œO¼Îù¹>ê,ßSCq~¡-ò•[§½ ÈtºêšC²é,Vm}H虎��d_ÿ"ËíÀ;³éæÃ�|±Â¥q—§Q�U7£=˜Ïgq¾V Ákç‹)½²Õ÷€³�f}€†+÷&6(Š+âè¦éò]a´CÉ—²�’Çæc1ÿ,$Vqò¹œO‘€ òýtm;ÔÝ䯭ÿigôÌ€,S"ŸŸƒ¿±Gz–î¼²É:H\*¼D(€|¾Íòù%úº5�– òå —�¼Ûy²RÝŒv¿äÔdA´³ÈWÁ«Ú�cl×…âŠâ,¥Y¢]lPW4P^,–|×O•|)õ“# %V;q>˜¿ŽB>™æL·R8Aþå×p/éë_©!´�EþaM‹ó[éDðëCS-ª>%ó±AQ\)Ñß6Oúüˆ|)±ÚC>1ÕúHN>sº Tÿ³º�¹�šò‡"ÿ˜& r;ó\!¼ •5é5çÛ¡ÝŠ+ç3i–”oPW±8¶1Å•ˆóAê§�/%V’|ÈÉÈ‹×áëk..>ë©5H¸þˆ|O÷�ÙÇ"ÿˆ& â|³°H¯ Òc �BJ·½@(®Dn¤YP±!R\©¹¾ Wjn'"_J¬$ù ó’¯Ãß=—�y†žƒ�gb­&’ú¨ÉB{AòQ“uI·[Õö^¸½ƒ{'/Äõmcô»ŸMz˜ìÎ[«%?†¿/7BMÖÍÉgÅ{«„öu»mfu»®®¤Áê7$ß};¸hÝ—÷m›�ÿ%µ‡Hþëž+cäCñızšØ6ï}90[ ùÐì6V¢ï_G~jzèÅe÷å�÷´‡|ÿ4ù>’ÿêäóv«PÑ3ãf*Õ¥kêJ. ™"šÕfÓ²å­4è¥Ø òù*ýÍÑySÜR¦AÉg_vñ�nJUJ¾ØClYM#»æä7RVÔKÙÑ,G.íÕ¾¼âŒÃ;ôÔ�’èÓ+Ë¢YҨí`ÛùÙ‡Õ^Ç‹@DÅì"ºí òE1ÊÔ5òâ"„x˯Eþ i²$ùzׯÙÕÍ?Ó'%ë“Ôsœüü6ly+-Û ²Qš$¿? FÆ�wÒ¥äw³„L Ñ´ï×µžÜCli¶ÁˆmÿÐ*Û‰Ù;-›Ó°lCíË«’¯y$ìÓ+Ê¢™Ïµl;¯½N�ðëÞ^T Âɯdê~_¯©ÔK‘ÿJš,(ž0=Öw …Æk¢¼Õ?ù=¶¼•Ov«D;}6?P¥Á;éRò}ʯ¸Â×ì|³'÷[š®¼îö¡Q·K‘½”évy /Ù—Wí¾,ÃQÍȵáv^‡—, +>d)'_¼þö.DÑ}˯FþËh² xbñÅ:¼±˜Û“P`ŽYc¶¼åÖÈ|ª+Ü!}ö– ó¶mÔx›8ˆó«±ùUl&%ÈöäbËÖK§jlyðÌ6 a1%_–m¨}ycÑ�Ù0¼O¯(bä‹ÚŽpåÀk¯“E áuoY Âɯ߃©*'_¼å—#ÿwæd°Öþ|ßîàtNœ¯�_¦?%ù²å-ßVÅ2Ú±Û”è„ä�ì¾ÈÁ°Âgzæ{D[¦é®êóe1ˆêó•¾¼IòeŸ^Aþ\úü%õù’ü„ÏO’/KA8ùâõGP‡Ê[cË·üz>ÿ�&Ë>’T«j-–;·}Çž”";Vœü¾¸¬0K�/f¸Ü$·#ßùUçÃ+Š–·Œ=kÊ2Aá wÊžMã蹩�O2޶gÆŒtiœ/ö[úS²â+çû"Îg½”Eœej_Þ$ù²O¯,‹f¼¶#$Ÿ×^'‹@ŠY ÆùðúA¦Kÿœ|ñ–_×çïS¦$?“ƒŸŽ&¥X,O�_-œF8K%ŸïÌrˆÜçëm¿iï’ϧ_IE—˜Ûu‡äoÜÖÅ[Ðî×çóë�é)Væ±h§2ÉlS«òêèS‘|´?ðùGædiùóð=0òjiª÷T]Ö.ùÕf§Œä£Ý…&ëDg¦$ù»– _Ñe!ùh÷ãó÷k²„À ªhÖÚ6f%ú* ‘U8òªïÐgCôEò£Ù°¢^S>õ«h8õl¨»BòÑþÞ竚,!° Éç}Œd_%!²’ãOæú?¿™Z˾HÛŽ:V�/ŸZ)læ™l¨»N>H>Ú]ÌÉ2MóMÛ‡äó>Fj_¥N!$¿ÁÚ¼)ãb•Ù°B—%Ÿ …ÿÍì7tW?Kþw—í[Ù÷é }³e3’ÿëš,k±Xl¤À*$Ÿ+ûe_%!²’ä³~cù¦:43š +tYâ©kmE_#û ÝÕ7ɿղýùç·lî6’þgäŸÒdIŸß(Q"òe_%!²š'}¾:.VΆÑŽ|ªðù—ë®®"ÿúeû)òÏnÙŒäÿ!ùÇ5Y"Îg«�½&Õˆ|ÙWIˆ¬äÈ«™Þãq~H¾2V0!ŸZãü uWבõ²�ýU‰V+^ÊnIòÏnÙŒäÿ%ùÇ4Y.°"µt®‘/û*I‘•yõN!©#•ٰB—%ŸÊr;î7tWß$ÿVËvF~¼ÕJÇž­ òO·lžõ7]$ýÏÈÿ[M‹|~)Ú¹á²]î![­@¯Ê±$ÿÒ–ÍhDþŸi²>Æä#Ýùmòo³lO´Z�nÅ_’ü [6£ýù¥É§ +úËäßfÙžhµRh‚t>çŸ×²íÉâÏíùW.Û“­V:Ù ©Äs;g¶lFCò•ü+—í;­V<'ßTóùg·lFû³¬&j²~ÞnвÉGM’�ä߆|Ôd!ù/Jþ¹š¬³fWÍ]ã{ÿæoOÆzòÑîÔçÖdé™ÎA6í½É‰š¸ÒC×y†Û8ÝAþúÉXH>’­ÏßQ¦ø›¶>»Œü¢¨GtZþ¢{ÆÕšë'c�O~=,õ0ü@òOh²ôQÁV#mÂŒ+~— —�fÛ‹G˺Éçh±ë9cm('Ë—ëd©5ÈÌÔéYÌ®œŒu6ùk+Ͳ´6üF%­ÁYm]6Ù8Ã=ûèô 9Ã,­¢ƒÂð¶t/?½€Ï—Å]~G›D[îråzá]ðùÑl{ùhè󷙺œ,ßΓnº¿ÔéY*ùß�Œu6ù-¥FH´;'Í>‹ç*¹åÌ¡ßÏBsKO?¤ÕžO]¥®¦”¬é Rùü>ŸqP�Ë÷]6g[Þò£ÙöòÑ8ù9>u²Âœ}µi�ëW§g©äw2ÖÙäC‰é8Ff VÊ9@~оxÓ¡»D/ÜM‡7GlðçX›ÌuŸTLzkÈŠåM�‰n|ã¼Ò?á𹙪=F»_ò�ÍÉZWŠ$*ØB™axÈ�fÛËGw|¾˜,Owwfî$=¼ùd¬³É·iÕ3Áìƒ}ƒwÈ×R°¬œĪÑ¥îð=ð7;4š³G²by)¦áVé_H¿´}k4²ªöínÉ?®ÉÚZïÇ|> gÛïõù؈Éò¤T³IÍÓý›OÆ:›|cD`¶)³�#¿œ[-mCz£i]g§±ws嫸¶0çÑSÖ2í5çF�¬XYÌ/ÂáSŠöíNÉ?©Éj¸QÁ�óå].Ͷ—�Ær;4°—“åIË(‘w#Mƪ÷‘­Bë„ÏwE|Ÿðù_e+í‰Þ@˜]:0•>‘Ïoç»å÷"”òÄä–°±ÿalˆkÑ3Vj h�Ñî•üSš¬ÿŒ~X°ÕH›åmX¿Ãå£ÙöòÑ�|M3²�Ï“åɇÖ"k½‘_hì#ÿZ…Ö‰8_úüDœÏøªñ¢¥ûjò)Œóéj¥Ú^[•ú.ùõ’W&Ñßj�Ñî–ü¿Òd™Í/|n*ùMJû{jH Î/ˆ”©¿uÚÛ€L§«®9$›ÎbÕÖ‡ddvYŽGl,²ÜôÁ²�q¡¸_�/V¸„|pJ¡q>ù¯(Úc´û%ÿeæd­­ÿigôÌ€,Sâk—ƒ?ºGz–îРm“3t�WU4ž×—‹ÈçÛ,Ÿ_¢ëƒˆ ep¦Éå@Þ‚í]ǰJªöíŽÉ™9Y_ýd`c¥†Ð>ùOü¹ýZÝÎÜøÀÉ=ò=ÝÃÏþ±ÈGMÚK’�š,´—%5YÒÞ³ñûXzóääsN–�ØÝYkìc}5!W9<�ü2¤�:û.ÃúÕ4Ë€¢=�Ï? É ‹]9$A‘ä'[c¿´þÇÉo±ËSç“¿×6ÕѲ¥O‘Ðgòù eJ#3ÞN;äûqòwínÉçïJèl f®V »!ÿ'FÑo»Ó'Ý ßy툞ËI5M¦ƒ„>“ÏO�_â×f˜øÊ/˜TÓ°&ؼú¼TËë.oŸ$ºd …Ö}“/%4’|Ñ ¹’_ÏÒ”üÎgÐ67ÜçÓ?Rô\N¨i–ú }NŸÏQM³9�+òàóýözSÉó&Ø¢ú¼d�¶¥2'ŸwÉ ­ïÊ©~œ|Ý4ݰœ:$ŸwC†憈vÒ£�|Ñ3®¦ñs(ÏzVŸÏ­“7RÍ(Ú ›`óês8%ôN>ï’)´îs…ÛX,–¡„&ŒvànGŽ."ײõwI¾ì¹Óø…Vß?ù5YÔ‚®>`ä^Ʋ5Ñ!�WŸ‹^”Œ|Þ%;RhÝ'ù,Ú‘>ߤç¥rH>1¦ltÑ F¥ßw|¾B~PÌ#øÏ@þaMÇ…ËÛÙ%Yhao¨>WÉç]²I¨Ðºcò¥„&פ˜GäW*d“Í’qjCzÚ;?3°8Ÿõ\VÈJ¹¯íû0<:ùÇ4Y�ËMG2ÔëÖù¢ú\%ŸwÉŽZwL¾”ÐŒ³n¡‘ÿUÌæ=íÔ2ùšóN¦ŽQb¹ÞsY!Áª¹±_ÏÓD“Õu K ¾Zç³ù¦ _TŸ«äó.ÙŠBëÉGCò“è_«Éº£Ž©H>’>úWk²�|´G$ÿzM’�ö�ä?ñç†ä#ùH>’¿7ÒAMÚ ‘�š,´—%5Yh/Jþ9š¬J\©‘Ôí1 ŠfQ½ßúNsØkÇe!ùHþù>¿&+€j­.È÷ºiÒ�&¿—•\ã‚¡»í‹È¿Ù¸,$É¿Üç'”)yêç«øQN>m/ùMáñ'zuºæ/"ÿfã²�|$ÿrŸŸ š ;mö¢©Èº½�Y-S·ÙÈ‘|QF;U#MŸ &eÉçO\#­øÄ@¬Ðn3. ÉGò¯ñùLV50‚•µ5ƒ•6cä EžÐííŽÈ’>_ï òõ¶ß¤O“²ÄóƒL=èµp V’ü+Çe!ùHþ5>Ÿ™¯�þ‰;úg±®Tä ÝÞîˆ,AþZvöh¹ôBÂWiÈç�Ì€�bmw ÖmÆe!ùHþ¹äÖdåµ&©5j%N>¯Q—º½ÝY;>_µ‹IYân�Tk»±n3. ÉGòÏ$ÿˆ&Ë+P¿Þ+¸M•|©Û#;#²$ùQœÏŸ &e‰»Òçï ĺ͸,$É?ýÚ,Ò7(¥_&´URȺ½ÝY’ü±^ûs;ðUᓲÄ]%Îg±n<. ÉGò/@¿&‹ltðæLNSȺ½ÝY’üX>Ÿ>ALÊ’w!·SöÂ�X7—…ä#ù ÿës² aKÂ[�ËBò‘üóÑÿÝ9Yƒ%y×ç¿ô¹}ŸüÚ¹Šb·»ÛÉ#¼�Bþ/ÏÉj§ŒìE|¬÷‚Ú&÷\ò«àêç‘?ƒ¶ÒÓÉ–&IÏ�è{$ÿ‰?·òe›Ü³É/mOt×I�¿kH>’ä‹6¹dY4¡¤‚t#3 yÚ#—ªyÇ¥�ØTX�°fIôT†µ÷š®ÄåŽoi£JÉõYͶ'íˆvÍVÝM—|$ÿ>É!MV¬Mn®º™gÞHϳ�Àñü�1"%{Ije(°ðûzŒ|ÑS9$Ÿï8Óû~]ëÉú æó)ù²œÃ*ø¾Û&Û鮑è;#ÿõ4Y¼Mî¦97K¤ÀBø±AïUª¤ä±&¹#¸[äë¦i.eÍ�|¾#\oóMíT!ùòÒžÕg•hwJþËi² MnOÏd2v�uN$¤—¡?êEÙ6NX0ò‹‹Å"�=•CòùŽ5À:Û“õ’|YÎ!¯M Ý)ùçÎɺX.•È÷í±ÛÏ`;+«é4'&_µ&|>z”"¬ÀB‰v„Ïo”è:6"¿×¬Ï˜'}>’ç>ÿÀœ¬7MÓÕ±8 òíá™ä³Élû³Ü‰lÝâÂþaòÃ6¹Õu0’÷ ÏYœ?¤p  ƒL—úïDœÏz*ì5©FäÏŒéÒ8_Ôgl´#_–s ù�âóÊ”7Ûß´õÙõäÃd¶£-çƒß#_¶É]–R†Kogt%·Ã�&×-”ã¹ÞS™ÔÒ¹FD>é:¹*�vD}ñLƒåvD9’ÿ(>‡|zKÿ%éi³²•wÙø¬H˜ Òb™<™ïc㪪£™2;ƒ ˆI+_Ìf,Ú)UsöØ÷l³²þ òÑ�üc>Ÿ%)ù~G›DI:w¹r½ð.øüH˜Òâ™<™ïSÉתÛFa93G¤¥ è‚ñ‹‘oÑÁË}nŠU2ëoºH>’ÿך¬7ˆÏ›Qý½ÕeYyÈ�OÆbƒ´x&OÍ÷Ád6Ó£äÓ“ƒAß{¡EZPߟë0ò!ª0鱦֯­pÑ�ücš,êóוb¤¹²†ÐW!¼ äGÂ,u�hªD¾�‘ßX,_|: l¦Ar‹‰ Œ|2o´t&“1$í4Yço­÷c>Ÿ„Â,u�hªD¾/ç+äC=Û‘äsüCŸ’�äBÿ°&‹­pn”¤ãq¾¼ �"a–:H‹’/ó}Jn'F¾Ö :Æ*$ßËÍÉ¢÷Óä×ÚKç\½<ùG4YŒüÿŒ~˜¤k¤Íò6ÌÙÁø¬H˜¥Ò‚LžÈ÷1òa½à$¢�²½w$ù¾gë™Æ“¿¶ä(g²´„¦’Ö:,iišðwè;¥‹•‘kùitPx{é:ÎC|.òÿD“Õ*üÒ禒ßRº~æÅºfŸ]««ä–3§Z1zz¢KõÑò³æF{—2ƒõ �™ù'#ÿ·5YF>“@òªd¾ág$ ?EÏNM‡¥�¤5�ðæHÿ?Ö&sÝ'“�rC^·ØÔØUh*+ýŸ›ÑhÊ2n_˜�ä?¸&ëÏÈ·ixÅ«’E�Z‚|- ËÊAÇÃÿRº"Ī;"G«zÇž{$¯[,5A}[3OúÖ(hdÉØ^’Ù!¾{òŸøsSɇæpÁóÀŠ‘_έ޶!½Ñ´®Cžés\�z~ÖxÑQÎ#åú2í5çF�¬@Y,ù‹pøÔÇÄìûø¯@òï…|ðù®ˆï>ÿ«l¥=“?Pðø"ØXïúüv¾[~/BiN²&ÇéâZ™L&5 m×(.ñŸq×ä¿�& â|éóq>ã[”“ùÚl'Î'3£Ú^[0F#I~½ä•IÔ<ˆ¬ (I¹kò_I“�°xU2ETô&÷·N{�étÕ5‡dÓY¬Úú�t«�”b¦Ä—�åv jÓ6fÄ…b}A¾XáÒðÈ€S �óÉÝ`:ðý’ï俌&kmý'«’—)‘ÏÏAB«Gz–�P69CÏv édt³0%awOÈçÛ,Ÿ_¢ëƒ(eDM¦ýólï:†U"£¬aVñ½“Ž&ëxߥ¾mŒnü÷w¬úM¯áßv¨« ?IDAT.ø«*5„öá|þaMµá们€!œuuÅûñÅ1Ú ò«ÍNùjòÒæÆBû°>G™²eW4O“Ÿb§üpÖÕ ¸Ù¾‡¶ÒWLýÛnƒ#ßÓ=döq}þ>M‰ú.y¦ÝÒÖDè§xŠÄ6‹Kâh–#veý�…¶¯U¨è™q3•êFåK™Sa‰ÖMé!éhcÒVeº)øûJµ¼½œDG¨»÷ùhÏáó¥&‹¹gÑw©“žoŠ”|¡Ÿb»YÓM‰®M¹Ìcä˾M-½ë×ìêæŸé‡i}ÂUX¢uS¹N*iö+I¾5Ú–ÊaG¨áäc€ä#ù?îó™½i&µµì»¹ê %_ÑOAvüSûJ�/{xÀœ¬1b}¨q–hãA�½Ó*Æ»�ŸÏz9ÉŽP7Yáž²ä¬S,½ynòk²¬µ°ï¤û¾´µªŸ‚‡ˆ>I�/û6AqŽ(MVbiÙºif,íµ•`IòEÓ'Ñêä;Ñ‚ý$ùì$ÔÙ{¶ NôñÉ?®É¢&û.…>?ÒO�Ï_öùùêC±½2q½X7•üÉ¥Åcä·¶Ç—ßIò÷Û`¶Z=$ôÇÈÿ¼MävÙw©Æù¡~ªcÓ8?¿/·¾M ùêCœ|Ѻ‰”Œ6©ì4ÝC¾ìuòùu[ÑCE_°ŒÕ‡QÏÒ…†œoM<[wú¤£v¢±—S¬…-3¨ézxò�i²Xf½+û.ži75?¦Ÿª³ÜN‚ü(·‰o•‡8ù²uSKû ï]½Ž­í>òeG¨›‘/›¦Hòµ:ù4fr¾5é|msÃ}>%_,ÄålžÁ4µ4–£=>ùi²Æ©ûƒ·q£ÇÈ×MÓ ô!ùôë—{“ó­ùÊv’/‚29›ÙzÞ­n�П²·�j÷ Éò{ÁWáîyÇÈo,˰iJíÀÝŽœoM:®eëï’|¹—sÃU.^·ú¹ÿ ŸÚv³Y¯×÷ Éò³Fª´zdòY´#}¾ùA×±!ùr¾õÌ K€ôûŽÏO’_BB˜| þÏ“ÿÄ9±]òeÓ”\“b‘/æ[�SÒÓÞù™�Åùl!®�¿nÌVoz?i$ÿÁÈ—MSÆY·PŠÈó­I-“¯9ïdê%–Ûá q…ümÞÔ1µóä¿�& íQÈï–˜u’ü×›“…ö>Ÿ¡ßÝü0ù/7' íþ£�.€ÿãäŸ;'k×¾;ø~«Ÿ’yE;$ÿ9âünwóóäÕdåÏ#ÿÀàûäï™ Å$ÉgoÉÇî_h²ü È?ÛBòw&hùW“ÿ‰ä#ù—úüýš¬ãƒï§9#UÙ|&ö�¥aÄK1i{™vb§ÄÔ*T�tÉGòשÉ:>ø~Ú÷?³õCƒï×|YÖ±gëB‚|¹‡'£½í7mñ6�|$ÿ/4Yog ¾ïN ¾§{ÈÒ0(óKòù­p�µ$ß…. _ßùƒõNHþ£’ÿÓu;'5Y›ƒï—¥´�r� ¾{È‹¥BÚÅÉç´Ô=¢8_)“ùþç&ÈG{XûCMÖñÁ÷åʆtÜcƒïÅ’|èn9�G;êóÛ�/Ï•œ|´¶¿š“ujð= ^69÷Øà{±‡$¿“Ý�J<·£îÁôpäwÑ~ÎþhNÖ©Á÷“¬›÷ÜcƒïÅ’|â9ù¦šÏwb{°=ùËÅ-mÙ_ÞìH_oO5'ëG×Gj½Óo‘¿ZÞÒVýÕÍŽ„äAÿ÷çdýlf@©wBò‘ücè?G�ríDõNH>’ÿRÙà°Þ ÉGò_ó ན_­,Çúyä—¼øï˜5sHþ·#�'Ñdý=ùަÙú"¼?J Ýf+ªž$V_.­ÞAòbÖxë/¹ò?´üväñC!ùÇ®á>—&ëùUMÓ3Õeô€=ŒC �´Òu?¼?ÓwAßy,N~c1nÙùÃä[sj¡ÏßÅ5îóé¾fg>ÿ¤7“’AÝÎSi²N‘_ò—ƒ\zu�üRfð5HW®"ŸþèS§ÞÎèVΖ5·9ùü÷ «çJ,Ú©h)«q$Ú1;Œø¡¡[F~ß52]•|íÌ †á̇BòϪÕ‚Z�?vœüeÚ[vŸïÆ;÷ùâ¶Bþgº¶èê<Î?æó#òCŸ?5šŸÿŒqœüz~þÙ_<¹Ïï«öÖ�ÛàÑ,ù\hÇž~€ü ’&ýí"[ç>_Þ¦VwØ/§!Égþ½¥õƒ¡¹’äŸá󗹪\�†ÑŽˆSÚšAmÖ7èR ÿ-òëð»ÐH�Ÿí¿X´3øTxÔ |^eñ¿7þŸ>D¾ç²;í|íÀmj5þ+çÅÉÏÂc�Kȧ>ÿ=gYF•“/nsŸ?¦¶ìdèíʷȯétÚòâä/ªvªúùääÇ>õò­ïZòãÛC¾úͨ–yùä¥ÑĦñ›¼M­îˆúi’oòOÔ_· +6ˆ>gÚŽör—ü�ó­Æç²TåiKq[‰vú&8nN¾}ùMéóóÉ.ÏjíVâPOJ~É—o÷"ò7v�”+k(�fäËÛÔhœO@:3!…!mI>Ì|Évd3ÎSä/ÆmÈíý娬.gÚ8¼åv>?Ó-z:àäg›g‘ßI/Øï‰Ù\,þ�8ùC8%ÿm¸œ¦Û‰C=ù>³n‰ýÚ!ß0»–|8F©+vŠü’¿‚ÜŽ,�& ™”·ÁŠ™Áz�¦ß¯HÖ®KÖÚºü·üޱ’Í8Ùc‡É×4�åó[é\¡Hi¯šÆ@Þóù­å ëæ‹œü¶eÔÏ ‘7,žÛÉfN�Ï’ý”ü†­§ªÉC=%ùÝ’‘/Ñ?I>Ïç³¾š¬¼úÍ6šò6äómÏ'd•wr¢þzÜÊ— ˜™"šq²Ç’�Õ ?K>$"ùùýSäÏNµ¾Bò‹üív äë=äoÊ®'ŸÈçCòŸ™|FL—“¿Ý!û`v-ù[F~WìoÈ_ÞÖú·;Ò“‘¿ë–àçò7eדOõøü`?Bþ)»5ùƒ›iø\ä fø{‡ü̓ٵäGìoÈÓÀâV¶\ŽG·9=ÒäÉÈ_GFÉO’°~(»žüØÁvÉïÿÂeèɰ;N¾nt¼á€#?FÎ !·¬Ìú×µˆÿ½{È�~üÑè íÈŸÇíñÈŸ_e'Éÿõ¶!LÁÿ-òÑÎ5äæ©ÈÇ ÉGCCòÑÐ�|44$ ÉGCCòÑÐ�|44$ ÉGCCòÑÐ~Ûú$ímƒä£a´ƒä£½L¨ƒÑÚk†:í a´ƒä£½N¨ƒÑÚk†:í a´ƒä£½N¨ƒÑÚk†:í a´ƒ†öj†ä£!ùhh¯Eþÿý?4´W³ÿûßÿùŸÿEC{=ûŸÿ±¡JÕ-_KIEND®B`‚TreeLine-3.2.1/docs/treeline_ed.png000066400000000000000000001027571506556630100171640ustar00rootroot00000000000000‰PNG  IHDRù²xý1åPLTE‚   -ø( $  “#2$*"$"%0 +<$—&(&*9$ý'-3#.=,.+2O9*3>@?(4D131Ý 06=ù7µ796/:J>A3>N-2ÿ²2;Ÿ;AH?A>7BR+K';FV@HOXFHERro@(Hɤ/0DMYNPMCEÿ)\W3]2JS_MT[=\9UWTNXe6e7NOÿR_T#r%[]Z^\_?c‚«GI l˜X`m^`]B^Ü[ah0oa»Íû¾óÿ;Ï<ï«yÞ÷—~é—~™èW©¨FF¯YIaÜ ô«Ÿšù©_‹÷@ÇðÇž= š}饙ӧŸýB'™Šj•ul¥“ïþå_úåOa†ÿ/œÄà¿ô§ ¿š=}òsz2ÕªëðŠ'ùt/hþÁâ¿ôôÓúåÊ,|€Õד׋î¾{‰ùwßm$]hÑÞ/i§î^¤ðÝ+rä#¨ÉåLÞÓ5Ñ’ÿ“�¯ð$üŸœý2¶÷³Äð¿tú$$¸{ÔµgÇØØ–m{î¾{ë8ÖmzÞþ‚[·ÞÖ—ø–NÁ¾|Hغg�¿ÕnQ;�ãb{vi‹] Xg£ÆNØ,ýë�Ü;´«{Íãºì··UÛОaw„4i~Ûµk×n›d»Ò»LY“÷ìNï†ó³{™PcòïÞ:ÿ§ŸÞ+/a—çô—ÿêôiHúž×m[ÌÌÍLî¼m|’Ô^v’éáäÖ¾’›Ûhëm=i7Ü�ÜuÛ üÍ-„&Ç÷ì?¶ÓfQ;�ÛõÖ={v¤Ñ�­.fnÔØ ›¥­û·ç¶�¡äή5Ö+m;ìvNÅî· 8òQ×ó¨w!Ô9-�OÑNkòm)$ïºí¶]2Jië!Pc?ÿ6¬/Àÿé¯}™Ô«O‚¾<Ò;†äÃ3hç[ÆæPóܹs;a:s¬ ÈÞvÛÎñño½Í˜âëÿÖã;o»lä}é´{ü†Û¶Ž¿e|œä“o;µL çηÞvÃîù1ÈÒ“õuŽãr7¼þ�D˜à’°†q`wÜR2H±mã;ÈRLŸÙzàÀ}'º–Þ¡í£ž¥ÏݰóJîè:úÚ¹s�?wŽì·¹#úNża¼Ë‘í4„e€÷–]3ÍìzKO²}éù;¬Éo…UÌì"Öd ÿ­o} þOüMýþéÓ�tï[F[7lA ›ÇƶÞp¾Ì›7oÖ¦w£¹ÍoyÍÝ““©-7SLöXâÀ½ã»žLí¸–OΡÃvo2Lâüqò->NÖ ä�A©q’µSKÖ×å a×–“{ q,>9™#%ÇÆÓ‡˜]KÉñ`|€óôd|÷�»wèÅ´œ­íÄëÒ[ï�<<™׳Ƶ9Ø@%·vÿØæ10‰›7“ý7vDŸâS±&ävŽÌ(4Úú”~}wÎ`’gvÞЕ< ôV´•mí[‰,wVB ~+�ÿ›7€î… ÿøéãošÈ|uvö÷ßtú4$Ý}Èk¬…&ã;Æ®¿aóÊ&÷ŽÃô@ü0š;ŒæfÐÜcŠÉN£cã;Ús“ÇvìÀ k£ós ÈQÚs8þç„vãÌùø–Úc&›ëBhn-Ì@â.œ8s Ã%á¤BÎ�q£ä„¶3æ[Ë!ÅŒ¼Qm'Æ»–ž;69ƒoÖ÷O›»“?N{Ùrð.èG ïˆ±Cp*ölÅb=2soG[÷j“ñcÛ|¸l]ɃJ£qˤSzǼ󔨓�u7üŸþÚ×Ncòìý_þÇÓ§õä‘Öx¼qtlë¸Ì öfmÚÚ=¾ z¥�)\ûItø5ã»ÑäÖÍc;ÈÒ›Á›ØŒñ;0¶Eç#¹yÐ#™@þŽßܺ«½ÅH3×…P|³Œ&7@)Hœy $îßÕ†ïç¶l>f) ä¿“ ê–×@Ζ­¤˜>C6Jvb«eé-×�mÙ¹«�¶hYÆÜõ„|سëwîÞ½{Çõx'w`ò·iG`ìˆ1ÅäãâÖ#ëìíh_W<¨È€ ³ãØáñ®äA¥Ñ¸eÒ)m�ßU“=hüŸþ«?=}ú$�ÿñÓ³_?_Om�o‰˜‡+ —9½{÷.ló“;îFí­ °’ãItؘµGç·l{ý–B “ã¯ß:þúë‰}=äìØ¶Cçcë–$¬ ¯“ýõ[€ñ4’Íu!𜎡øXš$¥Ç d¬éxÚR“OJ™9[¬Åˆ Fv¢+ 3qWIÖë�¹m„||Ì{`vÏ89~LþVrãÆŽSB>>ë‘™ã£}Yuð¶��ÃŽ��oëJ¾~LWwé14f™˜É[üøÛ±Õ’LÈ=hüŸþ¯ú¤Nþ—ÿô¥Ó§!é¶×�¸¶mÛ „‘GûØø5¯'Ó×´Ðî=hfóØtÀ˜Âµ? dmÛ�œAɱ]»wlzw�a‹¹uÛë >Æ0xÕ˜|ø”ãf²¹.�ü=„iH¼{'”Ô LZJÂuÛBlín$o&_p±ÎL›¬ï„ué8šÙºh&YãÆÜ¶1L>>è�wß}÷Îmä`òÉn7vÄÜ!|*ÆÆÆ»ŽÌÈÜ6Ú×u�ù “ß—<¦Ý¿cÝÉ€<‘‘¾GG¨ßJ>´ƒ&Pcò¯ßº þOŸ~ZÖÉ©rúôiHzë¶×t,�sOȇ˜NC­­[T”¾÷<ÚmLñµ? ·È®ôî]“(^ÅžqÀìXj'ιf[xÕ˜üm×ì„<3Ù\—•ü-sí䮸á]¸äxü$¬%çÐäì‹@uóð$þ‚‹™3dÍd'º–¾ð<€m>ÎÚaÌ]ƒÉ'»vÍøøø5Ú 0É¿f›±#ƶ=sø0L­Gfd^3Ú×õ6óÛØáÃc}ÉùÝÉcFÛΘ5yü^`þšký{ÇI�úz ÿõ×€Þÿäå�|òMOi�n‘NŽ]ƒÉ¿ˆŸîØ®«¯Æíajb̘êæõð.W ¶`pÇ!¯­Ý×\ÓÅ^5&l,5³¹C¾¹. ³A>I„g).yåîy$OZJ^½§…fô„…Ãøq�‹3d§´�èZv�·CË2ç6cò{O�µvúŽì¼RŸjU´§ëÈŒB#~]-à��õ'ÞNwòØXwºž<~ï8�q5L,ɯò¹þ?o�ÿûäø<$ý樓õØæ-àðÀ‘mÞ|%IÙL„r6�u¦�xõæÍcWoÞºc ä“ò�Rœ|âÿ±ÍÚ‰ò�¥6Ï$µEµdËºÈ ÌÄ×lÖJ^9†Ý/KIHØŒ®Þ¹yókf bŒ‹3Ú¦ñNt/ û¸eÌȺҘÛq¸†’Wöž²óÚh;rµ9ÕNÅ•ÝGfd޶nXÆä«¯¼Ú2Ñ¡þuLþÕ ëáÛ‘Ó§g?þ¦ÂÇßô¦ßÏÍÙI¯¿z èÊ•Y`ìÀ�÷þ򿯡kÔK^i¿µ±Éó3硞q%.fÌXJ ZÚ¢­°C»¯îЮ\Ö¶úº~“ Ô„ü+AÛðÇ5Ÿ?y’˜ûÙ“'? I¹rë×6oþµå[ÛÎä�ÔîÍv3Ckó²îÐHkÛ &¨ ù¿FµÂÜÚÏP­¾ùõz]¥¢Ú8â)ùT”|**J>Õ%¿Âªj81ÄJ¼YUô½I…©­ÔÑ…ZñP§aà~ÄbKÞàÎ'Õ2’ïa@…Zj‘KÅEX“|)£–Y»RYU­2òpäÃf9oR1çíÖ¨¯BSzHòµãYú} Èfye¢x¡…UùUqz©äGC*>QJþe&?¥(J}Qc AÅ$§QγòÓJE‚&_…M;2ú.C¾y<æaE¾èÄå‚Ñ!Nd�UÔª“W¬øRò×ùi«·#º9ÙöR�2Ó¼#Ro©°�!ä×"gLQëqÞ™ò•¸“×úɇ�猇’ª¶Fý{ŸävK |°ªª9ç+v%Ç…mWl– EýBÑ™r±ÑŠ� ÀÎy|€QÆ!ô1"p”)·õ4TX¥êtÀ¤÷„øj4O�ƒÉ¦ÕXX­»JŽ�; ÷ ~¨¥m¾~fù~¥ˆSFW•|–ç½ùAìð8ú¬9áýj2€-ã"ä×Ý"&ŸE�ë]òy€LrÚê×|ƒp²³ÆprùØ·iFÆ{¡º2˜¸`¤bãí�ã1J…ðœ°xÛâ�Y›·!¿ÀÖT_¢ë4SbØWêg7P=R>Rù€ì„G-r ©.è; 7L4å¨÷û�ätr@¾~fù¸ï]”ÑU%?Y©Lä{.—ËÑKE4X©Tªj nÏ"ä«¢ ®x��:_�W=p1e¦Vc`•.¾>ÈæOù'ÓÖ¨·'ß+Â[ŠEð“ÂÄUB¼[ì#Ÿ�Q*„ï#'v{àK*.˜ÛédÛZ‚K¬°Ó]§!”ˆ¦c©~vóœì¨×x™‘4òaÝAÍzðYˆ; ÷�§â+õo‰œÎS1Î !¬E‰¥Œ^6o'˜X%“Ô „+U±'¿îIXl>D l>W²¯áê~¾�®«à“5ê߇µùpH9vÚö–2m~ùioVbO~ÂOm,§!ð”³AW_Y…«¯zÕJ~ÏM›ÏA�ÅYe ·£ŸB>Ü-jó/£ŸïœªËbݾm§Ì•UQóóký�˜|5Ãé~¾ü|�¢F°Ÿï¯¨ÓY»¶� nÛáŠj…�ikÔ¿_ÀÏÏ~¾X;Yàçk¥zÉÇwD È÷Šý[©°˜?ëi(³‚ZãúÙU}<¬.ʻȯ»DXÂôóÕ4R³¬pÛŽ~fùÞªì¥~þålÛñ°ÎPù¤A½ ™¾¨þKVœï3å˜|Õ‹Ûv¼ƒ´í¸ýZÛŽÀº’6Íî,iÏ]þöÆñ�ï¶äׇÛv²¨­â¢Î%hÛÑKõ’_ x`§5ãäR}›ñcG½ë48R¯M£cœ�çZ†Iu‘¯J>_03w´ ù561˜|ýÌò“..LÛvV•|ªQ�³HÏ%Ÿ’Oµ äk¯,º3D³ÔË-¹ôRVk»¬º¤=ZÊÎ_ÔnÙ.Jɧ6ŸŠŠ’OEµÌäW¨¨6Ž,ä·¨¨6Ž,ä/PQmQò©(ùTT”|*ª’TÈö© Qò©Ö;øEÙFEi™ÈoRQ�¦ ²\í“,.e�½äOµðŸ¡Y¬“§N™[¦C8IÖ8k»¾íNžY‘sWŸ^Rñò”²Xö‰o>ÿü3gú’kGž=þìq|l Ïê>Žîó:ðôüÞuG.æèŽýùçÿ\Ó§±õf|Zס!ùü‰çŸ?aÇ@C®TäF_rƒ³¾ Â`ô³ËI~«…ÿLòÛÍŸ=õâ ôO>Ñ›Žw±R)—%©hÇÚ,ªÕjgÏœœµYŸŒGw›Ÿ_ò+µÞ”j «Ü_´:=-å SåééšýºÎ<óÍýûŸyàùç»Ó�:vìØÌ±Ã5LþÌçºòºÎk-³?�W¼êŠ+ž¸ˆ£;üÄÑ£O€#Ú¨7Òˆ¾1Üϼã}ûö½ïŽƒ³=çJ™Lv"“)*¶ä'PGËO~¨@>Fÿ¤-úsGNž=¤vÓ[oTòU²oµ|ÅŽ|L÷Ù“ó'û×7CÀŸ?¶"g›P\>gIQÈïr?úÅR©T©T ¥RÑüüæ7¿ù̃ß|p÷þ:6#Ï€Ÿoúô¼3²/lkãïU¯þ½ë®[üùúÕ¯v>;¦ýQCŸþèÙÎ>‘ÄϯˆÍÿ‡'?~º1(÷¥/×áÏöüí»ÿ{gæçÏ>¿ïŽ“Ý,f³•s �êDF¶%ÿÈ'tYò{¼L>š?}òä‘CVäàÁƒGŽÌŸ={äH×±Wu*«‘/çóî�Åæ?täÈñgÕúÉðÏžï"ß\ö4_´?ÍJqªTš*tŸ,Ë‚†ÍW+]O!�üJúSÅâD>ŸŸ(K¶kl`ðýgžy k‡ü¹ó35¹6s¼ùé·¿ýÑÁÞŽìóÛÚøë^õªW¿êŠÙþÛ¶s0_ýÛ¿ý*þìAÿ埓àÖ7¾Ñm<~þró8àwÄyvÐéÞ‚t|ù_žþñ¿ Bÿ'ÿðÂ_þà ¥Fÿ‚sûö�>}úĉӧg¹Ãz¬j¶ ¨j¥¢ªõb¦Þµ Nþ'^¥ëh5¼ŒþüÙ_´Ø‹'~úÓWŽ>q’ÏžýlúU¹^–²ÐtÆžüGÍÎÎ9r¤×þ4ŽaðÏ̶?Ñõ¬\*Ø�æR^Æq‘òD¹±ù²RUºnŽ®à+r©4=-÷’_,NÉ6kœ}ð£ûuô|ðK�G�Íœ?/Ï�7�¿ý�{;²�!Ögã��«ºnÿèãÚ§µÄsÏý>ŸÅ®ÎÞ½{»œšŸ<÷\óx:{ï¹çžo 8=…þºb!aQÁ–üç^~á_~©1üçà¯`CþÁûO€ŸûZ–.eep?ªÀ§ÅÊYÈ_Q›oãí`çÈ�zÈ?z’ܳO<ñÙ£G-×H®5ΑᔢhG~ûЯœ9sæ•^òˇ''1ø³sžî_PÉJà€Ø ŸÏfsÙ,vO²ÕEÈ/ÞuW<È3GicÉ]è0óÓ}ÆO<ðþö?(a«ÿ`£‹üÿüùó“8é²Ï‹FÅ~ÿÄuW|âü¢äÿŸ¦ºÉ£èÓŸþ3¬ot�ÿòs8ãV¬äÞðïúÐ/üÊ�7ÿÑM¿ÂÚ’ÿãú§—Ÿ{îe;«ÿ“—_ø'øû¾ ùsw„Ú-BgŸ¼£óäod$ÜbÓô«U)£Ø�¿R~~kjÿÒÉÿo?úÛýÛ¿QÌd ÿˆö(Ø÷è3£Q©VÊ8È…\FLO˜ÉÓÈXáÜŸ?s╟¾òÊÑ“‡ž™­=: ^ÕÉ““à(K½ *™<æ1[8×èV)]˜®)µ©ÌÔT!§6ú·¨K’§«Ý)2Y¯öòRÅšGȯôe˜k|æýïðݳ�ç÷?óÌþÎw–ûüÌ1 þüÂùÉFŸºÎ«ì �©fã-¥šÇ>¥ô/k=˜�ýïº>n-Ð|î'ýÆaÐ8ÓÉðò\³qnçž±==…7ö¿}¬ÑMþË/ú�Æ&ú†™ñ’Ñl4n½ëvkðßv×oÙ ÿ»ýžË‚õ�ïÿ©?õÂ�_êÿ)`ÿûßyȆü'Àæøžºÿ}OtŒf¶¤ÅlF²'ÿ[ÂúÖ �ß­ÙóóçÏž�ûÑßýÿÿ¿þÍ�,ä?óüìÂOŸùÞ#½ÿ×^ka¸\®µ›ªR“«•¼-ùò|þèÑç¿×CþäÜÜño~óA¬fffúÈ—§§E¸™òùy˜ ªä~,¦DȆCìÛ¢*f傘)J½ÇFz¹­i¿ç5Ê}ä÷ekœ#äŸh4Žj¹ÏòjŸ:~�“.ûÂÆ2³ÝAþoõ’ÿÏÿüÜ ?ÿùÿ àÿ_òþÎ1ÈßkG>ÿmƒÑïI·,ø¥‡úþSyè©ûr=Ï©ú}O=õ®§žzè¡�Ø�ÿü�˜ä£nò§ÌôÊe ¿ÇÛÁ&¾�üƒ?Ý×úéóÀýû€ûk¯³\,I’1õØåÉ&íÈo}î³'fgO=ÔMþ�™¹'>ú~MÇ现9Ñ™l&={©”R½é\^ÄordÄJß‚E¸K¤l6-kÝËTá�ë†oõvòX•¾ s�ýwŒþÏ[œùÂáÚÜÜäå¿øoðv òòu{òÿ塳÷v~ã7ìÐî þÏþC¢Î3çç€þ ÏÁý?ÐÛð¿†�šßdëðôÞ–]ùÚGúè]©’Ú½˜*Ý÷‘‡Þõ‘‡zWAí[ðÄûî¿ÿ˜ûï�¾rÿû:T3¹"ŽïÀ¥,_fo§�0úJ�·sð•ƒ`ðÁÓyÇ›ß|íµ`ñ#¤RE–§‰¯ŸMØ‘�ŽÿÁ£³³Ç}ôÿír†¿pèÐpžy·–:”¶9Ñr:“ÁV]L¥2µÞÃPóiœY©÷-˜+4ªb¡!f²b÷ª’!c¦—ür_†¹Fìî|ôÁwï7ê?0g]ç±ì�É™¹¿ÿ›ïö¡ßãíäÿø¡³'ÿÇöäì1Õ…þsüþ™.‹ÍÇè?wüÖ[÷îírƒÌ5Þðµ§ÿòk`Úßð:¨Èö£ÿ+…��Ÿÿû]ïzÛ»Þu{²ØW5©—Þó®wýdÛ�?wÇýý¯Ü�uGçñ¨frÙ"€ŸÇV^mò{¼£†ûßþõï-5܃Oœ9}ªæ�ìûľëþܲdiJªð‹S{òg�îsŸûü¡ÿôwßµ‚xàÈ¡ÿÃÔ‘#v6¿!�Kƒ•ÊÉjÃ}+ø�a©<9Ó•†Xî®—AF¯pÓ}ä÷etlþƒ€þû?úÑ÷cô÷[°}öQͦþýÿûw¿(åíô“ŸL§ÓÊ¿üø©‡¾ôäK6äÿfóßmôŸûçŸùÄÕu‘ÿ³~îYâê€'iC~Wãeßž ƒ¯¯¿íö›ßf>Aÿm¿6ä7Þ±oß¾ÓÁç¾;>k±aÅ,v3ªÃg¶  $ÿÔ·¾ujå½�¶~‹ý�Y,îÃ-;ççffN9ò{Ç,ó%Ò¶3UÈ‹ñ¬-ù³°ÔÉ“_üî·Ü:2; ûÞ}Ür)ëÙB±XTUø(d;Æ­�üo­ŒŸßçíš·’��_›9~xòÐïYí%Ü·Z«f>ŸŠÙ‘ßž?{vvöÌì,FÿtÜ„c³3ÚvÚóÇg&%û+UçZM©Û‰Z«7·j¦«�ŒdC¾¢©‹|xØæ¤¾ ËÏ<ðaÿ£]Î~cáÙFýE¼�x ·ç7þñÿñ;O=e%¿R*ÁéS~ö³ùÎO~ò3ÛîÇ:Ÿ�Ó÷_týÅ_üü?kfüW’úg}nÐr�ÿÃ?œøzª  àªôÁ|ñƒvä7f÷i ƒ÷í{¶kéZ6_’@¥|vºûé½6¿ÇÛ™o²Úü£ŸÕõ Ïwí}ÞTÎn¿Ž–èÈ‘g¿øÝ¿û‘ÁÉó:øçg&寲kJ̦mްbC>þ ·X¶ÉèèÌÜ3|ô�|Þêåã7mèÿͼ3Món_d`†­ñ†«Óåíü�dì%®NWÆ2H‘j²¤ «\QÊ•svY³ß½ï‘Gö½û³Ç{–VŠ™‰Ba"S�{.Õ ûù¸}ûÜTÿš;d¾ uè°™zNU¬RÏ ¯ÚtG_üøKÎÌQ ·iž[~©Å¼l“<­»Xå¡3tÍ>sâè3³]IÇßþGMóÔý}öxWf÷y5€Û¯ÿ'Oýl GwìÓÖÞ›ñŸu}cyÏ)ù˜«â?[Õå£OípŽjD%MÙÅáNI´_Mªõ޾mß ´GY**J>ÕRÉ/PQmÑþv¨6¦¨Í§Úð6¿€¨¨6Š(ùT”|J>%ŸŠŠ’OEEɧ¢¢äSQQò©¨(ùTT”|*ªõFþ÷,Ó.|kûªl†ŠjQòO½wÓ¦í£³›°H‘ÇáËUŸ¼D$·ÃJn9½ù˲”ó±œOl Ì÷0 ë+ÓëNÕGþ-·œšñq ÿÔüü¼†äUóó/nzüÉxþÔ�ï]”üåØŒÈ¥åF1T#3m;òÅ–óØ-Ú¢0llò¯úIò�"�_…o°Æ?ؾiû‹ðT¸qÓöÇ ’óï½eþñí›®zøÂmÿ BŸÄˆCùO¡ù[®Âtö–MÛ?¹Ýv3çß{ÕUš76óâ�›6½÷‚›YàÓú·pÌ/”[ ��6Jð‚È4tò’X\ËšösŽèBΤ×EaØà6ûã§úÈŸñª S›¾5ÿ0æíŸœÿÁ¦Éù[n™Gðíì‹Ö5¢bKþ©Á|ÿàªçÞŽæ?<#LŸºj»ÝfЇn<{jû'�ÍÀ-1áÍ”˜ºA¾ì~¯4C1”qÉÍP‡üFÜgfU¦Z5o È,P68ùóŸ“ûxÝH– IDATÍÏÿ�é€ozï¼æwlüÅMà½÷Cèáo„DtÕÃg»×`ÆŸVlüüí§4£Ž®"wÕ)¨FÀ}ƒÞn·’õøvc3·¼÷ԛɳ8ÇáÈ£p¾ñ%„*N´+ù°W4³°2A ?OQ m;ÿ¦óg7½xêÔYÓ 9uã‡Ð‡°·qãÃÄ-ÿä-èáMä±ðâ-›n|±ILeJí±ù/^å¶_µ}ûö«~÷×UWmš?¿é,ÁÛf3óxí/n26ïí�_p3Äæ×W…�ö&ãr»Ý|Û›EHíØü…'YJØ%8àक^J>qu^ìõó¾ªÏæßò°f»ç?¹½Iw¢Üççcã~‹V'øÊöÓ`óç»l~÷fL›olý`Ó© mf�ñÄ­‘�x-³ËæãÎŒ‘‰6Q†’OÉ}èÅóg?´i¾‹üùyì£køyìç¿Hü|àôÔüãóº$=‰Š] wjÏà磳�Ïc¼a+øšß¾Ýn3轆Ÿ�7ƒ? €³Ü iÛ)9tò~Õò=~~«™e$# nЦŸ’OÉÇ~ xäà¾XÉÇø-§pócOÛ†’ØQ<9= m}òFÒ¶sÕ{Ñù[¶ßò0�ö–í7~r»íf:m;x3ºªÇÛ±ß nÏg½bK#¿•Xw µ¼�fZ†ŸÏºE3«âõ”|JþúUÙA¯5ÕF#¿•o«Á(½ÖTŽ|/ç×鵦ڈÞ%ŸŠŠ’OEɧäSQò©¨(ùTT”|**J>%ŸŠŠ’OEEɧ¢ZäSQmÈÑ‚è@‘Tt<\ªUP¡ÙûGEÉßj6{ÿ¨(ùTTt ôÑ>sYª5-Úª9”¦P»Ý-4›�FC#¿Mµ†EÉ_ù¾…|úì[»¢ä_ùÔY^³ÍjK"ÿü'®»öŠë>qž’OÉßPäŸ|Ç›ßüæk¯xõu'/‚œµÞ•“F~6KÉßxäŸA¿cõ%?Ëù¦P÷q )1܉Yv}’Ÿ ‡³”ü Gþ'ÞñÇ_ùÊWþ£ÿ #­Å'Õz¾ˆr‚Ö}_,ÒjfØÚz$ÀÇèSò×/ù¹Q®ëÚ¿ã÷ï•_y6úFZUï§5'˜ÅbøÀ=Ô§>¤ Tðpx\* _ò(áä\¥5J~6&è÷‘ïçøäòð‘ôå´ÞÍ™r4óU¦¢ªE?ËúKª*C²3vI?f|,çM)óÉ0`E öEÛü\?øèÍï¸ÿù3g¾÷> ÿ Óæ ¡B½�üV–«£¬³Ò ‘ÌN´ÒŽ�_tQYP�,¯³n…áÄùuE)1²¢ÔMòKl|z:ÎI@~Y™"e/V)6U©‚í'H;òÓŠuÛ-ªPÚ‡òvr}à£kßñÇ�<ÿ<¶ùW˜ä#9æb2øù<Ïç ?ŸaRZ§õ £¦°÷ïÎ!gÒ)!Tá ­5ìçÛ“ŸðÆüòáCb0f&ù� . bòU5»øË¥p)ý[(êŠÕ ïLÂ-ç�)¦¦“�¦®êY’�ã#Š*q wˆÒ>œŸŸë]÷æwüñý÷¿üü+®³¦×~”sÖjµ¦aóÛegá�J[‰ãž\iät�.]ERÖù®d‘™L~�ÍàR"‡É¯ùÔ%\.F6ÈwVÔº/ªTÜU*µ`‡üZ öAÏ’&”iov(®Ò·².¾†{íµo&ÍšW\ñ‰®Œßç燣}6¿àI’üz0¶¾È/öî„ ù,<9¦Rcôbuìç3¡Kp;²,|ެ‚'G‰…U¥BjŒ{É V0³È-€ªQÖ/¡Uóº+®½sE§USNTª�@7ù­É™Baº€ŸŸ×ý|Å�D•R«^Ëäw¿·C&puàZó9ìùø;ä+•J©Çæ+i—|‰6_žv‰j(‰ï—Ë%T�ˆ+ϦÍW2\ÅÈš NÞ ÞEý’~ɺîÕ¯†Úí–_²ê�u„•.òqF¼EÚv‚zÛŽDÚvj®”äåøàšìÏ;_*Zd!_áX‡ƒcŠª»1‘ð…üüà¥ûù:ù%^ó`ºl>øùªS4²B‘š*Rò/•|üö«7êÛ ¥A6_ä*ÓÓÓþ¨špk96×O~‘´í°’Fþ[½„¶·íðùu_¬V— jÚeõó•šÈ�,¸)%ÿ’ÉßÈ* òóQÒÎÎ+J\`ÝØäö’¯Náöü¢ª‘¯úâ—ÖžÏzR !_­†œ7«·í(f{¾+mf•<¾@œ’OÉ_ òGC%žÂLÉßhä+ÙºˆP˜)ùŽ|/LJd 3%#z;T”|J>Õª‘¿bµ.?ù ÕÅkeÈ_b¬V<¾Xn8EÉ@>}ð^´V†|ÛX-Ãð^MÓÉ»Eɧä¯òíbµ�Glɾè¢äÛÇnQò)ù#HþбZ@>B)/B­„ÀGhÚÏ9¢ Mû¸@Ô uÅnUœ;CÈW¼ ”ssÎ4%Ÿ’?*6ØX-L~ÍB(áWš¡ªLµjÞj»“­k’o�Ýj{­'ù5˜}®„Ô %Ÿ’?2Þΰ±Zø=q/¸2| ¡Š“$e‚HâZM?ß»UÆYÑ Ç\ð¸@|Z¥Þ%”üü!cµÀæKN 5—ÛíæÛJØ%8|(ïÁÈ›6ß»•wÃ$Ba‡gƒ`ý%Ÿ’?Ò5\»X-âçûÀvk��D¢M”ñ!ÉßC?¿»eÚüT(@Bu’J>%¤[5mbµùM¾~¾ŒjyŒwÓï??‹ª¦Ÿß»Õñó[¡`«™m¢4%ß–üœ�å|b‹â|ÙÉ·‹Õ"䣄·í°îªx}˜CŸ/éøùÖØ­NÛN+Tý‰äZ«ä§'.�|‘KË�bHknS¨/'ù"Vk1òµž¦t•Ùägp•Þ¯NtõEJg¡èÎ Cþo4ö†c~¡¬„xÿ’àQïõ‹jõÈß*]°§© �¯dœ Èœµ’ϱÓÃ’_bŒ0æ°ì¾?Ö”Ý9”qÉÍ%Ÿ’¿ºäë=Mùÿ¬Wõ0‚ ¥QV˜PÕZÄáŒ)jÊr¥2‚áí�ŽŸ$Ç…µÒW(JÈ7;†Jñ¼˜wqøQ º9¹C~ž…�€Ã‘Gað+,¸‹é0i&¨Pò)ù«K¾ÞÓ”N¾fóÙ´’p�$rÅ�TSÌ„Z·��;~ $êÊ”nó]e¶¢Z;†Š)6P-sSjÎQ¬'=õn›_W\YòžGžu»ÝB�4 «”|Jþª’oô4ÕE¾üFV]Uô�YðæyžÏhä×T5©˜ÞŽK�D oÇèŠËB™”Äb‡Ôñó9Üv€Üù^«ãR›OÉ_}ò�ž¦ºÈÇ~>[©ágA�×f3ÎJ¥¢hÞ®„x·h’_aË@¾µc('Ô„CIÕëp¹\ŽBOÛNÉ¡‘�|±F»"Q?´È_øC30@l¯[òÍž¦À@«i/0Ü!ß´ù„|‹ŸO¾ÕsìtE'_�†€|kÇP:ùÁ¤M{>ë[ùJØÁù ¨�à…4CÛøG„ü ÷ä}¾óöÛo¿óNfý’ßéi*¨Ö|^µ†{Ø1ÈÇ~¾'iK¾XUKl•”ÆäO³\¦«c(�üœsª.‹õ!~Ã-;(á#B>óôg>|çÍ ;ov°ˆ{¡çÈåz¤_¸§)9àöÇÁ¡�ó\É ¿æ¸mdžü¨ƒs‰ZiL¾c2]CéäÃ#ƒu†.D~+ßVƒQJøe ?ן”}Ý“÷Ý¥‘2¯š‡a8_ªµDò‹Lrdɉ÷vZ^ήSÂ/ù}ï.£61ù·cðo þ¥I¾Øªe…àÉ�ònJ>}cm4ÉïC_|öò±É¿Ëw»Yù"ïó”™’ñšNÑ fU´`-L~B`=SÈ•Õä2,ö—ò}ÎÃâ_ìÅ`”u—ÓG­B%Ÿ’?€ü^ô™§¿tß]Øäßõ†SDVò‘;e¼š©“ßv'ÛEV#?£´E¾i�ÊÊð-ìÄf¹ò •¶‹Šl¶bÍ ¾µ !\”|Jþpäçnþ’áìønê\4�|Üx_'_¿È㦷㒬QY�Êr äçš²îíDSHôé³\uB¸(ù”üá¼æÉ/}é3Ÿ¹ï¾û>|sجŸvl¾‚¥“ok›ïs lÁ•Uçh�Ëš?ÑKAàâàí Tå”båC¸(ù”üáj¸Ì�¯»éæ›oºé¦›£wYBLù¦dØüT!¹ËæË\l>Þ#*+Å86ˆ‚àÉOù‚ØFÑnòW>„‹’OÉ®U“ùð]9üNn]J3Y+ù­ZÖÕéj¡(4P¬ËÏ/;š(Ï,QYž„¢(yVÉx›( äÃb2ßEþ*„pQò)ùÃ)éa~çÃOʵsSwZ/nÏ÷âö|½mÅ]þ”Þ¶Io'îÄ=…†•%±¤¯6O %<�4�ŸuûÑ.ò+ÂEɧä©z:êw0¯»óifØ^Ó‚é>w”|JþðRŠéÃüîP`)¨ÀÊ”|Ú—òZêKy9$:8OQò)ù�ü‘õv¨·CɧäSò)ù”|J~Ÿ6FL%Ÿ’ß«�“Eɧä÷mnè˜,×àüÅGÕ¢äS]fò—“e3~–I~’)Qò)ùk‰ü%ÄdU½‘�仸è¢ä·(ùT#Fþb²RÞÞˆ,ƒü›á`Ñ@ÄãžêŒª•ñpþ*BΤׅNJ7¢g¢eÜHäÃS“õ•)Ì£CþÐ1Y ¨'"Ë$?lñY |ž¼`Žª5å”Úx´9g`•É2Šêx8-½à’¯w©³ä‹-5fû^*íng$È“Å9X¿Ü‘e��ÃObD¢­ÚŒjŒªÂ�-Ž*ræqwz|�á®�'�Q𲓟`¬÷€P°'_ïvD½¤^ÄÉSS‚ïzÿáú¨“U.é SÂGÁÛ“•R€Üžˆ,ƒ|rXbòþ1bkF –Ïév»E-Eôq!¥…P‰7 ^vò]\äÂä+ƒÉ_B/âä©÷™ý‡ë£NV™å{4j¸‹Åd¡žˆ,ƒüëp8˜”´1ªVPÍÙ©y·õ`Ì´ù£A~�ñ؉°ªÖ%Ê8„´Ä¥|Ò¶ñŒ‡ ç"{'£NrE³ÿp¬Lȧ�jŽH«æÀ˜,ÒîÓ‘¥“¯0yEQ&ÐÆ¨Z§„ÎeÛ„üJ©Õ ÇÀÏW‰Ÿ?äG‚ /šäk6Ÿ‰ÖŠlÙ®ñœTŸâ êEö"ŽÏàBŽ“�þÃõQ'IˆÕe ¿Oƒb²ù½Yù)òlPز´1ªVÖÃ9Ú͗¼¬£˜ÒxkDÈW8Q…[±‡üšªú2Ý݈w¼�pòb{×Π3cô®�:IÉò/"&k¤µùØÕÁ�èw‘Ï‘QTº»×ÈŸò Nðc.¶q�ØjfÉè?\u’’?:ä£%Åd­eòµê ¸4!%Ÿ’Oc²(ù”|“EÉߘä/eœ¬NT–ëÂcj9Ë”|ª!ÿâb²Ä€ù|Pú¿i*ZÞwC(’¤äS�ù“e’¿ˆ3Ô#‹’O5‚ä/-&K «Ê³‚…c~¡Œ}œŒ‡s±·£„E¤�‘Uå’^W eXNˆ"gÚÃ…a�)�–1Fy#+�éøùÉ(7 ±cy U®¹ŽÉ§ž”—“eŒ…ÕE~ÇæëaacdÙ‘oÚ|�üT$A”|ªU%i1YúXX¨ànuÈ/8JHóóõ�°Hy}Œ,ƒüx´C~F˜n†æ,Ô„)D½ªËûKÖâ1YÚXX¨à“|$ºY­mG YÆÈ2ÈŸöp᎑ø Ò!œmJ>Õe&ÿrÄdEW°'BJ>%x­rL–ÌU)ùT£@þê*Á®d—3”|JþÆ%Ÿ’OɧäSò)ù”|J~ŸhLÖJ�:¯óQ�&ù4&ëbN &¿(×%üâÕè’¿”˜¬�Š&×9ù8V'Xíî\y¢¸¨·£¸©Ñò‡ŽÉ/¼®&gy×xJZïä§•²/ÜMþ¢~~‚g\ …yTÈ>&k/‰gj#wîV�|­³*½sqÒ­8x;—ðày9ȹ+ù 9kR˜G†üác²¦q'ñ¨ä¹€Œôè,´�8_]+ˆû°‹£�ˆÞŽŒ²îrÚáÈ"}€,=þª¶Nȯø‚fçâÄæcò™„:Í•Õp Vq{zÚvbt˜ˆ"蘬`µ$ÔÍhÑYqŸÜ–´ÁjL9åFæˆX@>›mÅ…Xs‚odá7tÒþõâç3Þi³sñù 醜—?ÕG~„Â<²äŠÉQ(*ë35V›º$ÄwêÀIRÉ “ïƒû� ÂU�ÁRŠB~q}�Ÿ®Oá>4õÎÅMò�nÈ«Øê�ßHUë9V¤0�¬·3(&KDµïÉ vÂí˜=:«Étêlî$‰AÔFÄÒ¼¤E¦8ËÆYmg©Æªë„|• ,¡w.^é&¿Ïæ/x–6íŒr wј¬«ˆ^üš#:«có%†s8XÛ{<"V7ù†ÍGñX*¸~j¸ ŸUõÎÅI·âòmý|ªnÕ“•UP™­cpãÌ‚�Õñóc~EQd.gŒˆÕM¾>@’žìú!_�ûT½sqÒ­¸…|Ò¶ã£ä�,ù}“sà1²O ÞŽ�µ×ÛvZ<¹‰bA}D¬òõ²À'ƒ¥¯ò‡P2HÉ_;äo q²VTRI•‘’¿†ÈGfœ¬UÑÅ9ãuJþÚ"=‰¾¥LɧäSò×ù÷l8Qò)ù”|J>%™ôö׺u/%Ÿ’¿aÈ¿õµ_ÿ“?ùÑk)ù”ü�CþkÿúO>ø�w‚>ðÎ[©·CÉß0äßúï¿n�ÿöך©ûgççgü˜Eh~v?%Ÿö¥¼ª})/¯É'¾1ùoÿFâcó�íÝ»ÿÄ"äCþÑ3v9{)ùT£Fþµzì»Lþo&ÿƒ¿ùNÃæï�Lÿvâè+göï=1'�?óÚ«“Ï%µ¬½³óç�î…åž9}‚z;T#çí¼±|ìåë&ÿ·÷¼Öðó÷#ÃrŸ8 ßf�îÝ{fÿ=��Ù»÷D‡ü½Ggͬ½û÷îÅIèêíP€GÑÏc/ø·¾›|B~Çäß³¿�¡?~?Ø|üÚ;qÏ lÜ òa?ç÷›YÄC:aæRò©F­†ûÆ7ö{ùD|çžÎMAl>1æ˜öýí3 ÷àí^‹Íß?¿×ÈÚ{âÌ™ó³p#Ð.%m´í¼ö¿ýNM{>ðë�ZªæçëäÃŽ�u‘Ï=g3³ÀÉŒ’OÉ_Cäð�=zâĉCŸ{­¥5_kÛ9¯‘Oœù½½~>¤ ýFÛû %Ÿ’¿vÈû¯¿ö·ÿäëÀþ£x­5ÝhÏ'äï=q7Þïµ¶í Ô>óX'kvöÄ3”|Jþšú%ë�Píýí|ýµCý€»ÿ<ý wÅÉ'1�”üUxWóÖ[ûÚ|l£ÚÞÎQJ>%Ý�?¤ðÏU'önTòI/ +C~khò[”|ú~þJ’_ç`‘ÁB/ùQ†a}Å ‘Ÿ ä"$H‘$R˜’¹¶KB¦¬�(��â.�CZÊáLç ��6̾M�I¯‹,*ù9ÈÖú.…ÂiŸ)º¹ø ŸV…VÚæû€¸ „ûÈ)Õ°p!òe®¥Ì;€žu1ïpD])Ñ:¹ˆ›²Èg)|¦]äkmw²]d�|&ºPá‹(áWš¡˜Ù·©3 õà¢pbK•Œ¾K«Lla‚ *2/Qò—e'Æü¶ñÈOøqßRäCUâN>\ò“g“¯ªE¦&ᮦ¸!¼\ ƒ‡ƒ›ó—-ÞŽ e#¾ ˜~€?–vbÞ~�ÄÝ“bá^ëÒ˜üLñc $J|¡ &_A(%=ÚUœ¤4îÛÔ‚%¥=4ô~ìÈ 8`"(Rò—cþŸoÿ‚ѸÿÅ$¿ÀÕe§Â×e¦¬Æ}Óµ`T•˜ˆRâó˜üzÌ¡JÊ´7¡Ö]‰zž�©9G±žôÔ;äGR11‘ÆCÉ’GöU€w™S„†Sf‰³Þ`ê弚OçÜn·3™Çý;Æ€|Ü…o:Ød\�Ì·�¾M�emÕpO�h}—�{¡pŠ’¿<ä#@¸‡ï�|…-f‚ª¯˜qª*‹KN ¿ªª±ˆe¬k‚”j‘Úƒ15ˆ‡ÌrHòÅ€G.„\`µ#qŘw!A¾„>ÒŒaó1¸zç£}6_C]ïÛÔ$¿ÇæSò—�|@ÿhéä�Ž%_~y‡ØZ®¶2–RcÉXH­1._—pïÉ©€ N×àÛtHpò^5ëÆ®Lõ: �£Ð!¿Ê ¨ÁcÞE.‚ dd¥0'‚y‡Ã-¤ÝÏÇà‚ŸßZ(Ê?¿Uá§ÀÏ—Q-�ô¾M5òÅ|ÇÏ'}—RòWÀæ#æÛ¿Ð\~~O%*¢ðB¸2hÑFÚüªðÖ <ÈZHé#ß2ÄYýH�x‹j6àM©*WÒj¸†Í‘ÙP¤¦ŠÞŽÍOö¶j:Ãpt˜÷*#¢‹oo‘©¢��”!5Èy’>½³ìçø@•´íDֶܹѷ)!?G¸%È™6ú.¥ä¯ Íÿê&_h5*QVºpCsùbKöEûÈ·–ò'8@ZæYð_âþŠ:�Õýü ƒü@RU|ÞŽŸïœªËb}‰íù©PZ0½q[æFÎæ÷‘�¿†] Í�lÒ ‘ô¹Â-B¾6Ž–F>\k/Ôë<Ú É9Ó½�”@ž£C¾Âp×á<þXW’´í8ô¶PÉã Ľ0õ²þp|~ë -…üjU]™ž½WP�•)ù#hó³õbU'?Ëv54w° ùÁVË'¢…Œ1Ž–N~ÍV®PiKP=“ÙB+Éò³ÎJ3ÔW?ä/IÁÔEü†[vqB¢gämÑÁyrˆ’?‚6ŸH#¿È,t54› Ø$e Œ} çëãhé~>ãÕJŒ¦HÅ­ÅòƒðP˜åVhÕÉ/L«Y¶BßÕ\Wíù66ßB>Øü®†f³›�)IÍ¥×ÆÑÒm¾ä„Ú�.ŽâøÎðò½x`¶²ÉOã6è[Êë‰üÿõÛšÍg{òÁÏïjh6°{ÈׯÑ2ý|<Ä6/”TïœkÝæÓ÷ó×ùˆù€>ó †ùö·¿ÝG~«Q‰±RwC³Ù€ÝM¾>Ž–A~“/àŸ`d>U‚*Êj~~F˜n†ˆ’OÉ�7Ö0ú˜û_ü¢÷Ç,Üžï Û] Ífv7ùú8Zù(áCY·?‰ƒ¿äñǼfÛNP¡äSòGâ]M@Ÿù�ÿ^Óš¹œ”|Jþ2ìF^%Ÿ’¿qÈG ³æ.#%Ÿ’¿1EɧäSòi_Êë®/åÕõt6bLÕˆˆÆdQò)ù4&‹’OÉ_Yò/“•±ýÕuGD/¢e Á¢äSòWÂæŽÉbœ‰ ‘ïað Ç~¦·/ŒNV,�‰Pò©FØæ÷Çdµ$>{!òÝpsÈ;¸J>ÕˆÛ|»˜¬`‚�_ pî 2úûB ‡ ä']%ã@~ ä}Ftöv2Î]¤äS­›oÄdµ+Ž&¿íI´JœÙßWF�AƒüŒ¯„Ü•ùzt�ŸçKm¹ŠJ•j‘’Oµ&l>öó™P“_æÀÐGcFß/ø=û²I~:Zò¢ùzt~?Ik¸T#Üž¿XLV-ÃäçÝ0Ÿ ý}áØ*Õ$¿îˆ¦,äëÑY@¾/³ÊäS­Y�^L–è²³ùi„¦MòQ�U0ù¸ÃGчÓptÖe°ùTkX#“Õ’ýÁn?Ÿô÷•ñ6Q´C¾\B˜üd5}>#: È/8JH®Rò/Qž?Jþr¡?0&‹áƒµ®¶­¿/”ÀAZ&ùX@¾ðø>#: ·íˆnÖ]¤äS�$ùë(&‹Š’¿4ô×ML­á^ä›Êô�5ªUÒ”vñ%ÄW�F¦Pò7ùƤäSò)ù”|J>%9´ð‡f¤Ø¦ä/§*ì {³j8AÉ×ÈÏfW�ü ÷ä}¾óöÛo¿óNf“ï1Ʊ=,®Â—j˜g=¸7XOZUsœ¸´+ä.…Ój†t7WT¦Öé^¼Ê[3ðð1ÁjùÅîÕoXò³ápvåÉgžþ̇ï¼tçÍ¥þÜÅF¢w•†Iƒ£A~Z‘£nUMq¢,<ŠZs$9ÍŠ„ü,—Q/†|A©•"ì”5C±-ÞC~Z)ûÂ}ä÷®~£’àcô—“|›a ²¯{ò¾»4òCf#¦G\„|ܱªÃÓ¦+Ìþ´‘!�c[Wxl‡GJM ˜Ñ¤£Y.«^ùøkЯ*AžŒ‡ëLx\x]WPU…)ìí8^WH!ä'œ« ;“ô¨jÆÃ x„­ŒÀÅtoeêHÙ IDAT')�§ÁF&? ô—“üHúmbòoÇàßüË!ɯ¶d_¬³ŠÅ·9:ä×b>µÀÈx.PýQb‹™¢ê pK¾B¹ é䋬ª¤kJ$œû•z…UªNLê„ü€¢øÒª"ªEgU-W ò+>¸9rR}Š+@} §$B¾è”j¡€¾zZÃ]>òûÐ߀½|lòïòÝδ,äkcWU9Ñɧ ÇŸ¬“Ó”Ÿx6á˜_(‡ã~Ö¯DYOEOÓŠfµq°Ä`Œsá1TÖkáUöó€,«U:>Õ£U'Ùœêa½ÊÅ]&�ü<£õY'~vSbØWJ´”œªÆÉMVâsJÇÏg¼ÓÚ÷pRMê GÈÀ^Mkw'mÛYVò{ÑgžþÒ}wa“×bLÑbóõ±«ªL¬)±2 ŠGLòB£ÜY˜�å†_ȶâA-M+*³ÅvŠòÙL+-`?¨-òͮ«ló• W±µù)Ÿ_¹òÁæ×ãn§n'®£†Ñt,ò!%¡¹ôi/œÖm~} gLù'ScxW<„|/®h³%JþJ“Ÿ»ùK†³ã»©ó®�¯�cRů^úr( ¤OyL?Ÿñ(åq„È ¥ìÔÒ´¢x\‰6Ÿ'¯æ·ôQ\RWáÕöóU§¨p½~¾Y²7 \<ùàç§½U0Õ:ù逧œ º ½äÃ}ˆš~~Ê O‡t]�ÄÔ$8>ªƒÚüÕôv˜'¿ô¥Ï|æ¾ûîûðÍa&i%_»Šøù� g¸ä2m~#îiÊñðžø{󸬞E�q°ˆŸÏÖPÆçØBWáUnÛ©‰`൶·Þ¶#²i¡ì Ö/Š|¥VвSÄ_‰ä—YA­q¬ÒC¾TP”P‡|…Ϫ\Q­ð1µÌ•U±ÛÏßèä/÷{;}n>sçënºùæ›nºéæè]dgóíÉ/¨vòM›¯‘/seȽŒä3 ëJ[Ûó§C<ëu«îÐE OÚóƒà›ÔÊ _u†TÕëW{ÈŸ‚ ë�øä÷©¢Ë Åð>ù¢ZÛN=!p½-ýJùRÑ¢•kÕd>|WN�}]J3Ù.òõ±«lɯ¶êq¾uòM?_#¿ìh¢%9¤Ó1†ùÝNB«ÀÖ–a½ùf+énSò©F•ü>E�éeY ÇûWÙäSò)ùôýü$Ÿë³r£QòGš|z¢WD”|J>%ŸÆdQò)ù4&‹’OÉ_ÎÍ-“Eɧä¯ò‡ŽÉ¿ҖmW±H%ŸjTÉ>&«¥Æ<öä΢äS�,ùKˆÉ’àú*!^ÀïÙ"÷Tw–Ö‹r‹ó_gkÓ~Î] ä[µ”ñO ^Tc)ù+IþÐ1Y�¸!¬)»sHdJ(/te™=çÇJûQeªUó¦6ùàøq¾TkоtÆ?E]¡—9ðÝ™>òiJþ*’?(& ­Q……Ëš“°ª¶V¥g£¥á†ðkñê™à:$ßèü©«(ÆtüjY¡û¨íïƒnò…V3ÃʽäS­ª·38&k!ÇÉyÖívÃ¥5^4¶fi#d¡¶³TcU¤„]‚÷~ÈÏé¿p”'Š*îEdù�ˆW2‚ëÁ)t§\Ê0eøŽ½ÃMò§}ÑÉÇgsµ‚<€à\ˆó$5oGˆƒ’¿ò5ÜÁ1Y93^kàï!g6Åc8ø*m¢Ì:"¿®(%FV§µ8ùÈ�2‚ëE �$QÔ•B‘!_w³u<8XK2Èoe˜ j‰�f4g1Ð�]„|Ã…¤ä¯|«æÀ˜¬V3ËHÈk´+Rù$˼H’à S¨é_Gäã°YÒ—H8QæYÁCÈݤ7©òýq2¶ž ƒÆÞç f1ù71•;~>ÃèN=6ôø,¦ù¦9¡ä¯ø/Yƒb²p% ®«vp¾B7ùz–ù`vs U¼¾@b}’oÚüœ£XOzêv6_ ®'§Iæ¡á”¡†„ÉZ„ׇ›ßˆ†à–H¸�³Ð`ê�FÈ7\HJþe‹ÉZ³ZIòƒØáqH=äW˜’\¯õ&'$"È— òq5–U ?Á Ž ª1 ˆƒê¯Hm>Zýw5ûb²(ù¶ä{.—ËQèiÛq‘\¯‘æDç’½ägTfëf 7å#�SÄ�üh5½ÔÏGô-呵ùI›ö|/nÏ׃ë5òE¦Š P³í!?æ0šmùç¸B#€ÇP]@jÈHжJþÈ‘Ÿu)šŸïœªËb�¾½@Éß ä+ΩµíxXgˆ’OÉ_çäÓ7ÖÖ;ù4&‹’¿1ɧ1Y”ü�Iþb²2m�ΣäS� ùKˆÉ²{ÿvz¢‹üþ97Û“GɧAò—“Õ÷þ­Eùüº­ö e‹z;T£Lþb²,ïß‘WØ£™öq�¨A>|pEííÜ îq<éu¥(ùT£HþÐ1YÈúþ­yt·ÝÉV�5Éoe¹ºöv.&ŸI¢'Sò©FŸüÁãd!ëû·zäÐ-á—ª‚¦ŸÏàÝÈÛ¹„|Èóç(ùT£ïí ŽÉBÖ÷oõÈ+ ;�ãWb¦Ío—�Yíí”Lg|J>ÕÈ×p‹É²¼«G^a›ï€œ�ÅÏG7 ùTk­/å%Ädu½«G^??‹ª¦ŸßZ�œ©�Gþ=T+£‘ˆÉêzÿV�¼Âm;Ÿ/éøùÎx‹’Oµöȧ1YG>õÉW@«K>¢1Y”ü�Jþz%Ÿ’OɧäSò)ù”|J>%Ÿ’OÉ'¢1Y”ü�I>�É¢äoLò�É2:�Nä·¬õB~…5¿¦”üµMþð1YUøô3þ Ÿ|üâ ªw'F’öäËìH’_ p¬7½ùµTù¡%m’?tL–;È ,éèÎŽüjKöÅÈ÷ÖÈo�&ù%6*Õ þEÀW,ß)ùkžüac²’.„’qVÒ½�v$ÐDç¯êäË¥ü9“^*x8_eXNˆV9ÑÉã× ´²U.é {A¨ ”À‡”•�Úšü@�t“¯ª9Øû¢ª:ã^wDQ¸A�(q w{;’— Db@~”&TŽ1BÉ_›ä“•ñ•�»b�ß …ZhÊ)µS^“|Å�g`¼™‰VÚÑÐl>kJ¬l”­2 ÝÛÉ:+Ípp壶†%¿Îf g>£¤5ÕéWê�¸šñÀ¹ç‰‰«u ¿îJÔó,�Ϧ•”@mþ:"PLV&-y‘N~ i#Â�+Žªáç3ÈσíÇÝ�¸s:ù „|9£,™%äÁÐ+ŒºâQ[Ã’_côÄ$öc\Õ wBÎ¥*¼¤Æ"ªÄÔH ·ÈÃS!ä{ÁûadJþúñvÅdeêŽhÊ Ÿ'Ùùœn·ÛQ4l~#îi#g¡xR鎟ÈeÉ,!ß‹_þg++þó’m~ {/þ”êœÂ¾¿ªFãug^•8­m'ë†i4¦ùùl…’¿~j¸ƒb²2(È*ùÁ´ kfÛ¬áÊØ¾×ù]6_'[/Û!ß°ù£B¾éç›6_TÕŒKU§„ ¡n’oÚ|�ü0%½´jŠÉÊ ¹„LòQÊUC§„ÎeÛFÛN=ηù2›'~>¶ýÙzY2Û„;e„éfxbW–ж#m;6«ùùÞªì�C†ÛŸù¦Ÿ¯“ Sò×&ù}“¥Ái’�Rne=œ3Œ ?Ÿ…:0!Ÿ´íHM{¸°I¶VVkäLðiÛ *#D¾Ùž{êÅm;IÆ ™ Fê�¯–¼¬?7É—<\ˆ’¿.ȧ1YºœEý‹èíÍ ¦èÛ ë�|Dc²ºÈW|]¿ë¦Õ,ØzJþº$=éRÉϱëo·j�nEßX£ä¯_ò黚”|J>%Ÿ’Oɧä¯_òiL%c’Oc²(ù“ü%Œ“Eɧä¯Qò‡�É’ü,ç›BâP£¾åp÷š Û,1°NɧZcýj“Õâ“j=_–|¡Õ’xí­Ÿ%Ÿj$É.&‹¼Wž<¨•øhÃ* I>w®ìLú\á–N>|ZV2ŠPƒY@97çLk+XäÓŽî×\ÿùCÆdµ„P¡n˜ì„_i†bÆPY Ÿiùr[-Ÿh�ß®8 Z–A>WBje½Ú|:fÊÊhÆÉ’c.6 kàòPï­8�¡²Ò8)$"çÜ1ÓÏgBmíIa�ϧÕõëíPò× ùÃÅd�j?·É¸Ün7ßևʊs0çL’÷“1康S Ä´W� òKÖ/Qò©F…ü!c²мnóËÚ¼6TVJ‡|$º4òSaxbù-$=”|ª!Ș,9QY¨¨àna?_Fµ¼1Tøù­…¢ÜM~«%ûƒùE¡�bÌB3ÛDi�¶J>Õe'¿Oö1YõˆÀ: j8·í°n¶B†ÊBe?Ǫ]äãׂ5=+îò§˜…†ŸÃ�Zd”|ªÑ#ŸÆdQò7(ùˆÆdQò7*ùëIúyÃ'Ž’OÉß@ʦ:*Pò)ùESÕZGò¥�/zX>\]”|ã ­·\*Jþz ?ʼn²ð(‹’¯½Á¡÷–KµÖÈ_W1YËE¾ÂãNvGJ ªÈ”Ôt@ Eýn_ÅJ¾ö‡Þs"w­‘¿®b²–‹ü#ãI4€»ÒŒ)< Óz÷‚ùÚozo¹ܵFþb²´7–•k9‚¹Äà‘ŸÕÆÈJø°±w§‚ª0¥†âª:áé'ŸÚü5@þðãd�"_5‚±2võ»ðîì%¿cóËì´PsTXE %!]è'_ï-—j”Ézœ,qaa¡µù-�üjKâõ‹´š¶Ö·Tk-�¯p†Ÿ¯:c!Õó«É×{Ë¥iò‡'K‹9A ‡ ùˆÆQ+ÈsY éÝèãš·“ñpî"RB¼�2ȇ®h¾·L–² ¬EúTÎûà©ãâb¾<�ã\¸Îèä.Þ{Zæ¶·À³i5Æ&lȧZKä9N–F~F�A¦Ñv'ÛEÈÍh@K'¿]æÓ„ü<_jËUä�5ewÎ ¿•åêòñRÖ�µtòe¶ØN1@>›i¥T$Ë—�üN{~Š)«Y<¸%=‘?hœ,–çù©»•™†Ä·5Ûª±ÚèX†ŸÏDZ„ü k©°0—~>ƒ_ƒ3ÉÇKYÖÒÉÇoü·y Ì‹Q+|áÞl^>òéo¸ëÛÛ4NV ÀQI{�Ê4ò8f%Gí„Û)`†ËùrKt�#äûˆ»ŸgÝn·4l~»ìÌvÈ/ë®±1°–N~<†7˜×ü|¨ˆ>îâ¥äSò‡«á'Kóv‚àÉLwl¾èUP­›|ÓÏ×m>ß¶Ôpá#5£´Lò ›„�ˆ›¯“�P=£äSò/Ï8YZÛNÆÛDÑŽŸ��÷’/±uL~ÁQBàçûb�vE2Úv$gʈÒê�o ¬• ¡¦ÏâçkäWJ­V˜’OÉ¿Lãd‘oJxi½m'’@�ží!ù¤mGt³¸m'ìà|ÓÏwÆ[F”V‡|c`-5àñ'ô¶oÁ _òr|°Nɧä�JLö|VLm~™~ü§äSò‡×…c²J *°òJo¾ÙJºÛ”|ªÑ{KYtpžÜŠ­=Êñþåzß‹’OÉߘê#¿Ð¤äSò7"ùMJ>%C’OûR¦})ÒúŽÉZo‡j=�¿¾c²¨·C½��›»,ãd êEÛv(ù«“…²–�^ð—T%ijžÞ_ÀdY;ÎÏùX>PºläÓ¶J>Ö°1Y"—Q§í5üÁ.P0XkJ™EÉÙtMÍF­Z«I>õv(ù„üáb²xü®æ‚3�Â1¿P&c^*U¹¤×¥ÛyãE}ÉÏ9SF#c€¬^é!çaq°KËõ¢ÞÕê‘?TLVIëI Dag éc^é*U™$ªqÚ« !oQ8±¥JF�.›_bt—©PiKœ¤�¥¥‡zQo‡êò‘o“•gÉ$éCa‰¥�y¥w®QÅ¿¶–fÒËzŠÚ ÷f�.òõ5iЦ´±´ôP/êíP]>oÇ>&Ëbó±_£�y¥w¨DƇ˜Î}#Á5⚯°·ùR@¸¸6º„êE½ªËWõ�ɲøùšG�Ǽ2l~7ù¨ÎT±ù¦Ÿ/ˆm<°(YZõZóÞNÚË’{~ÂÅHï*î Jò\ŠQ£�¢hÚÈn„XgšÒ=*­šb²ô¶�&!_óJïPÉJ~¼Ô¨ÇùÝÏ× 4¸ÌæY"'’¶ðñe^'_õQoGajC’Ÿ�ˆDIcVV�øñe嚪2é)·vŠÙÈŽú•W¤x_òû4 & e<,Q!_óJïPÉJ~ÂÃràáqÑõÆÜãR‚ç*�²ôöü¬ÛŽèä¡^—ÑÛÉààÄ�äG!Ûëô!^fí½�&?X×pxZ:Ф�³<äUÜFv››ú#ï!½�“5¬·“”Zš-$?¤Tó>AŠüH >y°y$d GN#?7²e\ãI{)Þ£B>Z_ãd ëídp�QlFU«AÞ™„y+À|7gŠ�Ù5gB…§<ûTü…¤ŠnÎ_î'?ˆ»çf�o"¾€ ¼b’ïŸ2²+¸M,ã¦x�ùëIC{;‚ªˆŒ¤ª¾¨RqgÔœTŸâ ª(”kƒ|5P¥ eÚ›Ðl~ÎQ¬'=õ�6?µú›ŽoQ›OÉ)òIppžY¨Þ§çj8©ÀîMò^­ŸÁ€F~0ÉÖÏWÀÏ�AUûùÙŽŸŸ šÙm\»¥~>%ÿòÛüZ$ˆûÉw¹\B@�ò N.¦zÀÿ‘­6:$8y¯F¾×e…ù­…Xd¡…d6׈Þ®*¸3ΊâMà,�¸ÐF™ÙQ]¢m;”üËO¾ª8³j‰¯“y!]W#15�É _??©©¢W­›Ÿì©á&ðƒ#n´çO>¡µçûqVáw?,íùÚž?JäoÈq²H 7éUë¾X­.T®¨Vø˜*z5¢µíÈ¿ c÷GñyÕS?ß9U—Åú ßpS±¾$‰ºõ£Lþ†'‹�/s9µrpÞ¬*ºü¡PL­ÇÝþ”µ=¿äñâàîÇy®„;w†’Ÿíï9EÊSšG˜ü¡b²´_ – žÁÄàh‘OßÛÙ`ä“…ü\Óø*”!¿�t³BDî›§äS�ùÃÆd!™1Æ¿j "_{1'ìÊ×k©Îï¿Æ|7ù-J>Õå%Èq²PÒÇo[âa­bŒC«œèäS�±­Œ¡²$¦Û»5ç�|k�ߎšx4-•’Oµúä7Nr§Êø•K2¶±ùL¬)±r‡|}¨¬¤§{uæ<îR߆%[¡P M9¥vÊKɧºìä'«Ä(wª@m5òùròõV‹xÏ8°æ¼îíaXb i#ÂÁ/Ž*%Ÿêr{;ÆÉÂ# bóMz0ý|ÀÞ$¿Œ.hó­aX"Oz!÷9Ýn·£HɧºÜ5Ü1YëppŒÔO¾>¶•Iþb~¾5 K ¦Y Û¢5\ªhÕ´�ÉÊr²¢(þ˜8öÐ _ÛÊ$…]Ò–#æ»ç�|kÔpS®*8%t.Û¦äS­2ù}²�É Äÿ|‹ž¸´A¾1¶•I¾Ñ~ˆwÏ»ºÃ°p«fÊ­ ¬‡s†©Í§ºìä¯û˜,Ú‹8íKy ÖuL%Ÿ’¿!D½êíPò)ù”|J>%Ÿ’OɧäSò‰6dL%Ÿ’¿1c²(ù”ü¥Ž“^¶vý¥¶‚—’OµÒä“%ùYÎ7eíjòs¸¯ÊL÷¼®Pò©.?ùCÆdµø¤ZÏ—J¾ÐjfXÙ:ߨDYi“/³~ÊëÚ ¸˜¬ªÖÑq•ŒvÕJ|´wAÈë)ùñë“IÿÉØ“p,àñÉ:éðÁNXÈÇŸ!¸{ ÎWÆ�\>W¸…ZAž È„üs!ΓòNæQ‡3Ñ‚-E<î©!?œXŒü Ÿ’¿VÈ*&«%üÏöΟGY kãáÉ@(È Þ††’ŠŠÎÊÊÊ@cç7°¥¶¤µ°°ÙÆÂØYYRØ�m -¡“䎅‘8ïÌÀ(þÁuï{wÕõœdU„e]ýy8 s�«1¡^',çwítÓðp@ÖÎ¥ 7•pÛláTìfR‚›jŠ;-Nz>¨ÌZ.ÈŠ$3¾å}y�7Ï­çÁzC„õ¶³Ž5/ÈNâ˜,­Ã'iŽÇêÈ7ArOZ‡¿Í®�?v| ÿIɯÑdÅž&’´ÌÈ—HQ)8 E‰5`ÎYS÷éªF€›]¶XÖõ‚ÐÇ'äÏ„-óTÑGX!‰¼ë±u‰ˆË‰ÌØ7q$Mèц. 6ÿWøý0ùýta5ëšæŸ“¿Ñ—@þ³V;5š,ʦc3ò7‚¦ëº´cß‚†Ïêü¹†;ˆ<«ôøbIúºÝÀç9Ÿùh9}6µ¹×Æ»®®¨Â–�¿¦ý…G&» Fº¦Ý·çRÑ¡DLîA~–õŒ}KqÖ:œT;!êt9v‘Þ5ªÝ»ÈÖ3ÜËš¬\©ÌùÅTü€¶�4uß=œðÈÇ[er^çïs~A~`¦8aäcDj#v0Á+×Ûçü;’YnÆ[гœOɺÙ;ZdM'‰ô ùïÚÈÚQÍËš¬¸m—ŽS¸]uí'cR}»ZqÔI�Ÿogñ)ùØ'¥J©Ïbc;ž’:\ÔùùôKÓ)Èo·ñÆ$ÕÎ<Ï›©ó3Vçß�|R­™ïo)~ Ÿ¼AÖ IÉïWȨdSTØg ÿ,.k²V-U”›)fnWyWuŸŽ¸ :âÂQ_ØHr–gäÿA®Ï¢ãùJƒ1èØNˆ9ùk‡Úd1ò³†étMšHrWxÝ’•N~Ïœ¿š*ï²¥øž|Dîí –´:�¿IÓ”œþ°OIþ횬Ÿê’vÇñ|Zçûæ¾¥xtLþYΧÕÎÓ’�oÕd½ù©4ä-ÅYëð ù§u>ij“[¼ùYÇâ-ÅYëð ùllÇò_�üçˆïž½Ðs�| ÿÕÈçY¨@>�ÿjäÏ4¤tV@þ¯!4Y0Kù5ÉM�ÿšä É*ç– ö询ò‹u#DÖȇ¸¿&«˜hÃnë>']ïæjtOÚáïɱ*¿äCÜ…ü5Y¡˜ãT•sfj�9ùWâŒüª+¯lxN~äCüù·i²rÂì°i“õ¤Ú骢1¥·E}Ñ—åaùô¶á&YôK=Vé—õn#¹½-í¶Fò€|ˆ‡ðÉr|ì]rÓÄ#h²HI.„eÚIá¸ÚéèNǸBþ©ëùÔ/+2-go·54lÏò!À' ÈòÁ' Èòa–2�äCù@>Äc‘¯Ïx½>áé£(guÔ6°®Ÿ?ËÆΣݻ}âßþ ÿ—�O;S N=ù1eêýí;ɯŸ?[Cþ4¼}âßþ›#4YD`בl·Ûüòÿ->"¿Œüfò¡Ú©À@“UmA­Y•üF÷˜|Fm<ºì«R#eä;ŒÇ¦-i£ÁÁ? â5€ÒgxdˆªÏ.t൰-mJÂêÖfÇBvL/’¿Ê®8:ô¡9,¦ÁšëI×éàw I­’|_VÈF|oÃbo¤Úáþå˩̤åÑ(gå⮤š/Øô[SóùŸôÉz%ò鲩~D>nw0îÛx¨D›¦[%Ÿå| ÷¨x Œ¥ù.^âI´ QÈÉ/mJÂêÖ¦æù&ÆÚ²oŽEJ´aØ:[ÌÉw{8/ꙥÐÞFÒì°·ÙÎ òK‚òåTfÒò�Ø(få´xÓ äóEB¾ÐÃ ŠŸŒü[}²ÊÏ´,fY*«,#ËÏ_ƒü,› %D²6Éþ"R[òé Õ.žŠì€%äTÈ.�Ï{IW¼ÜÉfÛçä—6¥aAukÓ£$¹-ÙÉ’¸ÄÝb9›óT’ßhs$—´';Ù¸²·�T�_ú”/§2“–o´/ÜBö_E……]dä“i�žŒü5YGäylµqu9ªî‹�¿òdšó#q�úrršóé Õ ï”y"f¤ô FÈçþ•î»Vá¤:ªŠ:ûj‡ÙpÂêÖ&ý¢H!öºX-E��:È'†pò“–d»^Ò?ÞwO÷FÉ/;ö–/§2·¤ú'ËY¹ô¿ÊhÎ/å$DgðläߦÉ:&ŸÙš-ã…°ÿxyÙ÷/îV�J¾(‹Ú%¿ç�Emp¹Ú!ÀÐdYÉùn@Í0Îsþ�ü2ç«ÁŽK~“œ ´Š¡6¥aAuk™óq¨N¹�қʻùÒ’|ºlÒÔDL�r~¹·Jί%¿’óù’[¼Ö IDAT¬Ü2çóÅ'&ÿ6MÖ1ù‰Õ8!ëþžü²ìûw«G%ß}Oб�Ö8¶F~1¶Êô¬s ¾oš…ýW¯�7–…7„Õ¢Î/ü*äOä9&u>©ñc©Cê¥5öHµSØ”†Õ9¬MiAë|ò¾]>œ#9Þa2 ¶ûä:x˜â…¸*ëü<’¦û½UêüZò+u>Ÿ•[ÖùûÅ_C~�&ë¸ÎÌä”|»s ¿(ûþÅÝê�ëü‚|žó›Ý³ñ|Z·ëì¬ÓW%·ÛÉæSQ»Ú�í„Gþ28ÐE}†‡ºÝ¤™º£Ù¾°-mJÂêÖrl‡à)¼ïÏHª9�¿0-·ÙÁžŒJKâÊØN±7 yæä:ù|#v +fåÚ'q¹ø{ª�MÖqΕðJÎ/߈ñ{xxò#qÈê|¯yçÙ tHç¯c'EµÑB~þñü[5Y§u¾u²*öÅìK�Ÿ dβ,4Pãžäo¬àou¼É{úîÓåã]æ¶ŸŸü[5Y´¸ïÚ*l¤ žù•±�`^³¿˜ü‡›±6�¿Nn#ÉŽ>¿Qn"¹¹ú…×pk4Y´Äac eŽ'E+Ïût<ߤãùe1 äC<#ù5š,uü¤ï�äßgš¬|r÷Ü äùw˜¥ÜVúÈò_�ü' Èò�| Èò�ü³M�ÿšäƒ& ÈMò?¡ÉâÊûNçÊÊËñCêÐKz)_Œ›5Y—…W\y_’ïÑÛ;]I1w~7ùßw×d]^qò›ÛíöR�äC<ùŸÑdQáU!¹çíhAón!§]’_¨©Ku?]Yhø—’¨|3m¤ø„|iS â^äF“¥û\r_¶ pïô^>�È/ÕýŒüÒ ‹æü’üyâ@ä}ȇxò¯j²ìp-äíÜ!"Ç·$ŸöH¹ºŸ‘ÏݰäûEåC%[ù÷K¶€| ÿ¶jçª&‹æüBr_¶ p�©~Å+Éo¼v\ÝÏÈ/ý!*ä—]2~h3�äßv†{M“ s.¹/Û ÐœO•i�£j§T÷Ÿ’_j¶xÎò!îHþ횬BxÅ%÷¼½­ó‡xyZç3u…ü‰žï5[¼Îò!îHþYÔi²¸ðª”Ü—í(Ü‘e¹­Ó±ªî¯�Ÿ;HÝ7 -¤ô�|ˆÇ"|² ^”| >Y¯Jþo Èò�| ȇò�| Ÿh² ^“|ÐdA¼&ù×4YÚȇø äߪÉÂØF›Zò=Au/½ú‡.YŪs â>äߪɱ êÉoå«™­]ë°;R/XÅž�Ÿù?Fþ�š,ܳ:NAþ»�äööÈ•Í×Ù¨=æêj/qîJȉ®ªŒübÓÂ#vÝ��¹öY è4:ˆ™¸ù?Fþmš,¬û jòDÈ�¦ybúG.¨ÅLµ¶ƒ§J¸óMœëMû Èª�_zÄúîvnYÎO¥Án&%…‰+�q/òk4Ys!ņ¿¯vî‘ jA~ϢΔËKºTqU-ê|I’FÜ/°o-xµÓ§‡’FÀMÿ€|ˆûT;5š,šÁ{#?mjªlù‚ís¾¥èº.Ïv]]Q…íÞgŒ’¯ò6Ü#vÛÕäÎŽ‘ßAäW”^akökȯؤW"’«¿UúÍAÜã ÷²&k‹DYFBHÉoµ7Ô—ìŒ|Zç»Eá˜)NNÈ/ªî‹ñ»6däûe÷‘'ßÑšQJ Qj.ɃeS�]Õϲ >÷ éóf?‚ w>"ßäÖ¦'ëßfüQÛý�Žj^Öd Qœ¦©í1WcoìSòÙØN†'Jˆÿ w”æÎEòK�Øé;^é#füMêü|;‹ï@~?�Ûz–ù(ˆCÇH³Ds¸/Œü!dC¾š¦3)øˆ|�|9"EœÖî Èÿñ+Y—5Y+Ö‡RNÏpMËéž�¿ÏHiâµc8ý‹ä—±�†”}õñÂF’³¼ùY6V©äS&e?ë©äŸõäY5@ÃìïÈ'�œ.#Ÿücù%-YñÒlÕ‘Ÿ“ßÕ²¬ëòm²ÁÐ$ 2Ò&¬Ú tQùw¸†û2š,B~âYÙDˆY’u2»M,…Yf8èíÓŸÐ ž„”üÕ\RòWz'�¸[vé½,P‰ÃÉÌI¦…ògÊ2[D”ü¡4Y-Âl.ÆýÏ’�_E“E ËÑ$ŠìýíZ$³Gâ(3D3ý»�‰Öù‚»¢äÏÙG«�¡)=•Èœ=ÄpòýÖÄÌäÏ¥QZœáºp’{Gò_c–2ÉùéEs¾oÙ‡>­v"²#BþP£_(7Þ³l"eôÔ9Þ“¿”›~…ü¬o"÷�’oÀ:�ÿýu~¦):­óS²*6�ôoÉÏ|õRÎ'&Ü“Ÿ9â’’ïú”zö�sÚ�ó�üÛI’à‹±½Û Ä>ûRÄ©Yþ†ü4�lg_磢Î7H�o¤Yë@~D^!¿ëf‰efá$Mm^çG!ðäïx¾Ö¯Žç¿7$ÑÊÃÁRoüú´Î—܈�í„åØNS’ÙØŽnûòÙÅ4‹Ýî˜Ù”¼wÉÆvúº¨Á5æû�š,ˆ×$4Y¯Iþ->Yí^­ V»äC<ßì…:Ÿ,1¥h@…{òw¾!ÊΤº ȇxtòoöÉ’¼#òñÁú°©�ÓÕ¨ÕÄS‘«OVOLù¥‚êPí„BTnSXhÑUKÔ—¥ÁLGtnŽ!ª>>’pý>òÁ¾óé\AoöÉ´Ú”|® :�ßÛ¸…!_ð¶oÈMc)Ä“h¢ðHÂõ ɇáão‰Ÿ$¿Î'k‹1!Ÿ+¨äSyîV–åB~®…ùkŒÑ¤°I¡'½þ‘„ ȇxòoôÉ`¯EÈç ª“œŸFBÊ-´Xµƒ ©IÓÇ¡£ª¤ê©Njò!îOþ­>Yœˆr® :­óS!åZ'ä«ÁŽzˆùEþÍ>Y„YO2ö ªÊx~C¯VaÅ-´NÈ'5~,ùFþYÔùdQÝ H¥‚ªB~ÞÓEäL÷Z'äu»Ùò!�|ðÉò_”| >YÿLþåŒ�ÎÕWJAÜ—üß?J>kd²ø€ü‘Ð$·³³öºë>|Z@þ“Ï»Au…âäy摯ÈkŒ[º�ÿä�ÊËé‹·YÖ·kɧ£¼ùEë\<1= ¼[Èi—äëÍÞÈ]Ïi ]sBWJ-Ví$ µàCòˆüUšÎ…8M©NëùëŽÅÈ/[çÆâ[Þ—×;½—ODNþÄÁƒ† ßíá´{‘š¬Ë Eg�…$ªFÙ Ù‹ã:_@3\v¢£m}ZÓè£å»œü�’8ã ù�v\œáFâh¿#ù ÉºNþ>ç�äÙªg¬Žrþv„bJ~Ù:·C;Ì9ý1½îqòIůäò“–Ä®‘ã±°ß“ü[4YÅgý´¬ñ’Ï:„Èáq��•Á…œ/“»Æžü…àa²&RÈ¢Ê>½‰˜BÎÿQòoÖd·îñšŸŽ\IÔ»«_B¾)kš&OŽÆv6âãtÙ:7ÇE�?ÄË}��ñ,¥äoP„GÂS¼WE�¿†:ÿgÈ¿Y“u+ùWý´¢­£Î°ú\~…ü݃çüÞ…ñ|=Ø�í¸åØNH¾ò–å¶ä“ Gƒ�fyÆ{2ÒåØŽ$ÁØÎÏ�«&+8øcôV¥-VázUlxÕOËášÅÃ:£‰GòùMÏ1,rª—6$*âjz¶ºxLò‡ZZÔùÊt+˜½ðœäß¨É þX½Ui‹Uº^±¸ê§%ò¿µ_×%G q’÷B¾šâIx¶·‰õn*É£V;©ƒ”blÇ•�ÿ;ȯÓdÕóÇ:è­J[¬ÒõŠÆU?­µ@žíÉr÷h_tÊ.òÉÓSƒœå‘íûMÜìU—-ù@þÝ5YÁ‘?VI¾»§“º^áý´Š:¿í­óé“ÊžüH*¾C@>ÄCh²‚#¬’üÒ«t½Âúi-Dï}ýNVW×Åh‰‡Âž|lyë]ù�¡É Žü±JòK[¬Òõ è§….µîêhÙ‰í™òÓ¦Œ¬ �ñš,uü¤ï�äßgš¬|"&@>�ÿëÉ?‹¶ò´z! ÈÍò�| Èò�|è¥üâ½”/h²€ü×$4YPí¼fµóš¬“˜˜ÅÕ¯ó~JÖȇ¸ù·i²r^ü\ÝW­àªJþi?% â.äߨÉÚn·òÛv[­}òýM—WçäŸ�qòoÔda,Ó¿’wU©½Æ�ÓÒ}v#œWÔ7±"¸âÝ•–Ùá? dô òCuL«®¾*ÅX@>Ä=È¿M“U’ßµÓMÃÃ�0ÅÅ í¤Ñ/úäíW¼»’ÑÍç(ÄmgkŒü™2cu~©¾âb, âȯÑd•äKä”7Rp`у½ •¶ØD̃àªì´± Ý•ÚµŽÀ>%¿§„Ån©¾âb, âª�MVAþFÐt]—võ b7ؘ,Y›‘ŠàŠwW¢=z�µ@ÎyG”|¹]Ží”ó‘¹ ȇx€3ÜMÏùÅYj…|¿Õ-ÛdìW§9?"ÛRò'Fïˆ|.Æú=ä÷M±ÍÞUtÉ÷}Ý’í<‚A€ÎÉ�>ªY£ÉÚ×ù1NÆUò¤N÷c;…àŠwWâu~oLVç§z¯J>c= ù‘¸è;—Ⱦµ(ù9úÓ ïNÇH2—|½Q´Ýæ€ñc‘5š¬ÃØŽ¨ûUò±£ð±N.¸âݕʱ�¬a:Ýbl'Ñü ù\Œõ äÏ$šýkä'þù�îqµãQòiÁw!Å�.f¾ñäñðäÚ'«Ýyè÷îfòçb;L&öðÓÊãÈŸá©Er>yŒ4­ð?<ùøs>Yñƒ'´›Éw\Ö&?ËFäˆ5Ë2¥cê­4shA#QWoÐj'4‘ÓòùmQ}Ë©­3òJ´n’2.uÁúC–£ES]Ç�Oþ'¢+vñ¯ %x1?H}9É;]9�l`�÷¥¡ÐÉV„ü)çÆ"!_ì§¾Z“óqO•{b„]7]{6{~'M�ã_EþÃÇ­ä'Bùd�Ö1Ú SÈ7a¤e©f^+ …„�áÎ$rTp ù&©~„¸†|s´ÁêˆV=EÛE >$ ÿ±s¾G«ÛÏ”)­ý³¬ÝY)ã,DÅØÎP'÷m¯¨óÅè„ü|ëµ¶9^…YH[,6ÜÕÆÓq4IOÎà³òºÎßçü ËZ–MÕ7uµ'ŸóKò›Gäwé„ÖŽ Q¡Ó†„ì 9 ø(Ÿü×ÔdÍE��íDâ°¨óÍelvÈ Ý ·œü}�_’ï5áîï!ÿE5Y|<h “Žíô4Ô¤™]!<�ŸÍMÑnvöä‡jù¿…ü5YEk@òEq~ù'¡ÌÊ�yºÊõaÞÎÓ“ÿŸ¬)ÚOgPç7“¿AµëG–ˆ¬ lòSëèºîä=’\ä?;ùŸðÉ£7üä$¡¦3a€úñzÖHšü‘èT¯Ýf}êis5ù7ûd�¨OJîJȉ±'Èj°D�"ùù¡…ŒÉÞâ*pZ†Î¯Ü8‹Žs(=KkæU׬­Ä%¹ë¶¬tó½–«Ü´ôÒâ‹?M>ÌRþíäßè“å"Šr¬7Ô…å|ÁÛ„bLÉO¥Án&%Üâ*æx¬¿˜ ŸNÔWÜ<·‚ªkÖ\àbõ¶³J Ÿk¹ø¦¥—_ò_›|Šþ]|²�ÅMŠélË‚ü5ÆÖˆ’Ïôˆ�€[\QµÖN(.Ýô œ !á—|qº^Õ5kLû�8²,ç¯Rm¸R²$q-ß´ôÒâ‹@þ‹’ò þ¼OÖÓÍq`¦¤~9#ß/¦ês‹« ù¡€dY”ò äo+aôáYÎ/6-½´€| ÿ;Èÿ„OÖÊhì(âB>�WÈ'u~¾�ÅÜâªB¾g§i£Ñò‹±�¹<$u~VÔùã¢Î/6-½´€| ÿ;È?‹zŸ,œÍÌ1œ>!¤¢~…|¼°‘ä,¹ÅÕ�ü\b_-ϽD>ÏÍ Çë–¬tò½–«Ü´ôÒò�ü!ÿÓš¬è¥üì½”Œ|ü9M�äÿòS@µÕ�äù@>�äù@>�Ï|²€ü×$|²€ü×$ÿš&ëÔæ cíŠn‹n½kH.ýáÓøË¦„@>Ä]É¿Y“E}Q†Æ™ÍÕù+OÕVT,ЭÇfÎ~Þߊ)ž@>Ä#�³&KòŠî¨ø:ùkÝ ÿÄý¢ñ““ôÅ âaÈ¿U“ÕJ>­_¶]Y+® "äsõ¦�ãù4~¥gjdë@"‡ò�j‡I¹×CÚȇ¸7ù7j²­6'¿cÅ»pÍT„|®žÂÅTü’|g˶æ9PJ¹q�÷Õ'$?0D©¹¼F>›¬íy\”9Ò‘ÒzŸ…ü:MÖ ã’|‰Õ7|6}Yí Š"ÆìØdÙ.ÌP.’oQÝìéÈ÷Q‡Ž‘^!?Wx'‡\”‰æ8‹€Þg©vê4Yìµ ò73å *B>WO•9?OûF1¹ø"ùÁÖ‘ŸJ´ÉN*û™:Éažõ�¬Ñ¶u+ªT;nO4ÌE™Rzi>Ñn�&k@0îÕä|®žbu>=3ü>ò'BLïÚm¥ÙR}z×PßËö‚Ü-ÈÂÍæ¢Ì¹#Ú!Ðû,£šuš¬©`¥ã:Ìë|®ž*ÇvÖ‰WC>•r=)ùÃÂ#«kÑd¯ûn¦N³F'ËÞŒ ù[)ã½(“,÷  ÷AÉ?‹:MÖ€–±åØNg?¶²±®žbµn[åÖûeò©”ëésþB|W9Ó¬Ñ#ϫձ�¶A�" Qæf¸Á} ÿiÈMVM��x�Ÿ)^#3=;»@þ\ ªúB”¹¶K OB>MÖ•±�‚ ±Ÿyb÷ù‰'µÏLþoŠoÏ÷…E6¤æBgäï:MxÇ�üßFþÇ×p·¢Ã;ä¿ù@>�ñ„äƒ& ÈMòA“ä¿&ù7úd]ŒsÍV}LL â^äÿ¥OV5ÎTX@>Äã“ÿ—>Y•8WaùO@þç|²¸!VÅ»j¯ÂZ¢žÑ¤ÕŽÒ×E/±Eg�[=œ >ŽÑŽl'5R²•ƒôÆÈèùw$ÿS>YÜ«â]µWa-…nQç+vKÖbmû8pðPsÙ�mš.ÞÝ|ŽBÜvÖ±äC<ù×}²JC¬ªwÕ^…Å|³ùäõ¸r4hÒdïõÜòéLf’þ³"GжÇlRü_D>ijõRþ¤OViˆUusØ«°˜)#Ÿ¬lúÅL|54b+ÒBlÒ³c1SŸÄ^cM=²F@>ÄýÈÿœOViˆU%¯ÂºH~«£âNWÌÏr~DÖCµñ8£š×}²¸!V…ü½ ë"ùjá "5Ò@}ß4�C�߯ȇ¸ùgqÝ'kWbU½«¸ ë"ùK!Àk±ÇŽ ’{ÛɦÓò!‡|Ðdù/J>M�ÿªäÿ¦ò�| Èò�| Èò¿ŒüuC¤=d»ì" íÁ¨G¸'¡6½†¡ …ó{»�}UtW¿Û¢ìíà#zòA“uÒjGHn$¿m§s4Ãùv»íÒ–S±Š‡ò"1º÷§zA¾äèOÃÅØj­—4[~ ò_R“5QjÉo“Õšwè!¾/�¿£³úÚ-öX§óùúmìtéU<úŒÁÈ�tÜè�|O Ò”]Άø€üä 4Yíb¢Ï–Î]{6òÕ4é‹‹Zòérl©ñUòc:©Ï®ÏÍEú8c¬)æë=ù~§$†{4ç�ïû�ÿMÖy°g‡Úï ŸÜˆƒ,[º’Ò#ˆ¨’»UGR|F>Y�(Ý,´�ÔJ3CPÕ0 td/äGTÎ0ÐÙ;A[Nm¥ –ȇ“°š¿ ßžâ�­›Â‡º ´�î;‘ÿ MÖ¯'? „0ˬvéƒl®¦h’ê"q8ùYËÉ·ôÝì9$ÏV=cu!ço™šaL§çü?ùrôT¹'F[©»I¬.àýù£ù¬wÐda®ª*eYGäwUјäwe5 ŸtÞU¥ön[Ô}Y&ŒHõ™vËÔü‡#ŸžÐûY6Ó,óçY³—9$ïÏöäw͢ϠS�ïvÉ�VêüYY畽GN_i�?<ÔùÃr²ëmbjÓ·ï�r>ÞírÛÍf½^ÿ¼&+àª*.Ë:"�îrh'äÔxíò»vºix8‡yGõ6o$×M¢]ˆB¼z8Añãåü¤åÒ>ùš¦©N6µUy™Aꟸšóߪ"™ù¦L¶•'Õ±�UHég¼c¬-1-mR“,å[#Øîp‹¼c«0 ï”^žÚPîÜH>ÿ{ɯÓd|†=—e±gEI’PYíh!%Ÿnµ äSc•Ha®Xt£eÁ†OÈ'{ô€u~ª ³¹´bËj•µ¼Ì!‡��“Ÿ’:¿ÑJ²ÀÌ"–ó{çãù2¦Lúß¾³Š¿[ŒçÛô˜2Æ I±!*´,¤§ Íà}/òoÔd\UÅeYìYŸàМo)ª8¡äÓ­2a½4²™´c3•éôee�CGUQ§Xt�x†Û3³•å%«p’¡YI^iÖ*Æv≭ƴüI-3K„ˆT Êt«ºk¸þùˆehÍ�BþÍš,žó}÷ü 7FÔ—‘ïö‹3:iQœ5TÈWƒn?4ù1eˆŒÌahv£áe«ŽnûÕñü¹a9Rîw$4§�Å•F-ùÃscÄ1ÿ†üa«Icø•äB“Uªª¸,«JþBÞà±ÀȘ¤Ügu~Œ“ñù¤Æ�¥G%æíòãȧ"Ò©ÈË*ùèHk˜ H’$±½/Š*>ZUò©uÖÀ`;ÝQ‰*�äÿdµS¯É"‘65U¶äS‘Š¥èº.ÏŽªO�«äÏ t­6ÞuuE¶Ug‰ ùkÚšc.;ýº r¿—üf÷øþ(ú6�ÿÉ3ÜzMݺ½ÁB¾´¤X¤®á ·­%çÕN`¦8©%Ÿó–|&¶j¿žPÆÇ¬$UT»É~9Ïy:}îïÉïtv±x•ü¤¼Èè�&©oŸ‘¿Bz7\þ€üÚQÍZMÖv»Í å›�o÷qŒJò'Jˆÿ w'£š-=ÅÁø˜|ªcì\$¢Óž«NÆêü/&?ù€üFòþf©ïµä7´·å›Öüò A@–Ÿï——'h�ÉsNþº¿Û©óúœDZ4ˆcú]¬'¿î› ä×F�&‹~8ÍÈ´œ.í¦`Zn³$ ¤4OÇówM#u:Çä¯*׺D~î ¯[²ÒÉž| “ÒMç´BL޲â—�iL„9¹� ³Ôî§éÀL AQf¾íÉâ‚ìÁ+ž«'?Èã¡êÖ“¯nHìs>�kä“�Œø‰ŠÎÈŸXHVÉ'ÕNì"d,Ùÿäß¿Í'ëòÓ–�ÎGIdt‹É“èìNïqòY~÷…Q:FKNþ9? 7 ’Ô‡´Õ=¨jT>.È/î# 9mVíx‚¬“¿Ïùï(HÞÐâ˜üž§“rþgâ7ùd�ô¦«!¿cç…Ρ: �éúâTÑöŽÉ§ß«ÿ òwzo7‰òÍ‹œ_>®�Ÿë½|"uþm9O~�Þ»þ ùæª�Wž¥|<ǵ.ç;iÄš§¤ðÇõ9Ÿ¡Öý ùvQÇ´üCµÓòË:_"±9pÿŠ|iš¦t�ÉO©ó±ä´Õ#¿|ÌÈ/®X‡2½.ø)òZÂî#©Ÿ$oaAþœ|�Bþhž¾kû€| ¿~<Æš§¥i  Ÿ?.ÆóQí–Žn{äIOB3ßi mHކá�œÏž»B~ž 5óV[k:ØU>.È/Ævô!^ŠùÖà&ò)llgj!É.Égƒý„|_e¯ø€üÛâwi²Ž{Ó}Ñ5\ßùà.>F¦ÏL%X«-ÚdvÁSòÙ[=Ä‘e¹­‚ü‘çÚ£IDATŠúWȇ٠ Éº)çWzÓ݃ü/ ÿGÈ¿A“¸ÿ°ÿv¯:7¿2¿ÿÛª�Co: ȯ™½P§Éf˜r…üмÄF\¯L™†È_÷¿‘üCoºB“õíñåäÙ+òëf¬Õj²òØj_#??� Òà ù•ø^ nÍnøÊä‡@~Í,åk>Y&®§�1Ã{7,§¥w™°ª˜ûcuœKä—[¤ÚáÂ+JþAÓÕôÊ¿�ühAŽúßiºørò¿æ%“Wùœü›5Y‰Õ¨§‚Ýe{7,*Î:ä|Ý_f)s‡-J~)¼"äW4]M5Å�Ö·“ŸEáô[#Œ¦_}äú¢—þðZ“%‚™&ÑÓìn ªnXòçBŠ ¿B~©Éâ[”üRxEȯhºš]òßOþ÷G~é?þ‚å‰5Y¡„S b¿ê†u Ÿjm{F…üR“Ŷ(ùåTdB~EÓE§.ϵoŸ·ó#èO¿°ÁÌÀ¯#âÖn~ùðf@ù@>�äC@ù@>�äC@ù@>ÄOÇdäC¼bl€|¨v€|ˆ—)u Ú�xÍRª¨v€|ˆ×)u Ú�xÍRª¨v€|ˆ×)u Ú�xÍRª¨v ^-€| âµÈÿßÿA@¼Züï¿ÿùÏ! ^/þóÿÎW¡7ÇVX©IEND®B`‚TreeLine-3.2.1/docs/treeline_sm.png000066400000000000000000001370471506556630100172130ustar00rootroot00000000000000‰PNG  IHDRﮎS~61¬zTXtRaw profile type exifxÚ­œY–¹ŽDÿ¹Š·ÎÃr8žÓ;èå÷5z䨡¤®W*e¦"#Üé$`0@šý¿ÿsÌþóç]¨&¦RsËÙò_l±ùÎÕ>ÿõûÕÙx¿Þÿöyýä¾¾nú~ýèùøž_Ôüº˜~ïy¿½>Ÿï®ózút¡¶_¿_Ñ_òõuƒ×ëo7 î¹��#z~á_wŽÏ¿ÇóX6·Z>?Â|½ÿ¼~§�¿F_b(>§ìJäkô¶”Üø¹z ó¶4PŸ^|]ðû¿ÍÛ[=cò;¸`ùê5ÂÀðC �ïúÊÏ^¯äû³å+ÿ=bµ¼±…ŸÛÛ¼þþ¿ß�ܼ ýµä_–ôý§oK½Þîøi¥Í�з·„o+”ß¿ÿôu—>^7Ÿ—ô®Û§;çünc_^?Û¯/Ïü¶jú{Ϊçìçéz̽™aÆ™fžeÖÙf_~……¯¼Êª«­¾ÝÆ”vÜiç]vÝm÷ƒ©�pâI'Ÿrêiæô÷U{-ëþbÕÜkÕü])½±¼¯¯–òv '8IZ3VÌGÇ‚­€ Æ{­™­.F¯•ÓšÙæñŠädÒâ,§cãv>÷¾v+— Ðù_Y7ÃBøÿÆÊ-ݬÜ�ëö³U[ýºpWHn¨IµïÛµL?zÎÜ Ê|*ž\wÌÍ=äÐ{ÓÓ[FéÌifà¡pÿ“â`ÀLqÆ‘¸H `š™1­Yòqc¬à£âJåä�3E3çÈaŽºK‘½=kÎrRæÎ+LÕbŠËÚ±Ì>OÃlÌÑWØyå�oÛ‡cVm;œsD=Bl‡'îÐö½ž=霉Dîp¶Þ“¾Î”J?q�½uo‡-˜]ZKqîda{¯6™f¢ÕÊÕöÚ…52x:Z¶¡¥Ðlià‰ E÷á­34�ö�[sÇ·›ëÖÜØ]ÊaþÏ�}9‹†ÞY;“ÄË3,Å0¼5wª@ÑÁ Öà¢LØò½Œ³xˆß±ŒéŠe´¬XøÕrsc7¥²èÙ]_;ç59Ö>Óâ™ GYf‡¥ÇN'39•9 ÚÍÜa¢˜âÊmæÝSd¡ð  ²C2¶°†UÜ^Ëš—xø»BÁ‹‹i¸à±cwÖòðÉ«MsFW}ar5¶µ1bŒ¿q»Í ®Ø'¾‹ ½u"Ÿa¢j kÚ6Ÿéd.ÌM˜|´¥]�å³óŒˆKµµ†±�ÙX¹ø�Ìc™âw;q¸°–ÕùÙÜìð®2õyþ`ø„5Ya­2¿­0A~� W: NÙ:zʤ Gû¤ÅS&�Ï­U±)»C?D Îªwü ô7_Xvî Å` "ˆHLžÈ´®R'ö2Î8™œ.âd?uôa]‹£Gâg2ͧµŽÌ'£p,I?»ï†‘,–!ó+f�AYnÅÂa±Ð�–çfð²½]X’`µÎù:ö ­0ÌE�(¡óqyÛÊÜ6ž¸±µh{]þ4�”¼Sžp[–µ;á|NY|›m¹’˜x`2€4S�ÄŒ™+^H“œ•Kš‡› u‰swà{/ä¯úJiGï–¬o€¹8_˜e39cÌ �Š@>ÑÛ´™‰Žmz°à2¶âˆM›óÆNW ÀˆŒaù�k�îq‹Fˆ88&áce{ž°l!Ô¤` ô5º wŒU�¡à{c·Øb•mÍ�Ébv®�üØ¢E@[Xx¨Ÿ_•/ dÙÆÈ˜�=–Åsn Ø¨uíícÄ;¸}K�™g±aàåÜ1¤¼tÒHóéŽè5'‹ˆ˜pó0én*°\´ØrL½ÇwuA³àzv®®Šf)s³ù.ï�LÂXÀáÂ⳺lHcU‹…a¢Ü>æ}Z0 �@I‰ Ü[6YÚs3ÿQ¢'/%"?ƒY‘˜¶=Ë2힊L[¸Âò±>~Z7‡ltÛÀkhà$/c£]óĸ—=³`µ³`ë`EÏ[ÝÆhñËyȆ1%EE‚Þ0íøÍs·›¹ x:P°ÉË–e¹mÿ“à`~Jz¿€°ÆaVñ.L´¦ò ½ý ÍŸÃÑu@Ð]?üåÂæû•Ÿ 7¦–ˆw;¸h‰Aïòø3 D>Ï ãœÍ ácc^Lëöõo,¢_zî4Ö±e,<6…ò˜¥ó£Ø 8 œšP³¡àýÁ!Ô„`ñ�2s¯`¤»j—ö�¼íDø.Äù‚ôš•ËÔƒI ytÓ›�<ààRÕ?Wœ ®ƒÇÖ{ƒ…âW Éu¦‘8“æ‚Ý¸ŠŠ3zëHf ì¢ <†ÈÂ+D‹”¸Öêù�AFŠÓ!-Ú^àk‰àWÚð8µƒàùu°¶i2“ ºÃP ñýµ(¬Æ@YÉ„Vd=!OŒ÷(êÏ@AiBA]%Â!½M ‚’{­!e;qØ@Y'sC 碀JÂzÁIDèⴭݱ™<¤‹ %'ÏD, {âWÖñ*úµº%ìk¬L77¯Ýk)!ìå]ËDŒ¸ Ÿ,\8ìD¨gt8,¸X™ºæàà�X‚‹msAÏs€zKYÈÑ™Thm'\ƒ¶�Z7BvÑ—�gŽ›€Æ´oJËÉX'`”Õ2Å2šYáíD>´Ãñ°•Ž®«ÃlD+�^à‰*.¬ç†õ¦‹H5¡ÚÀª'ÊÄ�^(±· êpÆŽW!j„°•°á¹±3aSû¢NŸ�0aM‘‹v"*Ñ3I‘%[ Ôº[3và |L :‘ÇQàÜ�/¶5#WŒ(ø¦•a•p|ˆ-$ªQr"íÎXô! Ï€ÈZÑ-™Ñ"ßˆî¬ ,5å�7¬Ê¢f� ëµ§ÖÅb”\…*†x „ð6?RuÜ&¡‚0 ù¦¦i2ð‘Þ‘/Å#üpTï)<±d¸º«±Œ�3`±,ÅQ™”±-0¤tùH”DÓ1Y8,šÊÉ»³Ã¿“3ÉbW™ØàÆ Œ‡àü£Àh›‡cm¹#Á„f™87$è\O5de®²Sñ›àÛ@ò¬˜oŠÉZæ –2Ñ_s"7:fâ˜îáÚØâ(„P'¼�åß LZLZt…g ‚j�*ÚLQ?"e ©Ûî1?丢i•GÌÃ,&GŒßÐ¤{ã¹Àfø=ÔV5nm»âŽüÖ˜UÜ6XÞ´N0�}3]8ƒ%)gÐу!b1òZpÂx\¢äJ=îI/B«|¡È|{˜ ÑG<Í¡@‚"ŸˆZHn(Ï`‚ôÍɬŽPæ:%€nkP'#LJ–p38z”Ê舔1~H«]‹§^i¸ˆvO'ÓÞÙ#,èM„@\#X5›™á!€õÔa¹Š$Vpß„ÏÂòx n3ÄhGÐƒË N lEù6ã�ºû&¸ËØÐ3äA@84'XDâµb@{AX �©òD/8'Òo¤ã4"L‹‡cˆHп%yivô†¡À²í¤ˆ’]²‡ëO$T¨8FÙ{¬¨¦!©à6±6·‚¦e²áÎñxÆxĸ²'(œÀÁþ2Ü'u͆ágèQ甊þ‚ö8�ÄbÕZÇ~‹â*V[øB€ð후¯0TîÔYxsv†”PŽJ�É•cà!>±Dñú‰õ�¥%”K¶kb)\6%"÷ëÆn"%ºïðE‡äÁÐ}ƒfz––0R.‚¾)Èß9àK�Ïs°ŒÂ%k�%ŠZE�,‡ØZ¡Kbì‚ñ„›dTÅ)»aXòéǼ;+c6™…¡ Á¦’>Öwm¼¥�&'Wb)˱†#¦sƃæuÑ[ÑjkÝ FÀÎJÐŒ!—æÐtáÙø§Ø¢Tsé±Z¥Œ2F¼�8î]L¾4üÞèómtÝc&'É|ïûÔÏßmþîíŸÞ äueÌ%ZcÅ9Š 4Ü< Z± à½$�ôïw"ü»ÃÃXVxãFésÛÞá|¦eÞ½.єņ>ÂÐ=¡Åf-ô²îÝf „!ÄÅÁ…Ï~F�ž) Éà“ §ë'5^†•C#ÑËŬ¨¶ìT™ìŸ�� vX,VâÃeô*ðŠ|õéH*ærS2‚ÌßL5ÀöLµ3¾¼÷ý�È*½÷2í_½Ù|¿òÿ÷Âæû»ÿîÂÓ* ÒjD¶Ffšp–¸�L 2á:"ªÞTrÀ5j#H>7CCV ï6`ížÉnüª>oÀÛ6� ùsžÈ–p`<�u²¸zÈr•P˜A,H"ÐÙ¹vX­UsÃð½WWŸ>5b_Ãkb…Œà–)Ö)¦Œ¥ªÈÈ ©(Ň•/x6B5ñ=ª®Ò'ÆŠ:I\fB^€Øúä0 �å¾›¼ªý0:†Ã •^"D…Øï áâF LY AL4ñ¹d™'b=X�’’öH[ÔïÖnFiu™dÇêNÃð l¯ùz³§Ý¡*YÓ (ç¯�ú'þ­®™2ñéÙë³"í.ÙVA° _qUêF‡9¦`ˆÓ‹U³" U¢¹km× âMë TXHLÝx®Á„Bà Lïµi&Å' ¤=f,ff^Á‘•R rCBÖËÇ0d²V­q�P‚î?ºªwˆ¹“æ ê)öDǼꮈ]ŒöÜúû�uÛ«²SPIðù4žKØõ;÷ýÃÄtbiûýã¼=�®lÞ/ýqG÷ãÇ¿\÷§c5¿ìs·E ”cþÔ�P‡JEá£jgž ÕÕàDû(8lÇÄÅc®³éçî+Ü*?Ò##\®=Úã¥ÎÈŠ·žTíÌPRÕ²ºbò¾ð¹=EjX5u×n¯Ï­ãO áDVm©eä¶ÎÏ Ñ+]Ý.ÊÍŽ õ&°Û&òïòD{ ['„šÅâÔ—]ìÝ`¬cÌÏU§šÏn‘`bìMuM¬°Ž²€É -µL (04TØ9Õ 5ÀÕ¤TUkB¬K.·ŽcR ßRG'‚Ó©+eÁ‘€5XT—+Ú2›lKw¼ TrËf7`Ïè‹�oaG®&ôR{�š|$Òái3 NÝ:E.¼ Ø÷mõS.<$à%ùT�tF+…)›Cݪ³^B‡ãŒ±¢¬¬ˆ"©8˜iNýq¶ÅÓ"¤ieuñã ŒPpÆ&ÂÕ"!h—"&ÓëÅåÐ8MYpB´Ö¯tóšQE5u.e±=ÊÎ5„ûÕ’òOµí¡ i¨iÐÄCÓ·š—xê=T¨Ë^ÓŸ•¬²D#1`«L¡ú?2ZuíÙªÐ:5"³ìÒ`ê>RŽøÔº ?‚±Œ­àꘙy":ð–@}q?Áò†IÎÈéÔkWStÇx5›Ÿ,§r‹<@HÜ�‹Ø–DÁ!.d^黟©T*‘Rbò�d4šf”«_&¨o4ggM%á{FÃŒ \ëd ;-ꘂN„d}¾µ[#µ�—V5Ž ½ÕÂàÎ+ÀÿùDÉvEª øo…q4KQ"A´*BÉäwÞõioÞ–mÀ¤ƒ<£©VnÓü*tVÏ‹Á:P(˜r� Qs­jl7GŠÓÓà9;÷Ëa¿ª+ªx®®Jg•ŸQ<ªCƒ ñŠîRÑÃ)ÿ‚nVÉŸI6Ø ”ò¬> ^»]¼ ŠYÄòÄBƒzǶ¶ËLd{•–Z†e"Ä'Ë´mÂyšÜþˆÅ,§Ó²ƒ‰êBñj^.!¯ÀV:!Ö𨚌‘ƒ·S/CF ÚѲ²v'Nâ'O É� 9„“1 3•á“_&, §÷\ÂæÔvÙÕÌÉŠ­­”ìV¦Âãm[ekQŒ¬¶Sµ¸nF‹‡H´·Ýè'¾v‹Gð‚8¸ •¥WÙˊѪ‹=©%9Åè P"@@¬nmŠÓÔ×áóƇZœÉ«göíš:#Üí//À Þ¯>‚ëÌ{ˆ¹¡�‹U¿”Í ;™Ù›ª~0ßÏÜ@û²TúÜŒ ©Â¬ê� ûmìQùÖ˺ሢ•êÕM0 *Úƒ:‰q$àªí?™¸‰Љ¦�h0ZVCYM .ŸžN;2ì:LÈêµ£«o€)Ü•cÆ`ÝRú � ‘†Ô«ª*·Äd@}Ùì‹ÌNóºP�‹ºX¢˜8´Ž( ÎmPÃû€ž¦T€ÁµórSsÄO>? ;è5µxª�‰òQôqCD5CÜ´=áÑÇ,�>-åx³W{ϹÝÐÖ»^MÏ/F¤@ðW3æÍƒÁ¸œJŒ^¹%…;cªºWµ°Fõåx¬Ž¥2²M×A@\[™¿€«-©'§î(b¿–tŸÕ…·Õ÷D´‚U|Œ·ê@Ø2cXJ¯ÉG™'Fá–'tw4Õ7턇 e¥lPtå—vv2ð·`”¦µ¢Rö¦j‚«î6#{ t̉ЋTe,w¨Ì'²³tµ1©tDì±»u*@ò„eMÐä ˜‰â¡t¿ÊFxÅÛÖÑ þ´¹n±@„ªIša¾à[[9¹ Øy–bXEcÙª(%¤&°« ¦*sÒéàn§ŠèÝÜ&Bdð4¬=âÅó ™¤Í7« RZ]u]ž‹+t-¨× ™ídGÙg¾UˆÞ¿¿ ø‰ñõ Ó1—‘ĪgZOÂÁhkÌ-ç0;õ/©ï¸ü‚eX¦ÕÔt.øŸ–ÐkÉ«õÍ)‡Ïõ£š¨ˆzPä)=s{‘ií5h;6õÞA 2ž‡¨áåV@Hp`^zJ;‘H¬�ãJr5ˆøÌ·–'¦ #áÁƒvÀ9Åøk…óRCmŠ7ÄŽRÑ>Ö€\Žçg�Õu[ÔÕ †ò}›¹‹Ø·‚öS¢Ëxé¬Û7¢ƒÔn‹çBÐH'Þ ò_ØŽÈ×QgÊÈÉB”´ÑžD0úÏ©¤h 4…àí3„v ‰¬þ8õ GüEÅ�XUÙÞsƒYr]pJPˆ¦Íûæ<Ô2¥‚ÙÝãÚ[ò¦•8Ef}Í ›jàȈyjK¬JáœõIcˆy øtîb-«¶Pöfá†,ý6ä;5¬‹^õ ŒÂ{sa°ê›¦Ù!Ã�ê· ‘ЗT Ä 2îa�|áúwƒo(&‰t†›­WíŠê‡Ô>MU•&�A(½aØr‡ˆ£íàO^QÊ‹‚÷­üE,3Õ W™M=)£¶ìRÁí€6†'YÙ§³ØËVw Ê°öë§$+�‡S®¬¶Ô�SÄ|•+`ÂÇQ³”{tá¨ãR[;’ª·¼Óº*§Ë$áÏ„ú µT«ËÌ0eµ#……Àá™4 @„R3 :]¯~ʪfBîÚí0F»šu»C!À½OH'‰W'5Ñø}zúvë;*ÃÐA—c“V(×n cyá�óQ7'J•Äc«�9j“Â�Ã->ŠôAtž*âSQ«¶Ò0=ðÞ(·0pRaÍTßÂn Xà€‡Œ_[õŸ¢ "& +qA'º–ø…èn?8 ÛŸ‚e;î~Ã;¬zèë>·]kÚYl¤=Èé:�"ljõô*fF;_úVe`µ¯g‘ª…_Küzø“®Wg<ŒMG“쵉“ŠÉ(ãd&×€‚ªo{ÙuëêÒHR7(ø¥V}—ê݆ãTá½yeî*“ØpÁœL�=ÂØ2v“"üRŸÀÔà¦Ùíš<*nž¡tÕ["šwA*J16m4/ ï-‡yà‘˜{nÙaYˆíä½ðJèê-ÁÇ+;X¯ ¤ tU/<£ƒg+™}9Žû.¤Wòn²h¯6i¬·µ’£ßƒÌ6ÿŽïÐ}£Nc, CSmPÙõ¦œ½­3±á5e¬KÝ›³¨gï~pCY¡ßjøOáÊÜE Ÿ¢¬ÏMW.Í@Ïjëf(pPÔ˜mw“Z­ÚÛ!_‡¤ÕÔ�$µ¨J–²gµ=pá(©®š0¦5Æ‚Ç$ qéR†"ÑîK-XK l»x⃲µBIVFا ²?•»û<¦NµÀ9áëðìz3 ê”ᥠk{™úA鑵À­våb\¶]aRážLðÝ��ï)Ù¬½GP.$þYh $½G™¾fömSGb9í¸ÐVt}ˆšuª«{Áš³.qÆ[o�/gyTöÎ&$ÔSU-K~n–+žè®¦:GÂD[$” F¦MãN¬ú[�3dèišÒ1îš½ƒã¹ }^j¤VÖS=äêÞ*A¿¸ï½ô•Œh½´ú¾€ÀE¢Z=OgkCv#(€Aöv±¯qó¤ÚWÕ–Ë{°z%ÏÕÌØY½}´a~ò뮞BìpªþñÜÄWôä< �$ÑfPÒâÆ÷ªšÈ‚¼@·cÉT;ê3Ç~Ò[ÛŒ%*Ó±Ö`EU¿S¦öÉf¢­z¶yÈkOCˆR!S݇â’åu6Cç J Úž¬=AK[8y®®êlˆ0ežÚíŠEe‚F‰pc�6�/(ƒš¨o_»ö4µAÀ3X§¶K4¼ H[tX{%ìÔžq·àvÀÏQÇ :²ÁÕœŠIUþ‚v¹t¸ë Ô%°Sv€éx âOPÓE\ƒÍOH…9Ô£_eé,QÕòßQ“'àœÒwa!Ž#Á 0éJЍY„߀£Ýí¼Ú! �«ð˜¥=¼Ö+ù}Ôêí”ñ�« §îŽØÔ“‚ï¥[’%ÒÁÀÌASY­ÇLsIñW˜C¼ÇXm9!<éQ™×�ñ˜¸å™ôäó0ÐsðµCÄ«1S[Úoq”Á Þ€¶Ð51Ã@&Ž0N(ïxZœô6©B_œ —˰DV¹#Å4ï–šù�ù¢Ô'&TӞȠ‘ÒªUû‰)ià �b‰œ™%¹ø-¾Š³` ÚI"�ßêŒj¶NJ�$O`a˜dy,Z…³ï|µ$ËVŠòÔã uiKnI)ƒIÐbÕà %µá´Kc%ð*�\RÓ.!§U� ’RI;W à €Á%lÃA› ‡Sö¡¢æ…ùµ²S_AVpÙˆšËœâãmÓžR©%TÕµ%MxØ6·NÒfvÊÐÒiß¹ú ˜»uLH¼aºóCf쓌ú‰Šõõ6Ævš�Р4àRÇ磬ÛÓg-Å}5EHÈê2yUC>Š!FÕÂjB�CÆ@¤m³jê[øMk:¡ÇÝMyê{ÒAÚ{Ò¢Åà`�Ó¥ÍÝÇåì=êå@8‚sª‘(!vk÷9kmO›€ž$ÚlEéÐuÚLøß ¨•äÆ2¶Ä6Ýã ÚÑöAØ’6àC&ñ@¯=Ðè½Ûò! „*�áhÚ/Èd€p¦:6m’‡ªéi´ácjESŽ ^®ÝQ;ûÊíúP^Z}º’ 9R¬1ÌÐשÐéÓ=HC&D;�;¾pÔÅÚdN½êRÝ`.OÁ.bÎ4jåU¬�÷<(ñ_—”™WpÓ†'x˜¦Ð¡“n¦W$ÏÄ'$’ëìø;SZ}Õè'Øæ»-yÜc.¨ã˜,ÈñP,�1aµ'SrM©æL¨1RySAs(ï'Ù41òÑ{ê0†®únÕ>©Ä_DÑÔF®}›BÒ»gjá è~u£2¯ ~ uU[>RPiùž®pjòMs7Ô|ä‡öÙànqu&ã!ðñ<ê‚[ð[£MÝøWΡÁô–GûžFÃl Ï8›Îö!þ¶ ó.L‰æ[ÑÔ>gÏRoª8”nV c‹Ý«À{«:àävF8‰y6ˆ½¨X\UÕ³-ªï<ž&—KXášá¶úëí[^â8i; 6Yuæ÷íh”ûÜM¥¤YTº¹.p¬£cO€É ­uMâÛ"` ;3ÝI J¡mæj"µ»]b-ˆT ‰ú^óP«€FÕ¦¬à¦Å‚/ÝWŒ«[%ïB· Ü`’W÷fGüE#=÷=,€¡ã™êØϾV�›©±RÇ?E D'$‰¼_úðÜç9æ Ë.Ž »9tußá—·¥?kO›Z!ÔJ<Õ·óÞk\n팀í6>#4ñ:!ÓæV¶í®tæ/êÿˆÞæ¾ÿz«e?è­ÃG‚6‡a:/-Æ~a¾ \º¨ï�ˆ‰�î7A¶/ÞíÑLjú†Ý3³>éX¶¥E¼x¿âmƒUSÿ«Ž±J²€7”×XðOçۡטr:àÔö¯]ÓS‚¥®oV¦Ñ>èµ{0Ê©…Bäö U Ô¨“Àˆ%@iñD¿Eú á ¢ 1@Ä‘࢒"�©àƒ8Ðb,C;†»vCsÀws»¥§TEÍD8«UQs*œMí…ƒ¨ï™É‰*�É÷t¤†¦‡U€µ&5- lj꭪' ´:¡‹'¾ûêò4HÏï nMa•S{¶Ž*UM4}ƒ}icÐÁˆ¦Ò¶>e‘>�ÌzPìÝGNp#»•¢�·QS…ÎÛO5tÚÐ-¨"Æ–D©H6€JÇxUþDRQÃj»fÝûíï‡þ½±<ÉŠè‘ÓXùÄ�…㺆šH˜µ(á œÔ0\Ó‰ C ò„[ÌŒã`ó�À*cã[Ù¼­~á&uÔ š·ò"ņ¸ª‰=µ¬¦$‡«û�‚QáT·p:§—›G›<4DA[:†¿æ4-�órņJóÉ‘ ‰dÐ Dë�ˆô ŒÔNút|HAp–† †“x¨P‹ÕÙ òêÙ¼GøÁ.´³PŒó8mQþ«/í< Øm%+¬ÅÒl€¨S~”ús:çeåmä†Ü·ŠÏàÿçÕêƒ*Œ.ôËR¾sgPR1"£ö–N"Ãý*•ÿý»ùÛÜþ¯Rûæw¹}à䮄ӑ*Wåmˆ"]Ð5nc 1¢oR¶:_"Y¥yu %qèöÇ«€ º¢YmHêb¯ÚŠy‰xÏÒÅ ÔÞ�³á}„À_ªûU á`oåØR´WG}Y ä,Q9 Œ´'° ã¶·Ó CݦÁN1…S¸'ëÜ á¡÷âJ¾Ủ`u7<+äï'Yçséü¨&m4jTVs²Ú÷U;Æ®´§"wæ .TœŽ~É:MDĬt\ºÞ6 –� c[øUèÙ. mKŽá‹h"®*>É`unœj¬Ìœz˜tîÓŠ”ìá(bÁjš0� Ã&n`uô‚œËÏšQYj“¸M¤++S••‡ÛJ::@QmnG‡M)5 ?ºýküp©HRiƒV&˜tn'œ\–C¬4ÁôPuY®ºŽD¹‡ô¼†¿�$8ZP7v„5*x³ Ú¢Ž,aŽt  !Bý¬Ë©'Fý¯ˆ{û:½AM0C‡Í-$Z•ž=)=0ê´Í³ÝÁæ×¡•ª> jÔ#!èÐ/,Ô,�@§ªh‰°°<µëªk?¦�|Xé'œI0”GTïîG¾¿êœ­8v1öÀk>%”t̘¨’Ž`³ù9X†x±7˜óøu>l$ktQ3zÛ&Ü¥Eb¨Umg� ¡-)Ui+�Ò¸ß�è|=Ÿe¶TªÀ4³RP $ÄØ#!)§4ˆÚ µÃŸÉ* ž·ÔVÔuY*Ô¹*Ë¡îCEí",�"Ä(³IêTXQ[‰v‚x5Ø€‚V]3zƒùÇwüö „ŽS ­˜ÛÆ£lÏyo``ê.ã�j~•ÕÞñ»¶¨Ínªl@nkÈCшãžÝÓ¶Y38TyËÚ{P™Üʬ¨UGÈ¡ó¹”:¾6Á’Ó¹z:6V»TŽwd€F çÃø | ‹¬`ÑÖ¦GÿîúÉ𭸯-„©¼Ž§ŠHõ[kã’*¯¥Õr“l Ë{ZË:„(¨‰E­ýéu4•º GÍG¥×îŒ'rŠ’:5{¼]ɽ_^é@uÿÐ3£ö4­ ºXž=€ã²e߇y÷ƒü8Pû6TU‘žÁš–Þ�M¼û}žëwÌwÀÖžgÀâ«0ŒqµEB?—‚�lu˜™šÏåŽþŸâçÏ`²ÚŒ YK'ùÜ¡á&’–S6»ˆ‰ ¨ÿõšzàÛEÍÇUݯW‰P ~é$”¾8r“T«©¾¸Õ¼R5ÙÚû§Ã½úš'" ­ú;‹ùÅó™{(�0§N�Q‡.j&%ªj6(YL¼ŠáLéU¹€?äÿÌêAEl¸v‹Pâ,´(ì0õgêïÖï#Êßõ°J—ˆ,BÞ¡²CÓIK�&u¸+q� s=PÌ.Ü#WZ*/6'™•J믜á‹/t•Ÿ“bÑ�@´Ö¦Ã´±cÇÛ®Ð]P�¨ž§YI”N=ÿq·UÍ*û> æÏgác˜J¬…N+<±@õÁÍmÕZ5îî~L<—¿3óXÁ›´x:3ºˆc¹u¯ó®”uT÷}hJÔ Gjj…§Þ\Ø|õá¿raµ8Ìý2_ówöû9†SÑa�ï«mþr¹ß‡ñ#ÌŸ�„Ò ¹þæP‚ÎlÜá90×OBŠù9޽ϕrý©ˆy*+k+¶£B �ZÌ)t5ÚÆ´Ámþ§1þ¯º ;° ÄPLTEU ƒ  )ú( $  #2"—$*"$"%0 +<&(&*9ÿ'-3#.=,-+2O:#.’*3>@?(4D131Ý 06=4¶ù796/:J*.ÿ>A3>N59š²?@>;AH7BR,?¨"BÀ;FV@HOFHE3P/Yo@¤/0DMYNPM)\WJS_MT[2b5TVSIKÿNXe"cŒ>`€9j:[]Z+f°«GIX`m~T]°[ah0oa_a^/qQC`Þ€~ceb\\ÿ‡cK<|9bkwDzDƒñfcÿ€¶.|§lnk<~i3{®‡ÊUr«mu‚tvsppÿ��&�Ê“tb=“20‹ÂMŽM{}z,�Íz€ˆ3Žð$˜ÂM“wPŠÙ{ƒ”¯{@A¢*˜áµvu…‡„l…úA™·€…Á‚‚ÿ„‹’I™Îf“±À‚1v�¹Œ�‹"º^¢[…�¤°Ö?§ë”–“Á¿ƒš¬‘˜Ÿy¬Dšœ™µ”•g«±]­Å˜–ÿq´Ar¥òu¯qg«Ùž �Ì™KŸ£¦z°›™¥·“¢ÿEÍ$¤¦£‡ªá‹±Á‚¼`©«¨‚¶Ö›°ÓÒ¨mŒ¼…­¯¬v»é©«ý¬¬õqÌ[°²¯Ù¬a¨´Å¯´¸¿À³µ²Ñ²y;è%”Ä”aÛX·¹¶Ô³³º¼¹ŸÊžº¿Ãò¹Q•ÉîyâD±ÆÄº¿ÿ·ÄÑÀÿ«ÉáÁÃÙÄÇÃ�âLèÁ�®ÑªëÄpÅÊÍ–àŒÉÌȳÏ÷ÔÊÃÈÎÖžæsÍÐÌ­ß›ÍÍý½Ù¸ÐÔÆÒÔÑ¿ÚîÕ×ÔÔÖéÍÚç†ú{ÖÚÞ˜ûXÚÜÙ±ó…ÝßÜÁïž¶ò¯ûá{àâßßàþÑæôÝäîùßÏâåáÓîÆåçäçéæùé©ßëýçëîÎòÿãíõüòìïëîðíìñúíóáðòïñôððôùðöëþû�ûôìôöóóöýõøôøú÷ÿÿÀúüùüþûýÿü Å–tRNS@æØfbKGDˆH pHYsuu¹cQ2tIMEâ #ŸV¨tEXtCommentCreated with GIMPW� IDATxÚì½¬ÝÆ}èiìþ·ÿ4@�FÃÛ¤êtåÆŠÿ¸©®½J-TkE\¼ÈÝöˆO_›Qšd±aËAy/ƒ(l­�Å'¸aJ5£–•@¿”e o$J|vU&2+{ÌèiÇLJù†âÄ‚w(*Åéì y~]éJÖÏ«+Ýó•î9g~pH·ßùÍïÜqÇlwËTnQ·(“r…Îîìw¬ÙºÓzÉ4÷›Ÿ?òú‘ù¦)�SYžâíÛ9)/]Úi�ïܺæŽÙ­[·îܺíØü±WŸýÁ³¯Îï•Λ/_Ú²˜ç—&›[.�Èåžà‚ˆ[¾ôÞ—x9q®·èÛ8wžç„ �£<Û2tÎÞ1óØc[¶=¶÷Ø Ï>¿sì…ø˜ÈÈÇ–H6oܼyócòCÊÆÍ“AÝÍ“ñÚïnw2|³ðŸŒu^Úâg±ÐÍ›‡ lØšÃJ{íºÙÐ\פ¸¡ý¿N¤²yݾ�2ö†�þŒ D°»nݬ5ñ6<ÖœGþ@ÉÆ ƒ‹Ôã$9îÎnX·y�úºÍ�Àu›×úºu£.‘li¿ ûê�ÆÎ¡ Rll° çÎ|Ûf?ính±®¾ãƒëÖnxlí^ø8PT>n¾-òdíÒÈuº³3Y (k"¬DhÍæ�¦ºvã6 ÌÚt¨ë¶YúìÚµ³^oßfU‡Û¢xÍέ&œY»v&HÖ¬�1Õz§ fÖn±vvfDÈÖ­Öæµë à8³mÛFSC¦LqË k¶n™éš`Ûc3›­Y¸s+œÙºS!ñ¶Ù®5«š}Ì'ÝWîënÞiÁu3*^?¼Ê�Ý8WÔ�`ç,0ẵ[LmãºS;gÖÎêFc«¥Î¬SM¸q‰²lóùiõú§¶��#yL:�'Ô;^7tn|)�sÐD^·vÝï¸sffíæ™½š7u8o[o þ3K#÷º$4g×dy诎hHÌ5q´/W^JÌL³{ûP¤ÛÌÙû;~ÏÓ¢øÁ*òI÷¾™{ƒdõ}ƒ�u蓎BöŽçª(ìy(Xc߉·­9¼1ÂûDŠøð¾¼‹£5�½£}§´ÕÛ¶iÔŽãY/Û’ÇÚêÄ>Žf¶nÛI�SºÝ-ÚNªß+xßwß}ëÖÏÜ7sßê0Y£Õ�¹3Ý›[2óp°þÔÎÕ3kˆ«0?JÖÁl'Ú·æ¾%ɲ ëffîÛˆæ:…‡”ƹV8€!\hvà±3æ6W'�wÞñþ{ï½oݽ{ðÃy]{\–çk…s‰d�b‰œËBUù`„ÕÃi'‡³ØŠíÕ¾o³®êb¬[½ú˜Ï®òó™JÞpsºåž{Wɪ{àÎõ5Øœ)0™U³-5ÜJ::š�hœYw}jÌ s.ߺïÄÑêÃö¦\[�õÕ–âÄ«�øc~¾Y«ÖØ]­6ÑŒžÄLWÉÆU ‰kg•à}ï½3§ºwU˜¬Öª�«ý^œzz…“¨sjçª{VwKÝÙ’vœ2Ný™¥É±µÍy6ªug�¸²{×Iç=s¢³5{ïÐ Œ{îY…f†ÎÙ—r”ƒ&ò}÷Þûþ;~ýžU÷®]µ÷ø«’÷±Wçßž¹wfÕ‰ÕÔ\�í[µêî(Ù‘�™ ÈÖmIwÚ=wg»0W¡¹z �küìž»%o°1Ý"â Þ«‚¹õµº9UT ¼¤#xçï—pwKWÓV?¬s6w Ù‚0$öš4ØIµÙ`õN²-Žgü|õáÃ��Áj+W‘xJ«•®äúìK±R8w ÞâúÖ­»W^¦ä]ή²2EÙ²õèn�=ux\#yÏmI6îÌ·([–(Çfîk¾ºñló½¶q¢Â†#'ˆ}ßO×H§¼z-Û:ã%å±÷®ºç×ïøõUw¯ºïî�ï¼óŽÔïwÞ9rïª{ï^¹Ëˆã`ýªÃ;WÝ}—›ÄÁ–»·D±¹zóáØ›ÕDÎNf§wïŒwÍpÕ]®?‹·¬ »âÐ [¿Ñ]=‹•�agµ#õcXU¢uÀ[³Ñ�£-f÷î-±À»Ô(6V?†ý@¿kK´/ƒªyçŒh�Ho ò qçìáÐõÖl‹í¬ÙoÙ»H_£%Ž¯Ó D&ÎÜ=ëÅhë¡�³(ÁÑldtñún°~Æ�Ѷ%ʲ{ïi¾VÍ œ«äçìÜÜÜjùã>é\-\sï:7n¾ûî5Ê=­sÕ¯ßñkwßy÷=wn8ôÎOTãqóðOþ“HíÎ¥’»îZÔcä{×/v¤îÃ�›ïZ<�»îüà–ÕÃTš æº‡“¹ÇÖݹqŸ—Zƒ›žnœ–øÛ¸ÏYs±Ë½àšõºA²êîkrÞýkwüÚ�ïÿ]ïÿºç^zéÀ�—ö>v÷ûß/|–½|põ¯ô�u[ÕõòÖVmÝÕ—Žzç•§¾4rç�Wâ|ÿùÎ;o+œÊJKðŽh1••!4:Ÿ7%4_œ¿ð'—x2ÈÕ?5W}èÅ.ut/£3�÷J‰¬@ÞÈ÷ÃØÎ•ä¼8¢y/¢Mä bšÆƒƒ©‹Îƒ(ަø¼³",ÈGNuá 3š-vµñ8 Ó‚"¬'‹ÞTR T$(ð‡wf؋޽H$oï>tåñ6`çIÞMh–ŽoŸªF„(I±’à Fc•ÊÖ+$´hžfT`!ñkBßp'0»‘È©od$KÇO EaÇCDFáDð&éÄ £nˆrÒ¦šg"BÖþ¤º;JŸê%J„‰L€äTÄ??¦GT@l/‡ÊdòT³šå4'ãxUÂ"O¨4›¼é•ÁÛ¢46ò.¶!´é˜·G)µ€Ú�ÕHÑÃ1ïNÇ­hJ„T}Ū®Ž5+9õ@¬ëjb(®¯i0Ÿ8¯2zê«À‡¦ã##•Pb@5H6iÁT¡¦ ê QÀHaÅÑy¤¦Jìh"�Í�; C)J¬Äžãv 5ƪ6gFªb«z¨Mò¦dn ’OÅŠâ­Ïéy7ê„HIǼ;ÆŠÐïXEúDÑœu|Õ·Ì]³sˆëþ$ïu3ŒU/´ŠÇ]4ɺI _‰s©±bã±úGSµHÉÅÙ:)éÆa7×mÇjjŒS/r5Ö-Ò�º�¤hÍé ŸºZÐMo Îa»˜Ð!Z¨âñ²ÆWÑíEM”(Pï.J²²ôÛHó†÷&Óñ&ªW;ÍânžKÞÆÞ±­È ¾=jDpœ…úí¤Ú][ðö�=-ä­9ÔqºX(™ŠcG·#g‘B)9QÓH¥¦»‹'y¶ª$‚÷œé¸)Ød(�ñ© €a!¼5j{f@5xÔ mÕ¥ÔÄUxipÇr<Á[‰WoñèKÞ1´‘7Qž¥0pDy‹Ì�(Ï“èA +p=-ê @�‚ ÞÝÐum cË 7�ÇÛW%6 d*v‘Љò¼È€§‹¤G¼-#ê`KO&ÚŠš·‹tS\ªÿѪe±±>Ž>f-o?‚‘bº PÒàc¾±þüú;UÝȼç,¬¬ò‰G?C4 ©ï�«izžŸcÙ¢óÄë! ˆl¢#O~ûA&"úé¸Àõ»Ô©ƒð½xÇM´|˜dÅð&SYráxêTV€~WõTV‚TSÞ·*¹Þ¤”SÞ·¹¤ƒ6é eJ®ŒwYU¥ø×JÙHuE²È1W‘ÊøØK‡‹xЧ|�³(d"Å(¥^Õ[<µâÔ{_eI)=ÕÈàÔ#7­n”ôλ¬rÁõ‡ÇÑ@bŒ£ËÌ×1o"þ î¿wjþÄOæé©ùñÙ)%yž¥ùdøü©ùùùÇœ¢=•^%îããl,æO�šŸL˜ä±�srÞo¿üòËÇN�Üé‘ÃGŽ�ª8tdè“×yÝÄDñÂ;{îá½Å{]Ðñçž{¾•í5ìÝ+ÂM’€Š’!H'Tñ`æ2ñ´ÆÏžMÎÓWz^îô„ž*uy˜öŽ—ÃÇïìÙw�Œ�+EA&ÿ ŽúÑ÷¥ì&‘ˆ“ãÇQqà›FÏMÕQ@]>ŸÏ=wªõßû�øø…EKú�¤Âÿ8¼ŸdïÞ†ðóÏjïã‡Òùµ¯~õ«{›\+ëËÉì6RúúÉ×Ï+jzÂ+™<}{˜�ØKFø=”çØGƒà–÷¶½Ï Ù›^o:ÒoÁ›ŸžÿÉ‘ö¢~rðGÍŸ~÷Ððáú”ý~ÏC½ix—G;rèÐøF²êìéw‡ªDÚ[ÍÃpAù—F(Ž£a!@&xçLJ‡ïž=;ðH6<°çûžçùþ vÙ$=ÿý÷ËßÿÑâ‘çNeyzü‡��ô› ô»€Û;ò�?×^ë�¼ïÃ?™È‘öRñ_þå_þXü ÎZþôdÙ;ðü®çŸ>?ôäÉ»v õ;cÃÃñÄ ¦~+A["�|ë_þõäà¿<ùÚ¿¾öz9‘�‰—’‚ì î’Hü$Ï@^7¼ÿÓW>-ä+ÉUñ>ÿ ï~5ÿãCí•ÿäí7çÙ¹ÓÇvï>4¸¢$Ë É�MòNw¿ýîÛ‡ Ò(³#/�:ýîüKQRŽ#e^øù‘8‚[�njü¼(>5ÌØwOŸž-�c§†¼= wF&ø¼ýùoìØµKŸo#>|P^ÀûÇ_þC)_TZå[o�,<ÿÕ¯þÕÛ¸¿üÙ[?;"Ü_my§ÞeÐÑÇ7w:=ðÐC÷w“¼ÿß·^{kRË“o½öÚ{µ7ÎÎÒ�’‚å8ö �‚8Îk~1ÁÛjÚH¹rÞ½²$â_#§Îž;w.}åß^lÝÇÞþÑ›o¾ù£ï~û‹_¥�G£0ðl†�3«›ƒ|WD;t¨�RR”G,x‹‚ÈûÈüÁßøÆ7¾{üp:âMqh&¢½< íÉ{eáë†iɘwöÍ_ûê7�Œ²ãÔÛ‚÷i!dž¼]‰þc•Lòþö}þÍâàË/·�D^B¤H÷!:¾U:xž)Ôå¹Ód€»ÄyvšõÎãý›¿ù›_ΆùôÚ[¯e¿Ü-Úg-ïÞÏ^{ëg塯>³c÷ï"P¾þÀ§ZüÙîïï|ç¾ówæ8Ò«÷ÿÃw¾c-àí÷úL\”í xKî¬O�óyïÙ³gÿUò.‡¼Ïrvöçÿöoÿüóï½ùò·¿ø‘�üÞáöº“0Iâ(ôÀÞÙ7;°×¤AöÚýí/~{ÇwíKF¼…·eè¶ï™~1V;Ç0ô–›Óž;þµŸþÚ�!ŽüØÛo/à-¥QÐóî½üGŸÿânQ…w�rv88|Äñ•3‹è·ä]þìõ1o\ôz'_8Ó›à�þð·~ë7ë7¿œ·qŠ×^;™ì}~¤ßå/öÚ¿î}^è÷ï^¨üàÙGzà·u:ºñðDÞág?ûÙO�áC oÄøìgÿ·ÏNò.<+……çša{Q‘åyi`ºto!œ“«ÕïöNÉúûÌÏñ�ƒòü»óï¾ù£—wåkÇùã#Q ûöBÞg�ˆì_¾òó6 úÒ^ Ùºï¥IÞ%65M3|2YÎ:Ü¢ësäÔóǟˇ¹qäÈ‘cï92Á[ø§úÝ{óÛôGŸÿüŽayÞ;|8/zø•~…Lðè·!rò_þåä ¯W€÷³¿ûÎ ¯Oðþñ—ëËÿø‡#Þ½Ÿžüå¡ÝO?=ä}æäë;ž~úé»&y›–%M¬¸ãûë¡î!ïÃO>ò¿«Q1‘¹ñ©G?eNð.cÛ‹*ì¹ö Ê×KÊȳÛã&xŸþÛkÖïºyl~9( �í®êâø‘{Ÿæ�„¾ïšjË;ð~WtÀü÷¯´…=|¼™ÞN�ù$ï^Ž"”Ð×@ð°P|�*ésɈ·d*Tüí·ßò¶E…/¤-χåï›ßø¼ ¾c¾=âøó{ÅÓ)�ÿcoTžÓV¿�nGÁÿý¿ÿÃß�ä¶cšÁÉŸýÃÏN.(Ï¿œˆ¿ayžþð‡»Ÿÿ«gžù«AyNnÑ>§(/-ƒH1Ôàܸ®9ÅDv¡ëG¡ï A¼^ìúaä»A›Gyuí¼I� 24O9Òb˜? E(ï°J-P3¨†­»=(=Òˆû÷¯´U3A…¨b‹S‡Ûjq\x5£½ç]Äyß⻿v`"GŠ#Ç„ õ[œ%BðäùËâÔËßÞñòÛƒ£oÞ'K£~Ñé�§ße!úü½_þì_Î Bzâ¹åùÐ=ôy2,ñ£¿zæ/þâ/þìÏþì?ïn¼²ç…ûsŸûÆÿõŸ[ýî]Vf<œaz^ˆèó$ NO‘è†øãxÝP‘a¤†7l‡×|É»wE¼Å Kýnß¼E�ØÈh.­w ‘™(„$É Z3Å*<.yÔEåTJ''¹2öhçëÏKúÔ©ùS£˜47SŒ�ß_#g²…‡ÓìRWJ�d>k¯(•ù¦Wwƒï)¢÷MèdÚ Ý…à º÷~$y_fªÓùï[SÂOH]ÕzÅ©Ü2’…þ„\öR¬𤋮iy�¦Ö¦r[K<à�㩬ÁÞÑt�ËŠX yóþTnáSÞSÞS™òžÊ”÷TnWÞ'N_QªçNð+L‚_ÚŸájÊêzó>½gûž'¶oß#2ù¨øš´çè¥Òؾ}ûÑÀÞ}Š]YÌÌõ¯tÔ†û½)«ëÍ{ÿöÓ'NÝîœðß¿ÿìž=üÄÑ£çØÑ£'øžýg�ž–?GñI¼ü©Gÿô—Áï=zº/Ò�¼ÇIȾçèYñïèÑE“`J’‡a�„!åq•}¹ŽUøG뵚£•¨LQˆcœ„ˆá¼Ÿ§Sx×ÈûèSGOó£{Z*åþ=ïnßÿÎSG·ÿŸ:±gÏöý'¶Ÿ¢À!ó€ÏÝ~bû;GEL¾}ÿþÿƒµIm’8ñ”HºI⩉$܉$˜‚AÓy�X©p©ö¶Bs€cªd ;Žg¦*‚�çԞ»FÞ\`;zô©=û†ýO‰ßû·÷Eñ~BÜó¿îçâ818*ÿíÿé·U/ªêŸîyj¿(Ô÷ ²û÷l?·ýì‰F¿GIÝÏ÷7Iœ~jÏ�÷Â$oS Jâ; ‹}SÇ YbC»Är)°QOðNÈr9,4)HÕb ïyŸ;Ç÷ÿ­(ÏySžs�o;jyôÜö£{žÚ~úÜé£O�Âúþç98âýÔ‰O�Þ³çô‰wdqpNT Ê&“iîÙ/“`§EÄÅ’å9Íõ†X%‡VKÆúµÿ¬ô8ñÔží§÷ìÅòž==ÈdÒ5EM:Q‹ þÄö¿ÝóÎQjŸÛ¿gOÃ{”Äiù±çh“Äös£$¢qLņ ±eš ….Ô S·Ò>‡AIU×°A®fvÎ!ÉAM5釛Дݵòf§OŸå¬åqîôéÓBã…GÿìésRõÏ ¯sãJ6™ÈYY6ˆx§¹8à¬HG|,HB| “8»x%+‹¯‹^ÉÅ�Jü*˜ôUQT"vÅú%g%¯ŠR\j�MÙMÇ[¦2å=•)ï)ï)ï)ï©LyOeÊ{*·"oƧrû ñžÊÊ�ú~IZˆ´ùW¬Ä÷KVœÙØÆ¼íòß ´—{˾_‚FoNÅô¥¨Ë~ŸèV}¿¤Œ¥ÝNù¢yT!ͧrI¡ÁdŒ3Æn±~Ãò¢¥mQÉ;ÃS¤—’$™ä}z÷ÃúÐ{®e„//Þu^yÓiûRRNò®¿ûÉO~äCØÛÐä±aÔ2Œ¨ß¯Lñ5fLôzyñ¿œò¾bÞÇ>ù×{þú“ï{x^†T*Êc¢�R°-:V‹Ç”ÓWD¯RJ⸷ý•#íÃÎ)!%kW siÚNtÃHÕ¯a¬à…4·,´‚ÅÒ<"—3¡ßô CëÆ©¦ubдá˜f&‚ Loƒ9 ‡  =@�’ʻϾÕu Ž·´¼)ìéȉ‚…~‹žDÞ1-5ÈzŽÞðvïD‰R†s€­TÞ· \ÈyHÓ|ªz‚5fBÉï'vÍbÝÕ`ø‘ǃœ[$…ñ Ä|ÊûæÝNìÛçÃ�þ¨üj?�QÀ”wSoŸšŸ?Åo5ÞS¹JÞìÐÃù½‡´Ã¼®Ï›JAHN°ï±WåU·ïE¦…[á¼�}òÏ¿øÉ}øH’w4uá+ײS*Xã|¢Jqkðæav�òøJã�Û¦i%Ã<ùÊŸïÿÑSyß§ž¹Ú³tžšf^8†ÇjÏPï^—P•PÓˆyfš Uh&¦ßdÞ¼.㵑2‚øQË »®X_Äæ´buU³Æ%ãôY]Ð6TøË(ò®e˜ô…›ˆ/’(ÙmÅ›�ŽÇƼôö_ä}·¼»�êÕjŒ`�)@±ž«¶àÝñPéV) HË(-ŸÒ›Ê›¥>ðc£×IB䆞êNè«9ÌûýD×ôÒÑŒÌOCUSMèÔ>aàðÐ Ì\×µ2VL@|(íGÔ4R4‡ª@5t�MG”ßFå9 ¼ÑlÿÊ'ÿüÛŸüÐP¿»‘÷æ4M¥–Þ ì¨oJýî„¡šª ×#µ.¼¾Cû"ƒ’›É;…J˜³ x›<˜˜HU=#Ð Q×T„¨±êÓÊKB£Tü\I’« zâ"`¤3݇-‘T¥u U%‹Õ" x™ŠÍoÞý‰ñ~à÷>ò‘½o0ž«’s&e¡WkvSžJBr�¤J¢èfEJǸ™¼3] 2Î@ÇTEõM ÆB?Ý÷k¥6À‚·Ï€@‰•ªR2=T ßÀÀêÄÈ妗;@dHDñó `µÈ5»¼Š-Õ½�xOÊÙç~ï}ïûð7Ûin¢‹G=� ædPQÏÐUO¯B¨— „>‹ )¤ŽëiÝÜò<÷�Ëý©ª3¼Þw,XÄë=æ¾›vP”›áˆ7�¡¯×QÇá¾áéy7Í6Ó‹r×#!QQJ ‰LðîÇn®kø¶*ÏJ}dïÞCƒò}0p!Z?í"7Þ®tÿn?qnv{�‘>õY÷+?§~Í#Ü  zÄóýV†PeêAùL„J,ÛãJ�Ù Ì Öz5 ¡n¨~säš`ÚL¿:ÞÑ8ã¬GT?BngÐ&3íÌ’“b!$0õåȺ)œ9 ®–%±ÂäÓ¹ª¯Q5B&Q|É»¬A¹’ßPý.’dŠû*yOxbmSÇðœõX‘e»´Ÿ;Nαã,¶5X†,p¼0³mÑ`*ýŠ3?÷]/£žë&(aaÍêÚA}CyOåúô¿kŠâ,^ù²87›Ñ*žò¾aã-ýKL…°È nÊûdSÞ7Ž÷r”)ïÆ»\Gˆ_My¯Þ¡òõGD|n‘<­‹ó§å”÷­Ç;›h�• ?ïÒAû<âfQr›þ”÷­ÇÛñGLyôì×™?·q'¥IÆJÒ¯zX°pïÁ _¦iÆXž@_|PN³¤LÅwžNÒäú[ú™ò¾ž¼­Ž?ô¯ÕgŸüÔ<ô`;?fº´¢r6¼KŃuÔñ5œ¯ã!èÃÒÈ7Ã8Q}5Ñ�ë)ïåÍ{ôÒEøu9_òÐC÷·ë3�®î…& á˜wr…D�Ǿ…ô€kÈ x ¡"ð™íë!7È”÷².ÏÇËÑ­'…Ì=¹¾-Î…~³>ðÞ\ëêsŽÄï™1×oS õKlé~Ã;ê›Ù”÷ræ�Ž›dÎ#Š�ó`XÀËù±R–ç„j(ÛkTÅ$R}�ckA×G0tJ ñзL,ËscÊûê�¡ÚQÔêÝ—kH8Ms&šay¯¢¼_å¼Ïr*šoËÓ¬àyš2Z‰Hi%".ºhtZß2ýoÎHäÚËméÈ”÷ oY–2å}ãxöÀ˜ò^¼ ¨t…€bóÎË©\BÈå¯wèsW°=ôˆBÛÚœM¾Qʦ%–¤…ÁøGD—ˆ·h.3IšËFè¥y£ ]¦J³ù‘v¾ÄQ¡ÑL”áf�‹šž[2ZªTëz›"ƒ9×Ò%â]/£­ŸH-þ±\üË–Ï^_ì=Æ×ôb¡z?0œ3=ÚÅžíWÞœ“»ò+âÚ'¹c#™ív( =%›ôš¢]ŸØe®ë�s‚ø�áͦriy¯õÈ#kÚ¢2A˜Vž©zðL­kÁUè½ä–9—Hsù!‚…N™š()‡¸§ÄjY (VK_¿ÃÓöùe%Òt‘È$rùïY�tä "sj=OåýD£–y«˜U^຤‹ûýx¹T/ZÞZÚS°BX‚«Ìíè|Ê{9òžx_Ðß4÷”›O€í‹d ¡z0X×Z�€ùa %ésϯ*×1 SFFVâA€j­—@F>†§ýï¥æ�½÷æ=™±¹ »›0X§ÔX#” €¾4p&ßâ‘o­}4ö ›_lèÝ.nmÞ-$jïóæçw ³|…óNAÇ+®„·ìcÑ,½ ”i×ñýì yÇ¡MÍæ©dަ ÌÉYîð °RæaÄWoª+ŠôƼÃcK&G޹މ]hÿÜm‰¦YCœ)9ÃAÌL-À¬ŒBBºf,ê�•Æ›ÕõÂñµ—žøÌ{Ê,¥ùõ™å"OÇçóNpD‡¼’æô@¦‚ÔÔµHqÇiºÒx_Ð^» Þü�~â÷…ˆ˜O|n¹È…¼9ç½!oæûÜ3L›‡®Ðu5Vãþ­·‹ÃµëwûwE¼?þ…/<ú‰O<ú ï§Ÿ¾Hþüwí¸Y¼…Þe!y§%À¡ÃlÓ4˜¨I¥& î¯8¡Q»•2Š®€÷?ú…G%ïO4%úËßæøgÆŸùÌç¾Ùþ~zApóµDå¹ä Ç’{Ô¤<4E¯ä–bAÍm¸•g €ÒËÓï�ÿÆoüÆÇª÷'Öþ~óå;ÜõôÁ7wNþ�;„wóµëàÁ§wíøþÁƒ/ï„ìÚõ™»—Ž7/y@›=Ôú¬äU!þzEÅY¯¨ûuQ­@Þ—Yü7>þÇcõnx¯ûxÓ^{Y0|Zßw<ýôŽƒâ«Qà]»w½ü9áõ¹Ý;vIϧåÇŽƒ;~îåKÇ{*WÉû3òÇê-ÊóG7ü~ëóòާwKý>xL€=øæŽ7›âúé7wí~ói©Ñ‚÷®Ï|Fð~ós ôƒŸ›ò^þ¼'TýÑÇžß»÷›�5åûO¼Ü¨µÐñ7…öîx³Qó'žØõæ®]oŠ_»wIÞO4¼Ei¾[Q\u°;0V5uÅŒ²] oAüO>þð'íÈ˲‘ yG:/,=`®-'|°Z2'Jͬ®Sª8m' Õ±šºµ‰s›†USAŸ G83tÌ\Ý.noÞ—ÓÛ}â‰Áײ‘¿¸€wà1Ã.�š]¨ä㹆St)S›ÒwEÓ]�@ñNÌ`¯XŽªÖÕnËù0@:‘Á3å=ÉûÁÛ@A3CÏiB"�i>¯ ©©’Æ‹œ2䱋%á}-‚nàJùÛD¿_ÍÞ®‡‡¼aeÛÌÑu'ßd@�B$N7L"§Z:Þï­�Ú‰düâ‡ÝÚÚ~½x?þïlÀ[.Vòžƒs‰(Ê©‚»TÐÖYh†ðFmSµˆ=ì<Í+k¢±ÅÉðAcc{A•}þÓÇõ«(Ù¤é>J�¶"y³/<û Áû íÅløî€çp‰4‚µãµ’¼‹˜†è ÞK×>¾™écýÁni•*«r�À¢YO)ï>, l^61#¾rXÖ\Ê?=„õÔœ±%Ýamyðî'›¿õŠúøß¼ø‹ Þ…\Wiý\¥¦e›Ùz×°sŒUÌ–ˆ7sücº &úÝA€¹„ý~ tßÝd$„y¢è¡V†Pn„ÙìÅ€40U…v€ ›EF°ÉÈû}S5Es]£z5é%ëµH»¾[4ܼðG~ç?>EN S%T¾}Td}žöÊ8îÕ8Ž+žÇ)c8^*Þý »Ð¼f “ûÁ&L•…±iAaƒ24ãnÙƒ¹‚3à©DnYP ˜ê÷ RI 2ƒiŠ$Ýâ�Uê�æUZФ§Ò\M)[y¼ûÉú;�&d\íñ¥Ï†EúcŒ‚@G}É-‹•¶¼KÚVä ˆëÁl½nZ¹«UŸùš®ˆbŸ®"�ixk2G ŸûwÛRÆ0½@¿Å6P¸>¼û9¾ùCÌ‹ìggj(y§ZQµ0(_NO2¬¦Í~+¦�%oCŠÒ$UH¿1R*ÅJÔ ß  7a ¥¾h�¤iZ ™�)‰‰‚Wï"”»|ó8_n¼±mùe˜õ£‚8vZû%ÇVÔïcÛŽkßÉ‘å•$`uP玤¶-î\ãyÌwÚ·– 'NÑB�°P~;>vÈdz"jè �×>ÿæ ¯'u®¿ê-3ÞS¹aýï×]ï ñ†ƒ•ã1H&gr>¹_¢�"ðdÔÝåýzrdUU£]ùÒð)ï%oéÂH:- …*lÍAÔ 'ÊO RÌÕfކ¯æ+”qw†GÚùðÂÚŒÂ)ïeËû{ÿþ+új:?·{zH}/«×§¸ëù…à�ú¾4ňË$ðä’h“—u�ò¤™V©.R¢!ÊÓúþ”÷²åýÂhüœEˆxF "ÓC�n |ÏEŽ›©9ˆ<›÷™E\˜ËµX!t“ïêĶ/4-.¨â85HP–Ly/OÞ/œ‘ó%äÕáø÷T/Ê;¦ÝÅ*%j¬2¢b5ž³-P6¼C&ßåIUQžS¡ÈG‡rx&²Ô¬ÛIûbíÊgT¦¼—ª}þ…Ï<þ ÷ñ‰ñs¡Ç…yÑÍ5Vz LT¬d”´ú5+ 2É»H¡èÊŠËè3Z%Q4§b°{mý)ï¥êo}äoþ÷^üÅÏÓ!oßmš_¦E» pG(…£É%OÌ¡br(®‚f ŠT«,Ý'­tê9 ¦Ë¢é”÷ò_+·>pÿý}ðÁÙ!ïv¦©ªjñWq&?x-¿›…ÿâŒýf_ðºbµè·\\“ÑjŽ46å½|y‹²{Ö—¯™^§_"ÞírÓ6˜ùhJß‘)ß:_R?›\Ÿ(�ÊÓ±kÊ{áxËI#ùu 9Î˲潢àÕ"S¤µðËêŒOÁ‹bòµ{Vµcð"�‚Æ#û õÀÿÊx£À"†ÛÝ©ƒ@À×ed ;{åð å>ê»Ö8©ÊÒ´Ø7.l»Õ”÷Âñ59žªÃñT¤Z°pÃvÞ¤±°7˜J DÞ—)�|¤y´cB@FK¿s½yJ˜oÍŽÈ(ò`/6Ù•ónìq¬ÒÄ�äû/ˆéF€¹á1äc‘r³0 9” ‘ ĪÈO¸ÜÑžfÄ7ë�ÄŒ¡Þ>/\ÿõ©µ®GºU–…¢¸ „74+‚Z<â�˜–":”ëňZ–®™Ø,ò3¨…Ö¦v#:^*9�TM/©�Ú‹í«àÝØãJBƒØˆ%V‘&~à 5 ÄiˆVÏE¾ÉûLeŽO|£1à›)~Î|Ýt¨JÌ£ˆMy_¨ß-ož“2Vµ vBÞ#©Zƒ 2¢ñ9®h~eyà†w?UD‡;°,£(ú-TN!<Ò¨Ž,—ÂŒ–ä*ÊsQ4ôÓK\ÅÓ4ßaž¯GÜô ˆ+¼UŠUÑØ4ƒ¾k23R O‰dRžê{5sB;âÓúû¼öÚ¿ŸyáÌ™x4~.´3�à�!ì”0å±ð$ï9•2EÕAÔòÆBñ˜o ™Î&x}ÛÓD¼ËZ9³hû¼§RÞ !40j+Ð}¦‡†§Û4/ýn¬4÷¹å‹ú›ÙM@Ýcžæ) áqW¹}^þ¾Ný1ïÑÿr¼¨ýŸ¯ŒxÇ Õ<Ç«a˜)‚7K GOCÉÛ¯*Áx:uœ2•y® üD-u+£1H`É|:ÉÛvʬºzÞr¾4 #ä†bh¥)jŽf»ª×°—ñ„Å ðæàZ•3ö¦úY­˜lÊû¼Œ¶?ñ­�~ëÅŸ¾yGšföÍ�uÓ¨\"ªB=—Í]CÝðê²  –.³¶€¢¨eÌ5Œ ÔuTš&†rÉCmÒ>ŽûAÔ3/s�÷¢¼yÓ®¯{%ce¯â"°�^õ¤}o(G{›©]‡š DÜRŽëVŒ�ÛËFÛu_cîêû?ºFH¸ ÇÊX£Î‹aÇv¢Ó;öᣣÊì‚þúeö¿Y-mÁöŠë7ÞR;°žò¾0«˜UU;róÆ×ü¨•0¼n¼y}{á¾.¼#+õM®èX˜å�¤áyö¸š÷÷Y%íqU¢|—ópí¯ÓjEÛãºâöÚKŠ]öÒý寻±ÇÅGö¸Ô’Ò—¡HÚãØÚ�ØãâÖ%|Êû¼þ÷odïÅ{\Ü�¢àBޡΩ9´ÇU%{\•îõX©&©:²Ç…ÕÔ© œ»Ø0ÌZæ÷¥=®ÔÐbæèV1å}Þx‹\¯¨…¤i6a’‡axaÅg5Í9žVÜ¿“ÍSz�LÎ_È[ÚãrzØãr êÓEìq¡�†­=.CÚãŠÒÛß×UóþË7Fë‘õ$e-D%)t¹.Š‚óÕCVЪÖqIKá¬úeAkf!‡Ý(ÞØãB̉ve¦$ïe�«áÀ—5µÇu©ñÔÚvbÏæ¼ÔL{qÔqÔ$æ¦01L�¨2¢z¡mT~Ü(ýnìqUtd�‹J{\°Î‹XÍ¡´Ç9Wâ�Ú‹?íq•ic�k“/íq¥e^Líq]À{<_"ZëÌë@'Ѫ@wMà0Ç×ÃZ «û<^ÔWÛ(� ÖMíq�×eÁ�~ëð½ïýý¤=Y]FšäÛòެ¸Úf¼)÷*Èë¡Jo4ïk‘©=®‹Küèø�ÿø=]t}¹h ñ,DŒ¡sÑÄEQDŠ(B “„Ö(Ì8.Y\/%ï+°:1Tê«6T1.–“IŸë›dzw*@ÈMm×\È»H’dÁ~•={âÞÊ4Lª×"ÞÅŠƒ.¬¼y."' &ìêE�õ†-\Oo3Þ¢Sƒnþ ¯EúcjQV‹¡|­¡®9Ë¹Üæ nÆ{RÏSòF}35ÐÕLz·ûŸ²zø^gT´(y_ø´)ˆÚ+T̨hø%†|IB&�kÎ'¶Cy”­øöâ]6–²•Ž×Ÿcf¸_`…Iâ^’*ŠBšÌy9£Jšò 1P¨®cI!""FÃ�ô‹0Ìd`s¬rõJtå…¿,ˆ¡ç—Ï;±'�r²:¤]ËÉË�U¿ðœ@ša“¦¶Þ…ˆsêznÎÈ Ç‘3&,H¨G*¿¦!�EByÈIއ¢–kæ»>.F"&ÂÈñ«4m®‚ö+ÏózqÆ"Ç¥Ôó\zûñž°çF9”z�@Ñr�çb¡YÔ°#Q†¾MºqªÆq)×"5n–¦ùjD9ê¦0J¢†ƒ“Æ` òžÑ/×3 Í÷Ì2ŠÊ«ë÷.od‡j·–ý¼›ÃûŒœ/Úó.ðG¼UV*”)–§`¥*uѽ)¡)Ô‡Y17\«) CGI�ÉB—úN‹²”kÀ¼ÔðÉœë©Å%júKó®ÃËê1¢°¾½yÇ©?À]}û|ë^9óø/ü±=î%+RÈ�ƒ†7ˆH&êºJ¼M•¸ÏÝ�i~ûª˜ëGZíºº‹»‰"AÃ$YYöF¼UQÙælÉÆSoWÞQÚH_}ÿ›nyòÅÇ¿õâ+ÿ>?/5hjD³€CVª”‡Ð1Sµ®ôžf††£ŠJ8&¤¶,|ÍTRÔ1ÕÔÑ­NáC;Ê mˆšO^‰oô{�Q@]Ývù”÷5òFmeøÆ×è–‡îèÁ¹¹�Á¨ô,äÎËE¯b¥Ü’Y¾ïY²’ËßE%~ËNXYTýf¥c9´ä¬(zò£�EݼwЯ+U&ŠKïß<å½T¼ûTYã†a’«¿�Ø»à´WZ¯Ly/ï~U^ëе¯z˜ò^"Þ©._¥¯Ü›¼êgÊ{ix³-/¼ñ�Œ7ü)ï•À»±çaÆ¿¢nÙ¬’ó�U¹ˆý� ʨ9/j•‡Ò¤nU– šf<Ñc}ÃgÊ{éx7ãçŠÞ kZè+¦]�çLëÅÌPz1›p¹ùÀèÁþÄoÎ-"G®5Ók×›µ<-ûƒ5g�q1[|SÞKÌ{°YðöÎY Eèó8Ún…©wÃ\ׂ¢ SS ˜mèr�š[‡†î0ªër¦²VrÎSM×}Ý–È8U(ê Ñ!×ÌjÊ{Yðï'ÉÒ¬ð@€r5·Ív=²R�ë5¤Y®äfÎŒÐqH¡Oä6e½”ªØµK�nÖmôÛ â¸›�@bê¥;¹§Õ±N ¯È/ö:Ê"ëS‡Û¿.v„,.0�|,ÎÛ–�}9o¢u‹ï'y=x·ö<ðØž‡QšX,ÖZÞÍzdÔ7ÂLÓ6¥Íús÷õ@Kšõ©D׿b7á�˜ o¥1`¡ß·bÓ釾�ûw8WÒ^C�Yzõ"/ˆÔf¯ÏQæML�x‰™v·md`¨š=z ¼tü|eófûý›ŸïUã[¯Lî'Ù'*uŒÐ¨`ËÛñ{ 4ÚÍœDè·íQ� Ö#{z¡4¼#= JSžg5¼£@ò†….ôÛ92z”^ ïÀi7¡IÜq3äUøYä·3" r¿h/¦a)&™®é�BaQ…}?Wôæ­Q^ .@à§<÷ý^¡YÉÊæÝgæ'¾õ±o½ø‹“hÈ[ö`Ôh©ë0�EÔÐÂP‡ÁÀ‰©=fç•4£’ ß$̸…‰n@*× @ÍLL£¾Ÿ˜ ´Ê€†¨_;Ú¥f+/ä�&ˆª.©šTaªd.Á Å#ÞLG^ …„ž4÷ez}EAT‚D�ãž Ö¶†�WÀ 5 "Ϩ£¸Xá¼û̺ÿþ�®LÖqÃw9&÷QÖ¨ƒ_ƒJrø{ô.Ç ÒmÄ´(A™KÞ¸}'DZú¡§5¼-[B嫘×Ð^kìq‰>ô„=.ÔÚã%|2à-íqq5œ°ÇEÑÐhíqÑzÊ{¢ÌC�~ëà…I{�(ÃÏÈ5�4 ôXM%ïÒÑ <ï3AË@¦µ¼-…Và¤�;Ô71ˆ¾vÞÚã‚�=®\¡#ÞC{\œo�K§ë¡RÞNöz®ÇxKÔØóø'ÇòN|?¬«ÐË"ðñCŽ´ŽõEk¬ßO%EâûG~˜”Â?fÈ0 ‚€”~ˆ±p"–æ‘ká=´Çe»ò*‰"íqù°Î ¤ ›oíqy…¯–XÚã"ö¸¬M~}Úãºã©<𹫣¹©¶ÂµÇEõ {\  –1BÄc¨Úuk�KƒZÞ§ ×Úãò¢�=®M=i�Ë"·—=®ë2~Îã ÇùMnÈ^ÔW¦oÆö¸ËZkAö¸ú#{\ì6µÇuxWi3¶‘ßäVìu¶Ç¥gÓþ÷âù¼óY7ç…m{Ëž÷å׿òEã�u�_íüÐ8QÎnEÞò}©jÖI IDAT`Ï7Ï�Ëž/aÉ¢kÐòñ@KÙuà]`Œ:=kâ¼U‚'©E¼aÃ�{·�Οãh4;›á5ʳáó¥<_ì6ÉhœÈã·&ïÁzdC6˜çaQùþʼn!�°~éfM´ð8l ÃÐ Oæ?õ²v„È—_¬bÜ÷˜´í%”ß2+ %JD "¦L©f¢½(ÏÛÄ‘Ólr_ƈ^³6ß¹eyËñó“áøy¬ Ü§%,)ûaXd{ÚšæIQZ ç<ÒIœêæ J9KP>àÍJ¤T PÑïÅq™˜\5oƒsf(P“ö¸ºÒ—Î-D@“V¸8•[Ý9­=..-Ř%Žá³ÅsØÓ49ī饆™BèïŽÕt�5ö ˆäÞyrhXfZ >AéBõUMó³9# Ú•ùA×4LæûD/L $…HÞ¾¥yÖ#ûaª5f\¤b7b0vŒ$*’ ‰R‚Ä„„sP¯6Œ �$‘B:‹ VÍY¶ÎtÇ5IÒ«æ=§I{\TIr­±Ç•NÚãê‚w%‹Ü¬£éq�æJw �á³é̼ã®e‡–ÓnIÞìK�=�@Ûó°LQyÅ›Q -�� Mj˧ܱ™ç6¼YÍ,Ëñúž•&zò#iw}nx“ä*N¯ Ý¶(oRŽìqùÁÀ—ái�‹%JZç�=.Á»çøI§åÍ�9Ù¬H´\³'ëFÜè$"£T,xËnÌc„=#S«„9ó®Aµ¼{zRÀ €ù�·PlÕ#º(-RŒõÞ’¼û¤±çñ7¯ŒÇÏ ¨ÙšÐX5âÖúŒг3Ó“û`â[²dÔ]%Ša”ÏN1ô,“vÎJòVofëžw-¼SÇuS”³ˆ±ˆvm—T ¥=.W®A§žã’Ö—ëºQVÔ÷#i~­Ï"Ï‹‰çyyßuá»�¸–Ü÷‘šëiÆs×£¥ðÍ=·É´41žxAÀ²°ØMD²¤lB“X\¢ç'%bØmÚP4loIÞ}òØC¿óЦn·3²ç!ª½‚SBë~EE›TübÒGnï.¾C<5žŒP�0—u»�M]p.‚¨ŒRðkའ+vù–ÖKû¼vsiÜä¥yËm<•t?h Eð®uHêšF./Í›E—mÁ9õFåIPOy/ÔzówÑ�®_["Þ¹-a>žò^ãç_záǨë?^>ëÏ)™ò¾¡ã-oXoüŠzí6‘¬±ô?Ú2’�*¿Úñ¤½ÿÁ6“’„“>2J]ú½ñÄŸò^†ãç]ØØóÐõÈWt}Xº3m¸Z ÒE;ut=ÎGSí¹Îì‰ÖŸ:º©‡Í ¼¼và$ï|ÊûÆóž°ça‹–vd™>Ë Kvf™o¸tá« í¶; §‡-33M³À�×±ÄóöÜìŸò =®Ð›+¨-Ð-I)�Fuž˜¦O³™hXùpÕ¥lišùÂû!ýïß³¶àê^ÿù¹µõÚwñ[gM¾w¼dJ²²#­Ã�ó‚ G(7‚Qx@“¸ðPÄ^áÇ0éÿ‰ü-¿'ßýѤ향Qëiì‚õu�µ#7ÀŠÆ˜~)GsœŸÒ¶í�ž"»ý ÍÓñÆ{*&¨à0À%ÎRmÁ<€>i94Ø @%c‹ºØ+¼Øç�ó¯!vŠGf?S´1,;Æï,{;ƒ.Æz³¢ñî0ªr¨Óc]$Ba ÛÄÙÓñŽ–™˜Îœ`‘Ñ\R£’#²(mà*z£SW¥Þç}æ?§iÃv¡éT ÃfB&å†`2ÆÄÈ�w“ Π̳¢K(:„tØy’`²„ƒ˜¥o63é~=®8`›`à–8ÓÀû¨ ³ÄÖ®q*Bرxï>¸|Ü•·'Ë2TƒV�2jÒ·fxÏ) m_ú"kÑRçëtد$ M-”¡©çùÉx_Ê;àýÕ·Q›ŸùÏ‹íU†qb@"=YÊàl“-¡ªåH.ðN×:=ãÍ-V;š¥oÚ¾ð~Oý±ÿ½éy|õßÎõ°-ùTAUí ”H5hPCVµ±=瑱Ä-PyÓn›ÁwäMúô�ªù‰x{¾Í`0å�WT[\¦)4åÓµ×<Í=®Ç¯þ⋟üͯËËo%×¶ÔuÁø,\+æº(µ)˘»Û”y9ت,Ó¬}s¨áFøµn]=™Cªæ'âm�Ý\º·õ¸…™t<9ê·„ˆ[z\‡éÿ7ŽÝË|ÿ—€‹Ÿþ›W¡Ô�þüùé<ߣÇe»M�«Û/¤4·õ¸\ Ú|!²Ï%Žz\â¨Ç%[Œ—]ô¸î·Ð9÷Ìô<*æHù’—|1—ø>=®æŠŠª† &êzQ�K]ô¸^6Øôöü›ìŒ|ˆ—Œz\ÖÞÖãZ¢W C¹¥ÇUô¸ú‘éÂûì>g¿*ŒŸYúìô°ähy­Ç {õ¸:SƒÑÉtñͰéq™—ô¸bÒ—Æ-¬—vê/z\/÷¿¿++úÝðo¯íæ½ ßßãA� ª"ƒ+’±¦=.CŽz\U~ÐãøI�«#8Ó§Ë…÷Kþ–/ÿß Ø2÷¸ªêTLa]œ�.Îe–æ¥{ 9Õ<ïµ5›—ºÉ’rcpÇ@uG�k=%UquzÑãz5ïè?OÕµÿüOD4…ç±kïº6ö…GµFÛµ£†¾]¼;§®Õ];�mg��z?̺íf̳'áýå¢Çõ½¼�ñÈŒ· @¬[É� ÇESnØ/^à/IŠK ì«�h^�J\ñªÚmI…®¤xw¼oz�ˆ•ºN…º-=ª#âSmüÙ¬oïkèÞ‡<×SéyÜøÏãÈË3¶ñ®=°lbRƒÈÛ‚ÖA …Þ�ŠÄ܃i…ü€¬ÂN‚R�#‹JuwÂÑú[¤Tö®y¹9Ý|7®·g8ZuJº0+©nç'®NÛÇÛ¶$ˆëqÄ÷{‹‚[ÌT‡Æë±áܧc0gþ‡ÀÛýý¯~x¿>ó§jpy7+ˆ©M·ò†wºFý‘7ñuo½‡âŠxÝ€7KàwO 6jÓ¾rn�Iªã@Ø2–œƒÂšÅ/1‹Í²ésúBê¯LjÈãAÖÎs¼^b®†Å�@/ql?ޱÑÎÏ�®ÚXeãêjÛ¶q¸h 0•¸| Gä¶±:ë³-è6.…=QÁkK’ÕÂb®œÅ=kÞkÿ×ÿñ7ŸþëÿõíoW|zâ]!QÆŠ£“Øžçx9òÞÚsx§Î¢‡7>ÕŸ6K.žŽ7 |)†½>­ä>Eºd§Z‚Ó~EÑÄ "…Tü’¨u¡¡þÆÔ¥„!ªhçqÃÃOšˆs�@È,l)¡]Bê¸i ÿcðŒ^ƒÑ�3WnéÒb*0lbª”ÂöÈÛ ‚û8ˆ´Ž˜Â>M0ˆ-{ŒÙˆ]¸¸€$³Ïš÷ÚÿÕÏòóɵ~‹Yç~ÑË´¬fvC7lƒ_]ß�>Ô�ÁYãM§ýlVgÂßÑÆõÎ÷‡£Ÿ„÷.j¸Ôi]…nu“º‚gbNÔ¢0yMÅ %hç-¬ ¼]üpy…Aƒ cë´‡4Îrfqƒ¤17ž�J„YRã"Ùž‰æ é®á`Œ D»±O:¯[‰Ðí¯rµñöyaÓ*�‘ø5Ñ%£e0t 2ûn ¦‹õ‚â�ð3÷§öWÿg¡|ÐLª÷ê3Mö Þ„7l-‹´sH–;y Ú:"/4yo}1 Œóºv,‹J±¡ªÐ°@F‡ èT»T‡NH8?@U0 UÙíIQt)M�©«¼ˆÊ •XHJð‘7ákQl¼( I+‹g õ~ˆjaáe7‚¬(Ì3罚á9êy„ö|€$Bâ.Ùx—,í¯dQ©½Â|Êê2¦^8òvÃ^Ì[.: £~T_fŽ\ V�æ2¼˜h^ƒîÀ»Ve=¥Y4Š ö±Ï™çZØqÐ7*éaÝG3¯ �Í�y¯ R°ßx+تîÄûªÐDÞ>Ëõ; “} Þ†Å'ºçÆ»ßË+&–EpÞévmÛ%tûŒæ7kÔ°TQìuöuhwg^²6êu­[š†ñ1ÐYVÍ™îôÚ 3gÝ"¬«a*&ìÀä6Ù:TÛt³ÀæŠUNòJƤëù–]¼|Í«ÆÔ6Îeq5kœŠ aü„Aö®‰jaIÎ[ûÚÄkˆå9óv¿üêwréðïž¿öcËüÀ™ÞÀ·s±/É{šÙòDþ–ÿSTÔÌÝø-ÝMøŸ­ŽÍS1u]÷ªË÷|p¼Ž»¾ÀëB¿ÞÃkš“õÛ½Ï\³ü xõ£*¦ ÌHbªŽ�7÷¤B|Qsb$œL—¨G]#WhÓrÖF��k}ÎÛ€~ÖþÂûô¿çøù¯_D=�öÄÛfÃ~@(µ5ÂIG Œ±3^ÖZø´îÁ6mhÞBB"¼¡Þì¸�É"d<áÕ¦.¦±�îÂû9ø×–ˆz?ûéO¯g€oÁª[§lÓï8†®ú-bd=îq‡¥³££S§ÄÑb[·Ãnuñ.¼?¬?uAWuÊ�ã¼ð~_¼ª<:ÌëÂûýðö”¡¹5T\x$ý±?ðž•ò­âÏ_×:\ï»ï ÿjÞ׉aò‰Š›×;lã>7ôg«¯¿eÓóȶ„�Þ˜Åik¼ž?âAzx)Ýn/ûE³¬¾ŒßëaXÄØì̪³[&› 'ûëùÃ÷äÿæt�$ïý‹Ä­d‘ììç¾*g�ËÐa~-1W©Ò}´¼¿ƒ�7ÌOþÔîÇUЧP´é+Â7G[}ËÎèe£Ã()Òíõoæõ Äwö#\mLJ x†FnéýéüH @%q¨;žqÏøw5äÓÐ6fZ0^36È’/’•b"{®C«þÚ¡dƒø¬4ë²WSï+VvVܺ&;°£*›“ÞÕ¤äΉBزI?bÞgz„6ÎÀÑçÕdZ[XÇäªÆ[;ĪPÝÁH“]6®Ó^ZëˆeՌ蜜ºâjŽ œ1tö¾ê ¹øŒ l+Õìc<ŠX¬qËT÷Œw²ßÅxÒTy$a:–@w MY�z¬K2ò|èÃÓƒÇm2¸ÕBÜŒ>á-÷³ƬhBàØ%Ñ1ÿR5êpÛjå/¼íy¸q£%:*+�YŒÑ õYt{=�NB×Oi#cÛì µÊÎ\•,Ü[Z.dOÄT“q¿Ž;ZÖ•5òè€V¨OFNC¥Wˆ!iÝ`{Ÿ½¦wQ}=‹¼‘XõjŸá´(V®Â%LÛã̾ÝrŽ�u Ø-Ȉд7è3šsÛûœÓ$Gü‡9éäéô°¿7z‘·£­ƒ wš2©›jÃ�½"$5˜±ñ^Ý"Çðæ”QÜ#?mÀ²zšPy5X¦ðóÞ2qSÒ¶x‹(í‰â|>°Ìh¼_�«±£fÍ%ªW–úkcŠrå2ðžŒ.|†é’.òö:´AÔ:|ŽÎcŠÏÅ$í4¸ÎžxWkÎ :ê¨2ßSôÇxÔóø�éyx zϰJzA¬LÞ•8ðž�4ª†#ŠÌáý] *é 0†«*;y·„�CƒL¯·ö<´-ûÑh(+:x»ª;ònA¨­÷Öoߌêѽ"ÍÊóŸLck¥Z�s‚Xh'*ˆ„ l 3—@T”Ât&8+Dóe«á Ô1ÿw0(b~à�×ßâÙ_|ñÉß|ý¿¹6^—4Tâ%§µ_J¯çÛ”fƒ)]XHEL±Ûš¼˜VËhØ?¤i+õÂÒ\‹v ð³´qUšÆÙº,XÍ�YÊ”;–6Ì©°y®œâ‘wÌ2ÎÃÎY¦©¹¿ÿ½%ü>$ÿ>hnÅdà›7×o‰»Ýá¿ wmY»}°Ô·”;n=&øv¦ÚÜÁ[ðíß–ðûãõ¯ñ?ýäÓÏ>ûìÓêqy*‹'?b•ä'Òóà©~†z'_Ìcxý…÷kïϸÅ!ÌXåäÿ;èqmã¨n ö‚G·.ã¸øeœŽÝg?�ÓE�ë÷ù“|ô¶¢ÏNÏCŸô¸"öM�‹!Ä…¹\Gk£>éq’!Üèqçú_æûßéWúûþ�¼—×D%-öºÍ¸çƒŠ@~vä-¨×CïF�«�z\…±~´n¨Êû>[°ì2‰™µp¡i�^H…QcÓ‹×+ü©[@W×}ËXuCuhâÎAÚõýîlÇëĶ?ÊUß� í êic\~¦2r¾Ä)­ï†{õ¸ØrG�‹á8 gÓƒÿü¶Zð¹WÓoz\îÂû%Þ1>•Êk=�ÐE.ý8oõ0r8¸uF¡‡mê5£7aÏ;œ¦°³ºÏûÐ%;ì“H�½·ƒ¶NÇ‘—-9¼“ʆ«W:“ÃÇJ–íÝœ¿¹üÿùËz\ê Ç¥÷Æ1zp™D=.{W�k�?Cõ忨½ð¾S¿�ñÈ%S,_²|@%ìÂ[½Î÷®䯹”–ç 28ð„£±B¬é`‰Ì6-ÁyVIÀxD\F ë®JTEq,JŠn—™uLR™‚ÍŒd[ê* �%½Û×$½W�«˜�ßôµÝ¦Ç¥¶­©�aH[_Ç>* ‹z\õI�kŠŽqŸVYõ¸º‹×ëüçqðŠíñ^2ز’5Õ›ï³%�h¼ç¼L[Z³ÚãµÁšÊZ€ÌŸA<²*ÞutíÀ–!‘Éãð,8nu•H—IZY!·Ìƒ�·ç¸ú´æÍ]=.l %×z\�j�ÉàÆrÆ—î¨Ç…C�Û Y®­=¿Öãš}GH®)É.z\ç/Þ¿ûÕ·QÏŸëyø –°®»±¡éÁ×í¼Ù7pм Z×qŠ-¨ó…µ>¶çýêw^{ßGÞ=°:‘ÀJ³�˜9*y6 «ëcý^—Fìeu—÷ÚE=®ui¯çµs à |{K�ë%ëïF�ëÒ»UÚ¿úË߀/ýõ™žn0í ¨ºZD x�ÓŠ�BsÞÀºê#ïºÄµT¨áC¬Ã�«jX ƒdMò,ï¼-)Rzx§yyË,mb5tMR-mE©•铯3Égnª'ñ¯µõóŸüÍçÁo#¥œý å¤Ã‚S�·ë¤ÔëV�ñ�Tsè\õ£SR‡=Q ɵQÝÄøVv®U¦óS8Ȇ_ñ¾ÇeßÍÛ¥»Á†E«ä&{>i 7­‹ü~Þ‘}:�z¾íÎ4µžÊ¿š>{çúaÓ»ðÑ?�?µ}ñ¯ !79ÞŸ‰¿Å4Ms ûtÞË3²9Vá%w §Š©Œ¯KS¼t/âøØ±e¶Îoe(·¦¯ºîÕ·r¼ÉƒÛå �.u-48a‡ôså½퇗Œ¾O�KªÑγ]fç—yŽŠWQ;kÞ<6u΀Þj|›ÐÌ„ãâA9‹šZ›i0WYܺnlÝò5Û´·Â¡œÙ˜-a»îvA£ÒDöËrXÝ~ÃÐ%9³™–áÔøßÅïP§Sømãz›Jèbú…°·¤ÇGäàðíæ†Ø=©kHòͳ‰êâRO­÷’b:!ÈhI…Ëšðg!²ËZJð„¥#¥© ¼wQ4„ÞzCõÌKŒ¶Ó ùbÞPÄ\Bëw™âq½�±Úá¬Â{–dp ÁàÜe8DÞcJ šÙÓ——Bõ|y»ÿüÕïZ;�ß>;=�ê ‘6P½Æf7Œ°C6ég¨:° $Vx±ÆGy)zhºOZ(}ÁÚtÁTàÔ²lÖ�²è€J¤‰õ;µEš]ˆJh0µ MÌT¨ 'ÞÃ:ih{`�]’^ÃD‡M–9Û„k†•2wЏ ÛŠ«À»CC«Ü¦4F‹F̳åûß¿+ÙwšùS¿çvæ¸õµ1æ·ÎñÁì>—ððVº›ÕGðýoKš-3öÚB…B÷Í$E½ˆýòx¹kc*®$ìï òXë‹l™„Å®6€1×dá! í¹ç„VªJtÐé¤M–i——üT¿‘u%Í’ê! ¼C¯#~lÜKYøÈ ÄRW4‘w±òÔ«2ò®we)J¾ÆöÜâ ÁçÍû\Ï#ô”ÄùÐIW<ÁÖaúJû8‡˜œL+›Y �öS€ ®ÑÉãÑrjÎõÃyÛÀûãXGÞ>-†:\¯Ù׃bCÜ£n0SGÞ¾¼Šµw(«òvW{ºkMêxà½WH4¨kL%,ªÊ´KøÝÕ7¼-lÄ�÷L¢ôGÃÆ»†­ê�ÄÕÆ[a-‹U�Pµc{LˆV áitå¶ÙsçõÏoô†Þ8��áι˜£ÙW¼Ø•æìîëlÑØÄ=-«f™ƒ‡óîÃÅû`‰5Î5&²/MÌô>W<ºjZƹ1q,g ÇI]U•iƵíÖzóܹ¦ª” [õÊ¡�ÂIáP-¹Nr> ƒ×¼2s¸”®ø644á$ç{.„k–°Gñ.ì »‰*7¼^¯m§|«g!ú6Øûár£2�ëÂW�R^Qò/|pcÿ.dØÞ�žGÝèÈ{®[ s:tM:†î7HŠBS÷°®A{nˆ’4;UÄ.ɽ4]–º]5ÀÁ€´†‡ÆÀ—r_ÔY®¡,Ø ^©dôúx¦)y°fÊÊÛ·`$xhÿ™ñþê»8^r¦çq¨ßE"j�·*Š :Àp®Š`—òµ¶Ý„–4Ð÷ñîXð)æhvQz6¶çM7¼CÀª]A }Œ½vkoóàãË*\¾«Ý…÷Í�ü/÷õwŸ[~~Ëîªq5šŠ¨èäp ¦YÌPMXsà½-#ï!:5b{>ÅÍšMa²÷h4Ó‰7ZjÎ5¯Sô¸Ì}_ýï_þü×õ<ºož¤)Gi"xL‹qu¨Y…:˜ÖTk°DWW"XK^ãá)HÓ�ÐP¿‘ñ9iÐàña†±gr�ÈÒ`›c*.¼Ÿ�mþå¿ÿ䓟}úé¿;ñŽÒòÛÿ(Þî7Ùw»…~o‚îÇ@ð-³³§¶�bôQD>z�ÝQiž™£K9&qÞ7»õÂûøSGð)—¡|Ð{|áý¾xûXsŸ¡ÿüRÞo¯Mî”ÕÞIì•®²oø÷6w—^{Ø…÷sõ·ü�¶4Å–G×ϳµÆŒw¯Â¶°?¿x_� ”/§I?£Ùú_úLUÏÎ�ÈÄ~áýžý© ½ö§‚‚-ÇØ/ ñ>ô¦âl�LûÁœfnx—›Ãþy—UXê°ó§iÃåÂû9ò>×ó uô·8†°©˜o: 6† X\«'äIDAT�è1bf«B†UæRŒ¹+L…p»Å¯…“Jð˜"Ä–¥sEð…÷³­ßG=�AÏ ”¢¦¤1§œ`N«¢4@ŒZƒ!ÕŽŠŒØ¢Ê$FO¨çÀû*cµ†a‰F’ bÒ*ÿ6íù6–z߬U+Ž�©ë,^Ù¥·�?$X¸uþr“Éö‡8±ì õ<šßžÅ§ª¡ËœÄ�7W;ÎQ³RÑ"ü¢KµO”+©pƒR}ƒ`¬ß»Zi�B{^sÏ2º'¨|Ô7¹O�‹h„ð];r‚›o^g¯ã=Åô�u‚ñí¬“âdR.Tˆ�‘·g¿øòðküŸÎô°‹p3Á�‡Z:ÁoÆBý¦…Þõ… õ»(Ðá.òvÝDÓØž‹íàȱ„§56Ããšä{õ¸†˜Jlf…´|vÂñ²P^90M^NbW¶Üµ¡é™Ë²\bLV^˜™±bKeä]ÑPÁE™×¼èl¾ux@XY›²hgt­gñqù[\ñ_|òÅ×ÿ÷qúûkó€:.)¥½ /ñfÌ(V-¡Ä(R1eR\9¦—l\-#QQaA˜ŽS–’€,níÞ’wßIšvÌSZ -Z¦€†M™9di‡æ~[͆]Ÿ•Ñ•Ð3¬“¦É Ò(ÃU¡¶1‘;&Òñªi�ÆvWÏ„+.Ñ”¼WWþé'?ûi(�ißü�ÅÓëÐv&N{ôcw¯>SRðžtË8κ9B ÜL�B8àuMâ PØry§(ÑÐ PA;lõ;a\“zFóŒtb GcJ÷?HÕ�§ñŸ³º_–§Jl»”´xƒðæûyƒ`õÓj \€a ætIÇÃkà 1àP¡Žl¼m"ëD#?„ƒ–z«ßÔ:w ‰Úµì±…f�jÖîcåí³ôí¾÷òžcÔD QºT˜@‹Ú ÏŒ ¨ AÈ"Ú …!(MêD…ù†x�§œnÑv"!D¥r!v!z¡0Ôáq ]ÌtþHyûÿ™äóêŸ!ï-c‚w6Ž©T¸¢šVT[ÝV�?¶­Û­=æY8ìÚÔ»ì¦Ø¶M‰¶Û‘~»¢ÿHyoz ýæ^=÷ІÙ/ó÷7Þ¾5ï§,3úáÏûÊxE$¢ ã”҃ͧd§«u·Œ¨!!î�õJT•�× Äº“î x¿™׫?Á_xŸñþ¯ß\ûωÒ/f ÝX3z?›ÙQ>Y³)¡,ft2ØQë¼ox"ÜŽ ¶Þè7�æàù 6”èZ¢G¿ÆË„žôôxÞ¾<èqå[M¸Ìêâ7˜�YÂWOz\ã}ƒ;êý©6/$ËRÍ„ÂVî2Ðj˜¢`‘“¼�~) eqUÙÍeúIY‡²h®:¢B�zó.íÖáŠ5áu�È—Çó¾«ÇUFU Ë3=._ƒT'1®=®Ó†‹×}¼Ïô°ƒ�ÃvpojdÒ`ËŠ¬tÏjGò!Ô^ ¬Â*FGïšÙ™a eGhR‡^’ž‘=òî×ÎeÊQÏB§èûhî×ãÂ'=.×ßèq»kºÑãj]Tº fÓã³®®õ¸ªm0ÔÍ…÷9ï_}ê·JÏã‘'ÜTÈ+TS'rÊ}Yfµ7UœGYCßÃo¯`H�pD 0Í[}ÚxSÇi™pÞ<ä+¹Wèq�çz\uÔã" p«¥ì%=.RUáŨ=®*Ð_ô¸nÛVõÅoà—_þ�oÏýçqJ”@u³k ØÁPfC¥ò¯ Ruï]Í“z@ ¦%ÝŽM‘÷¸å¾æ­aÓ´oÈû®FW‹szo,Koˆ—ô¸üµ'㋃¾èqÝ*òù“¿ùœP|â=ô«“s'¤5M°Ô�­7µ”¢Žó2Ñ,s¬C®a‡“uÓù^9©�´^ÍÛí�êKë‡Ö÷¢~P{êîÓãJ‹IßÑãÒâ¨Ç%úh_šÁEýYM�z\ã¦ÇUlz\³;sÑãz©†Ë÷¯’X?žä¾ø7”Šp÷êq¥¤·¨%0Õ‚Pí!j&ˆœô¸hظ<‹ÒG=®æ¨Çu5¯= ïú”ä=®—JÛ|ø[rOÿûàtY^%£â;ûš«e?ž·öÓòžeô­yv¼ß¢Èô¢ÇõŠûü_þ¶w†>?=�Wô'®ë­û1Öà÷Òÿ欈z7-å]E ð·ÒúøwÍ[×õÝ÷ŒKÛC¯Â¬üV¤ÒÜÔ­¿ð~¸¿e�c,Ÿ-bô)&³¸m½y4ìn‚º*3ï˜wUgí4ÇT5‹usXò³!ÊM“µ°Z¢[uŠ"\S|�wý…÷ÃxG}ä¬;ùÏ)¥AD!/ëZ ¡ $¤ëG]‹ÚŽ¢Ò*ú]ó¦Î/„ÀNŠÐÍ’û iè•jƒE>ìP�×Pb ¢é ïpsáý0Þgz¢JP—–f¨+è`Ú§•ФI:ÖÖ;EDZ¨AK±¼kÞ/PQC[Óº ¼›Ì<3P‹@›5¯©˜¡í²éù.Þáý]/ÑÇxäðêvu‘D]–‘—É‚”c˜�EêRx#7P™~òaˆ{õ¸æƒW·ò„7l-‹´ �î³½Š¼UK8ø8²pëõÂûûïó/ÿî7ß}þ-?Óó˜—åEå(kÁŒ:?ê4-r—EÞÀÊÜè-Ø÷�ó¦~Õ ÁB¡6Ùx—œ¶W²¬ä^f²šátGÞÝNôó…÷®ñ·W_þÅ׿ùÝÍ|ƒ´V%Éö3î\™#Q.—¼«ã'ËÈÓç[½Ë{P~õmU[[‹°¡_»..™`V£+Ùj+ªÖ5³—Á`Ó¼ª.öÚCÊø·þÉŸzuõN¼í8£xœÝLâ¨è1ŽÎFÝYëjdæmý™û[.¼_w•ä§e¨3âᅳ¼«>î…÷{ã½ÚÏÓvïL8ûÂû=ñîHÞ“Kù�G /¼ß“}þ×_}΢ßð ï�Åßò‡TþÑ”ó1™¶³ÞÇœ¶<½ÐmyÞÓqYfã´”yYŠ×„Ž„æyá×6³}ý – ï÷è_‹þó„Äù‚c�åœ0Gj5s=Íp\¯ÕÑW £¨u@Ÿ%ˆZÏòEÅï–ã]ʱ:nrèõi/¼ß3ïcôÓüzv…GóöÛTîWÍêl£Þ«s÷±ùêð°¸pͳ~¤ó—ù¡§Ú1”·õ•.~óXï{ô¸DÅýÇW$ôñ ÄìÎßëÀ¦´PçÎrÆX*¤¿ðÞ4éâ“ÿÑžoqÏøw Û}7 ^e…ñMVš6,è"/F'2y'ÊydzÊU�K]ä•Óy¾oc~œî*“|ÒEÖ¹²È‡?lÛ��·ÿßI¨”N=?=�ðW„k3Å©m?É¨Ü )ëa‡päÍÕÔÀÖ¨vt¤XƒŽòz×Ê�¥Ž#쯡Ù55¶òG`庞±oæˆLLhÏë%¹ª¸ª iÁ�"Xý©ü-ø»?²%_ö]gtÓ´/ëy ÷zÊEØïUÓÜ–õh«Óªé:ÿ6¼]¿ ‰€zÔ œ—˜n¼ej‹­~+ïE:“ŠŠŒ)sT¡Þ$-Pu2¢y�-l5èáxá}‹wŒOÅÕµž®�ÚÒËbÚò[ŸVË!oòºœr"‡íÑ“æö\¶nYf»wÌ&üÚR$×Û·á=a ËæKŠèÀR-q [(i´×‚efÂc‡h2…·w64']J´npxN`eãþ ï3Þ_ÞøÏÓL²ÂRn)ìäŽ‚Þ ‚«Ó>p¡)è»}ãö]+Yëý 0DvõŽâN–Í>U��Êó·â}Ð7ö‡œHnSK>êm:b[g-.nFá-X:žq8å ãuá}ÃûLÏc^Û¡½Þ"¿´Û¶°i•Õ—ÚÆùߦ-²YÉRÜàÂÀa†Ú†ÖE lt»…7èüVíù¥¼Þ¿úö;ø][œéyäÉ ùö ç,÷²Èj¯K(¢¾CŽª6sE�é[ýnÌôìz\2›{Y�  ¡Ký>¿ÏÿýW¿ܘåÏNÏ#êqå£öÙ¦ÇÕ'Ú C‰­ÒèFshz\yè7,í™—Üô¸>­,³Û‹×ÿ9ãéwúŽÿÜß“bÛá Zýñ'Ýåm±3z­Ç…R]“T{N¨Z BÚƒט’Ô¬†Ì‚ù®ñU3T'=®!¥¥Nß(ÛÂGàoI6;Ø1¦B㲃w_Æ î¼Î‚ Äv}E1Iéõ¬3Á™pÿûðŠYúWéqõî5OO~Ñãz5ïè?ÿº½öŸgóìÙ$j–R9+#)mÓÙ”êÕÍ ŽË¶ºV6ZÊÅ…]~ÇJi†F¹nÒ�= ¹Ø9´ª†�¾o”O1tïÿ&³åäÿw çÁEÇÒÀ›öB¦ÛÍQ)£�ôù¦Ò˳´$¡MÈFê Øå@æ{Ù�­HÒ�£ˆ›U\UÁV5jQù·ã}3KÅ^ô¸žDÏó=¡=26i’a„(ªÈ.ež×ÕxxsyNZ hÛ�ƒ­�h¬mD=˜aíû¸4Q×£ª3¶�“‹W.Úkƒ}®G^EóõÛýýWß4£$ÿç¢çñƒhÏÅþÞ¢~GË7Ù74ìà¿Ø’sÚ{òG‰öÀÅûú•™½}§Ú3éïÖMiûÕÁ.¼Õž[A‡å-yô°Ñ¦çAHÍ“ûÒç¦[zpWß¾ÒöyØe÷ˆœ¬ýîÞØ>Oñëßþ›ôLσÞkh­¨%Þyµ As³ï‹ÎQ‘ò*Üm¼�,[�j"ÆC{Þ;'àˆ*Q¯š¸È;ý~Þ*Î �îTÞÖ½U™Õ�¾ð7í[ò‹ÿöiÔó�'Þ�vBzÂvMæ…Є€FBt�ª¼Ñ.ígx·QŒ§ê|*LaŒK§="0<�Á 5vcùÞc¨Þf:ðöoULýø({NÝÈ2¼±Íþ÷O>ùäOÎô<ªynëEs*TâÿmÓ¶÷ âqØs:Ⱥt§ãŽ—xˆkÕ)ÇwW»r|ÞR?ºôêqÇrü åÍý©–ì·ûóAÓ„úmÙ¾ç oýå}¨°ë‡V³‰ïïE�ËÓò޼ÓâMÍ£½ÊÙŸ‘zß´­ÂþŠZå]A3ñªžos·¼ö´_þ“ùCÞ}×ñû÷çêt`Ú?ð›¨ÔŒ‡®sóàÒ˜­ÿ=ôâŒ÷n´5ý~¨Ë´ÆˆÌacÒ¹!éPk�z�kqiÉ4ÄéîðÖý®â ¥2Q-o`yg¢îË?“H¡²»óþÎé ±“í¾¦T$òÀ»ÙWûF´‰èžoqj¶jy*�Òï» B>°4×g´Çr›·ïvã0¦Ñ<HïåÞzPh´Ì ™@‹Æ´x?ïMáuè ¼­zQVÔÉ wµ˜ëûy×ûО‹Ä;~â-!̺¤yfíy|Äcæºã€ÓÐþ}—åHù½¥ë�íUÝ\ÿ�·;EÞLk»IŠ@³ƒt׬k—Ìë’ÈÈÛ »€ÁÃ&ðNÂʵßñ†wËör/ʽ�J$ÙxW}¯U_EÞ야ÛÀ–mÓEÞý6ÈPÇ“ú¹ñvÎÐѹsÞî}—ùÁ¼[gi£tîå½ë%d2p-\FLœ³ìpÚghAB^�¸Ÿ@¡€†Rì'|=áäš7H@"z„è1ä%8˜Ý Tîn‹$^æ]fCxš0 ©Ã¡a{µG("¨`Ï‹·u†ìŒsòÃÀ|¹�÷”¥ieg–�ey“çEŒ±›‹47kŸ…«³дñ2Ë˰rÒ»î�mž¨íg0 †må¸q[‰¡žý�úº\ÃáøáxÊppi/óÌx[¹¿2áçoû¾Ë#xÛ%¹âÖÞËûe�Ã=ãH‘m±‹Hô-Þý{ç==‚÷ Š)>!oÆÛU÷L\7Íãyw�|FúgÂ;†?³,ç¼—÷]ÆóVË\�áŒé yß?N,ºá‘¥—M÷¸ã»çÁ{šç9þ—ý5ïn~ßÅ<œ÷áÛÎã9oiÞ®{ÐÅ©ª�+ªuŽêÌóèŸÚ›æf¤ïý÷¿{ñÐQÈkO÷)ž)Æ;èF¼M©åfñy·Ïc8^¾ù©›ö¾y«2Ž ïñR>Žrá}á})Þ—rá})Þ—òœa› ï�Š·¾ðþ˜j·¹´çUí¾Ôï�ªv›ËûûãªÝ—úýqÕîKýþ¸j÷…÷ÇþÀûR>–xÿ‹¬/åc)ÿø/þÙ?ÿ——òñ”þÿˆ†.ß¼òTIEND®B`‚TreeLine-3.2.1/docs/use.html000066400000000000000000001372531506556630100156600ustar00rootroot00000000000000 TreeLine - How to Use
    TreeLine

    How to Use TreeLine

    Contents

    Basic Usage

    Detailed Usage

    Basic Usage

    Views

    Tree View - The left-hand view shows a tree of node titles. Parent nodes can be opened and closed to display or hide their indented descendant nodes. Clicking on an already selected node allows the title to be edited. Right-click context menus are available for commonly used functions.

    Breadcrumb View - The top pane shows the parent and ancestors of the selected node. It is blank if no nodes or multiple nodes are selected. Ancestors with blue text can be clicked to select those nodes.

    Right-hand Views - The right pane is tabbed to show one of three different views of the data. The "Data Output" view shows the formatted text, the "Data Edit" view shows text edit boxes, and the "Title List" view shows an editable list of node titles.

    When a parent node is selected in the tree, the right view will default to showing information about the selected node in an upper pane and information about the selected node's children in a lower pane. The "View > Show Child Pane" command will toggle the display of the child nodes. If the selected node has no children, the view will show a single pane with information about the selected node only.

    When multiple nodes are selected in the tree (by holding down the shift or Ctrl keys while clicking), the right view will not display any child node information. It will instead show information about every selected node.

    When no nodes are selected in the tree (by clicking on a blank area or Ctrl clicking to unselect), the right view will show information about the top-level (root) nodes.

    Data Output View - The "Data Output" view shows formatted output text. It cannot be edited from this view.

    When the "View > Show Output Descendants" command is toggled, the "Data Output" view will show an indented list with information about every descendant of a single selected node.

    Data Edit View - The "Data Edit" view shows a text edit box for each data field within a node. It also shows the node types and the node titles. The types of edit boxes vary based on the field type. Some are just text editors, while others (such as choice fields, date fields, links, etc.) have pull-down menus or dialogs.

    Title List View - The "Title List" view shows a list of node titles that can be modified using typical text editor methods. If a new line is typed, a new node is created with that title. If a line is deleted, the corresponding node is removed from the tree.

    Editing

    Node Menu - The commands in the "Node" menu operate on the selected nodes in the left tree view. There are commands to add or insert nodes, rename node titles and delete nodes. There are also commands to rearrange the tree by changing indent levels or moving nodes up or down. For many of the commands, the descendants of the selected nodes are also affected.

    Edit Menu - The edit menu includes undo and redo commands that can fix problems. Cut, copy and paste commands can operate either on text in the right-hand view (if selected or active) or to tree nodes.

    Format Menu - The format menu has text formatting commands that are active when using edit boxes in the Data Edit view.

    Shortcuts - There are several shortcuts for use in tree editing. Drag and drop will move (or copy if the Ctrl button is held) nodes. Clicking on a selected node will rename it. Pressing the delete key will remove the selected nodes. If desired, these shortcuts can be disabled in "Tools > General Options".

    Files

    Templates - When starting a new file, a dialog box offers a choice of templates. The default has only a single text field for each node that contains the title. The Long Text template adds a second long text field for more output text. Other templates have various fields for contacts, book lists and to-do lists.

    Sample Files - Various TreeLine sample files can be opened by using the "File > Open Sample" command. These have more detail and example content than the new file templates.

    Data Types

    Node Types - Multiple node data types can be defined in a TreeLine file. Each can contain different data fields and have different output formats. See the template and sample files for examples. Nodes can be set to a specific type using the "Data > Set Node Type" command.

    Type Config - The "Data > Configure Data Types" command is used to modify node data types, fields and output formatting. Refer to the Detailed Usage section of the full documentation for details.

    Detailed Usage

    Tree Navigation and Search

    Keyboard Shortcuts - There are several keyboard commands that can be used for tree navigation. The up and down arrow keys move the selection. The left and right arrows open and close the current node. The "Home", "End", "Page Up" and "Page Down" keys can be used to move quickly through the tree.

    Another way to move through the tree is to type the first letter of a visible node title. Hitting the letter again highlights to the next possibility.

    Selection - Multiple nodes can be selected by holding down the CTRL or the SHIFT key when changing the active node. Individual nodes are added or removed from the selection when the CTRL key is held. The selection of all nodes between the old and new active nodes are toggled when SHIFT is held. The active node can be changed by using the mouse or by using any of the keyboard navigation methods.

    The "View > Previous Selection" and "View > Next Selection" commands can be used to toggle through a history of selections, allowing faster navigation through the tree.

    Searching - The "Tools > Find Text" command will search for text within the tree structure. The dialog box has options for searching all of the node data or only the node titles. There are also options for how to interpret the search text. Key words will match nodes with the search words found anywhere in the node. Key full words will only match complete words anywhere in the node. Full phrase will only match the complete phrase in the proper sequence. Finally, the regular expression option will search using Python regular expressions.

    The "Tools > Conditional Find" command will search in particular node types and node fields. Various comparison operators can be selected to exactly match, to match a greater or lesser value, or part of the value. And the True/False operators give the same result regardless of the values. In general, the value is interpreted using the edit format for special field types. Multiple rules can be added, connected with logical "and" or "or" operators. The "All Types" option makes fields from every type are available, so that multiple node types to be part of the same search. The condition will be false for node types that do not contain that field name.

    There is also a quick, incremental search of node titles. By default, it's bound to ctrl+/. Then, matching titles are found as the search string is typed. The F3 and shift+F3 keys can be used to go to the next or previous matches, respectively.

    Filtering - There are two filtering commands, "Tools > Text Filter" and "Tools > Conditional Filter". They work like the corresponding search commands above, except that they show all of the matching nodes in a flat list that replaces the tree view. The nodes can be selected and edited from this view. Use the "End Filter" button to restore the full tree view.

    Searches for Conditional Find and Conditional Filter can be saved in the dialog boxes and loaded again at another time.

    Defining Node Types

    Type List - The "Type List" is the first tab of the "Data > Configure Types Dialog". The list of data types can be modified by the buttons on the right. New types can be added, and existing types can be copied, renamed or deleted.

    Type Config - "Type Config" is the second tab of the Configure Types Dialog. It contains a selection for the default child type. If set, this will be the initial type used for new children with this type of parent. If set to "[None]", children will default to either the type of their siblings or their parent.

    The "Change Icon" button allows the selection of a custom tree icon for this data type. The "Clear Select" button on the icon dialog can be used to set the icon to "None", so that no icon will be displayed for this type. To avoid showing any tree icons, the "Show icons in the tree view" general option can be unset.

    There are also options here for adding blanks lines between nodes, allowing HTML tags in the common format text, and changing the output to add bullets or tables.

    Field List - The "Field List" is the third tab of the Configure Types Dialog. The list of fields within a data type can be modified by using the buttons on the right. New fields can be added, and existing fields can be moved, renamed or deleted. Sort keys can also be defined to specify the fields that are compared when nodes are sorted.

    Field Config - "Field Config" is the fourth tab of the Configure Types Dialog. The field type and its output format string can be set, if applicable to the field. Extra prefix and suffix text to be output with the field can also be set, and a default field value for new nodes can be entered. The number of lines displayed in the editor for the field can also be specified. Finally, an option to evaluate HTML tags can be set to recognize HTML tags in Choice, AutoChoice, Combination, AutoCombination and RegularExpression fields. If this is set, special characters (angled brackets and quotation marks) will need to be manually escaped to show up in the field text.

    Output - "Output" is the last tab of the Configure Types Dialog. The left half of the dialog shows the fields. The right half shows the formatting for the title (used for the node text in the tree view) and the node output. The formatting consists of text lines with embedded fields. The fields are shown as "{*field_name*}". The fields that are selected in the list (multiple fields can be selected by holding Ctrl or Shift keys while clicking) can be added to a format at the cursor position with the ">>" keys. The field reference at the cursor can be removed with the "<<" keys.

    Field Types

    Field Options - The field type and options are set in the "Field Config" tab of the "Data > Configure Types Dialog". The many different field types are described in the paragraphs below.

    Several of the field types use a formatting string to define their output. For a list of available formatting characters, use the "Format Help" button. Entries in the data editor which do not match the format will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with "#####".

    Text Type - The default field type is a text field. It is the most commonly used field. These fields are edited using edit boxes in the data editor view. There are several commands in the Format menu (and also in the context menu) for setting the font style and adding external or internal links. The edit box height expands when re-displayed after adding several lines of text. The minimum edit box height can also be set explicitly in the "Field Config" tab.

    HTML Text Type - This type allows simple HTML tags to be used in the text. Commonly used tags include "<b>bold</b>", "<u>underline</u>", "line break<br/>", "horizontal line<hr/>", and various font tags. Complex block tags should generally be avoided. Carriage returns are ignored and non-escaped "<", ">" and "&" symbols do not display.

    One Line Text Type - This type restricts the text length to a single line. It does not allow carriage returns but does not restrict line wrapping of a single long line.

    Spaced Text Type - This type holds plain text and preserves all spacing. Other formatting of the text is not permitted. It could be useful to use the "Tools > Customize Fonts" command to set the editor font to a mono-spaced font when using this field type.

    Number Type - In the number type, special characters in the format define the display of the numbers. The format uses a string of "#" (optional digit) and "0" (required digit) characters to define the output formatting. For example, pi formatted with "#.#" is "3.1" and formatted with "00.00" is "03.14". Regardless of the formatting, digits to the left of the decimal point are not truncated, since that would display an incorrect result. But use care to show enough decimal places (either optional or required) to avoid problems with round-off error.

    The radix character can be specified as either "." or "," to handle internationalization. For use as a thousands separator, use "\," or "\.". For example, a large number may be formatted as "#\,###\,###.##" or as "#\.###\.###,##". Press the "Format Help" button from the field format dialog for more formatting details.

    Unlike most other formats, the number type also uses the output format for display in the Data Editor. Of course, any new entry with a reasonable format is correctly interpreted (but the correct radix character must be used).

    Math Type - Math field types are configured by defining equations. The equations can reference number fields, date fields, time fields, boolean fields, text fields and/or other math fields. The resulting values of math fields are automatically calculated for each node. Various mathematical, relational and string operators are available. The results can be numbers, text, boolean, dates or times.

    To define a math field equation, press the "Define Equation" button in the "Field Config" tab of the "Data > Configure Types Dialog". This brings up a dialog with fields to reference on the left and math operators on the right. The "Reference Level" pull-down determines whether the reference is from the same node, the node's parent, the root node, or the node's children. The "Result Type" pull-down allows arithmetic, date, time, boolean or text results to be chosen. The "Operator Type" pull-down allows numeric, comparison or text operators to be shown in the operator list. The down-arrow buttons below the references and operators add the selected item to the equation text below. Portions of equations can also be typed directly in the equation text line editor.

    References to child nodes must be enclosed in a grouping function, such as sum, max, min, mean or join. A math field can contain a parent or child reference to itself, but not a same-level reference to itself (a circular reference). The references only contain the field name, so they will reference a parent or child field with that name even if it is a different node type.

    In equations, date fields are represented by the number of days since January 1, 1970, and time fields are the number of seconds since midnight. So date fields can be subtracted to give the number of days elapsed, and numbers of days can be added to or subtracted from dates to result in new dates. Time fields can be subtracted to give the number of seconds elapsed, and numbers of seconds can be added to or subtracted from times to result in new times.

    The "if" comparison operator can be used to make the result depend on the value of another field. The expression is written as "true_value if condition else false_value". Of course, the "true_value", "condition" and "false_value" strings must be replaced with valid fields or expressions. If this operator is inserted from the operator list (under comparisons), it will include parenthesis as placeholders. These parenthesis are optional in the equations.

    The "join" text function is used to combine text from several other fields (or from child nodes). The first argument to the function is a separator string that is placed between each piece of text. The remaining argument(s) are the text to be joined.

    By default, math fields are shown in the data edit view, but they are read-only. To hide them, uncheck the "Show math fields in the Data Edit View" box under "Tools > General Options > Features Available".

    There is also an option under "File > Properties" that toggles whether blank fields are treated as zeros. If checked (the default), a blank field that is referenced by a math field has a value of zero (for numeric operations) or blank (for text operations). If unchecked, any blank references also cause equations that reference them to be blank.

    Numbering Type - This type (not to be confused with the number type above) provides fields that are automatically filled in with the "Data > Update Numbering" command. The "Format Help" button in the field format dialog shows the output format options. A single format level will result in a simple sequential numbering scheme. Use of the "/" level separator will result in an outline-type numbering with different sequences at different levels. Use of the "." section separator will result in a "2.3.5" type numbering scheme.

    Since numbering fields are automatically populated, by default they are not shown in the data edit view. To show them, check the "Show numbering fields in the Data Edit View" box under "Tools > General Options > Features Available". When they are shown in the data edit view, they show up in section numbering style, regardless of the output format.

    Date Type - In the date field type, special characters in the format (all starting with "%") are replaced by elements of the data, similar to number fields. Press the "Format Help" button from the field format dialog for formatting details. Non-special characters will be output as themselves.

    There is also an edit format under "Tools > General Options > Data Editor Formats". This controls how date fields are displayed in the Data Editor view. Generally, entries in the data editor with various formats will be correctly interpreted regardless of this setting, but dates must use the correct day-month-year sequence. Also note that the date editor format does not support days of the week.

    A default initial field value of "Now" can be used to enter the date of node creation.

    Time Type - In the time field type, special characters in the format (all starting with "%") are replaced by elements of the data, similar to number fields. Press the "Format Help" button from the field format dialog for formatting details. Non-special characters will be output as themselves.

    There is also an edit format under "Tools > General Options > Data Editor Formats". This controls how time fields are displayed in the Data Editor view. Generally, entries in the data editor with various formats will be correctly interpreted regardless of this setting.

    A default initial field value of "Now" can be used to enter the time of node creation.

    DateTime Type - The DateTime field combines dates and times into a single field that is useful for timestamps. Special characters in the format (all starting with "%") are replaced by elements of the data, as in date and time fields. Press the "Format Help" button from the field format dialog for formatting details. Non-special characters will be output as themselves.

    The DateTime edit format is uses the date and time formats located in "Tools > General Options > Data Editor Formats". The date and time formats are combined, separated by a space character.

    A default initial field value of "Now" can be used to enter the date and time of node creation.

    Boolean Type - This type gives two choices corresponding to true/false values. The format help menu includes typical values such as "yes/no", "true/false" and "1/0", but users can also enter their own word pair. The data editor boxes will accept either the currently set format or any of the typical values.

    Choice Type - The choice field type allows for the selection of text items from a pull-down edit list. The formatting strings for these types list the items separated with the "/" character (use "//" to get a literal "/" in an item). Entries in the data editor which do not match the choices will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with "#####".

    Auto Choice Type - This field type is similar to the choice type, but without a format string. The entries in the pull-down menu are automatically generated from all previously used entries. Any entries that are typed will be available in the pull-down menu for future use.

    Combination Type - This is basically the equivalent of the choice type with multiple selection. The formatting string entries are separated by the "/" character. The pull-down menu shows check-boxes that are checked for currently selected nodes. By default, the selected entries are output separated by a comma and a space. This can be changed in the "Type Config" tab of the "Data > Configure Types Dialog". Click the "Show Advanced" button to see the separator setting.

    Auto Combination Type - This field type is similar to the combination type, but without a format string. The entries in the pull-down menu are automatically generated from all previously used entries. Any entries that are typed will be available in the pull-down menu for future use.

    External Link Type - This type can support various link protocols, including http and https for web pages, mailto for email addresses and file for local files. A pull down dialog in the data editor allows the selection of the protocol type and the entry of an address and a display name. In the edit boxes, the display name shows up in [brackets], and it is used as the text of the link in the output view. The "file" protocol also provides a button to browse for a path and buttons to choose either absolute or relative path names.

    Clicking on the link in the output view or choosing "Open Link" from the right-click context menu in the edit box will open the link in a web browser. In Linux, setting the "BROWSER" environment variable to a string like "mozilla %s" will result in the desired browser being used.

    Internal Link Type - These links create shortcuts to select nodes elsewhere in the tree structure. To create a link, click the pull-down arrow and then select the target node in the tree view. The display name is shown in brackets. It is initially set to the target node title, but it can be edited. The right-click context menu can be used to clear the link or to select the target node.

    Clicking the link in the output view will select the target node in the tree view.

    Picture Type - These links add referenced pictures to the output view. A pull down dialog in the data editor has a button to browse for picture files to be linked. It also allows absolute or relative paths to be used and has a small image preview.

    Regular Expression Type - This type allows arbitrary format strings to be matched that restrict the data to a particular format. It uses Python regular expression syntax. Entries in the data editor which do not match the format string expression will cause a blue triangle to show in the upper left corner of the edit box, and the output for that field will be replaced with "#####".

    Output Formatting Details

    Output Format Examples - Here is an example of output formatting for a book list:

    "{*Title*}" (c) {*Copyright*}, Rating: {*Rating*} {*PlotDescription*}

    Each of the field names in enclosed in {* *}, curly brackets and asterisks. For more examples, see the sample files that can be opened using the "File > Open Sample" command.

    Title Formats - When a node in the tree is renamed, the program attempts to match the title formatting pattern to set the appropriate fields (the same title matching occurs when editing lines in the "Title List" view). If the title formatting is too complex, it may not correctly guess the intent. Things like adjacent fields with no characters separating them should be avoided unless you do not wish to rename nodes from the tree.

    If the text data used for a tree view title has multiple lines, only the first line will be used as the title.

    Skipped Output Lines - If all of the fields in an output format line are empty for a given node, then the line is skipped. No blank line or embedded text will be output for that line. Note that this does not apply to a line without any fields (only embedded text). Also, when a line ending with a <br/> or an <hr/> tag is skipped, the ending tag is retained.

    HTML Tags - By default, the "Allow HTML rich text in formats" option is unchecked in the "Type Config" tab of the Configure Types Dialog. So any HTML tags are treated as plain text. If the option is enabled, simple HTML formatting tags can be used in node output formats.

    Commonly used tags include "<b>bold</b>", "<u>underline</u>", "line break<br/>", "horizontal line<hr/>", and various font tags. Complex block tags should generally be avoided.

    Other Field References - References to fields that are not contained within the node can be added to the output. Pushing the "Show Advanced" button on the "Output" tab of the configure dialog makes a reference level selection become visible.

    If the reference level is changed to "File Info Reference", fields containing file meta-data can be added to the output. These include the file name, path, size, modified date and modified time. These special fields are shown as "{*!field_name*}" in the title and output format editors.

    There are field references to various ancestor nodes (parents, grandparents, etc.). These require the data type of the reference to be specified. This selection determines the field names that are available, but the data from any type with a matching field name will be shown in the output. References to fields from parent and grandparent nodes are shown as "{**field_name*}" and "{***field_name*}", respectively. There are also general ancestor references, shown as "{*?field_name*}", that take data from the closest ancestor with a matching field.

    References to child nodes can also be added, shown as "{*&field_name*}". These also require that the child data type be specified. The child data becomes embedded in the parent output. The child data is delimited with a separator string defined on the "Type Config" tab (with show advanced active). The separator defaults to a comma and a space, but can be set to <br/> or anything else.

    Finally, a "Child Count" reference can be added. This field will show the number of children ("Level1" field) or grandchildren ("Level2" field) of a node. These are shown as {*#Level1*} in the format editors.

    For examples of these fields, see the "sample_other_fields" file (by using the "File > Open Sample" command).

    Math Fields - For more complex output formatting, the math field can be used to combine other fields using various mathematical, relational and string operators. See the Math Type section for details.

    Type Format Details

    Generic and Derived Types - Data types can be set to derive their field settings from a generic type. This allows types with different output formatting to always use the same set of fields. Any changes to the generic's list of fields and field types are automatically reflected in the fields of all derived types. This does not apply to a field's output formatting, which can still be set independently.

    There are two methods for creating derived types. First, a derived option can be selected when copying a type on the "Type List" tab of the "Data > Configure Types Dialog". Alternately, a generic type can be specified from the derived type's "Type Config" tab of the dialog if the advanced functions are shown.

    Conditional Types - Conditional expressions can be used to automatically assign a data type based on each node's content. Conditions can be assigned only to a generic type and its associated derived types. This allows the automatic assignment of different output formatting or different icons depending on each node's field data.

    The conditional dialog box is accessed from a button on the "Type Config" tab of the "Data > Configure Types Dialog" if the advanced functions are shown. Each line of the condition includes a field, an operator and a comparison value. The operators include equality, greater than, less than, starts with, ends with, and contains. There are also True and False operators that will toggle the type of all nodes simultaneously.

    For special field types such as dates, times, and booleans, the comparison value should be entered in the same format that is used in the Data Editor window. In general, the starts with, ends with, and contains operators should not be used for these special fields, since the comparison is done using an internal data representation. Dates and times also support a special comparison value of "now", which is always interpreted as the current date and time.

    The "Add New Rule" button is used to add additional condition lines. The lines can be joined with "and" or "or" operators. The "Remove Rule" button deletes the last condition line. If only a single line is present, the "Remove Rule" button completely removes the condition.

    Conditions do not have to be set for all types in a family. If no conditions are true for a node, the program will select a blank condition rather than a false one.

    For an example, see the "sample_conditional_todo" file (by using the "File > Open Sample" command).

    Copying Formats - Another method for changing data type formatting is to copy the formats from another TreeLine file. This is done with the "Data > Copy Types from File" command. All types from the chosen file are copied. Any types in the current file with matching names are overwritten, but types with unique names are retained.

    Child Type Limits - In addition to setting the default child type, the child node types that are available to be set can be limited. There is a pull-down list of child type limits in the "Type Config" tab of the configuration dialog if the advanced functions are shown. Only checked types will show up in the type lists when using the "Data > Set Node Type" command on a child node.

    Tree Data Operations

    Sorting - The "Data > Sort Nodes" command can sort nodes based on either node titles or key fields predefined in the node type configuration. The predefined sort fields can be changed in the "Field Config" tab of the Configure Types Dialog. The "Sort Keys" button brings up a list of fields that define a sort key sequence. The fields higher in the sequence have a higher priority. The direction for each key field can be flipped.

    Numbering - The "Data > Update Numbering" command updates the contents of fields with a special numbering field type. The field's output format defines how the numbers are displayed in the output, including whether individual numbers, outline numbers or a section numbering scheme are shown. See the Numbering Field Type for more information.

    Note that numbering fields are not shown in the data edit view unless "Show numbering fields in the Data Edit View" is checked under "Tools > General Options > Features Available". When they are shown in the data edit view, they show up in section numbering style, regardless of the output format.

    Find and Replace - The "Tools > Find and Replace" command can be used to change the text in several nodes. The search text and replacement text are entered. Searching can be based on any match, full words only, or a Python regular expression. The operation can optionally be restricted to a particular node type and to a particular node field.

    Replacement using regular expressions is quite powerful. Searching for ".*" will match all of the text in the field. The replacement string can contain back references that consist of a backslash and a number. The back references get replaced with the corresponding parenthesized group from the match. For example, "\2" will be replaced with the text that matched the second group of parenthesis. The "\g<0>" back-reference can be used to substitute the entire matching string.

    Spell Check - There is a spell check command in the "Tools" menu. Use of this command requires an external program to be installed (either aspell, ispell or hunspell- see the System Requirements section). If there are any misspelled words in the selected branch, a dialog will allow the word to be ignored, added to the dictionary, replaced with a suggestion or edited. This will spell check the text in all data fields of each node.

    Cloned Nodes - Cloned nodes are used to duplicate sections of the tree. Editing their data or child structure in one location changes all locations. When a cloned node is selected, multiple lines are shown in the Breadcrumb view, showing ancestor nodes that have multiple parents. The selected node will appear black (not a link), but its clones can be clicked to select their location in the tree view.

    Cloned nodes are created by copying nodes or branches and then using the special paste clone commands found in the "Edit" menu to paste them elsewhere. The clone link can be removed by deleting the nodes or by using the "Data > Detach Clones" command to convert them back to regular nodes.

    Cloned nodes can also be created automatically by using the "Data > Clone All Matched Nodes" command. This will convert all identical nodes in the tree structure into cloned nodes.

    For an example of cloned nodes with multiple parents, see the "sample_genealogy" file (by using the "File > Open Sample" command).

    Category-Based Arrangement - The "Data" menu contains commands for arranging and flattening the data by category. These methods are used to automatically add and remove levels of nodes below the current node in the tree.

    The "Add Category Level" command allows you to select one or more of the fields that the child nodes have in common. These fields are used to create new parent nodes for the children, grouping them by common categories. For example, in a list of books, picking the "author_first_name" and "author_last_name" fields will result in a tree with the books under new nodes for each unique author.

    The "Flatten by Category" command is almost the opposite of "Add Category Level". It eliminates any descendant nodes with children, transferring their data fields to their children. It will rename fields instead of overwriting data with the same field names, but this command is most useful when the children and parents are different types with unique field names.

    There is also a "Swap Category Levels" command that will swap the child and grandchild nodes beneath a selected node. A child node with multiple nodes under it will become cloned under each one. Any existing grandchild clones will become individual nodes with multiple children.

    Printing

    Print Setup - The dialog for print setup contains four tabs. The first, General Options, includes settings for what part of the tree to print, whether to include lines to child nodes and whether to allow page breaks between a parent an its first child node. It also has place to set the printer queue, to make pagination and print previews more accurate. The second tab, Page Setup, includes paper size, orientation, margins and columns. The third tab selects the font for printing. The last tab, Header/Footer, defines text and file data meta-fields for inclusion in headers and footers.

    Print Preview - The Print Preview window shows how the printout will look with current print settings. It can be dragged larger to show more detail, or the zoom settings can be changed. It also includes buttons for the Print Setup dialog and for printing.

    Print to PDF - This command prompts for a path and file name to export a PDF file. It uses the current printer settings.

    File Handling

    File Compression - A TreeLine file is in a JSON text format. There are options to compress the files (gzip format) to save storage space. Individual files can be set to compressed mode from either "File > Properties" or from the file type pull-down in the save-as dialog.

    File Encryption - There is a file encryption option to password protect TreeLine files. Individual files can be set to encrypted mode from either "File > Properties" or from the file type pull-down in the save-as dialog. The encryption uses an SHA hash function as a stream cipher - it should be fairly secure.

    Auto-Save - An auto-save feature can store unsaved files with a "~" appended to the file name. The backup files are automatically removed when the file is saved or TreeLine exits cleanly. The auto-save time interval is set in the general options. Setting the interval to zero disables this feature.

    Saved Tree States - When opening a recently used file, TreeLine will restore the states of open and selected nodes. This information is stored in the user's TreeLine configuration files. If desired, this feature can be disabled with a general option.

    File Import

    General Information - A TreeLine file is in a specific JSON text format. Other types of files can be imported using the "File > Import" command, which will show a dialog box where the type of import can be selected. Alternatively, using the "File > Open" command with a non-TreeLine file will also show this dialog.

    Text Import - Several different text formats can be selected for import. Tab indented text creates a node title from each line in the file, structured based on the number of tabs before each line.

    The comma-delimited (CSV) and the tab delimited text tables use the first line as a header row to create field names, then each additional row becomes a node with field data taken from each column. The CSV import with level numbers creates a tree structure from level numbers in the first column that are incremented to show child relationships.

    The plain text, one node per line import creates a flat tree of node titles.

    Finally, the plain text paragraph import creates long text nodes from text separated by blank lines.

    Bookmarks Import - TreeLine will import bookmark files in both the Mozilla HTML format (Firefox browser) and the XBEL format (Konqueror, Galeon and Elinks browsers). Each bookmark becomes a node with a name and a link field. Some information in the files, such as visited dates and icon references, is not imported. For an example, see the "sample_bookmarks" file (by using the "File > Open Sample" command).

    Old TreeLine Import - Files from older versions of TreeLine (1.x or 2.x) can be imported. These files are in XML format and generally have a ".trl" file extension (current files are in JSON format with a ".trln" file extension). Unlike other file imports, these older files will import without showing the import dialog box when using the "File > Open" command.

    Treepad Import - Files from the Treepad shareware program can be imported. Only Treepad text nodes are supported.

    XML Import - TreeLine will import and export generic XML files. These routines do not have much intelligence - each XML element becomes a node and each XML attribute becomes a field. XML text content become fields named "Element_Data". This lets TreeLine function as a crude XML editor.

    ODF Import - TreeLine will import Open Document Format (ODF) text documents, from applications such as Apache OpenOffice and LibreOffice. The node structure is formed based on the heading styles assigned in the document. Any text under each heading is assigned to that heading's node. The import filter is intended for simple text outlines only. No formatting is maintained, and objects such as tables and pictures are not imported.

    File Export

    General Information - Files are exported using the "File > Export" command. This will show a dialog box of available export types and options.

    HTML Export - The HTML export subtypes can export to a single page or to multiple pages. The single page export contains all of the indented output. A navigation pane on the left with links to anchors at node positions is optional.

    The multiple HTML pages export has one web page per node. It includes a navigation pane on the left with links to the pages with sibling, parent and aunt/uncle nodes.

    Multiple HTML data tables export creates a table in each HTML file that contains the data for a set of siblings, as well as links to the parent and child pages.

    The Live Tree HTML export uses Javascript and CSS to create an interactive view. Nodes in the tree can be expanded and collapsed, and a separate pane shows the output for all descendants of the selected node. The first form of this export creates separate files that are linked to the existing TreeLine file. These files are intended for use on a web server (browser security usually prevents local access). The HTML file stores the relative path from the TreeLine file to the initial export directory, so this relationship needs to be maintained on the web server. Only the TreeLine file needs to be replaced to update the data (re-export is not required).

    The second form of Live Tree export creates a single file (with embedded data) that can be accessed from a local web browser. It appears the same as the first form on the browser.

    Text Export - Data can be exported to tabbed title text, comma-delimited (CSV) tables and tab-delimited tables. These formats are the same as the corresponding import formats.

    There is also an unformatted text export the dumps all of the output into a text file without preserving the tree structure.

    TreeLine Export - Files can be exported that are compatible with older versions of TreeLine (1.x and 2.x), with a ".trl" file extension. Some newer features, such as cloned nodes and multiple root nodes may not be completely preserved. TreeLine subtrees can also be exported to save just selected branches of the tree to a file using the current TreeLine version.

    XML Export - TreeLine will import and export generic XML files. These routines do not have much intelligence - each node becomes an XML element and each field becomes an XML attribute, except for fields named "Element_Data" that become the element's text. This lets TreeLine function as a crude XML editor.

    ODF Export - TreeLine will export an outline to an Open Document Format (ODF) text document, compatible with Apache OpenOffice and LibreOffice. The title of each node is assigned a heading style at the appropriate level. Any other text in the output of each node becomes normal text under the heading. The export filter is intended for simple text outlines only. Any HTML formatting is stripped, and objects such as tables and pictures are not supported.

    Bookmarks Export - TreeLine will export bookmark files in both the Mozilla HTML format (Firefox browser) and the XBEL format (Konqueror, Galeon and Elinks browsers). TreeLine will look for a link field in each node that becomes the target of the bookmark.

    Customizations

    Options - TreeLine's behavior can be modified with several settings available in "Tools > General Options". Most of these options are covered elsewhere in this document.

    Keyboard Shortcuts - Keyboard shortcuts can be customized by using the "Tools > Set Keyboard Shortcuts" command. Simply type the new key sequence with the appropriate field selected.

    Toolbars - An editor to customize the toolbars is available from "Tools > Customize Toolbars". The number of toolbars can be set, and the buttons on each can be defined.

    Fonts - The default font used in the application can be set using the "Tools > Customize Fonts" menu. There are also options to specify fonts used in the tree views, the output view and the editor views.

    Tree Icons - There is an icons directory in the user configuration directory ("~/.treeline-x.x/icons" on Linux, "Users\<user>\AppData\roaming\bellz\treeline-x.x\icons" on Windows). Image files (PNG or BMP) placed into this directory are available for use as tree icons.

    Translations - Translations of the TreeLine GUI are available in German and Spanish. The translation should load automatically if the OS locale is properly set. Alternatively, "--lang xx" can be appended to the command that starts TreeLine, where "xx" is the two-letter language code ("en", "de" or "es").

    TreeLine-3.2.1/icons/000077500000000000000000000000001506556630100143465ustar00rootroot00000000000000TreeLine-3.2.1/icons/toolbar/000077500000000000000000000000001506556630100160105ustar00rootroot00000000000000TreeLine-3.2.1/icons/toolbar/32x32/000077500000000000000000000000001506556630100165715ustar00rootroot00000000000000TreeLine-3.2.1/icons/toolbar/32x32/dataaddcategory.png000066400000000000000000000040121506556630100224140ustar00rootroot00000000000000‰PNG  IHDR szzôÑIDATxœ½—ilT×€¿÷fóÌx<Þ¼à ˆ!Ç,bI�€E¤ E")- Ð?IUUi«(­”¥j«*U£BB”&­š¢”¶”B0©K ئ2f ØØx¼^f<žå­·?›­@iïÓÑ}W:÷žïžsÏy÷I5kwX�4@# µûÿ§&M¾Ô¬Ý1 XT§€¿5Ôî×ÿç5kwx 0�`° HÞm¨Ýÿ÷i�vÀ|˜`–‚ÒêYÀ£@®�ð€¼\PZ]UPZ}¦¯³I-(­¶ö‚Òj³¯³é¡„IF� @ @Cí~µ¡vÿpxÈty½?yó/6¯únl]Õ7}$¼õPšP³vÇë€ü¼¡v¿°ûãÅU žËr~}{zæ¶B¯ËJL À4:m¶œ/ìVïO·ÏO:ößX¯÷¿Þm;-~mAªu�˾…QûV–ÌIÆi—§&#ósMSäö�hOíõEöìªtÿA¦gÁ�€ì—77üÂ]á>·}ÍNþ Kʼج2B$Iš1Y7¾Î(1ÕÜóÊ│˜ �ä¿]¹¢kvٚ˒òžaaq*BN|ÞN§ÿ)¹¹,œ“ÂÂäõ­!T�]¯Õ¤í{`\YVT.×{Š×HëÖ/#¿¸€ONµrùŸŠG{üá§Ÿò·Éó¶­H)ÚJi®kj^(ªSßDv½±2ë¾ äi`þvß•KRtlŒÚƒÇøÝ/?äÌLJEwóÐh`ØQÿþ�¹ßÖ5h,ªb”x\V–=âE5ͽ?¨|á¾6ïy*»,9¾§¨,›ª�뙿´»Ë…Í�$¬IÚAàgÛ.ÚcºÇe•5{º¤¸m,�ë%ªh»¿s¼¯æ^¦BðÕ·W–?=w¨]¸^eØý<ËÉF×tžhEÄ�è‡Ïoµ-* Û¿Ìó«‹ï¸`Gÿõ-#Ȳüë_m(j¸g€OOd‰AÏ[ ØždYEªfÐz5H×@˜’Y)T–¦ÿÇ]]é súâµ,²¼sߦånºÖéÃ�†M#–)¬‚É:k³YXX–Á² î¥þ–å{W^ºÔŒߺ›®eú zSþ†âd¹Ä®¡¤0î[ta D»Éò*ØäÐÒÕÛ¶¬~áÕ…B¬KmûC¿ÿ®83œyrMΟŸ(´¬ãb——9Å™÷°ß™Í04¯cÌÅÈ0QSõ'OÆ®,¿4rþ7ÀÉ»˜&u¾‰Œ.Ï=ÂG­^<ž•¤¥ºnžsצ&õ�Ï9²ª‹(1âÄIêÕœ¥RÍrøì}yúÀ4¤à¹p:‘c¬+kçè‰KŒF Â÷%¦€QbÄPQ�ÑñØ‹«¶øâÇw8ôÊéfÿ …þ¤$V¤ž`c¹�S§Z +ܳDT™$‹“14¡€®€n�–éÁn³|oËGvÞ1Âàügú¢â�6¶Už'Òhá|³‹’Š’Û8ÜÀ!ÆoÚ‘NnVºP@WAÓÑ%+ª#¿LfÔßûnóÁKîÈx]ß1óÓ”º;ð,Zê&;:Î7ªšx»Q¦»ÛEƬœº’¡È~” E\"DiI»:eÕ—…PÁâÊ>*ç”"$ýð¨iu�OFn@s(`<Û›�NAY³+Y_ÖÎkÇKqº’qyÜSºš¡q8p„£«ÚˆCAÁ4Õ„qUÕĦ „ªp9©….K 6,ºHÁ)‘o¦Ô üY)Œõw€!˜—6ÂÎEõ´žõa(úŒÄˆë§]Á4•™Æ�C�$E¡‚]‹&À ·«[ 4$·Jø�0èA‚õål*:Gk£ofå…8ˆƒvø]$)àP$ì Ø4�u‘H“D�˜ª„ Ë•øû –”¾>«2Ž�DþÀ8ÞŒ"0¡*7ÀÀ5“ökéxÓÓÐ�_Œ¿O eÛ„‰ml²dàPÆÚuãªiHqSA:š©£™º2ÂÖIÀmR„Á@4D^�×I[/¹Ñ6G"ö[+[xë3#}É$gÊÈá–ÖeMíYp5ë_„óÂØU°ê )¦!]˜h¦è™ni(ö5kÖæææV¹ÝîÒA½G‹%,vAW†›â�NrŠ ÍgãÜNÞ8îã±Õ5ÐG1ªZyþªÜrótö´µ±²¥…ùMMK÷¶·ïtÅŠe@<2N¿åäü‹iRµNcÔ�Š1Lša—&rMS–°æ†mˆ^E]\ñåªÊôi7ÑÖÑÁ’Å‹©­­¥··—c'N/Â&¥Iվ߸))®æ<Èãp,ÃìþæEÖݸ‘4¢¥�œs£ÿ“É$}}}Ô××3¿©ii[GÇþ–åË—±§1)®r$jÏé]Qàhéjä¼þÌ ›Ø}~+Ö†ˆ±ˆHÙ>Ò‚ `òäÉô÷÷SWWÇ‚yó–¶ïÛwð<ÍŠµµˆJf4cµg<|jèÑ_X×°…]߾̓Ó^‘»¹ˆ ·Í˜A[Gǘ«Î±²¥… ’ÞxlB,b27Ç’¡fÞõ÷³åø*â8¦ma7'?bƒyqÃPO#†��Ë444ÐÐÐPp=+;‘CAhøâcÄf%9zø�µ3_`ýÌ­£ã|ñ1Ö#V“Á½˜ÀÐЮ ]̓‘=SWW™="Þø[B“ ëÇNÎô~=¶ÁDqªˆg­€±œÅÅŠ”Ra &oÖš·d9šä»žS´-øœ4i §',ÇÎÓϲáÖ×°’Á²šl0€"¥øâp¤Is4ú /Xó½fZºæðê‚wY5»•wNoâ©;Ð ˆ(& ÅáF_g ð5Iàjð5‰u‰<"βzöó¼ýëfŒ 0Æ`�TÕ ŒÙ€dfákH@@h„$H˜D[�®' ¤ëR'Æ’}\ù.¹¯Ì[ ÇÒË&«'Â3àLňã#O€Á`ð%‡d {NíäÂ`/*™l/J„ ñðb<Ð2D”ªù–!†k±b3Hj’ÞÁß«"âé/æ­»ƒ�­˜:1¾ .¯9¹h²Óß€à‰¢•‰XøÛîÙÅgZi�õ:FR¸8š�€tûÜãs�k€à¡Ïî> àTG‰(Y#4IgyìÎVÞüþ9ž¹}Gf¹JÔˆb^Î?d ˆIHHH‚PBÀ1·þ>6{œ-G×òÉÅk°ÆbŒ)ÙóþÎW6B„Ãá‰�¨Ád �År6þ‰Õ³6²jÖÆì¸«c@�€“ê÷@n+$" È©zÔKœ‰¾B².ÝaçŒR–©ÿZ@>àð;rôB3I:B‰�Ì º„€üÓu¾�ûè^srQã`ñ ŠÈøL‘l”«(pe˜ Rüb=p�!Âg$jK}hái¨„© `8ü LO„– —|qÿE@ fûèÈ@ÂòDp¸q6ƒæáV {Ý+"™X&�W&L ›Ã¸T ÀT'ÀRC ÎLÍ™a15L"ôCtAÝhTö˜600Ð h9÷ѽ¶{q£Ó8Ë¥�â?ÌÉææ{·Wñ©r>M¦e‰ðªÈ”èú€TŸÎ)`H*„THM!Šõ¯fIªºþÕ eŠˆ¨D IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/dataconfigtype.png000066400000000000000000000040231506556630100222770ustar00rootroot00000000000000‰PNG  IHDR szzôÚIDATxÚ­— l×Çÿ³3»3{ûÂÞ5^ãƒÅk æw.â––*!�¨BT"¨UmÕ40à„4ájdµ$-¡j‹dµE�¢†&!iÓ\¡ŒmÀØÆ¶w×Þ]¯÷š«ßØØëÅ8„O?ï{oÞûÍ÷þß7ß0£ﺒåË㢋îôüOëã7Ô9UÍUzz¬ëÜlÌí&+êg-v[*C1é‘î> ;„Ï“c\ÚÕ+þ0/“û‘NÇ©¡§Oþyh[É;w`õ�ÎGæ—;hãpTÁ¯ß÷AGw¼ôpN¼(ËÀû{eüö#zúøÃÒÞø®Ò§¿6€eSwO±éñî°¼ŽU1éѹv£à²r¨¹ƒÑ ÃT—€®ˆŒB›/ò¢¹;¡Ýz”®ïfY¹ûéX–¦™Ø­—Ö¾2€cGË?r�~v%ŒÒ\sŠ�èM(`0éuHÈ*8rEi†ÛßíF}gž“røXP”‰Æ»BRS0¢¬h¯tŸ3Wquå¬ ¦¿”æëà°èŒ+�nlÆêhœÞ2°LÉäqª1†ï•YÐNžê Éøã©M/â‰àË%󯰮†+ȱ]»§ÄèÔ±m„þ�R7Öj`4'ÓÈöß“T8-.·D±ý¨_ëzMz¥ô'_éÒ·6�/Ÿn™ÂqÃn´´©vÉ69¦�h¿§fðûÿtãÝÚ°¶ÜºDì–ÜúZPW0:Ýš™…KDM}%åI“ |™7f�véÆñËý¤æc‡�óu„¤ðøtýêËÏK#ž«¾,ßþ"oàpµ‡!ÑÉ(Ÿ,ÃÌ3#¼ èè6=‹�aO?Ø.Ì5¢µGDŽ�Ã!òD�7F¡*ã|Kì§‘ž=£l�W’ó™6’20à´+X0QIyRE6àjGÁ¨¤òD29ψ ‹�€I9®žš1ŽÇKÇ|´¢Š‹mñ€·Wr&v%�d`SÓ\�½¥¹æiµ>ò@\íœ:^†Ç©ö?µ,ò8v¶Þëç{îlF/ÌdTùÙoä¿?ßmF¦Yô†öÛifqš¢äïç °¬¢¨X÷¥"ÌÝÞ` &{WXœ[$ÕÆâDMM W¨“Y%ïûfu2tʵ1ÿZ6=MŸm•“"½á…òüìÍ|ÖÕ¦¯$AþíVíàœðÄ Õ\€#aé—ü»{[‡ß§¯h\àÇ~ô�iV�EPSt3ÑjÀŠ?]œzˆ®' "�@Q PólA¶eK”1 Ã4{z¶¯ÿós:FòKF}è7Ô?ÿØœ¬K!:¨›y”MwöãÓÆ>DDE;žu?Eb<8 ßܲ¼(ƒy zZ‚2D9uñ53Xì;Ú(AbÌ(ï}`D\kIl²Ë^ZfæM yÁHÿL hȦdõÆ'=hˆhò%š[7» ’[½OZ¼öJˆŠ‚á¶q�ï·A•E ·³\ÞW~d4/¤U^Ú·jqöÚt“+-Ó&È)Ié>—þ¦ipÚÚüñQÃP3Óæ†ê²‚Œœi“nBÕ·Ì8tÁ�£u¨QŠ$YmŠô¯CÞÙFÕÓ–‘G°±áþi.óñæ^Á˜ŠÑlÍLV6†#ç;p±= )CzšUšXèâ¦MÐÃÄË£¾Äæ:l?ìEˆŠ›(i)Ç®/ýpm~]*À¦¦ ¹6ÝE»Õjê¦P& ×Â�—ô Š2XP­Ò¿Qˆ`Û©I7å Ëœ,Z4TïÕ÷¢µ[l«ùEQÞ¨G@UÑ“v#÷*Ï!4!S(<×ÅP –¿]­Mu³óIõ€èÅ…|ÊGk#±³m‘ÍÞÄžÐ6ÏéÛ®gÙ|éÍ¢ñã»Ð)áNÌÊÛÊyÔ´EДbõ]Š»~}~J¿%½¦—O)÷Ö�2îÄ ÒtX˜—À_O¥þ§(þeºSw¶OÕsy$,0 –å(ü8\ï$— „Ãx¸Ì¢£ªzàdÏú¬ÛBîñ�0&€›mRUkÈ3Þj EDü·Ö׿J¦ÅÐ2½8Ã%‘\ê[èèé/@*éÚ3üýW¸Š¦* Ï|[QäŒH4®}�îÔ±ìƒ%ã^ò†Rß<+J꨿š6ßj­;¸›öÿ›6Nã2&IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/datacopytype.png000066400000000000000000000040261506556630100220070ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  šœtIMEá 2*Î&ö|£IDATXí—kŒ•Å€Ÿ™ù¾ïì¹í•ÝÖq/À UDÑ`cS4±5ò§–¦7ÿi(V£¡Ôh¨Új­/Å&Mš¶6µMÓjiµD�ÐEc×"—…]vYØ…Ý{8{î—ï2ÓŒ &¬Ë÷g~Íû>óÎ;ÏÌ'˜Á÷ã73 *ê½z"ãßùÖþœLåýü¦¯µük<ë­Ý=R$‘öwdŠÁîÓ‹óŸC|‘ÄvŠïm¿üÑrY¯ûÖª†Ž‚§- I–ΫaVØâ¡?'8•ó'toª«võ¬k•„©Í ß¹$ÝÏ�<Ø z,)¸¦3L¾¢ Û‚¨-)û†¥Í!ž}{ŠBÅcÅ‚i×'‘ñI¤ýïŸøI×of°~°cÅâøÐòn£5n`)�%–[ %èl°qH ŠeÃÖÝ)ö�—ßÏ?¹èºO†“ÓØÒ=|bÊÏ• Wc 4mªc`àè”ÇpÎchÊ'æ’9Ÿ’k↳.~åý¢®ÖZåokŒÌK´Õ�0e 0 h#ŒA"�Ú  R´ÆM›�|¤¥LI¯Ë>¾pèâ0µsc/*Ôsà´¡©(h­Õȳ -l&ÒšŠëÓÞäP©VB ÉùlZÓLÈŒ%½/½~0Ëp¢ò§,|ùâ·À©)%²îÎúP`”„ñ´d0!Â6ïîKó��ý»œ¶ýaOæ/½ƒ�–&0à†£�Á”G}LBPrÍØô¶à™7 ÷Ž=>º2Š.+{†½£ŠXH#½2ƒ‡‡1‚‡�nhÖîxhø670oÜ´ÐÒH h˜‘¼´H¶¢÷|6Àº}Ί•umãiwÉdÖÏT†ÜÞ¶e‘ÅÆÐ–›Èt” {çHÁ¾1‹%Ñtµ_½µ÷ã8OwlëÛx侎–Æ-�-Æ ´a˜,r�Öæ~õà¡’¸X³í:Z$U‰†Úx뱌^P� GÓì9| ýÒ Ÿ:ÖWm91zDzH»£@ ASX27¢xýÃ,ûOWyÎl+^<öØ›g>ˆEÕ]íͶ¼±3ÂÝ×ÖÇbq¹öúÎ(g2F›øx.ŸÔ‡P�@MêÿüÊ…û�g_ÉW$Ú4†tYshÊã¦î8ñ°TàÎm]BŽ|´©Þî8S HÚf;\Öâ0‘¯.uN]Gèè•�> ê4JV!¼jÃ6ŽcA¤ágê¶-ç5¶LÊ 8ë \^g36år*ãï’¬쨯‘=K¯ˆ°h^ˆ3¥D5pÞÕ`0å²áÖzžº³•õ7×"µGC¸š'ïŠÆaåü(�Š­äŠå¿S÷ïÿ¢¡®ænK�6c –„Þ#žÚ>ÉPÂísŸ<~ò–«"s–ØR`+°Du´¥Ä`[�`ÛÞ"c¥ƳU@Ï5l¼9JßHŠÝ‡Oã³)íûXÍ &oèŠýqù+¦Îj:jKLEó‹íIJžqUtÓஎٵKJ& !ªòBTm&B€ :¦r†œg�Oƒ¥ï»´5E˜ß!Páp4ûF<¹».^ãÌ®3XR­ ³j-:›–ÄC’±„ËÖÞ)*žùyðÌâ�ÓyáI[𬭠æ,Ñ+\×ÙÈW{ê9¡oŠRrRÞóïï:‡n¿z~t™­||]­‚@k­E�%p,ñ£†Gn›€bý‘Žy­á_^*³Ù–˜œ|ë…·.¾[º†ÇR•gð ºg–®îó'ÌöŸqŤ®gJ5sªRÃ{Ç4¯õÁè(iðá<³�8ã>?� œwÌäƒý›{Ìyd&f›î+ÿü/é7fj¶ðâ’F'sö4úrÙ¡/b¶é|v•8Ðà û›Ÿ¿î²kÏtÌviÎ~-?=Þ\µY’¦þãé>¡Ä{×v5Ü«�䣑Ôp%í=À¯–þm&¿øÿu�.Ö#÷\IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/datadetachclones.png000066400000000000000000000026021506556630100225650ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  šœtIMEá +ÝdÉKIDATXí—_lEÇ?¿Ù¹½»¶¤j0)1‚F‚DÓÒh%”àK�V(B€ !`¢/$>˜£¼‹FÊŸ»¨Ð¬‰ƒQŒ¨(�Z‚µ­àµw»3>ìýíuï®ê$ó°;»³ß™ù}¾¿ß áM÷í;†b™õ}¬Skàû~_çÊ•+o*3Lëí;nÿ�víÚ5{0™üpÊVYA@ÌH—¯ �õ0¾‡àc­­¾~k¹÷žYH$èîêbI[[ûÁdòðšÕ«;?÷œ‘Þǽîy^£ñ ‹X‹ø>6“Áf2Ïã®æfîÛ½±ãXãWý¸µ–Y3ï&ÑÓò¥KilläêÕ«|qâÄÑb¨÷<¯qÅîWo¼t¦ŒcÀU0îñå–uÌ~g"iĆ`ŒÉ_Çãq†††˜1cKÚÚÚ==‡»V­ê|¸Æ7ˆ7Ž·ïc2ûû =Ñi8°nòÃ%míä kqœ(¢D¤bÏ5×uihh`dd„¦¦&žZ¼¸=yèÐ1@ë ^ƒ•ØX£‹Â ‚Öqlcùy€E/®âäöõÌys†4Xº sfÏ&ÑÓ“¿oŒ¡»« ×uŸâ…¯y@,ŽÎ¿,^€¹Í'ñÆÛÁËïïⷳ瘫\Äd O%ŠÑÑ›´¶¶ÒÚÚZ6ž•+¡@E\´Ö(GeŸŠÀÅš_^C³REìh”£ñ­‚ H¥nq+u3﹘ijj b D©£.çN|Í�ƒWòÇ"6 ¢xk‘ÆÁø S¡jªí„#+Ù‹r~p�î½»`,]î[ˆ(°†“ë;yཎXÖâ °H¸©‹¢Œ�±4^ò“Rû5†Èò§9°aÏoßÄ–sjãjÜÓƒ�‚ˆÉD[lM ð²DÔÇ =î–qa€…[:8¿q J¹(¥p”ÔÔ+Aî¼­ÇAŒA²â&qéÛ³Ìw\ŒIcKN<,8m…\à.�hUB„™”‰DPZ�QU-ºÀÇD¢‚^+ Ô¹ôô9ŒŒ€¥�#&�~&…( ¶a9Ÿ,RVG‘é ë8ÁÝhŒÃÃ5qü™%,þì4ÙŒi§&­oÙ¶³Áú>N$Ü�¹Áj«ñÒf–½²•ÓkWм¿%cß›’€ôs_�Yܸɖ‡ûsn'ÖˆËõQäÂ�mjçÌÚš÷ p É“ ¸\³"ʈ  b$|Úƒ´áþyóH¾þ¾ïÓýÁ.~9{†Y‡¬Õ4�†ËFrDƒ8R,@„̯—hY×IK4ûüß«”«ŒL!J()'‚ˆ[øxn‡þ!=ú=*lµ~²%OYŽŽ% Œˆ ¢D•Õ^ãØ·)òû &Vרa8udÛÎ…y"«ÐæäX/:±�š Tc›¿ùn30ˆç‰p]¬„Û¬(S^ …�*RÀeàwàŽB�îNÉÝþ‹ø+ÛóO*­«§Ô¢*X X¥* ÈŽWžYh7J…@  ª8IU¡@Õ"@9 [_�j2A¤‡Ï�uh×¥·ïS¬I�õ*–i£££§[Iæ�ï>²àèm°Ðø¦²µŠBD¸žJ�Üvþ§×jø õ€ÀåJ¦3³DèbÏF€!`¬†_ç1 %UL*ÄʪˆÉ›Ƴ$Õœÿaj,D gIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/dataflatcategory.png000066400000000000000000000110171506556630100226150ustar00rootroot00000000000000‰PNG  IHDR szzô pHYs  ÒÝ~ü OiCCPPhotoshop ICC profilexÚ�SgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó�³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@� $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€�˜&S `ËcbãP-`'æÓ€�ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E�[-qWW.(ÎI+6aaš@.Ây™2�4àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD �*°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼� AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”�²Q=Ô µC¹¨7„F¢ Ðdt1š� ›Ðr´=Œ6¡çЫhÚ�>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱw�EÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö�/{ˆCÄ7$‰C2'¹�I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ä�äÃä3ää!ò[ �b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5�ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT�©^S}®FU3Sã© Ô–«Uª�PëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u�5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§�¦½E»Yû�AÇJ'\'Gg�Î�çSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕF�FŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­�­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}�ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)Äi�S›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ�›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCO�gµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰�A�[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA�‚­‚åÁ­!hÈì�­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕX�XIlK9.*®6nl¾ßüíó‡â�â ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©�¼L LÝ›:žšv m2=:½1ƒ’‘�qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³�¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ�7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TR�Ö+ëGǾþ�ïw- 6 U�œÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF*IDATxÚ¼—kl×Ç3;»‹÷ ¶±¿0¬cc›ü"$)mâb’¨ i+Z4qy|hÓ¨-AMªJT QU¤J µR­"% 4m"bIJa1ÛÁÆfýÀÏ5~ìú±ëÝ�™Û¶)C¡éh>Ìœ¹¿9çιWBPZV¡³ô{«*ÿ§Kb|­Ò²Š ÈNÿðVUªÿs€’GŸ³1@’�bàqÀTz«*?ž|¹´¬Âè÷L€RÀ t‡€mÀà'¥e¯•–Uدñ1—–Uî%À° ˜à­ªŒz«*ýÀ»À Ñât¾ú›CuO=ôóðJOEMîD´î�JË*^TàuoUe `뇅ßš÷Ã�ñ‰ëÒ�…pT€]kî1“¿4)ÎßnÈ5¾eâþðGà иùo…Ûòã•�Ó÷0­¥ð>q&ùªS`t¡K×…«³?öÈžÚÐÎMù–í÷¢ ~ $ýè©Ó¿³æZ¿3n°Û¾C¡Û‰Q‘B IÒgUÔ4‡Gõ�?^bß~7)�€9ÀŸ\Þ2×½b½{Æœ'ÈÏœ‰‚£'›hn»‚Ãå"ÿ¾dòÒmS ¼ A¢*›Qƒ,oÚ½:3r;}M“út-œ(Á$–Ñh ß�@¾;&Â=ÝåNµÓ?yæBk l½- ÔfÖÎÖNÒ30JTpWæY�ÈÜÛ– ›Þºm€S}‰Ÿ'i’n8K]KÁ]Ya¾‹¹)¶-ë\|å¶t�OkFXæøˆ¶†³ôô‡ˆhÜ•å-HÆa5½øƒ¿Ö¿2­tM |1σöìtòöÑxV®ZŒÑh¸«�»diÕgZ_üþ{x¾qßv=%2 äïšZßÞõ�xá�N<ɶ¯æ¸¿„Âòn\BºFÜP²léÖšªsñËË8#Á«ϼòwlnÔ•¯¾(4Î_Š‹_”ÙÝȺ‚óŒV8μÜy×}Ô42LIÕ~ââlH†‰(‰›×I©¨ÑØË†@x«âÄôË�¡ët]jõa_”l%)4ijž³¼Y-ÓÚj!!%y*lDg¸»·__X×AÜz¯"T } � 5µàÓš•É;™ ]ç\°W{²#)ž´.³çPînb[Õ|â,6,vë`cƒ¾Fjzcˆ©ˆéb1D(ŒôDMº>ºÔ:ÐiËq�sÎÇì´|rfõ³i‘—Ê32‹–aPÆÝDTc¨ã2Aߥ;–¦t] \/ÚBAÁ�"Ñ®Þvì i”gùè ÄñIµ™¼’%!¡ë-†›wH!@×tI×TY×µ©ÊUIÏ… œ,ßñ5ÔXˆÖÙ�ÍØ�©lðÔ22P[?“ŒìùF³<Ôey&zôTŒ±p9ØÖ×ÛSgà û€Ìø㤠�îP�9íÎ8º;p…F1šÇs¿¶ ž]ÿ4Óßi#Ñ•ÄÀ ïÜx 56`:YÕ>š¶þé7ï¹Õ0’ÓŠ+Ò].—ÇjµÎïQÛcငÁ$hI°’ÙÝLrÆýÌ2�±:»™_UÕ°øálNûÔ}¢ªR_[C ÿJeÕKÏn´�oQš2 oܸñ‰œœœõN§³@Q›3úGú hªÀoe »¡qÕ–¦ö²¥ð ¼çQÇTÐ ÔˆÊù“Õ„[j�ͪùÓþeË–Y™¦E)€¾wïÞÜn÷§yyy G–lWƆdž š$AÊ• ãZˆEFñ˜ßc±|Y¯9a–sŠ–æBu5–hû)×È©#£ÃŒÛ=è€êóù}>_5p6½(íX®=«1÷Í¡g2ƒO¶2êÏtÔ\“ó‘æHþì®ÆÏß¾X}°sâ O úx�»¹þ=ä1“×SëÝûIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/datanodetype.png000066400000000000000000000042211506556630100217570ustar00rootroot00000000000000‰PNG  IHDR szzôXIDATxÚµ— l÷Ç¿ÿóùüŠçiœd� ¡!ÒÂQVº¢jtÛ*]JÆC¨€&Vh;‘µe£Õ²Òi+Z6 ªnPƳXËJ $- �Äà¼l'~œï¹¿°{Ø”eÒþòY÷ÿÝÝÿ÷ù=ïÿ‡±¬QYzáb#sUù‘GÝKváz:òˆ?¤§+î‰ö¨2êŠ|¸ýµ+þRe–[nþ×ÅÆ»í/TTŽàÖC<óŒNUW* ó€ùêu…þ¨ŸÈ„üÉlT>*èÿà‚�KËgd’ºÏê¡òÍŽËÿùH€K¶‚@]Á€*xì•SlRËìLfÜÉs@ÅÇ�kf,üZ€ÖÅO\ »oKÝn&úÄH‡Â²j� µ,îJŠŽ/B%µs³ Ž�mº®2(w­©hx(À­e‹TE¯WUª(�¼^†ï¼%0˜ü †�ÎjcIA?Qn{<à#fû{²Ù`o0`œßrüãLã= Ê~׺™K ÐöÜ‚!³%O/ø–f°c'ÈÜ”©D1™‰Ð~“ð®H~p™Ù`32 K±ÁÓíV\mmc9R³'ò2�gMô|q.Áß?»ç( Ã覸ÖW\I pý;ó†”HÁ†sqCÓ3UnR©ªWµšQ"ôµßR\Í—0èéÓ$gÄlÇ®·Ý>&=:v4ƒ½§ã^gü¹sãÌ'¸ºdN,ð� @’´7pÒWU)ŸïÛ‡÷&Ù"gžÙŠ/žÚ›/+Сîä…ØÜa央€Xسyf{Àå§*cüõ/©»ûä®Û‚5¯'�aК�?lk†hH‰É~P¨ÃûÇFÛ ` Ù}¶jÚê€/˜zº tÝIP’óÒÜùFR€SKkÐ0·J#[Y¬Ã»Çâ!ȳq•ÂòÍ®À8×¶J· iÞŒ€"|£5A‰ó'«qhwm‚|О‡÷¶\‚¬ã4òÕ%,Þ9¤  ³LpDÞ¬¯.Û¨hœ[ •ˆ dmd/ûŽÔíI8úÝZ\ž¾ÔÈ|YExíYÚ›Ù€õezÔì?›�¢ÈO7 �÷¤W6”m�œ�U¢PB!Dº5aBƼ…8qä¨FöÑó{p­d ’�µÓôxó@ÀIòÒ†‚âmq‡ ¼oTu:rfú„E%«±Ý€¿ã‚*Ëð[T|:YÆ•)f´h—¸�î5£7{ ­€ŸBÒ�J¨šªÇ®ƒq€ÜTœ¶xžøBÒËM›Ê=ý;=&Õ®ÚìUÔku—)8‘ïÅþù%äÓ²ÊÈ¢ …z[�»]@÷e}M:ø ¯Ào}A°ªT�ߊ|ƒZŸaÑÇæ¢¬v»Ü‘±·3+¬ytÂl´d¯ª›x­i“2iv&ºŒ!ø%†2xÚ¤ˆ$"C!ÈÓ0JJAÇq:ƒßƒ7õ­Ø:+¦èñÇ#ñ$ÌÏ0ÂfÔi ƒ‚\ué3j6$^Áƒ3ímkE*ZXòMÙ°èHáEx"/À0(Ãæ—ñ—‹�ó~\U6#höÄ÷Kô¨;GKФ×6QYQ:„àx À´-pš¸VÓ¬lKkz7Jí±Ô>‹RžÅÉÈ_qxð0î„Eôò"HP„¹_‚¥�G>Ÿ‡ÎÖAtXêi!;ðÜ$=ö�ˆ9Ì`’ì½+5âÉ›È6dluMô +k,&X³°#{'&égáª|¯ö¯BGH‚ÂŒ~ &�ÔzoZä•“ÍXRÌâÀ©áNÈêÆf“V Ý\ÓLÙHøRsY÷è ¦å<‰hé.H��¹¦§ñ¹ð> ‡›*ï¢àéa ^ð‰àºü°x-¸)„_=…EE,: `10p¦”+ªrSS­˜º�Då,×ç15gR zX9V„¤Ò  ØÎ…pÀèãÁ¸½0ùY´†xÄ.ÌÏâÄ™a€4 ‹T3û«‘du‡¨�š„*([OÔÐ4ÀëPN£ÍÖ�\C¬C½^EP1 Ð O8 öÑú@ú^ûlÃS¬þr­}‰5pŽ{<ãÅf Ìpš)f•ø+Ü}äÇLÁ+[døJ¦{Eç�o‰cÑy ßå8ñÄh¿Ñæ�ïj`‰‡°Wû@åÿò’àc±ƒV¬RIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/dataregenrefs.png000066400000000000000000000020131506556630100221050ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœ­IDATX…íW?luþÞÏ®Tv"ÇN%áÔwgc 4ŠTA¨ˆBjÿ&¶.°ÀÄR!T P%¦"†R#RIDh<œhäËi$‡vp‰ûÎï14 Çý±@(ŸtË{ß{ß÷»ûݽ߇ø—A§¨\.Íåruß÷§ �Nßîõz7ÖÖÖza®išÚÎÎŽŠËÈ€išÌü²ˆ<¯”: Ì3³¯”ZpQÓ´Ï,ËÚªÕjºïû?ÈŠÈc®ëþî› b  ÃxÀWDtŠˆî "+!R*žô<ïÌÔÔÔïÌ<­”z�ˆ4"Zïv»‹áºô(e]×'|`aFÿt¬T Ày"Z¼?Ž›h@×õI¹¢”z$.ÏÌ7•R®ˆÇ�Õ‡Qð1@"òyXœ™·ˆè\*•º`ÛöJ0gš¦!"§¼àh¤!Qwöœü%§nÆ›> …¯ ‡Ãg]×ý%Á4t]?FDO1óû»�!ŒŠmÛ7ƒ�Èfj6›9f~7¾®iÚÉQâóóói"ºàãq0sdD ôûý—”RÅ@ÑÖp8|Ʋ¬­$qèv»3—GqˆÈk@Dž �µò»hµZÛDô4€óÌ|YD–¬2ó`—Òcæ"¦Â�ÝWï$-0óB&“y|yyÙg`�Fq0ø+++›ÿ¤Ï!þŸˆFõz½411‘ߨØè!ôå:fgg¥Réz¡Px°X,Éår�ÍÍÍ� 'òÔjµ9ß÷¯*¥²ÌìÑ-"êèˆHGD¾vç›ýÐuý"z;úÖ¶í'‚œÈ,`æG•RYPJ¥Ü»{�ˆ "/š¦9Ùn·ûcÄkDôz¨÷Å0/îCd�j¬”Zm·ÛÞ(N¥R)Ñ%÷Âëžç�7�N§Nè{KD^ñbæO]×½LÔjµ†Ãái"z-\ËÌ—Ç9g8i·<—  #"«DDŽ8GbæïóùüB«ÕÚŽËGˆÈÞê˜ÙJ0P&¢9'’Ä|9JH8ÑÞ>H¥RïˆH�™ßSJM'5 áWf>ë8Î…qÄØ;@D—˜ù7ë"²dÛö'ù|¾ àUfþ.0b÷ÀÌ}f¾àL¿ß¯îGñ_`š¦6333\\\ôùf³™ &€»wäv6›m[–1vˆÿ<þ Žf×P)_IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/datasortnodes.png000066400000000000000000000011521506556630100221500ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÖ ,Ñ�â­÷IDATxÚÕ×»kTAð߯ h#jLâ[}l´H:!à 6ÚX 6Ëù/ÄB£¦PDA,D++­ ؈’X| ˆkqgá²îî½»Ù›à�áî|3çÌw朙¡:©•mQ­ìÀ!Œ'[ßœ'.ÍÔæúø«hâV'ÀHɉê]ô"ÅÞ¤O è@ÄTZÉWœ!”tàONÿ9(ó ÷‹IŸÖ&éƒþ»©õ†õ8§qˆ÷Ä[|ÄQâÔF0�_½6½^±± ³i#-ä:RZÍ[×ëÀh�¾iìJú¢½wÂ<ª*õ>ëÃ0ˆqœÅ�¬€Ä·¶þ�Xƹ «Ãf`.9÷ô_ãkx–0ªA‹Úû=ÆÞKßK=0c6Y^¦Œi¦J:ðaT™lº]ë@d´Ÿ•%o>ÿ%µ.ÿ÷ãöáfÁücCe ØŽ'Éø+\ÛèMx'ð çƒß7áåœþk�[s~õ7‚f°ë›Éå}Q›)íEdàÇiàtð¼¼YrMµR!ާ;À®‡F ã�Rqöà ãNp¹Ääm±ï$“XéÉ@d)ú0�«%©])`¡Ñ2Þ“�Èrü >ãddo‚~¤YæÍX«°w Åd*~KQŠÛCÑ¢~É:Ï�~d*—÷å/¿HtªÁ®EIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/dataswapcategory.png000066400000000000000000000120111506556630100226340ustar00rootroot00000000000000‰PNG  IHDR szzô pHYs  ÒÝ~ü OiCCPPhotoshop ICC profilexÚ�SgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó�³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@� $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€�˜&S `ËcbãP-`'æÓ€�ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E�[-qWW.(ÎI+6aaš@.Ây™2�4àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD �*°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼� AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”�²Q=Ô µC¹¨7„F¢ Ðdt1š� ›Ðr´=Œ6¡çЫhÚ�>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱw�EÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö�/{ˆCÄ7$‰C2'¹�I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ä�äÃä3ää!ò[ �b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5�ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT�©^S}®FU3Sã© Ô–«Uª�PëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u�5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§�¦½E»Yû�AÇJ'\'Gg�Î�çSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕF�FŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­�­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}�ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)Äi�S›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ�›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCO�gµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰�A�[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA�‚­‚åÁ­!hÈì�­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕX�XIlK9.*®6nl¾ßüíó‡â�â ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©�¼L LÝ›:žšv m2=:½1ƒ’‘�qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³�¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ�7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TR�Ö+ëGǾþ�ïw- 6 U�œÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF $IDATxÚ¼—{pTõÇ?÷îîÝMö•Í‹È#‰y’@B <–Åð*ê(­P-Ø€á!}ùG+Îhg:Ú¦ÖŽN�‰F¤µPТŠ@‚ Ä$�ò’lB²»Ùì{÷ÞÛ?ØD†Òv¦wæ;÷1¿ß9Ÿ9çüÎïþUU±—–k 5U•*ÿ§KPÕk¾ì¥åc�E@pøgMUetÔ‰‚ð?;WUaÖƒO›� c€™ÀC€¨¬©ªüdx‚½´\”šªÊè ÅlJ€ð©ª*‹@`ôÀà#à9`ð+{iù+öÒróu†ôöÒrÍè\³jÁ‚IWÿöê™Î?¯:ù—U¹b0ˆ€X Ü PSU®©ªìv/ÉñVëÖ—?jXvÏo KÊë bѺ£k}ÙÓ/J§½œà²e¤uOÉX-®ØüúÌÅS´5U•{iù°hŒ¥ƒi??7Ô)q«HL^9Á¯Ý�~Æ@ÑÖ6ÇjÝÎKZëË oP±}›h6›3ZÜms'É&„¾Š•;¼î.mlÜà-`/мþƒéÏ%j·ÄK+pJO0=×Dœ$Žuû ÓEMëˆÌ¯¨ómY_l|~¸6cRcˆ›3Yºo@p™7ûëùaF0ª|�´ãÕ ÕŠ¥€šªÊ¶Xåÿú�ŠâÜûu/šteøŒO1g¢ƒ$¢¨êˆU«QƒÍ¬e⢠nzíkÏæ›ÄëžÓÊ;ß8ÿ�°|N-;{Œ¡×¤ÁóëËÖ„†k{i¹‹@þGê'NuƒQIZŽ=߆F#Pu¢™·vždç‘V.{G@4�¢¬xäM[O¹ÖÝäXôyã)Z8;ZYãýò±Ê[;ÚߎæpÔšªÊnàùK½ÙYgNé0C||¸ŽÚOÿt|öæÕÜ®Õ'Â=ïÑêðß1ùn¡H¤â…ªŽµÃ6cÉ¿ý‰PfŒÓhÑY8V¯«=wÁ}æÌ¹³®b °¬îþâzÁïrqhÏAþñú»Tø±ÚQÛëìë××lß•÷l4Ò9èò‡QbKAÌñZf䙑EÍÏîo|¡½þE–…~E$«Zudëtв“(ÊNºæìû6 �í[Ñ(f†XVx¾½ 6vüènÙÜÄë_Ü õ)òINa•;VHVFîŸWËçÜ—ç½�Ë.SdkEËNÀõ}�ò€êþäc©ò>&hÎÒÐÞOH厈ʢQ²L__/‘÷㬠O`_c¾nÞïßÿñp‹¿-€¢ðy�7‰Ù–t6�Å1à'$óoŒ(£*CÞ}­õÜ›s 6\! Τ%ŒÏ�¸ñÉÝ6ÿ{YpŸJ$Éw�…Ùùôðœ~™¡·•;a(¤ÐÝÝKn`ñf+HV·LÀ˜^Àt{&£´é‰]ç7ß`Ï/�×v:4t ÌI8ÌÒœ:Žob(ĨôËx .OGG sZAŸ@D4s*p¢u AEKAq&’N³iÅÎúu£¨2ß´Ä%âîifeñ7Ì´ž¡¾¶oˆQåñ…é¿ê$ch?É)f�,i´¢¤N!$Äá APÖ�‘ŸŽ Ëw|“0*€¢­˜étñ{XSr–|õ8ݽ„ÂÜ¢`P&à sµ£“Gó›@²‚.žOºg¢·�%Gƪ¢„V«AQ”ÌAnøÁTjûd®¤&âênE+È,ʾH{C ~·dn�Šp¹Èð}FnfHfª›$B‰3‘ô¦‘q�!?Mgêð{}[ÞÿéÔÚÑS >·JgŠWw+È*ù¶ÖM©¡étr(:bT�ª(Á0žž+,Éjɉƒí…XS& ¢¼.-õ�D"‘õ{žšþümk@ŽÒéTñh:ãÀÓwUVY”ÓÊCéçhúªn@Pü.'Fçiæé@ÏÅ.è’îCo}47œÿ" ¯ø`õ¬7GkÅ‚p-"prÑK÷�øéH2‘×Õ†Ù:€Ÿ•Ôãõk¨oL =/ EŽàѼz�Ì ˆì«Ï&a|&AGwç%ä¾/¿PåÌçöm˜{j´> Æ@ €0«2=þA¸l�£{ÐAØïC•A•á‰âFÒ<ÇèêCP´Áæ?° 9´t‰´‰ ‰7&ÒÚØ„Òu¨êŠ;eÅþQœG@¤yóæMHKK+1�YŽèåHÀ- ‘TÚ“Œdö´1&}26}�¥ymü®ªŽ©÷Îb°×�V‹¢›Ë{<˜Róh¬;�{àjeÕ kž‰•+·(++{X’¤¢‘�]¯·_“—¡5ÑÈ”¦RÇM™ôƒq}l˜~šm'%èïaÑï2iþ2„‰kh©oFh=bë8ðîìÙ³�ÕÕÕC£l¢#ÊöíÛ?ÌÎÎþ|Ò¤I…‹%G4k�Á! rTÅ£ÑpQP{õ –¤kµ ù(Ñï¦DìPN8Mâ´ù�2�°ŒËÕ0FºªÓ¼Õ‡|�Ꭷ±hbÒÚ 3Æ',Íi޳Eð]•˜bð ®-ZSÆæáìk§·§{°Ó=îìÑ–é§Ú£ÓÅ¥•xÜBíï†[ö¾qôèÑ „cÿꨇÓë@®/JÍÄÅyI ¶©5§jìvû¸§xžÊL|¤Ã�Þxº«¸nØH4õ¶…ŠRº›�mûö«½]±m7˽rÓ!å€ LmÌÒw IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/datavisualconfig.png000066400000000000000000000116421506556630100226260ustar00rootroot00000000000000‰PNG  IHDR szzô ¾zTXtRaw profile type exifxÚ­™ir$» „ÿó>Bq—ãp�ð ||ÉnI³h&l‡Õo$vm$‘‰D¢žÛÿúçqÿà'¦ð¸d¥æ–óÃOj©…Π>¯Ÿ×_ÿ¤ûûþ„÷)¾ÿtÜ}žŠü�¯¯y¿¯ï·¯Jz?we¾ŸSßzŸøx`ÔÌší}]}?(†×qÿþîÚû¾ž~ØÎû_,¯�|\üë÷TÆ2ÆàÂŽ>>üÖ�!²‚Øb�wÆ%èHbœîo‹õûعÏá/Áûý»§¿�ÇŸCážü¾ ÿ£÷qoßÇîFèÇù¯™:‘òGx�Ý9«ž³_»ë)©ìÞ›úØÊqáàQñÞ–ùþãr?�Oe‹“ /¦|¦óÍ¢}|òËwü¾§Ÿ,1…wa†x�UÂßÂŒ/øø ð,+øLP‹ŸkñwÞv盾2óò\<óÜñÛÇ}wðù|>èÅÖû§~ÆŠu�e9ýæ*ñçS»ñ½÷ož€� h7Ì• ög¼1Ìq+^œ#×Ù“Üó¢»/ëýBÄÜÆb|�'ûh>û§„P¼'Ž|:+¨Ço–wlbÌ€SƒææžâïµÁÂë0Òs,@CVJJªp¨[´äÌ,[±jÍzŽ9eË9—,�ê%–T¬äRJ-­ôkªVs-µÖV{ -"aÖr+®ÕÖZïLÚytçîν�0âHÃFeÔÑFŸÐg¦i3Ï2ël³¯°â"ýW^Å­ºÚêÛo¨´Ó¶�wÙu·Ý\;ñ¤c'Ÿrêi§¢öFõgÔü/Èý5ÿFMˆ¥{]ùB�Ã¥|<ÂKNL˜�XHÄ‹€ÐA˜=Õ§„œ0{Z ),€š7�³¼Á´}°ã?±ûB9KÿnáOÈ9A÷ÿ@Î º7r¿ãö j«ßŠ/@ÊBÅô‰aã¢*ÿ¡ÇaìÈ#[®OÜ<<ŒBkéñû˜j)±üþ‹ûó©ÿî‹ûîYz¿D}œx¿ ¾ÍæmF lYÛë;˜³£%ñOÜ¥3s,;ÉV©Ý�nF€–sšeiï~%‹P¡’é`ÀæyÈÔìîѱq×”‰V_IQÉ\Ðïƒlp¾­ !ìõ5<š†¹šóÖz’Е6Ák•~Ý…ÿ°ƒ¯ œÈ¢} œVnö° ˆz�û°ömy¤^ÒiûôF-?¡-î�"Y�a»B­3®Œ¶‹¥™xðHчQW?)÷éù³«ÙЄ³õÁûêm+l¿„bëá©;´C9ª{v·�V‹ÍÉ5¤Ø”DÆÚ^aŠ[�sä82Ïnè‹õ“û嫯%ðwÇl Ö¥ÑúF9-o»œOŒý´ºòÝíˆ7uɨ!<ã&ŸÄÛ0a%׎-�0b~6p?GxðOÃ.«N䎅ҟØ50ÎÍÞ�ŒîÍÞ<²´äyâÜa„Î\dÚØ=Ûƒm£'BI@.íO¯{ø6G£”ïÝâ�æYì,|Aˆ‘µê<Íö΋h±Ê|ŒHTÛ3ŸÎ›h3é³4( |{qã.uÔÚc5$ # Ör)6™ÎÏ<,ì4¤6H\ÚÔ#·û²+ý­�ŽÍΤÒìeEè0×LVìV@‹ö°Ó±î�@�‡hÀ¿Ãà‹�q ë<ô5>±C�¼‰ðex&Ð\²TžµÝ �¶®Ô×l,{±@ÈÚ‡)ƒcÏeNÀ9H.jN6yBAŒåÒ!góÏþ$÷ú–ZÓ)ż”Î arÓ‘æ!µmÔt…c;°3ÉÇCvÏLržÖ«Ý(Ìe(m¾® g¸h¬u:Y[#yuš¾’GV…<‹$øyÌÚW-‡r±rW„XC™é A’|XßT”ð|¯ b¤pœïâên`Å““°äôô‚¦“oll¡p¥s$Xµovpí0«Œ]Ë\›T!ßpþc‘«} BÊ3XV1¥‡,Uݨ°�ÒÛCrûµžÆ5 =ÐTvOtr† E€Z�ìGi"O#="³Â:Où¡RB›qפ…YG]efeïÅÔ;cO3¯E13¢D+΄Ñ"Çæ6�:tÅmˆ˜}¯löÜ +[81í7Ô$ƒQ©1‡¢¼ö.ýYZ¾Q�Ñ`’£=E¡`šä·,)ÚqÃ}/*¿AÎ>W�Æ< áð,Ö.GÒ¢>Cú0;ë¢u&ñT$2|>�þR›²rzÌD�6‡� '¡OdeÆŽ„âFòdüÆ'àaèÚüB]2¹ ×®6ŠHì|Ò]Ï †ÆŠ%Ôt{†‡ÈÓ°}B_&“g¥B çìÀQê$¹2Œ^óôµú|° Dž¥±;d†šr¼c‹&=×]Hzô”’¥Õ²Fô+Ì‹è[r[Úø*¯˜,‹5*èiLÙönVȇ±oG¤oöØÖ÷Ù dÈLÎúÇÇ :ÊÀ% †)ç•Éwœ`fÒB¬ ^Võ<Ã#Bkž&›u²©aÌÎôV‡Ù]K)ÚpÄ”†G,â<¸�Ñì…(p ©¬Ò�üxTC~•ðT§ÃJµ<8qQÛS5#LÔŒBw‡¢‚T¨Z`.rF¸Î’6�ð#a¡VL "‹?XŸ+æYI_öT¹G6þ9ýõ+³ä·2ž�ãZÁ½À&/Y í) áø£ÁL)¹ª¹h×#áÊN•‡]²ú½2+ M¨©ÎŽç¶{,£eô-îU¶¿ÇzÚÝ”ÃÕ£ö$©DÕ•0Dƒ,�;ÅqS³ŠÊV܃2¦GÕ¯y¼*Ô\j¿4O³^>ÄZÍÏ^sìS •»”ê‘x ² CFaýåÉÏÃ&+éçê­óÜG•ÚÛS!(˜ªU™¢¨4!úDR|¡Ô‹~ O"OLŠLdÓv”ጠ>‡B�eo�Z�+Pj;!ƒ&l÷Õ`×s$»òQˆ.„ î5št'wög”äÛ–Pb"Ø�xÝjÃ/RŸçj•;d¬¬rÐK`½šÊ+%" êaSšt’p" m–¢^ƒ‡°’†U @îH2R{Ò#! �yS�óýx|3Ê0û548S£¶ãN’Âw-äßÑyÊ3Í+yxªSƒ–rHª|¶±îì!ùÙû‹KJùë†ú�1§‡;ŽÞ�›]=ò×ù,dpN5Hë•äsÒ®ƒC—Ï•siŠ*UÌ%í@u‘°# à¦~ˆŽI•š"‹W§âXu“.Þo<3´jrµØ)ñOìÞ“Þå¬}æC‡Cõ¦ÊÒ7”gn)/E‰„†�¨l“Á~…“¥«‡¡}#œñ§pþÍ Ù¯IbàšÂ¹/-ÕKùLOvßTÜ?w@wóãkŒ×žÉ–Ó2Í�kÝžŠÉ3àC¨ $i¬0ÛR›Ä“P?´¢‹ul=úü1ACüm½ºl/7u5@˜ÊúK§t­Þ(<óÒëµ OUª ~7š4ÈwùÏiîÊ)¢n—¯w{ ’^ÅXÎïár*È*wÚÅ(éUù€tÝG%Õó5i=nhmMõ˜$tùUÿÆ^ä�bÁ¡¢·=ºqÝ~'Þ9‹tò·±ûÓ �—Æñ?»¿\„vQ:۹ﲰe/…ß¹uÎjîßW«‘ÌfobKGDÿÿÿ ½§“ pHYs  šœtIMEã,:/<#eIDATXÃÅ—Ml\WÇ÷¾÷æÛã�ø£µãÖM졸¥ mˆÚLXÔEU²� �Q6 +„*(BHˆ´BÛˆ ²¨E­p„JCh͸ýˆLB—$�m96q=3¶çó½{‹ñØcûÅ GšywæÞûÎÿýÏÿœ{žþŸæ6###{‡††Nf2™ƒÆ˜ÚÿÊ�R ­µªÕjN6›=?11ñƒB¡0)" "ˆ£££¿[XX��ÛÎ�;'ƒƒƒ§�NÙ````àáîîn!i¾6šÿÛ:§õžç±oß>ZZZ†�=Àâ:ß÷Mc\(¶QY30>k»ásvr…cxþËÝüéF�ñë%¾Ò­9~$�çªm{Œ1ø¾�1F±Mh^¼ÕƯT{¯ÂÀC­ôuzŒ &HD5×ÅÁÁ$g.®ðn9„é( ¿ÛÛ ¡‡f묵¡~üÇ ï”}\íÐR6¬V-}÷DHzš›«†Î¸Ë=é(—ª>Ï�«‘¯Ì~y(Χ¢¡ajø Ðl…UÃÄ ìÏ$kù¨lˆ: ßÀªX<­˜Zªñ�#mDPhJáäøcï×leâ®hM9ì±%V*. ‹«Æ‚v+ ‹`Dq-çã¹ …"Ó겸°l%ÔñmlUÿì-Ÿ—&Š\uR$ó†¾VP"8F°¢0"hÚ Z�ɨÙ\@ôtžxTqìPŒtbCœ;†@D¨ùÂo.XÆòif ®’¢'mÑk]ÿ$Šç¶Î‚o 'ís?yÓß™�­¥ØQpl/䪚j ˆ»uqE"ŠÿR¤â´ðÄpS©{ùÚÙG_©²`<‚µýF ì[ÚZ]žýl�»ã;3М ‹{pþë1”_d¸³ÐnD‘�öùÛœÃ-ÛFÎéb¡ãÍ-§Þ†é\=c@)(ðÕ>»s„ Ï�‹ÇS¤#ìr ÖDfך”r ”Á·,¬ÂÞ~úªÐå9¼üö2ß¼¿ÄÓ�è� QØqܰ¨ßÝŸ 掣èM;8Za¥~øljB×¾â®âò|…±Ée~?^Ån9ïš�†èw°µÃÞJžL[ÀÞMÔW×¢FÁº¯]á[áÆJ„‘O¦ìшØÿî8³×¾‘¤Àó¯Y&ç+D"š¡=Qæ—IÅ#”Ä¥æƒ'eFFH)á6�þÎͽÀŽYp'‹ºðë/ÅIÄíÆgz±È‘H…oí®S>)Ïð¨-ót·áøc.ï�¯; Ê@sJnän½áPN½ë8s4F¡dÐ(<' X|ÂÇZÁÕQ¯F>_ �ûíZ2u§žßXAÌÆ\ÜÝÏD¤±žõ'nvÆòz‚ P·{­j¾6Æa¿›Ál]'"8ŽƒR ß÷·3�ÍfßÊf³ŸÞ¿?år9”¶0�î$Þæ9¥±XŒ'NP,—�@5)¥îK¥R/ööö~FD4ÛS<”�»5­5•JEÏÌÌäŒ1/¿‘›´C@òc|#€Y`FD‚ÿÌS³´éâXIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editcopy.png000066400000000000000000000015471506556630100211260ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœ IDATX…Å–KLQ†ÿ‘¶PJämˆ W¨¢#1JBÀÇön41>`«+LÄ…Á•Ñ„@Œ � +]�š†…‘D" ¯ R* M{ÏqÑ2-0mo;Dÿæ$“Î=s¿{îÏ ðŸ¥\"Ìõl*À�Î�œ³#nI%vww½}v÷j5÷f€àå‡!ÄÒñªwˆ®ßï`Ò3ï–Õ f€‰A’a6Q[sæd}cëk±ú‚å"Åb†ÙdD]uÕ‰úƇoÄé "éÕ1R,f¢öì©ã M­]Ñ@l�˜!$cιÛ7;†§˜˜[Dé‘ò£ÊN먃Ò‘—aEÙþ¸ÜÓ,®xf%ÔdZR:Þ}᪃…Ä!ÆíN|œòšÆ§ßË.8–\èïû³0?8^!Þ¿xÜäüùcHëyjóabÕ`¡4ýk5‡ `Ù¦eüC%ëÿ³;Ñ^^QÙ|ùbÉììäàúûþ-`Y y¯ÄưwWfÒµí}Û3r‹‚�%öž€"¹0ÅÄÀ‡¢ṳ̈ÍO{“Ós÷ðQSè &0b– “1©3¬ñq(Ìßi¹Ùò¤Ïš–]¬Y©@ f@�\0€ùŸÜ(Š‚¼¬Œ„K·ÚzVç 0¡×áN�á]�œ¤'' Û6‚á  -ÁbÙà-™w•¡|��€5q+.ۇљô|ÃòÒ²zÏß ‰À,q €Ì8�ÈNMÄùŠbÄß_"©>@¾} W© R”5M,` üÎ @>FKà}Æ{¿ B&ƒ½?ijˆ�D ™G2³Úˆ¢ðϤŒŒÛÑ?ð=lòÌÌY:* ´¶ óÑíºN‰äԜݥç*Û®è°ÀŸ©c_mÏe’Å``ß‹&jÌ„’bÝÐ €ˆZñ&:Öô!+ŽD"’AE`œ3GÐ:²ZrÎ�6ßkéˆ|UD,Â�úGú elJØß_ÌIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editcut.png000066400000000000000000000030501506556630100207360ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœÊIDATX…½—kLWÇÿwfgawXAy#ß(•g…ÄD¥QÀW4>ª5&jqA›¦_ÐD[“‚”6ñÄh4Š > Úš¶j1¶<ÛF âPA`ØeÙ���™Û êý49çþÏùÍÿNæÌ“³Hòv}ÊÖ­ü» ™Éèž²#c[ÂÒèËV ï 33“ ô÷9–š´”¡ä½ße«Ì=7¤¥¬�xQýûU[UN:`ýú’ÖÚÒù^s–…™ õ›ŒêÄ€æ¹&©Û´ÛÒüXvõ]4ÍkÞ2½÷œømZWmó£’û&˘aÍÑ7 ;^?dä å^Q<­È6~\€µ*ç"«¯4Ö6€*¾i!ÀmKUnÙh¨Ba³¡P2tÚRm,à4ºÙ£H‡@WyNXööR”^ªHjÂfÈ ˆ¥WQ$€P�#ý„¿ {ÑÈrÎP)ràà8•İj(Roóÿ Ðcí¸§æ§BfHêÐÊê `XH=ÂGú �cY¶çÙL­É:�€ uðËÐ[²‚-:ïà$«ñ% =ãHÿÎ2#Õàc]õ �Z+ÛØmfpZ7(²óë‡ÙÝ•¹‡‰ÙI€Ý{áuÉd " ÆrÎM¥»£!Û:£éKÔÔ8œ “áÀÀr^üy Š°Á”c[Ë²ÛÆ£ùÚKˆ&”2½yIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editpaste.png000066400000000000000000000017451506556630100212700ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœ‡IDATX…½–MlTUÇ÷ÍЙtÒN§L§L-0�FÑV£]€�U�…‰Ñ…,±Qº!DV$¢�¸ˆk4.LÐ…‰š .\¸W#ñ#&c06Péǰ§�™7�)ïo:mç½7â?9«ž{Ïï�sî¿£ð¨d2i¤¦³çµVãúw|ùÙûi¯çÉ𚘚Éï×Èž�UŠ¢˜Ð†qªÕâ^Ô�ñ·†Eî�!ÆæŒ„|(#&è½/½þæóGŽ$ƒ­(u~,ñ¡b«~ |1žHbÑ(©?®²˜ÍŠßçcxø eš&é¹´Þv÷Û‰^�ž¯='Jiëôñ 3SN~€3IÔhûЉ‡¸W*V/þLõñàÀNž©@Ûê& =�Ûž}ô±šsÂß©¿˜½>}p8{ýõ“üÂ<%3W½H Öó$»ßÕð‚É©9nÍæÉÞ5ë feXÚ©x ‘D)fçnóÍw?7Ìù7³À"Ô5¦ 9(„Ý¡ßÐ7i˜âQÙPq0+x¸Æw¤&4O“ưcŽ âK”"Å·_8š=üÃWŸ¼³8?wÍA‹ ÅyoòFˆñ±×‡Τ¶F¦ÿY¹¸wÿsçN¼ºçÎ�›“«ªF$€Ä5ì/´Ä[~ú»N~páÊæøö5ϩΠEÜ­½E›ÏGW(À#;û»N�ûü§î-Ûvp ­ËÍOѶÉG4ÜNW(À®}áÓï}z%Ò»up €à¥ý‚Ö‚XÚ[�É-Q\¶HôÇ;Ž¿ûñÄJݺW°2gi¤¼°Þ¤ØÒÝÁå_§¸žÎÐÛ¯ A»X¢í4á=‘Îv^yvˆéÛ L¤f0óUÛ®�ǰ[…ÖÍÇÖžNí$¸IUðW�@#ÚÙlp�T#)UgvuFTyjÒª<‚ €®ùÈ €=û �$b/¡[ž3€µ`…ÀµT�hãÕ5¨.‹“¤ü ­:`­7ÀÛ`ï@ +Pç!k�ÈuìœV: ­u; e3ò0‚–w`=ÁþGãr³ý{¡+v0ʵՊ¿»E٠Ѳñ¨E÷\:ˆ±œËQÌX.-9ÒçÛLÇ¿7+?ÀË—°>:œÙ§ Õãv  ŧ€÷àØ7¾÷r Òg¤/ß:o¥¨Öb¹gýOúÔ§ÿŒ¤JQIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editpasteafter.png000066400000000000000000000031041506556630100223010ustar00rootroot00000000000000‰PNG  IHDR szzôbKGD“{yÏ pHYs  šœtIMEá  *·ì˜ÑIDATXí—mlSeÇϽÝ:Ön°®ëØ sfÛ3:‚€¢¢ Š/4ÆÄ¾@£F ¢‘8‰šh4A?˜`b\|›&j|C£#‚8u“�FȃÍkWº¶÷9~h×Þnk7À“œ¤¹=Ϲç9ÿÿù?ÏULÓZ[[�îžÀf­Õ*ÝeÀ�¼¹©�³4cº�ݽ#Wjd¡ËŠxQìÔ†±žÿÁ¦S€ºqÕº‘ØJÄ(—‰2|‚¾ü†»¹æî»[óΦ  6¯¬~E ¾ñ»\7__V]íôy½tïû�á@@¦IKË…* Ñw´OW�غ³T÷ùíëD)-b=vo{ï¡l8žjE-ÉŸ·¶º¾–Xd4•ø½»œ¹µ5\ºdq²è¸yÈËË3J «.[Ò|¾m�p¸ûŽìy˜º€�Ñ[ž 1rÒO$L%ð•,⢠2&8pè(ýGFœ¥p*@–ž G¶?E)ŽàËcþ:I…HzcNÃÙ "\äú}ì§Œ1E@™WΘ„Ž4ÀÇ~ý‰aÿÑ¿¦è€ EÐ’‚mÄp±jå�Ìt9Ïtƒõ=×·_ºtù¦‡ïX08xì@f@ ’æ ¢‰ZáH„¨ea‰œ–ç94Ï­*|dÓÛÅeç4d"‘ôâ�?utðä† ìÞõZ3-ïÞëg` D®i2Ë天®ªðÑÞøÑ3ûœÆìØ]k´¶Ø¿¯›¶¶6~éü9Sf÷ŽÐÞ¾—k¯y‹5«?¥óçcxgæ3Ë失¶²`ý‹mE¥sš& Œo¼ˆ±ñR ¢1 K“Ñÿö‡Xÿè6Ö®ÞBÿ0{à¾5[øø£ß…£œ[UáZ³qóîI§` ‚TÃ¥âEü¸çÖÞ÷@FÆ}½õ ¾¿Ÿpx”ùó+Y´¨’ÞÞ“|¿½wU>½þ¾ÂY“’P4h-I·lB¦”â‹-Ÿqas#ójin¬£²Ôûíï` tý:À�o#Ž&==C éïòåçqs¸cY3Õ³g¦i–‘&ã9À �F©©©¡hÖL¼Å¼Åêêêp8h-ø|.Zæ—§4d0ÄÖ­‡èê:ÎŒ&ååÌ))äÖ¥M8„HD#:µk‰itšH$Âm·­`ÙÕËA„X,Šˆ¦´¢-P\ââþ‡ÓÕyœãÇ€bx8 (n¿«™æ ÊÐ'“²µ Mˆ’ã—0� P(¥p:�tïÿ�Õ®C©T K VbMË‚ žy~o¶uòí7‡q¹�ÜtK­»Óa$ã´m“ŽtH¶@[–Öˆ¦iRÞ<¢Ö8½gW][ÇËjرý0³Ë hlòât:Ðö¼ÚšÞaĸÓF~þ”á¦i`š˯«Ë¦3F!°oV$®rgkÚöެwB¥Îô”‡Ê7•=nN„ýï"Æ$HÍêB¢[ ,­±dúg¾é&×Ì›°ÆšŒ„ÀÄ)PûZ—»ð´ ˜m–3lÉ3Ü騒N”bÛŸößJ)žÞ°Ž—_xËŠ¡”bèŸh}î%n¸yµ}…i/:ù“…)2þU1œ˜.=¹ÄåxZPJQ__O8NαR Ÿ·˜ÜGzWTØ8ʼnh!bD’qt@@}" :] 5Qв`! Mç#'¦ah+ "¸Kæ$[º§ü0#F‡8¸¬¯|åë$W9ãKÄM€`Çå˜BêLO/ÀÄSQ‡•FH•€e4¦ëh�å¡Àò$c¼ª”"|ä�“xq†;¡ß‡DƒAFƒ§ˆF©;anK §b™ÔO²|óÅD' Èx)½å}¬WW -Õ†*I<_àœX \|&:°¯ôßÌß6vgÕ™¢òšÅ ó¯|Ðþ,-ÎÉuÎvŸ…Z{>m%ÀvéY¶u1 +IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editpastebefore.png000066400000000000000000000031751506556630100224520ustar00rootroot00000000000000‰PNG  IHDR szzôbKGD“{yÏ pHYs  šœtIMEá $mÚâ IDATXí—ml›WÇ÷ñ“8³“´±ç�fYóâ¤YMX»NmWЊ ÒÆÄX°~1Z[‚²¬š��†Ô©HˆŠU¼ u£íÔUÚÔAÕnÉ6Êœ�‘nÙÒ¦k²$M;Žßž{øàÔ~œÄŽÛq¤óÁ÷9÷êÜó?÷ÿ?Vh½½½Fp4tXkµ×@_0à�ç~è ÓŒBƒ—æwid‹ÛŠûPœÕ†ñ$ÿ+$õÀÞý�"ÉÄðΊÛ�2ü‚¾÷þo<þùGé-ù8 (u¸§áWJð/ 8çþòkœ~Ÿ�àÀ˜ …Ät8èìܤ"‘WÆ®èúéÓg«ô•Iû>QJ‹X?úîÑK#ù0žîEmsÝù�†@Éx,s0¬¥¥©€íÛ¶¦“N™‡’’£²¼~Ƕ�¶}ÂûÁÿrù½Ñ?«'pð úÄÓæ¯O�„3 ø+ïfó§Zs0<2ÆøåyBÓ‘¬"!”aéÕ 0ó}¥¸<6Á©3ý9cff¯S'’]˜›03ƒ›Ýo¡?|#gLPã“[nB3 ð¾hSÔr½ªsÕCBÀ°½r 5Q’e³?ÿ·’Ýÿ|þ·?™›{w• Z-Øæ 7{{¾Î·óV/ýh.ptûÎ݇~𵻦¦>ÎÍhA²D4 Ë"�“°,,‘›ò§ÉÆ–úòÇý±ß[s{k^"ÉN ‰ðF?O8Àùs¯¡5y²ˆY LC±Öí¤½¹¾ü‡Ïþ®ÏS}{[þì®5Z[ 9räoýëÍE˜Vw× ‹ÒÁRBÖ,¾5.Öº�´5}¢ìÉ_鯨Z×¾,aiùSIÜx^JA"iai r·£”ó6fÃQb €;êëÜ�<|~ÅX�` T*‰¾×_+¸µEµ„u˜jOï^�åo�Ñ÷ÎU*Ê×–­ø EƒÖ™whÙˆL)Å‹'޳ic‰D¥3צyöÐ/y¨»‡©k“4OÖg5ØÅèEZÞ_ŸúQ 6Œs6x‰È|„ X¡¸$ ©X»Ÿ×ƒÏ롹¹Ó4ÑZ˜™™ÉÈ›ÊÈœSœ[Å °®²œ¯ìlÇiæ "�èÌ­%©Ñ‹ÐÄãq~¸›ÏÝ·DH&ˆhªêЕÞ*†ËÇ«¦˜t\l}w)VNAKª™”�¶³ˆ(�ý¢i…B)…Óé$88Ä·÷íG©Ì–,-¸Ü¥ˆ¥(§"½ßoTãÁOEéXm»¤™ é’hËÂÒÁápØp' k _gË— [�áeA/à0²%Gk«01b‰úßærÌÁç›þ͈õQ+J)eK?ëb´ûeER,Wˆ…ÊØà¿�ϵl�ý¥å� •ºy•Ÿ¹áØsƒ|õÁ£ìßw’7ûÆ–%b¬È„Zg»h�ØJ`i�Wx¦¦#üé+<ñØ‹|4â�ÁIžxì$'þ>D÷Þtí´™3ÝÁúzºÿÀp8¬N‡ƒ¥K—˜h4J¨/$-ûö7J¨?ÿ=5FTíGïÝÝ{|<N€'º0�ž…÷Ìœ7‡T"žÛø±»™¹sf°ªsetÚj©®®¶ü-Wt.Zœ÷žòk÷Oœø¥ç- 2€­[‘wŸˆ22ÔO"Ém¤lXÁ²Ž¶²=ÞÇ©#„¢bÑ0Ʋ¥Rœãý©Æp¢ï4{?:PvÍŸƒCLW-$æÌ9~‚(Ë¼ß '¿.»&L«×I'¡³ àg=cghf¨qiÅMÂÀÑ|æPbÓFIùÿsÍ]©�Ÿ¾ýê?‡ûûŽU`@UDsa±¼lÞt;5^÷d/8¯ç�áy»W­^·í�Û.=sæäÑò: €(ZàéÛØ:y¯v;Y4·Åÿà¶7ÔMkmWˆT   "�Ûôô ±¤c;O=ù1¡P*ºËá`ª×MûE-þ-Ïîúª¶©uþøò]â‰;wdQû î>Å«¯¤ó²—Ù³ç¶H&t¥ÝUå ¾ÆÃT¯›ùsføynç�@ã…íc(Åô+"Š*œ<aËCûˆÅ’47ûY·n6‹7òÌÓŸ …±…²®À`d”xÒ`VËtïÝ[·Q2Æ„@E¹qÃ[Äb)’I›TJˆÇm}wš;¾&™²Ë2†¦ZÇ~ä“C}|uäwþ©¾’e¨"¹:´UP…ënhãûÆþþ({÷ch(Nõ 6‚ea�#¿‡[×,¤çôû»{‰ŽD)‚9�¦…Û7wà¯qgåéÔ©±XŠÖÖËVÌ@2áªä6ø¹eu;ng™2T•tâ�u[Q ØèãÅ׳ =Ý,µ.îhâÙç×lô!Ê„c0y²] DÙØgLL:¶(W]=‡EM¼¹ëm ‚\º|: A¶œ» ‹ÈXšé~ªšW–é$TU P[#¬]#¸\`j�2)y±Ï}$Ã@2>Êî×wñ�«ÖŸÏ $ešQQÈ)¡eÒ åØ1H…no«� 8p`+��€1¦ D•¬µ·†Y½þŒP¤¸V‰È•K^Ì6£âc%Ól*™Çq.GuÁZ»Tc«€tHfà‘¼MjõCÐähfØŽPm]P¾´f¨¸9eÈ»ð¿¶Ü�ÏïǶmŒ1ŒD"<þï§Y�]àxâg–Ÿ¾(ûû¿Uû[Jë@ZŽ‹Bp6 -0�‡öîsÛû~ \Eã¡*nu£¢$¬G§AeV!óŽ’UÀU’�”lI÷ŠË;WqqÇ’lRŠØÙóêë‚|éû•+‚S�\šÞÄeÜ(JŠ$êÏ…>º‡’ßÁòZ4™<þ:Öo؈eY¨¦AcÒ—UÄŸ]›Ý£Þ4 HUy´è¢ÉH„x$F21š› ]Ñ<6`$1FGÐq¿û,V F‹ ¥7ÿû¥�ƒ«Å2 ™ç+úÃ+�Ë&rX)Û7ã ¿Ù¿0šÅk|ùÉ­߆eûxóì•m—¬½?ÿY2¯«r¹ç_LZ‡Eí/ß{yÀ_Ê)š1ÝÀŽ®¡K4r®ÇŽxQ|£ cÿƒM€ºfõú&‘Ø*Ä(î�‰2|‚¾èêÛ¸üöۛݧ@¨-«ª^P‚olÀwžë¯*«ª²|^/{c0—iÒÔtŽ …B=rTWöíø¦Tõ;׉RZÄ~èÎÖ®ƒ“p<ÖŒZš;]Uí\b‘‘Tà÷ŽræÍ­à‚¥K’ ãV„Ûí6J */\Úx–c�p¨ãOè|˜À¦Mèí�…ð S‰|%‹Ytv]Æû¡ûð�¾P€áPeØz* \“½¥8|¤‡Ow¶eŒù·€ ‘ôœ€¹&oa‘çô±Ÿ2ÆÌʼrÒMèJ#|ÔÖK9¥MS& û�•C. ËïêÊ;b+¿~ïåGýGþš¢‚AKж!ÃÃêU·2Ãc�ìk;ÿ¬m½`ÙŠÍ÷ß²°·÷ØþÌ: €$ÍADµm‘QÛÆ9!w[.çU<°ùµ¶â²Óê&"‘tqJ„ŸÚÚxtãFv}÷=Z3-ïØã§§'D¶iRè±h¨©,xð™W~,šuZý䜮5ZÛìÛÛAKK ¿ìþ9ASf÷÷ÑÚº‡+.•µk>`÷ÏÇðÎÈ¥ÐcQ?wvþ†g[Úf–Îi@[þ8ˆÑñR ¢1[“Ñÿö‡Øðàç¬[³�îîAöüÚÃ]k·óÞ»¿ G8½²Â³vÓ–]NÁ(©ú†JÅAüøÃ÷¬»ëžŒ÷ÙŽ¼óÖ>Âá,˜ÍâųéêàÛ/ºÈ«Ì¥ËÀWP˜?aŠ­%é¶CÈ”R|¼ýCÎi¬g~Ý\ëk˜]ZÄë­Û°Úíᑇ?'Ž&��ýôôéîòéGÈ fqËòFªfÍHÓ,#MÆö£4@4¥ººš™…3ðá-.¢¦¦—Ë…Ö‚Ïç¡iAyJCzCìØq�ööãä䘔—ç3§¤€—5`¹2‘ˆFtj×Óè5‘H„›nZÉòËV€±XMiEZ ¸ÄÃÝ÷-¡}÷qŽ ŠÁÁ0 ¸ù¶FÏ.CK¼™”£iB”¿„i…B)…eYtìû�5÷®G©T [ vbMÓ žxz9[[vóÕ—‡ðäY\wC÷­?Óe$ã´c“®t H–@Û6¶Öˆ¦iR{æ|¢ö½c—^QÃÅË«ÙùÅ!f•åSßàŲ\hg^mOï0bÌ韓›;e¸i˜¦ÁŠ+k& Ó£ñ87+W¹S5íøÆ¤wB¥Nö”‡Þm½Û,Ž÷ý1þž!bLЩùO]H4â(�­5¶Lÿì›�ç.·Æž¨ �ñS 4εž¼‚¢à_+éÁã.M§À‘t¼;^:+¥x|ãzžæIl;†RŠþþ¡ù©ç¸úú•ßÌIûЬPõÉ"ÿónNL—žXâr<†-(¥¨­­%'çX)…Ï[Lv–+cU Ê"¦5¦D“qãt@@½/ :] 5Qдð\êÎB$Þ˜†a í(ˆ�W2'YR}í^¢ø1$›¬wÏ�WeÅgd¹ò‰‰&w4n,;/ÂRgz:“¢ŠŠPi ©´ŒÄ4£u«3ps(ˆ}Ù^ëL²ÌÜć3Ü ý>$ 2& §î„Ù!l- Ç2©_扰�`V6ö@@ÆKé oa¿¸²™6TIâùb o pÞÉè@Îu!2i¡8º{R�™Y^½¤nÁ%÷:ŸE##ÅYÙÖ<`×)(¡ýÃG/­øn°\[eˆœ IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editpasteclonebefore.png000066400000000000000000000031741506556630100234720ustar00rootroot00000000000000‰PNG  IHDR szzôbKGD“{yÏ pHYs  šœtIMEá ))ÿÛk IDATXí—l•gÇ?Ï{ßö^z¹…¶·¿¨t•¶Ü–”vº#83Œ#q[œ«�Ž?4Nc†qÃÅud11™ HŒdj�ST`a$›¨6ºÍe-+à e´´¥¥?nï½ï}Ïñ�[zïm{o ó$çŸ÷9Ï“óœïy¾ßóimmmVgïø³ËBÞ·àáWµÿ*Ó¬Åv^žÜ.èF¿ b8%–õÿ[Læá]{Uã­¨U4ª~Æ*Qäþ/|õ™Ï=ùd›ïã$`Ì�ÖªŸ¥dvÀiÿ*¯ªò–ƒtvý‹±ñqµ=×›p8ÌÕ¾«R9|âT©\Lݧƈªûýoµ_¾”-à…6Ìæ¼»¿Yª!‹&º;W°º¦€-››g’NX!>ŸÏ*ίܺyíº”}Ê;ÿÍ•‹½¿N`ß>äè a&o O$R()ÞĆO×e< çRýW&§%0ÇX®,��mQ�áJßÇOvdŒ½I…jzanÃìì ¢lð¿‡|ôNƘ <¨wÜ„và·|Ú†XÁÍÒÆzR+‡2U!ýÉç¿oùÇŸ~ùñÁ¾ T@UD“°MZ~vµ~…e~ï�^0Ô{},Ô¾eÛŽýß}âÞ¡¡�z2ó€¢hšƒªà¸.‘X ÇuqUoË}^›µ«+óŸÙÿ›Ž¢ò»ê²‘jz H”w::x~ï^Μ~ åŽëul˰Ü率¶2ÿ{/½|¶°ì®úì ¤º".çº:9tèïýóÝi˜öžƒ9\8èeèæE‚ËòXî÷R_ó‰Às?=ÔQPº²aNÊìò'’¸õ¼Œ'îâ ‹r€ˆüK �ˆu\>YYájß�3óöÀ\ËcIœ}û­EW`Ä—ËD¬Ÿ²Â®�ò÷ú8{þùËó>CI¾C7…ÈŒ1¼vôë×Öã8ÆFn óÒþŸñXK+C7™<\žÖ`e“1b¼‡Ð 4?4Ì©ÎË„'ÃÌÁ<=À-Àqª««)X¾Œ`Q!Á¢Bjkk±meddd^¥SãÅÑD`eq>_ÚÖ€×Î@Dª‚JòÖdšX,Æã�·ðÙw€*ñ¸ƒªPZQ…(•"Oœ'*×±È%Ò¾ Ï#ÅgPMœ…1˜ÚN#¢ì§MP c ^¯—ÎsÝ|c÷ŒIáŠâŠ’ç_ŠÀo­ ε¨õ­!ד7 )—´Ó!`¦ä⺸"¨*�‡Ðš»qÜY|�._Éþ&sr™rF°­%iQ"îâĈYê¿$/oÑßužI÷"Q7‡ÀÜeÉ Fs!H½¬j‚åcã]Ö”ÜGa0oΞԗ–u&4æöU~äF˜Ã¯žãË�¶³g÷1Þ=Û7(Uk^&IwASqÉ*}Œ£é&O²”’¤kÁ,*RzÿÒü¬tò�K9ÜM4¥©©‚�;WS räp7±¨$cUÉLÅib¤iLøâÞ=lÛÐÀ–¦[ï©cݪþðJ;®*]�üøù7‰F ÞÞQ&èïŸàøÑÿðúñž™ ˆ+óó@‚Ž5e&Tc ¡PˆH$2óŽ�1”‹Èͱ�`±ŸuëËyãõÄà34æÄ‰KLMÅðùlÊÊógšq(˜?+ ÌSA 4Þ»‘º†u¨&Ó²,Äu@•¥Å+U ‚y|íÛéú Ÿ�k€al,mi ~méLéS!°NÞ�GIW²d +j)Ĥ5¤™†%—ùýTS?xñ~÷ë÷9ý·Éó{ÙùÈžúN3vŽÑ 3á` êLL�˜Â‰E’3anW”©x&ö›ûmûƒ5lݾŠS'?¤¤,@¨¾ˆ\¯�}*~ì÷¸[F·‰eЧ¿onî»ðx,<‹Ïì¨Éü¿‘Â÷Yy¦`Eus]ÓöݩߜX´('×»8s§£²ˆºoûE+Àÿ—Yê](÷ôjIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editpasteclonechild.png000066400000000000000000000027661506556630100233210ustar00rootroot00000000000000‰PNG  IHDR szzôbKGD“{yÏ pHYs  šœtIMEá *üôí6ƒIDATXí—kl“eÇÏÛ®-­ëØ­C Âd€#‚Lâ%¢ñBðÂ/L¼à-f¢1ñ–à •àe1ÑD  ÆxC�b¼0TDÔ 6d–ÉJ»v½¼çø¡¥·µëžä|èÛ§Ïûþçœÿÿ©aœÑÕÕeõô†7‰˜uò£«ß~uc?'Öxö^!èy>;Ñ€a§XÖýü1fõºûª¦Ö¢Vý�ú+ ÈEWÝ|Ϫ[néòœ  `6­�þ¼QÅ ¾ò]{ù”éÓÝ�†zöü±pX� .0Ñh”þ¾~iܱ³Iúƒù¿ScDÕ~àŽîŽÀ ðh¦Ó;÷öé³g’JÄs›¿ö´0kæ –v.É‚NG�Çjô·^Ø9o~Þz~ãà½o•lØ€¼ÿh”áP�D4’ÛH!и˜Eme7Ø÷g‡ŒˆEÃË–J%pŽõ¥ÃÁ¾¶º«ìš£C!¦ªsá»A”E¾ï‘Cß•]S LiÐ 7¡³ àÇ3Gh!Ô´°â&a`_>s(±)#¤ª‡ž¼ìÖÔš/Þ}åácÁ¾ýPDÑ\Ù†-ëÖÞD�Ï=ÑÎîýçØìî¥ËVn¼ûÆs�9´¯¼( Šdú4¶N<=n'ófµúïÙøú®ú)ÓÚÆ"ÕB¨‚‚Äã6½½!tlâñÇ>£¿?ŒÓåp0Ùç¦ýÌVÿúg¶~[×<í¬±ä§ Ä)¶lù�yíϳ§ç0¯¼ü�ç¿Ä¶m{±E2¥+�®* 5^&ûÜœ5óÔêûŸÝ²«¶é´öQ”búEаþÞÄbIZZü¬\9ƒùó›xú©/éïc eS�¡Èñ¤ Àé­S}·mØôuÉUåšÕo‹¥H&mR)!·ÙýÓ›7G2e—e ÍuÕìÿ{ˆÏw÷ñíÞ¿©õO®.9†* ’›C[U¸âª6~Þó`£lß¾ŸP(Žg’ƒ9s›À²°Ç�‚Z¿—–Ï¥w ÄΞD‡£”(A‰HÓÂMë:ð׸³òtøp„X,Å´iµ,Z|*’)W¥<­ÑÏõËÚq;ËŒ¡ª¤ïxÚŠ�¦j^Ø|%sÚÓfY[çåìŽfžyn�¦jDwb &O¶ „([ûLˆI—ÀåâKg2¯£™7¶î¦mN€sÏ›JcÀ‹-'.Ã"2€fÜOUóÆ2Ý„ªŠêj„Ë—kL ¢“&$�"ö‰_É0�Œ�ÐýÚV.¹xá𱓹I3**9%´Lš¡;©àö¶Ú‚–±òÐ 0c JT)Žv{ uŸÂÀ¿…¤ªV‰È�Kž?fͨøµ’1›J1â€S<“ ÖÚ¥š=¤§@2ÉÛ¤¦¶¡b Žº]h|Ÿ§©|i%ÌP±9eÈ;ð#ëï¢ÚïǶmŒ1 G"<ôÄS¸w´hŽ&0."”ùüÛòO[Jë@ZŽ‹Jp¼ -0^¯—�·ouÚ;ï{pÔ½ÞjܤDph’}“ö¢rz!óž’UÀU’½)Ù’öŠ :—rvÇ‚lSŠØY]k¨ Wï!IK]T½s‘•Qå¬&¥Â…î>Ñß |z%ßÁò,šL^=«V¯Á²,TÓŒ Š1é“�(¢~<œÀ Ë¢Á=‡*‡7�—"ÁšŒDˆGb$#¹;¡+šÇ 'FécÍ� Dª\øíP€¢Kéuoa¿¸fh™X¦1ó|1@0<¸8Þ2cIÛ9+îÊ–LÄë«\îYÀ×ÖaQû›^Z ð¸™‰ß IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editpasteplain.png000066400000000000000000000021151506556630100223040ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  šœtIMEá --œÚvÚIDATXõ—]LUÇ3»²6lË×¶ÐJ1E ië¦| yª±öÁ�^LÔ‰Öć-oM4áɣјÆD|PS51$�¢¥›õ“X*_�¸�.,,°0÷ø0 ;³Ì.0àIÎÃÌÜ{Ïÿžó?ÿ{Gc›‡õÈX¼O)­KGý¬Ã¹Ï>ê�b—¦ow`d|±]! #Y‚Æ Òõ ì�m€v®ëµ:‘µD/ŽIÀƒ¦‡uú‰ç»ëì ûw@Ðú:*ßÑ„P怫�'Ï–UVúB%%D~ù�ùx\¼uuj‰D‚©É)U1ûÍà5µÎMS"Æ/_ÍÀ p1ŒÖ’â¥Êš*Ö’+éE€ß#åTW µ¥i´iEøý~½4XñHËÉû,ó„[‘?™¸9ö °5€žÔ,ÎEI&Ò „J© 6ë#£“ü3±H|6a°”ˆ£é†ÚªÞ\EÓ˜˜œæJÿpÖ1wbs±'fæÍM¡>ðêöõ¬c �²qMB¯­à랲ʙ;P·å"q`Äš9„¥²eÖ b—aíüÀçï¿9�ük‹ J%é²-êº:žc_Àçvƒ5cÿÎ×\nm;Óûê³§ffn�d×” 67wcˆ{÷û¼œ¬®v÷~<\\v¤6§‰Ø J¹÷<�‡ýÇï­¾þև׊9–•„"‚Hš¢T*1ÂáúAW5ø{¨™’}ù«:\páí†/uw6Ü™žøÕ–!3ý‚R‚lÝÍ9Zˆ-,³²jpOÅ¡À‹=}CŽ]°^‚´)$EÎ[C»q°¨€¯åæT €Pp�3ÊÀef@vwâóyæÑŒMÏ1'±˜ØLB±p`ÃÍ´ ÔÞøÝ¥Ažn;ŽÏ›EˆD¢”�”fwRÛzÕÕîÿhÎ�W Í"Û6!Úh¿uh©(÷5pš«,›ôÚK€½ Å$¡ˆéot@‰cçW²=6•å0Ê(i%ÜÓè–ÞíNº¿ý{WÁn|·¹t"¢;p Ý.–óqã0rMB‡¹† MíÏ,�ÙJàú· .Ó�›˜›¥ØÖæón2àÊPÎ:`ÊqF R$l:sÍU°¡+õ9u@_ÿ/0ƒ+››Hű—w¢NnË@ÿi<Âæ�©Ó%0ðÕ)—¶q)�†�Õ…V–XM.§ï„y‰ÿ]‘¼O}ŠñîùX›ÒµÒÔûF€h|¶ hÞë bazο‰Âò£Mµµ¿b}·š\)¾+ÏW íB �¾|¯à?+ܼ2bM™SIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editredo.png000066400000000000000000000022241506556630100210760ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÓ 3-T>6!IDATxÚí—]h[eÇç$MÒ6mÒ&u­³¸™Vp­¢8¡�aì…9X 2”]É s» Sçµex¡³0AæÅ&j7º2¤õÂ9œÔêÚÒïµMÒ¯´Iš�“sŽ;¶¦Mc¿`ö…—@òäüïóxÞçHº®s7—Ì]^’"k@[µ×‰…ýXx^–¨ c4�öTœÖðTìÑ{°P}MWÝ^'^“­ÔËŽã�u°µÔNU¹3-.ŠóG_ˆó¿—Ð)&å‚ì>.ôc~då—‹¼ûe™/·ØCŽ£ÏLòdU.Gåú §~(dpÆ9¬D/‰äá6@É–�E?:½�²Ä¡—ù‹ƒÏn'×–³"O§¦c||)@Ë@yX ꑟ€ÄRs¾ÂïœÀ5 ú�½·Ù\êbx4€¢(´I”9Ü…fJÜ.JÜ®%!Eá¬/ÈÏC¥£Œµî¶z€d¦Xó|%¥ ljõ�‡nóí�ùŸöÓ@˜5Ò§²‘¹<Ÿzr'öí�Å…fûž‡Mh’%ýéj’¯ÛHŒŸê‘÷€‰…Y�¨ ݪQf¾©WÏ!`˜1Nž2ÄÓÿwÂæÓO?MÞ– &«£à¹‹Íhí„p(Ð&’‡Ã@<½´TÉÉB?Ölˆ�ˆ!œ±r}Ösµèš H¨q %rNÕRõ]~åîôX» Â’¹Ú§ž¬%ÇÄœ›ûQ×B’”§œ4|Ò–ªpŸåóyË–^^ OyÒ¿CGÏXÖFd,†h2›ø?÷‡Ï|ö+$ó ›ï-c«{åýÿ×^P"£ž2y<ͨðÔrû·GûþJ»+Ñ胊ì ß ª¶¼}½ÔÈÄF„ù-¯Éãñ¬æS=zÓå.mWE4®LÊEØm éÙ÷oý*D îo9o_FW  Ї+M]ZME,:]9‹‹‚Ü¥ÅÛí‡D°AXÞ½Œ�ÕÌCHÍM]ZMEr6TÑÝí¸5ƒèÄ ÂzzN˜]ë@¢3B~ã´ä¥Øx'ýc�Rçw÷P¢ƒ6Ûûi‶Q„2ÕÉà$SÐ72 ±‘%ÅÖbA;®6uiµz"TŽ©�Ï*¾Þ3aZ&H† ü(›ø²fÂU,PÜä—ÚX&ñôy`�3atU“ñ¹d‡•6Þ ÿ÷ýÅy”áfIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/editundo.png000066400000000000000000000022101506556630100211050ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÓ 6*·-WãIDATxÚí—]h[eÇçœ|µI›díj?¶µE—­:è*lÈÊâ‚§®ex¡^l‘¡ ^ìBA&¬ ÊpXv14(b/ʘ�=ƒ ŠÂ\ÜtÌ5ÊìgÒ–$K›¤ù:^ôt3mú¥Õ]Øž›ð>ïóËó>Ïÿ}Ž`r‰<൰ Ȳ¼ì†k{úý¢�€ªóÙþ�¶W�  ý'øº¶ß¯F óÞDŸà¥Ë›û?Êé_øÒÛï׳Þh¹Åë»øàp›N‡RÖXOˆ¢—Ýý~ p≛l}”Pê·ÖðÞ‘q¬©]q]X7ˆEJù~Ã0þ–Aß½‹±(÷¬bs�ÏŒ‚hkWœ½ëQ ¸.ú1ô@{ÓMM;ÅYdÎM[yó)¢¤çCH>Ÿo.¸³×�@`_CœÝMµ$2,iØÜlwOp#\¶3(=·Ã§^¼äãoµ¡RÒãGõUVöí´­Úyt*Íw·uÐ2}röØËÀÌZ[Tàù¸TxÝì}xí)ŠÀ¯CÓs¹ãk†8Y2mÍÛ+¨,+ümà7H'¢ÅÒ¡£²xòs ¹Úë°��·’O>‚ž),&gCW(ŽËã,t¨*‡á„ÙX¹ØO€Š €![»®V@X @±}èG;-²~âG$‚H8Lǹ úù# öæÔBÇZ/ Oº@Ë&3qEvtdÍ€9 ½bpËû§1ôSèê-Éçóéæ³fê’@2È¡ ÔÔÓ^7 é÷­ÊmerÚ°a)=Ì4ã“®ÓæKvƒ"žk Jm}`fG;Es³f:Þ·lì#t•ÛaPµBx¬Ñ — Gµ¢ÐP´®=Íà‚ÀŠxîàºz]…üÌÙvæúr¯¡¤Ð}ÉñJcC=¥öâ›F"�ˆ�ƒ6 †> 7€m€AÜ€ÍöJH�€š�…·Þ–e®J#3qGÕ³Œ„ë·Õ`)¢wÕ¨öÔKB4ilA�Ý‚–iÀ¾ I¨vC,éÈ êâ?¿‹—0µÒ< )¹“Obó\Âê){¨º†RÛÚt"§Âøä]ÈL�6û•,�zˆã@üž/± Ÿt5Ì´ü€ÀÁT2QW½8íBAQ³TB±<‰èä§S¤ÃgeÛ™��I l­ºâDd–]™9Þˆ³á,’£ Ñ2wŸÖrìÖºËfÒ ÎB6è)òÉK$=!óŸG�Ô¼Z®` ¸•äkÍØ+_ÀRzÁRD¼õZîò3×H�}+{{¦€8pH˜Z¡¯z&\X@ à2Ÿa'`_ð¬€jÎŽóº’2µF[,Åk[šyXƼC› µ°ÿu"gꊾdj7¾ ÿ÷ÍΉ26ÜIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/fileexport.png000066400000000000000000000017371506556630100214700ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  šœtIMEá +ˆ±‹lIDATXÃÅ—Oh#eÆßLf’f‡¤Û´Pô ô桺T/E¬‡±æ"²Õ¢ö ˆ'Áƒ Tz‘êÁËZaˆ¢‡*¨P—aW=T© î²m¥-Úv“æßÌ÷ÇCÓ%Û¦é4Ó²/¼�|ùxóÌó½Ïó½÷8Äî‡F£‘+—ËS€ÓU!!PJÙ333_MOOydõzýR­V+Äyšl6K>Ÿ§V«=;?? „Õò®RŠ8†!ƒƒƒxž7—ÏçÇ�@k�"Vj­éííe``Ïóæ&&&Æ#Ø7“É$™L†\.G:�ž+ ã‘cb3 ¥dxx!===är9²ÙìÜììlþÐ&¬T*—«Õê‹qeå8ŽãÜ¥)åÕL&3Ún¢•cLl]A@w­¹®´ÿØ´ ¥‘tÚ'lÛŽÖ„'�j'Zi:)”RODò�{V+ÇaDÿ…ë¼Wzkßz$+>Ž,%¾¸éóú¿¸-7O@ H%÷¥Öš[Á ztšÅ~çåOóYõRGwœpee%’~²ñW*ßâXnÛ™ C¶Ê›XÂFEC×yøÌ£`xüÓÇæ¯¨‚èÚ�å�[¬Þ^ÅɃiµ,;ŠrIñËÍëÜ×{懮=5ë�|SˆÀR6–¶°Dí)ãâ²¾¹ÆÚÆê+Ï]{Æ3öùè÷¿v¥%52TGN#%øùÏkýk[« ç¿;÷ê>¤”‡2 ¥„P€ÝÝ–$Y^[Zôr§¾Þç„‘ìX‚nŒmºuž·ÿ¾Xš‚ÒþˆbÅRJŒÖwš,J„:@`-;Ž3ö×Å­?Ú6¡”2Òxd¨–k�¨µ¿\¬iûÔ«FQ ¶¹p�ŸÿølGXXX¸\¯×cOD?­ÿÈ;¿½�À"�Hóѹ"§S9FFFÄ¡·a†ñ'¢0@nkž|à<¯ ½¹sêûDô`fˆ©GÞç¡Üp¤z‰Öþ]J«5úRýô¥ú£‹¢X,º¥RéºmÛX–u"éû¾·÷ϋŢ�PJe}߯,---&“Éw…}Àé¦Kf0͆j~°[šØª@jwÍ#šoKÛ숾ÞfR²€ïû}ÀKƘ³Æ˜QÀk¾%·¢NéVåìQ“9à7 „“““©vGð?–·Ó˜9k°IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/fileimport.png000066400000000000000000000017451506556630100214600ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  šœtIMEá e¯£irIDATXÃÅ—Mh\UÇ÷}Í›És&ÍKhÚZ1J$ "•ˆ Å… ÄYDI3Mµº±t£ â*’•ˆf%ˆdQÙ¸ˆn„€¢Á,Š-�J›jÇÌd¾Þ{÷]óAR&ÓÉ›=pàÝ{.÷ýï¹çüϹð?‹8ÌP­VÝB¡°˜‘6)¥¾´´ôÅâââçGP©T>-—ËÙnN—J¥H§Ó”Ëå×××[‚ÐÚœÀ’RÒ�ú¾Ïèè(Žã¬¥Óéé#Ã!DW†!ƒƒƒŒŒŒà8ÎÚÜÜÜtÇ ºÕX,F2™Äu]‰ÄZ6›�î€RªkAÀää$Bâñ8®ë’J¥Ö–——Ów Âb±x¹T*�ë6ÍLÓÄ4ÍÙÁ•d2ù €ÑÎJ©®óÜó<<Ï;0gY–ßøî;€V"¥¤#ûöRt]ï,û%û÷6Ú¹©_�Ržéˆþ ÑÚy A&û;|�·'ÄÔÐŽ¨¸¡/Ïg×V¸ô×Yvƒ\O4càÊÖ×è¹fþžÈMh\÷~#&Øúó'^Í=Ï̉óÌØz×¼³qQ}SüS³ZÖuß÷ù§�C:¡’Tà �Ÿ|Š ÉKŒYEúñøø¸hzà÷Û×¹±{KÄMCRË ›®mðÇà›L™f#{ÀФŽjh¢MR„‡;¹›|r{‰«÷ýÈùÔŒš÷F ƒ�À—hBFºÅoþŠ_Ý_Èœx�§Î@à "ZÅ#†Ú~r•c¶ÛMMM‰»VC߯5.žïì…<;ö'Þ®]�ï÷„ ;êˆÆ“,<ñ!�º“=ïŒv•RÔÓrÈfÈîK96VWW­ÙÙYïNC>Ÿß°m{®_�ÑÊÊŠ£ëzÙ�R¦€[wÛÛÛ[±Xì}!Äp¬^ºS€¨zOÔÇú¾ ¶€`7æ”R¢þZÚò@EJ©™LæV €¶®ë�ø¾o*¥œú+ÙÙ¿H’I¢¾¶•íÀžŸŸþp0Ýß53¨IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/filenew.png000066400000000000000000000025311506556630100207310ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆtEXtSoftwarewww.inkscape.org›î<ëIDATX…µ—[lTE‡¿™9çl·e[ÛÚmK‹m‘Ø,hÄÔ0Q°‘‘Ö016&À‹ÆWMPyòE¢>¡¾X¹�tEC Š%…’.Á[ ¶�-Tz»K×îî9g|8Kï[Ú¦ü’ÉìÌÎÌï;3ÿ™3Gh­™ª–‹×ú€œdQLk0“’ÃhW÷G£‘5ë+êçÒÍHQŸöPEвL5ÙCC,ñÄ^�CìV[ä¹®ó|¨©mx¹¶æáéO8Ar¦J!@J1-)%Hó |>Aš%ðYkbn ”4œâà2SIã%ûCMmj&�Yfí Á²À4Á´Àš’ ‰›‘n±¢xeš’fˆP¨©Íš/À¬ë®ÔSs<7M0~ËY¥ù+ýJú6¡Å±PS[ú|n+ÓHšO™ !�> ü~,1)έô+é¯F‹æPS[Ö¢ÀÌK!¤·L~¿—22 ‚Y~%UZ‹ÖPS[ÞÄ1Rí‚9Ë4½Ý¡]p5()h9ßÉà�ˆW?–´¥µ[�§*ëëëíE�r„†â`6«Ë³¸yÚ;Àq¼ÿÂ#Ük?™Wàgðæ¢@2(Mp]/DÿƒÎ.oK+åHé•'=Àb††££ÐÝíÕ[á+(g¥<�©Z4Ÿ…žž¤ù_'( ¿B^Ó£HÔ n‹ 0:4@ßá½8ÿtb(=§È¨ÙHîãåÄ#WQ ŠN›E�«fÐ8ó5�Ç¡¯áuÊž¤ðê.ÜÞ³“Ö[)¸«u7Ï=N_·6QÛX#Ö¦B¤G"02â½hlÛ ¢T��pŠAG#dmÝJá�ݨëÆÚd¶¾Å}[|å•Dû†â�]ô@ª]�$·mHØã[ Æ#Y»ãQoÛ^}úú�t}÷eOv�U»é~î g”Ö墊Júô ýÕµ¸|özj€ä”)ƒI‡ ÉÜu'C)nÿe·ã/Û@ïÇïP¼Cxv;¸6¾û× ¥ExÿA~øížxI`8íòv±y‰I³˜éBÒz©/ºjyÐo(5f:[Jü~œ%‰÷ñ­©×B"³ @ùБ!Üá°wqq�„Íõ�õ¦ž †º½¹Ö��w4ž Ï@Ë©›^ƒc{æ.hÛÁIÄ�Ù—`ŽéU wС­Á<³—¥;ªÑ€HDÑváÏ$zê{Žž/ŒIå~“vñð�O:hIuhïV4r»”½|ùëêô·°tW5*¿”ÈgÁMÿåvg;�íÛ¨ypÐRYùÃ[Žé¯»ôàœ¢T0†áª‘,Çš÷‘³I£‚% nd°·È{Û¡ûx ûÏvr¶Õ‰Ç‚ç_Ü·AdÃN©0Æ X×Ïiðï—� ßû6é%Ucý26¿Á•ŸLâ—.’V�g’ ˜ (÷…w¹v¦˜ÄÚ)Z³)“ŠÖH%ð?µ‡†oƒÑ#'Ehg3çRè±[þüd²Y¶åU‚ËËQ ü•ë‰9ÊÐ��qw%a¸°ÚŽ­®ýUkíÀ"Ýf’X½‘pn ™Oä�‘î#22:­Ý¸¥Ì¢c¿å�~/D)Ï�;e(¦|r¤\Çq±åܾKç*Çq§ÕÍ µ¶?hhríŽ,hN&w² åhWÛs   mð=À¿Ûùèÿ6 „XdzIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/fileopen.png000066400000000000000000000042701506556630100211030ustar00rootroot00000000000000‰PNG  IHDR szzôgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<JIDATxÚbüÿÿ?Ã@€bb`@, ‚‘‘‘*†Õ´nVdf`�ÿý×Ï£]�þÍ@¡_@üŸ€¢Z4vîläæâ¾çã¥gÏÃÃ]å\ææùŸ>€b¡Øâ®†@;æ+Ê‹èûyè2°³±13Ãë7&¥� ¡ð—~€b 7¶÷ïhíÝÝØ3åÀÿ»÷ßÿÿýûÿÿ·oþõêÛ˜>ÿäÿÈÄ Ý@¥BøB €Aà?|àÿß¿Lÿÿýgºâ(‚:(Îðïç›¶¿{¢ö‚|ÓÞ·Ëá?Ó| 5 y_m†_?ÿ1üþý—áïßÿ@ü—�‰‰‘��ƒ•¡©kç—Cû–ùœ<²ô4Pßw°©¨ €ÀQ`¯#d¿©V›á�ýç/à þùvPöΓŸzæ\ØÆâ¹¤±ØIXTP�7ËÝI“AN†ŸáÇ� ÿþ¡šûçÏ?.&& ž×o<û€ð�FFT $>é'߀šÿAðï?äC=>†Ò(E†owþÖ[[+0ؘ+‚õüùƒ;ŠÞ¿ÿÊàæ¨ÄpêÜc#ŸÝWnÞía¸Ý}(õ9$ˆ…æàÐÍÏÎ\g�øò‰Á'ÁœA\” ¬üß?ÂéäÍ› 1¡F 7ï¿‹¾ùòßG Q5@áÏ @‚© °@!ø‹>=ÿÌðèÔ%K#yCM’ê¯_¤$xüÝÕ>~x¥¸ù4ƒ 4-À@,°D†ì€?ÀŒs÷ÈοÂÍxyHË­W~aØrú ØgŒÌŒ l,Ì �~Kx²ZÌnúý�óËoˆ¯_ H@ãîò¯~}üÈ�oM²¯¯<üÊÐr‘Á@C„AEš’N~þgзÐaPÖù ôèP6Ý{üï×ÏØÿ£†— ›�ÃéóOL eˆ¶üã×ß ¹Óo0ØI1dEj3Ü| IÄ ÀÆÊÀðòÕ/†—ï¿ýüþùÇ‹¯ßîê2|¹q €p¦��غ6Ýc�—ýNtÿÿBʇÿÀà‚DÙ0 eÅG/¿1èkˆ2dGk3¬=ÏÀðî+Älp™,ŠX˜ÙŽ�z&þäॠܿ™îv hüçxŒ¾�‡ž2,-ÕgàaýÏÀËË–ÿÌ=¿AÑ´´¿A(Ë‚äþügàdgeæ`Øx˜Ô ,Õu ¸uâ!Ãóc7þ1°ü`øõæ(¶ž�CàèùW ºŠ¼ >fü ÷|bbeàæcçŸOÀ¼ôX^|úÁ_�ìÏ@”Ç>¿â§ËC=ô÷Ço†Oß3\=r‹áÝ+ Ž/¿^2ü‘dørÿ((GÔŸÀJìµ»14F)1üUg¢| ÷¾fPÑ¥%†_@‹€f2|–\O_ÿgxÿùÃãç?�ü ?ÿeøüåÃ�o¿~ÿøÉðçóW†wOß1¼{ÿ�áï÷ß�_30ÿga`úÏÎðñ$¨xþ@ÐD BhÜ~ô‡áùëo >B À"žáP��Ÿáê½Ï Bâ¼ w€>|üòп` ²ôüø‡á�ÿõ Ðâï¿þƒæÍó· �Ùë/0H~AJ@vn†?ßî0¼;ðä€B„ÐÌ@ööÃO|ÌE¸€¿Õ  ȹõä'ó{`øÃÈðó÷pH€Ò(ü²ý�°ÁÅ:0¤?½ûÂÀÄÆÉÀÈΉ+`þËÉðëí!ˆÑ?ˆ – `åÀ¡³/|ÍÅÀ²Ÿ�Ò£wÀ þ ^†—¯¿-†XJ”¿@ ñ7$1þùÇÈðíû_†§O?1|Æ /# –ŒåÇ£Û@¾%B€‚‡È�þaøöõƒ·¥0Ó/ ` ä‚Sü Sÿ023¼ûøƒ�‘‰ ìã?`_Có踗¯20rr10ÿûËðÿÇÌ:†ý?7°ôûÂðzÝu ï+ÈO ¼|û† 1 9@_ #$ �ò030~þó±3<}ò™�“‹™� ˜)Ùÿ2°ýÿÍðõP (/!ÂÁðÿçO þ,#¾Cö'¸¬øÆù˜þþ³þø÷‡ –ý uÂ_€‚„4?8ýœa0ïkòy¶1À Ž?@¯þÑd²BØÀ Õý¿³AÙ Ñ󇈹€˜*Æ ¤yyCÛ2üxôô(ø@ð’pÏ©OÀDøŸÁȳå F`T1‚[;L@&&`EáQå@˜*ÿξûüÃ�·@×½YÿàÆ @Aá†Ãgž3$¹a/÷!ѳ˜l!ˆÏÌÌnÒ#,e‹!–©?|å¿Þcøq÷²ˆ Vž¿ô‚!Ñ]gE3Ùpˆƒ˜À!�)S’gf8x˜¢¿ßÛ �û°þ@�£àν· Êr¼ R¬¸;LÐ"ØDúù œÀ’î'0±�è?~1|¦úÀøóHî°¬øÅðT5}úö�áÍc`ªþvõШ/Ðø€b�…ñ{`!ï\~ÜZ72ÿC ñZóýf/�¡€©ò0ÕþÒ ôc`Öùüú7$A�\úš¸þCñ¿Ÿ¯Þo¾Í~ðÆ)@�›åÀà¥tè�wàÀûäÉ“ÅL&ó—övýž Mç2/°äWt§úª¥lO g/^¼Øæº.RJ„áGÝh.ªëçŒ1\¹reýåË—o^~ïùÄï¼{°g}a¿Å‹ÇSŸ©���=¾ï“ÍfBà8Ƥ”5C±«®ØÑà !Š=zô¨>¤óÈ;àÿ©†rvvÖ�zÐÈëú…ë¥ÑÀÜÜœ{÷îÝ Àæòßw0@õ÷÷;õ!(•Jäóy¤”X–…”¥Tõ¹2WoÛ¶] A:�vŽ;–„�ØX]¢u¿½;�â\×FÞÆãqb±Žã ”ªywûöí*•ÕÀ€J§ÓN£Íãñ8ÍÍÍÕøÖÇ»Q8êçNŸ>í=z4 Ñ‘úè?cŒc0:C033ã^¸p!^¿ÀË¥¯QJa) e…òdh«ze…ЫÊ7ʱÆæææÜgÏže~u 6—_²¯5À”=G˜Æ¨¦íà÷ÐÅg€ÁƒÐ�“““.»HÉuÉç·Èò‹EŠÅ"¥R‰’ëâz.A 1È0®Æ µÆD˜�� 9` Ÿý"‚@ÈuöìYg;æµ(8–A;sŽ ŽÚ¶ª:dX�d-úûû�T*•„�ÙÌ}ÍÖú¿ÙßÞYFÀÇ`PîåË—ãKKK¤R©š~òöw”ÞFWoÅŽê óóó™ßü"@Ø×–DW Pàƒ1¨ÁÁA »»»æÂð<Ïóª7]´hÔ#Tl˲ ð€ÖŽ^tñSB° ZäÄÄ„ ‹Åªu ºpT•ëz$¢R倆Âú¿¶3 Z ‡††SÎãè"žç±¹¹¹ãÞ�>×wM•÷;0Èofػϔoaƒ | òÖ­[»fA½çßV¢Y 0åJXA@C`PçÏŸwýX)EsssCO£ñ�Åb»®Š€~@Ë�Ãø…ÏëèÀ ëÀnü7†GíúJº Å�oÊù_©„a!RƒƒƒN£”RضÝ�í¯kP£rúôéX"‘è6Á(泘`�xËÞð.(×9>>î¾Î‹ÿUý~ffÆ¿víš ö45o#àû¡£çÎ�‹Y–E<ve¿®ØD7‹Úõˆ¤ÓiûÕ«W]žyeÅ[:ñKÿ¬ö„Ò Âÿ—.]º“ËåŠããã…B¡àݼy³�Ëå¼±±±âÚÚšwãÆ�b6›­êÑÑÑâêêª7::Z\YYñ®_¿^ÕËËËÞÈÈHquuµ4<<œøðá'“““³¸ù ¤ê²»�v7ˆ}&°Ô½{÷ûúúnß¿ß]\\ì^\\üraaáÈÂÂÂúÓ§O[£úÉ“'5úñãÇ µã8™©©©öÞÞÞW@Vjî¬g^øÆ"ˆ"$…ù¼žE1®"ömâß@Ö�=@‰hƒÐ@þ ׯ{‹>bIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/fileprint.png000066400000000000000000000031411506556630100212720ustar00rootroot00000000000000‰PNG  IHDR szzô(IDATX…µ—ßoTÇÇ?3;{÷úz fmc¯œŘF*$¡„RpÝd�Pyh$K•PÕ*R£RE•Ú?¢•*¥¢ê �D•—$ Ò* }hpxpmjµÁl` 6ØÞe×»{÷Þ;3}pü þQ÷HWº»gf>ß9g~œ+XÆNŸþ¸)�Nõ{žë.×v¡Ý¾=:püø¾اµSË EáÖ�;Û·li|j;kÁb±¤|þ¹ÝÔÙÿIÀJL‹1m-ÚX[q_¹\ƒ( ±öÉQ|n XkÑZ¯�€ 0ƬnÑÆ`áÿ/`iøÌo¬Eëh½Tð4øì{­“€0 °v^Àrð Ô«ŠÀ²»`6öø,Ø<7Zcí:E »»;žÉ uc1vep­Í¬µwïÞï¬)‡~Ø©µ~óå—w3Æ` +‚›h&RŠDggç'‰Dâ·žç�z/\¸P~¢€#GŽth­·{÷Þ×vïþ¶ln~Ïó¸té¯Xk0¬ >“ð}Ÿ7Þèo½õö»¹\îÝááë´·wÜ»zµÿ#Ïó~}þüù‡sº»»ÜÓóæöíëDÊù¬H)ÈårcðC¡QªhJ�¦\ÑäKC\B\XâÒ¢¤%i´Öäó9š©®öhiifÿþï¦Ëeÿí÷ßÿã‰L&³c```H=z´¦­íùßwu½úX*G‘›¹Õ1y=G".I(I".HU+šk"c BCY*‘¡Yúo—Ù¸½‹‰{—Ù´©€”)%B¤ôôOôö~q 8 Œ1¯Ÿ8ñ'K¬Cªµƒö¶Ô’ (dæª3 ¤…„µÄ-TY¨i€Kƒ!íÏ[¢Èp/wŸá]ö7|€®®ƒ�MÊZûZ}}±Øã"ŸÏb6µ0”_싌%B!€|`ÑsWÅâIÜ*màX² ߈¹’ì½NË̲۷¯K}øá””ò™x<ŽXÐ׋ïW˜šš¤ì½À�ÂŒÓ�àFÞ’™ .ù¥"7ce½×�£µ¡­.M[]zΗJmÂqœV•J¥•šŸaF”J¬µÜ/RHyäÂ?§à«,hûdࣷMAÇqóÅbñx¼^�¬ ‚×M†A2+èïc.Ó Á…a¸_Z1wÎD”bzz˜Tªa±°xŒ›7ÇPJ¥TòË/¿Âu::Z¨©ñ0Æ"„àva#½}p¿¸z8€Åcàv‘CMib1IDŒ�ç� “AWJÅø~ÀÀÀ0Éd µüè[IžÎ0šÕŒå-Så…С¤ÊÆ¡b]bh¢BU, Zlpê=Kz£¤¥VòB[3##ãLL䉢ùA)…ÖzJ•ËűXLî V¡ïܹsŸjàPˆÍày.ž— +‹I\×A)H*•� ˆÐ_ŸˆÓÓ>¾0~‹ÐùR- }¢(šPÆèqcBª«“sÎBá!}}½k‹ûVUåñÊ+�‹þ«TÊ„aø@ãaXÆuç›ò|öÙ¹uÐÐÐÈþý¯.:æ+•"•JeL !†*•®;¿U„€ÚÚZ\×åäÉ“,LÏjltt”3gΰaÄи >-ŠÅ‚Îd2CÊqœ¿ŒŽŽðÒK»æœõõ)|�tº…t:½ÔØËšµ°eË®]¦±±ždÒ%‘˜ uÄÈÈõ[“““wÔÙ³go¹nÕŽûaûì�±mÛvjkI§S¤Óuk‚km�Rpà@7ÍÍ�(%™­î¯r÷îÝ¿Ó ›�úÅÅ‹ŸDSS“sƒd³ù5Âí×»A†Û¶µ22rärY¯òé§çÿuåÊ•ßz.¹ÉdÒݳgÏO•R[›šZ:Þyç—‡víÚ¾¸Yðhª««8uêO¥sçþü‘ïû#ýýý³Ùì¿�IžôÝøÞ{ü*Ÿ/ÚÕ˜1Ɔad}?°Å¢oóù¢Íf ¶XôíåËÿ°]]Ýß_еdQúì³M?«©ñV9{æ ¥$Ž£H$¤¼øâ7hmÝúó¥ú=V”ž>ýqRÙØ×wmÕ´Žˆ¢ˆ( ¼Ï<55ÕÛ�*`Qaú_YûV� IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/fileprintpdf.png000066400000000000000000000024351506556630100217710ustar00rootroot00000000000000‰PNG  IHDR szzôäIDATx^µ—]leÇÏÇìÎÌ–òQªRKE/H´Rª&ò%¤¡l5Dã…QoA ‰Ü©ñ+FÅb”¼¼øu!k Hˆâ•(‰� ˆ$!!„haiJ�ºÝ™Çaž¤ì »›ÅòOžÌÌÙ“s~óŸ³Ïd„1+Bè]»vm‹ŽíŒ�²Ùl÷Š+V7�1M¾¼«Í—.]ÊX¨···£»»{[GGG!ˆë’XqèðïH)))! ÇÅ0 ™ÝØ@OOííí´´´tDçßwvv¶îÛ·/S @b…ã$PJml´F\ÀTøZˆ PJÑßžššæÎ�»@kýgp/0’P@RÉ¢GS¹á0†‹«_@d³6Î5¹žK:}.†hjjš¶cÇŽãÑLXˆRZ–P áhFžçbs9æ¹.À¨ÍÍÍÓ¢!?±lٲ風ª$€” ó—\øÿûc®ÍP__OtÇ{MñLD×µ€ P%A8­}àJ+Ĉ͕Bp®¯�ÆÆÆxPò?ÏJBý� Òш̵ÜÁ¡!. ’«Ð#W%PÅ´ƒÞÿ êè1œÞ4fÒB ) ó+í€V±�ÿû^gçF>ï$¹ö52]›`ð2S  (@K…(à8ˆ­;1 ÷Áâù˜={qÖ½Eøî+�É€0Ö‘0Œ¡¤1å(%o ¤<Äëë1?}ƒ CøèmÄý‹�­Oaæµ+ÀCBóìøÜ” e€„[¶cî©Glß�H÷ÁÀExæ ˜^‡øâ+Ì�?ÃãmðᧈGæ@hÊPÿ~BÄÍMïYÂ6¡ÞX‡h~*+ˆe `ɸ4ˆùíHl¿0¤º r�”à& ^}óÇ1ÔsO#[Àp²Yò” ™€–&€%oÆ�€d’ágW£–/!Ùë¬z®\±®TÛp4§|­s"²ô(ÁÉÓ¤¾ÛŠ ²q¬L•í@ÞݤvoAÕNÁ˜‚ðÖ„¾gÉt>QóXB‚¾Éæ¶~q€míÐÔıƒÅl6&çù—– CfFugDus%¯Kô}H¥p««ñ®®I“p£XÒuq=·²oâDü©Sã˜�û6>yòõùãðªªâzQ][¿ä C"™DJ‰¢æÌi¬`h[çW½Ä”S'ÈÕPW7k_còòƒS§8;ï1ŒÖ7|Oò8p mÏÞ6•þ%mø+ŸÄ›5 €ó+I×ÝM߬Ù8õõT}¶†6ÿŽZÒÓgÒ¿°•„ïÇõ€²ìr“±•úL¯…»½ÚÇWâF¶'´Cæã�$Î'¡´Íw½h¹$}�„ëÐP2@ÀçMôò6èëCýz­4ÊZ‹Ð €x&*O ûuÁú  TÆàØB£[­úa/fÿÌ�ƒ$&ŒÀ™9£�ø} Ö¼»¿%QQ@ØÐ¾�tdtÄ~?”÷6´6E>¾‡¨HÁåË6¶f5+¶vÁÆÿ!=Y9ìy™;¡ù»œïÃüÅ0®ÂÆm ]dwDaAS)0Ææû~~°×BÈ@:Ú„ª1†1—qýbà é¿U€`ìe€>`¸Àpø›[§aÛÇêk¸›Rƒ¨ïIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/fileprintpreview.png000066400000000000000000000042521506556630100227000ustar00rootroot00000000000000‰PNG  IHDR szzô pHYs  šœgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF IDATxÚbüÿÿ?¿ø ܹûàQ\°½<9zˆÙºê² Üì¸ÿ*ýó›�áǯ? ¿~ÿaøñó÷¿Þ}úÉðøþ­‘�Ž’¤: €˜P\ÃHÀò¿ ¿ÿþcø÷ïÃßÿþý‡²�®²··–X²vßR@,¸$.^¼gƒÂè/�zšAWGŸ�‰‰‰�™ù 3ˆb&FÆ ff&‹×î{ì$F¬§ôõõQøÿ@ކ0€¾fZ ´˜‘ L3ÀÃÅÆðë×o3Ñ%ë¾� ´&ÆÄDtbAŠ"F¨¥Œ@ ¦ÿ3p°20òs3ðq33˜› -]à1æQQ �ï?þ0|ÿú‡á'0‚Ò®´´4+;01þfxÿá+Ã/`ºøùëÃ´µµEç¯Þ÷.1ÔIŸ%èiÈ2C+¸qãÃõk˜Y˜8ØÙXX™XXXÀ‰”@_}þÁðûv½‰AV8“7@ �ïß3\¹ò×Ì ¼ü| ì\< œ¼@‡²Þ†oß¿3°‡ 01²°±3üçà†Ôo`ùÏðû÷†[w1â³Øì ¼‰ðÓ§¯ K—ì'46Qa)s1!6. e@?1óÇO`VüøñÇ'Ïþ|ÿÊðóÓ/ #ÿ³ ##Á4@xCàÀþ«À µ¸ ƒ‚¹1+0 üøÎÀÅÇËðhùßÿŒÀ´ÁÈÀÊ t ¬4Ã_ #8�Žøýû0mpƒå €„“A €0cQ+–½ ú�ýÿ“Êj!+悹ä>“|¾@ZAf´Öá£a?+lÍr_°C×ïp©]˜]ò)*±`š‘‚¢ó`Ò^þò ¬!ðáÃg†­[�€¥y”t€Áù�áí› ß9Ø�Ù ÷ à•†€0á33×ïÿA:Äþgø Lœœ@Xððásp(¼ùÁLtR \œ¬@ß0s0Þ�`–‚Ì@G0ÁôTDKË_ÿ@èÏo†¯¿>2püûKTV<~ô˜—2¼ü&ÄðçÎ+†¿ßØD…Xøy€qÍÎÞ?€œï€… Ã`éÌ0 ß>þ† +ƒ,÷_¼u V€J·¿ÀTüû?ƒ¼¤ ƒ¨;; #Ã`X‹|`þú˜Í™þƒ‹ç_?�é”+€E3+0{2þü¬ þ‚s!@8À®n™ÿ|ax÷ö5ÃÿŸ@Ÿƒ�è{6PbfFH� „ŸÀàÿõ‡‰áë_–ÿøÙ>3üe:’ˆ‚ €°:@VN\Ôòþ{ËÀ/$Ê "ÃÎÌ \ 2ÿ?8!‚ %Â_Àbðû†¯?þ!04€Ù”÷Û3`t0‚KJB €°ªPT”bàæacøüù#Ëg„9”~r22üæn`Âþ r3¨=f￘¾|ýÏð˜ 8¾½fÓï BâbÀ4@8Vððp2DG{3ôt/eø~ÿ,‡¹6ƒŠ’/Ðrnv %ÀÄÍ .ˆ€>þû\|øÂÀðöņoïß3üÛBÂ|àÚ’ œaô˜•T$î\Äp~ÛF&7{Y)A #@­66h#åЗ€iàÍ‹o ߟ?BÀz€Xgüû >‚ œÉDGO�¡¸8�AMS‘áóËÇ ç·ogxtý!Ã_ e¼ÀÒP€"Ü< ,À¨zø’áíÍ Ÿß¾fÍ?À‚‹�áÝã« ,ç›þ=Æë€ÂçÎ]¶ÿì\ �…+íkŽí8Àpå$?ƒ”Œ8?7¸ôõó7pÙÍÌ_¾þd`ýÉÎÀûÿëÛÔ´ž3Ø2ìeˆ³b—Ztì'ÖÚ €p¶€5*¸˜· �jž>~Åpôèy†—/€‰ìÇO`iÈÌÀÌ|ÀŠIV^‚ACK™�“‹ƒáð†å /OÌaˆ�Ð`q aøum-ó½›>ýßݪíãMtîÚðÒU`!ó�á?#¸Y r‹ª®<ƒªŽ<¸eÄLhÿ�Ù� è�Ї/Þ€KÅ_/O1èò_feA`¦Í õïŸ<Ãþ­[÷Wðy9v|º…l@auÈߺ:ZàFÅ0…òhMùÜJ‰ÿ7Íÿƒj¢ƒÔ‰y¤0\_zšáÞÉ“ JAÍè$6ýX©ÿ ÊL‡¶ï:V#ènÕò„5‚ôýû�££„–·aÊÀŽb~-ÝÔU GŸh1Ü= Œö«‹žß:"†AÂÎS^J„iÛþ ~5˜~€"ºUŒ ®ÞºÏpíîCœòÜB’ †«Ž?Óc¸{êÕ… /ï�CBÒÁSIIšcç­NþD�Z€BqÀ¯¿Ä9@[M‘AKW�[XŠA?}9î ÷NŸ:b)°å rDƒ°¡¹+'÷D 2a€BIó—og :0©cغ/ãž7ã1%% w¿?1gxô€—áW7ÃY€‚;ÀÊ@žÚz¥:°�c“bafŸlõý¸ü“?ŸÞ ‡0|âÔV]S˜=œ¥…N<úuÖ[ƒGäø5Ɖïy%Ø?þþõþóÝÓ L`ø™7qÒIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/fileprintsetup.png000066400000000000000000000041311506556630100223530ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDùC» pHYsIÒIÒ¨EŠøãIDATXÃÅ–ëoWÆçœÙÙ«×ñ5Ž7±;$i«"„ø†ü•©ŸPI¥RE*¢"4)J $䢨B€ú�"$øF[ÔªDUÛ� ±'öúÖ]Û»ö®×³;3çðaf/v6‰‘�8«wçÌEç}æyŸ÷™ÿç!ê“ —~©”R}Bʨƒ1Á ¦>©�à�ú™vkµõ\~¹tòÄOÍónðÊé—ä§Æ=¿{÷À³¶mǂշ¥m™4§FxžçmT6òÅbñ½R¹ôûB¡ðñwŽ¿ ÿ+/Ÿxâñ'ß~ü±'>mŒ ó‚9ž^3>m4ZQ©TÈfgç—O—K¥ËÇžy®²€¶m;®�¦ZuIZ6C7çÚ Ñh_cY‡ÉDcÑWfgf†.]þÕ��=óÜú£H­uã­ŒÙZkÁöhù �D ¥¤T.á8ãF‡†‡¿�N§_¾pélÇŽ4’cоÛ"Ðâ}ÊÚ‚(¢”b½´N"–dxxÄÚ»oß·:Òéž=&º#Aµ%« ï3wëwøžÞ6-�ð! �eY£ñ|�X4N&“±2™ÁçS©ÔÓ;¾uÍY¡8û³×Îál,�P´Oß,€R �`êη'þM>—§¯¯?ÞÓÓóÝó—ÎŽí¨õ…3#Gèí,3wí4k¹AÈ6ɛ塬ˆ…1†ZµJ.—gaa‘îîîCÉDâ©• Î‚15ºv¹ %Y�~�O¦ÿŒÑ-¾Uç¾!F%ñxœîîn3ö�îgWg'ÉDŠŽtúK'N¾oÀ0ºÉ@„ﱕftt€ùù·˜»>ÃÀÁ§‰D»Àø²ÐüC!Q l€xœt:�¥ËËù‘x<Þl¶e@·ôyëÛí ü,Cû:èŒÏ3wíU6Ši!…C¶Ìƒõ"›¨µ�1‘‡”@·ì–Z£ñk ôvûìŒ�Ÿ¸Àjöo�H…ò!B¢¤BH‰Ñíݹ�[Gó¢ï®�ˆ.3:Ú‹“ÿó·~ƒïU�ÊBÊ@„Á±ÎBpŽ¡m›‡0˜�6Ñ’[‚5ˆ´‡2Šö7�:ËðH1n0ûñÏqJ³Hi¼±!%R6™¾!âúMc}ÝpûÆ®DEºÐÚÅwfèï5ôwm0ÿ¯W),¾�”*`!Ô„õ!÷[ü}tè„[óßwqÌ~¦ï­³ZŒ¢ì= ®³@"–gïÞ…{¿fáöëí6t!…DH2vÚ#‘o—AGßg~òû¬–zÉfK`%ñj¤?ÍÞL¿ô6w?®.""q,[Ûs6PÑ‘h°1Ñk­ç.}ý½v²ã‹ß¸7ñÏC¿=uç…šãýÝX\\Šj­Æ ­K‹K¬;qœ4Õ%…�>ªÕ.ܼB†½]s{qWÂ�Ž1Ôüù‚D†[Éš—b¹¨ðܪot9§ä]WHËÁ ”ò”“g,Àžœ˜Š•Ëe£ý2©®#xž»Í·[” �g5í#´v­ ï¾ûÎü;=l¤+;9Ø�kEÀŽ*µqåW‹W¾påMÏ÷¾šˆ'íÆZxû¥‡ŒÍJ¥vsrå�×ÿ’»^«²¸Á¿ÑKˆ§ÓÝãÇ3±X4Ö6U#iƒgûÂqªÎÔä�ùR©T*°µ EËÑ¢îBÿÛQ_Ók·öxz¶Ô.tý¾%tEXtdate:create2012-10-06T18:48:40+02:00(žñ%tEXtdate:modify2010-11-14T05:57:36+01:001qŠ=4tEXtLicensehttp://creativecommons.org/licenses/GPL/2.0/lj¨tEXtSoftwarewww.inkscape.org›î<tEXtSourceGNOME Icon ThemeÁù&i tEXtSource_URLhttp://art.gnome.org/2ä‘yIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/fileproperties.png000066400000000000000000000023001506556630100223260ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœbIDATX…Å—ÏNÛXÆöõuH v Ó ¦” ‚T6¨Rdö£>ˬFê#t1«¾À̦bÑ7@ꢓ‘B…REMAUAq“�ß;‹»vb'a5G²ì\Ÿ{Îw¿óÏ�ÿY¬¢Åׯ_ÿ ”ÎÛüíÛ·…ׯ¯¯+oÞ¼¹œ àÝ»w¿xž÷«1Æ•R ”ÀƒÖcLn]k�Öš8ŽÑZ§kÆÆã1ZklÛVQýöòåËßK¼zõjåÅ‹6Æã1ÆlÛž:�e‡eY)¸D’ߎãpttÔ}ûöía– '«¼²²âضmÅqLEc�R¦§JOÞç3Æ`Y®ëZJ©œO§hCÖAÙó}ÌzW Äp8¤×ëÍ4Zädss³Ô€~¿ŸÆ,kl‘ç2)b°|�W’PÉ³ëºø¾_jhVbfm/ »9{e+bÈ< çÀdGJ)®®®r†µÖ¼ÿžáðßžåº.[[[lll¤zA:NdªÈÇã1777…'Ì2"„àÙ³gcˆã˜»»;Úí6gggSìÝ‹˲ð<!D.’Ód Öj5‚ àøø˜8ŽBpqqÁîî.®ëN… Š¢r²U „@k]˜¶mçÖjµ�F#׆Ã0Ìé•Ii#šD®”âëׯH)IfDöý`0àææ&}qqAµZ¥V«¥zEU0•qO)&€Z­Íf¥TŽc ———¹}RÊ)ö0™8–e!¥ÄóAàû>ËËËø¾�çyH)B ¥ÄqlÛf0Ðjµ¦:ëLà{v:¶··Óõ(ŠÃ�¥¥%ÎÏωã8÷’ôÇqÒ{†T«Uvvv �H nlläZ¯”ß÷©Õj<~ü˜n·K†cð}Ÿz½N»ÝFk�c$Š"ºÝ.�Fc±a”Ä©R© µF�«ÿ rå•\«««4›ÍôC&aãöö–0 ç3P6ŽF£a¶ä¬îææ&ív›Ñh„”’G�!„( ÁT–)feÖH^^^fww—J¥’2�´ô"™9޳"¥$‚ÜX.8>IJ,ž>}ÊçÏŸÓäLB9) 3Pä¬( ÆŒ1xžÇ“'OÒ\X˜¥T!ˆ¤Ùd‡Ò,Õj•õõuz½Þb¾|ù"V’~P&‹ä ÀÒÒkkk…]pÀêÇ�·†Ã¡›Ô°1&�]QöO®—‰ëº ƒÊ‡~®�Û,¨œŸŸ�ÛíöŸGGG?Û¶íX–5ý·hŽL1ÆðàÁƒÛ(Šd§Óù£ÓéD@%�Õ®kÀÊÎÎÎOÀ0ŽãÊ}ÉÁÁAóäääàôôôo ô= +6 f¼¿¯Œþ³5•8ÿÃäö3 æÄFIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/filequit.png000066400000000000000000000031121506556630100211160ustar00rootroot00000000000000‰PNG  IHDR szzôgAMA±� üabKGDÿÿÿ ½§“ pHYs ˆ ˆåŽ)ItIMEÑ ³CŸJÇIDATxœÅ—mˆ×ÇÏ™ëª{½»ÛU¯^ÝÙUR]ßíÚ…hZ ´&,„@# ÄÔZ¡�OY ˜PZóRI  h"ùR°ÁCTÚ$•m×À®n\5ºu·wwvW½oÞ{çäÃÌœ;sïlB ‰çËÎsæüžyÎóüϸÇMª޶5oöÝß2ëppç }jJ޶5vÕ§æ3{ÝJf¦’ 5Žã€Ö 5š28ÐhíŽk­A;hÇëu°×äÓ6·ú®��8²sÐ~¼ÆÞºc;ÉM�l›â¤M1›4ˆº&dZtx!ü˜…³@YŒ÷�þ¨7ä„xð-ÀÉÖÛ™³a #ÿ¥oõÆ<߆ó‡PÊݱH®è¤˜Ë�î?GúâyâÉ…¬Ù{¦Íà‡O<ǹ矤˜Ï¹ÑP 4®^Dm�?á:~Õ‚Ÿ9Ôcà‹·>Ì}»÷³âw/O.D”"k�ðé ¿…Òó^ûO­ÀÅS ]‰€q@SFÀÀç­Þ3›LØÏê •Ú¬äB³H<¹À$\1—¥ÿµ?[ãÚmÔÅ.\”Ç/GDÀ‹Wç­]ÛŒéúß^‰¨ó€&Š„nòÆeŠW{�yÎÒ5 Ê}OûÑ®vÀP_dÚ—ËÐÙ“µ"e«&Û‡/|lì -í(¥‘PT¶ÀßOá˜])¹b6S£p¡X‚‹¥(æ³Q1$f¹n; 5ZtE^ƒ-B^%è‚»öÀ".\YSW�ööÅ—OìfRݬÆy ‹î˜Êöiõ‰ß…+Ã=.£’P;îšÞÁRýŸ1µt>P£í‘Iè'§(æ¯ê2æÛ#_ ¼-@¦Š€7ègûÐÙÓfÒ‡v×,Ámß9Ÿ“"ÖÒaìã×ú+[€ªT\u\!p³ý湊?Ú½/TjÅ\ElJù¬�O�7°|×ÓÆæ P.e¹U€/ûÕÐÚ-Ä@Â]:¼ßL¬k_Ëê_ì5Ù~ùä1®ÿ —^–É›W |Õ¯ÿj†yïÒ{G ÜMB mAà,p+”í£Ï“<ó.M?þõ›éêØÌÍo0öù†?ûDhlYBjåF«¶†¢võí—) ¸wFF~Tg{ßñÃ,W��š—RÛ~Iª"”‘mèý#Üùÿ�\Y1„)# ½,­ý“é{çs/ÿ—öŸï‚Dò+ÁÎðƒ§ÿNþ¶] ·b”2t9Â�|ÚfÆÜ¥*¸¿ç£ûóS4µ,aþêM4,]å•¢@>ËÄÕ>Òýç<° £0nSÎj8v«ïJwÓŠ6Ôô:´ãÔh»_ç“7¯09| uâ­Š¼z"ã?OϧG¸;6Ja"îEÅTÁÁüèã½Xõq”‹„û¥æ,ß>rúòé;”sE€ƒq1™Ûµ’IJEà”ͱ©ÑáÛ†ÆÍÿñVò¾G»Ë B)“¡0nswl”|úÙáI¨¾˜T;Q×Ü@¢}ÓšâîÑé®]žcáñ²Û;î5Î}v{]Ö”³ ÿË£¯f'¶ð=^Nïyû<’\^‹),¢IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/filesave.png000066400000000000000000000025041506556630100210760ustar00rootroot00000000000000‰PNG  IHDR szzôgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ÖIDATxÚbüÿÿ?Ã@€bb`@î€bAX·þÈÿß¿ÿ0üþõ—�‘‘�áÏŸ¿@ äÿFШì?`5U Äõæ#ÃûwŸ.œŸÉˆn@¡8`ýú£ÿmíõ�šÿ1üý÷�AFB,~ùæMºê2$ùrûÁË ~ýfpr.ù¿ooŠ#Å¿�¾úñó7Ã×o?þüE8ÀÔ¿‘ART€�ƒƒ•�ƒ�•áü–F’pçá+†¿ÿ28¹š0HJ†þþ|5Ü„ê`pýZüû„†n.v#yA>.~.’ãùÔ¼_¿~1°° &;€bAWò9Ù0ÀÆÊ )&À ry™ùáÃ'†ÿþ¡ÈZüÇ=8$�JˆòÀu7É…è§�Ÿ¾ûtj¹@!ð÷(P£ Ð͘A_SŽ�<Ü$;äóoŸ¿2ü&Dô‚ €0!ÈrX�Á@]žYyܯ^}`øòé Øìß@ G@¡†8þ*þ�Û^‚ƒìÐÕÿ¡4È�' âÿÀ>ú—ûçÿþý›áÍë _¿þ&¾?àrã– Ì\ð’Aôõ;ÏQø¡ ™†°!Ñ tôùÓW†¯_¾" 0P�rÀïßi €0£üá….‹þ¢9¿_¿|cøöõ´$„”¦3¡üߘ!@˜QÊà(ø‹ÕÇ�óóç/0¥îŸÀ n1ˆþ�°æ±ßÀ¨@w@± gX²DX�çÿý‡Ó¿€ýø´ôûVFVvfF.Vfˆ%¿ÿ"Õ PK�ôƒ'¯ÀÑð Kf9õ( \¬µàr ñoÀ"äcHQqì_$±¿ò=³ÖC†™ ˆ[‘‰^�‚÷0˜‘ …á¿ÿB‹ð¿Xå‘kJP( ‡@aä‚?Hñ R ÉF¿±ŒêÜò`ü…D º{@5~ùò�áôéÇ�ñ÷/Œ ¼¼ì@þoxË Ý„ `úòå¼9õáÃw”`Ejä¨AG°98˜¡µ,vF"*À†(Ø@e¸¬,Ö¬…žp%JHÂþÃðäP, Tü2?�…Íxarñâs°ÿþ!í?´PA„¸ÀB“–æ'@PaTŠ@åùo°ÏC* ––æÅÈãÈ>FNpÈÁ�(#þ€Ó¬€C€ÂȆà"œï!i€�� Èþl¢Ã0#3A}c``c�Œýÿ?C¢2`QÀŒâ€BqÀ¯ï¿¾¼}Ïðéù+pb¼{÷Fÿóç–Äöky‹†¯¯^€«á??€Ú¦ Fô 10Hýÿñãpà‚7Í@ê ˜Œ¨|]ìåË7Põ âþJ¿ €ºs @Þ7 w@€€pï ·„RIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/filesaveas.png000066400000000000000000000040251506556630100214220ustar00rootroot00000000000000‰PNG  IHDR szzôgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<§IDATxÚbüÿÿ?5À›™Œ÷ÿ‹å)¼½õ”áÕ™ƒ~}x3Ñe÷ÿ„ôÈ”â7~^æûÿÿýæÿÿ?Üùÿûé¹ÿwgåýßíÂÐOH/@QÅïæ2ìÿÿšñÿÿ»ü@ÜvC€O/@±€BaÝú#ÿÿþÃðû×_FF†?þ1�ÿA£²ÿ€Õ€hY¶ þŒÐxøÄÀð¥œ�áV?ÃO{ΧçA¢ðÅ@±¬_ô¿­½>ÐÀ ÿýc�‘K\¾ùE¡®º V¾OdàP2¾ñšžÞp%®0Ü~+ÄÐö¯ø¾ #.Ëo ¯~üüÍðõÛO†?0õod�`àà`eà`ge8¿¥Có¿Ïþ_á¼fe``:àÐrn†ç>0Ü”Žgp’–a�” ýÿüùj¬Ž P�þZüû„†n.v#yA>.~.¬®ÿy¡‰�Shîo�¥@5LÞ �ån“cø¨ Ãðëù+&œQ@,àøZ Æ@6 °±²0HŠ 0€À‡é€ÿ¿>00±lc`dçd`xÄLÀäô‹ ü ï_f¸Íé öÔ‡Ÿþýû‡ÓÄJH ¸‡’B Q~ ø¡àÆôýÅ ¬Ò@Æ^ ¥Üß²™Ùž½åfx©ìÄð hù÷o?€À]Ö8þþ…jº3èkÊ1𣂇›Ã÷ÿ?/``VZøšh9ÿec`ø&LOßÝ‹>œùÄðíóW†Ÿ¿~3à+ìœA–âêòüpjús»Ðòÿ@‹¿‚Pß'Pà`xx÷ ¿¿×}k@fÿ:_Ëp"üTü·¼Ù?PA¥A€<ÿÇ ú|"Ÿ0·¼‡úŒ ˜v¾ 1üøþ•á«%Û}ç~ýú.7~€b�Å=8*€ôõ;ÏQø¡ F+üÚÆ o LtŒ@�YÎöýÝëvýöføvúÃPÁrÀïßxÓ@A¢üá…ÌBˆ¥�‚¥�ó ,ÀBéËPII|ß„�ò¿޽”døÊÇ ´ø7Ø÷�’$ @¹1|ŒL‹ý=Ç « 2 äûßË¿ó‚CãÑ…+ 9üÀ>[ õØo`T ;€‘Ñ�vÿÿŸÿ @,¿aå´ äÇùßÿáô/`IùãÇ/Ó?›Xå �–þ&@`á ÌûøX˜N=bà–‘g`Y ´üÁ“Wàhø  ¥Ì—ƒ1Ô!¬) A Šk-¸KAâ߀EôÏŸ¿€Åî}¡¯‚ýßÿCŒø 4ó?/Ãó+äƒËdy%Àf€<Ó3k=˜þõëÐPt1ˆa‰N€b�ù½ ú ôõ7`!©ÿ1p=�ÍÀbl,í~}ý’÷ÿð}ÏÂðàÐz@ËC³3ÿüñlÆ�ï?ð¦€ç‚?Hñ Rüõëpö�ù„9¯•«}ÿœâ@)û?Ãó §~éF0üû Ér_¿~ãï@‹aå >"  }ùò�áôéÇ�N”�rPe`û,rÿ|:XæÿF +ýÇÿ.‹J2|qèãŸ`õ22‚àtðÚ®Àç€b�Õ‚ úÐç?~üf�“ã‡&Ê¿ð(ø ªãÛ00°ßFÃ]pZxÿ:Ãs%. [ØÙÙ�êYà�™¿à(•²8ªù¾ (¥‚‚ÿû÷Ÿ ß@ÁÔüáÃ7x¨€Áúæ$£(0ï3‹]6 0þüæ:ñ­«^éd3üùòR š‡‡ lñ_p=ƒÀ,Ä𠘿ƒ8Pp}ùò ÜÄ¥‰¾£ÈöØX‘‡›ðùÁu†½³æ0ÜQJcøûù'RTýÓììÌà,ø÷ÿ_äYøhñod×8‚ªÌŸÀìJÅ 2\V–ž&@øß.†}®2è±(2p½¸ÈpùØY†/–Y ¢Ð¬ )xé Ò þÿ :œ³�Ž8ÿ[< ¨¶úÌ2¿~þ�66ÿ0\¼ølà?h�Àþú-Ãßï¿ή˜ÃðùÃK17†?·_C *¨:ä�‘æ ¥ Âú(ªq'B€bÕ׿Á>ÿ ©@€XZš%þûÉÉðãú †_R– ÿUDþ!Jο(Y�X,°0°²2� ¬€Ã— œ ÿ@ó0¬ÙÍÆÆdƒŠOþ#$ ,„¢~‰h3ð eOp�,%A W&`Á ~HÙòœ ÿ‚³!3NË/`¹þåí{†OÀÆ#(1Þ½{)À|¤™Dþ¾~Ž$ŽTy¡«Ò__½WÀeÃÿÿ\8@Œ à10Hýÿñãpà‚7Í=x0¢òlt±—/ß@Õƒ::pö ˆ‘Z�Sr@11 0 w@€{Ö(ºå)ðIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/formatboldfont.png000066400000000000000000000025271506556630100223250ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœùIDATX…Å—klSeÇŸso»v]/ƒµ0&ŒlLA2DW)nUƒˆ~jÔ5ÙÅËÔhæt?H‰ü 1QHù`ð¶„^²l& R.Ûº9vkwm»µ=—÷}ý[ºîœ�•†'9É9Ïÿ}Ÿçwžóžç=à5{â~tû±øÒ²�˜€H(&>7‚dÌH¿F³A( Xy”Œ²‰È€>í†9 Í~¿|1vöÓÌúIçz�³0é¬fÌ+®'Ã7’¦j¾ëþb °–c5æ±KÌ’~®©a¾L¥¦ßooo�g&Ÿ_·ÛHÓôRãB…åë/z^[QM«%[vå'(‡@á��ÈsÂDÑFiÆT«�Í›ì•+Î4 šfz·ƒÁ4Ò­®®Ž¹l(‹]z¬É ´âÔ~0‡ŽŒF#�Z @ïu<¸»«j¯ðF.³Z¬8-W¶¾1ÈM\¹7³´€×ëE:1>ª¦Íš ÄçóEƒÁà¹`Ðÿ¡c´cÝúÖ=S€•ÌU oä:7~àäuÆÆLM°,-�i'OžìÍŸêz­èš_UŸÎ_Å�;\¯{<ó-0×—Ú2›ÍvÂ2riéá%.cüÈ-dc^¯Wĉ1-}¦`•¥9ÀÀpZ…REȼG{[\.—E29­Zºeâ’4}6g<Ï×�{T×…%ìè;Ñír¹:Òý¬Úàl¬¶¶öÉ�âÇ›¦ìëØí¬¹p€˜’/76™·¸³à8nemm­‘râŒ;ÿ.¯ÛÖ[ö܂ԺDXZÚ/ÙF¯óûý§2õ¬ÆU ꬗eÁ 3¦eʶ–ÂŒ€�@# ¬‘sàè÷I¶ÁÖ¯i@�þ@ ¬++€ÈŠ-)Þ2ÛnÙ¹¶{Ãòâ}`šº Üô`Š!x’bhA+VV+/|Ö�߆dV'Èz‹uÚVA�,Û*Ë‚…ˆ”AÜ\½å/æâ»Kº�¾³µ†>H�ø^KKK*=VVo�.ãè…ÒÐÑOí%íúò?¿x¸úçç�—t[06‘·œï¬ÜMÿQ}`—¢_âß¼y³>]ÿßoAss³mÐVƒÄv™Í?8´rÛ‚‹ZîæÎoÚ[uû[ŸÀ«³þÛÚ�Àç«:�œ£ˆ¢º�L›WsCw=õŠÇã©È !9Tind׊Ÿ BÏä €¦ÏäÇz4m*¯HP8sUÎ(Šç¤Ø¢cdZ_�30+¬A[ň°(6œ3Œñ1s¹¢¥›¢É,J¶Ýe×ÐÐ@'„¥oOUjÎ]Þwœ€ïn@3ší“P4˜L¦Ì¹Tk믟\ݰk-¡Õ¸ö‘ÓJÑPà£@Ú¾ ºZÝn7;n°jD­å$yå‡Ün÷aAòE©–Ë»+ßÜ4æ|ˆY¸ØÂ§PÅù½ßÛíÖ}éþ9€_«N„P!0ºú¡²í¼Àðê'( £Cã�_!FQk9‰8·`Ìè$çR“ri÷aÚÑ÷K“ÝnýØëõÎû`™û1qmÛquà¾gKe�&œ itdók@3£)K$ÄÛ†Û䑎oYJÙçóùzÔnf® &§mý¥¨ha�?©VÆ9ËÔ0M"KŒ›Ð'Ã}¬œ Šê0 -?ú›‹Dºóö/­¡Ú±ÏáIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/formatclearformat.png000066400000000000000000000031221506556630100230050ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœôIDATX…Å–il\WÇïÍ›7ófËØãñ–8©�–ºn³˜¦JqKpEi!$ �"µ@’¦ >P H4R#ñ…µB¤+¥{L¡-PA uB!‰c—&¸¤ÎVÇ©íx’x<Ë›åÍÛ._f¢©e§ Y8Ò_÷^�{ïù½s¯Þ=3ì'«©óIò§LáN|»—¿Ïô_h“ª�ßC�&ߺìª-FÉH�~ëùµOYß¼˜òûŽúpÛòî–´Àã E›]qߣ_ó®¹d’u®�G Ö"\‹úúFEÓj¼d®+í‘…ëJ'þŒ73„1}Œææ ^£~á’¬ÆÜtôÐ�#µ ;°‹)"AO0àW¾uI$¹Ì©»ÇÇÆ&Õp#B€‘M0o^MûÏïdåEèy�½“c#›uÃ[²PÉéü~oƒOQzv¿¨~nð·±  `óöß}÷P¿-G(Y³¨£Eéx¥a[ÓŸ}Vñj_¹PÊ\G7ï~ïÄd_MÄ×mq¹úêëÛZ—ÝÖ¦ú4ô©ýÒ\ëÎÕκюG¼iuóÐqÝgä`4Â&—‚çïz,{b0U2Lç{?ƒ__p€7¶°R•ä͵Ííõ-íZ0G¸>Þxä?|ù(+ä0r&ËïÆÇG~,Äâó˜õ¨.Y–cÞ€¢²Ãüûûøåª^Ô×’Ü»üFÔÆró¢i©':Ыl<€9�`ÇÓDsÒK{µîhÂõ|,ÜH¬©‰£X¢z”[7vIW~"Hr*ïŽÜqØúí×ßÁ± ðê†%A T[þ -–}µ[ZÕ³�8Î8ºžÂt¯äÄè¿…é±{ºÖðÇs˜õ*&`oœ½!ì‘kU6ô­‘>ÙÓ"’Çõ`÷PSoŒµt=Ý¿…oœ €çlÎkàõ4X×}_ÉÞöàê«BÚa\,³„&ŠÇÅ(dp]C5 ã7ÜxÇÍþ§^ùpµÄY3ð~ ›bí"åX:–•E–²¸v ÛÌ“Ïê¨>¯§�B–&" —¬ýî®^ï£ç pf’ëN›¦…aNÇLá÷ òz Y–p¸v_p1¹Óo"œ#Ú¢¥ë× n�ÿfÏ“4œ7€ãˆ·�B£èP(d�ÈS*L‰j$'§†ë° מ X³œÌd?Â> 4·¯ÿrhÑG·ï~†9Ÿó l†ózR7-‡¼žÅvJèÙ/àñŖñjó± Ç:N¤¡‹©ãƒ˜zŸÔ°xÕ5õ_ÜÜÿ"OüóW„ÿ'ŽÛfj\H5r9Q¢ ëX¥"‘ØB’‰ þp»Â2§qìqâ­7¡Ÿ>L&ÑG(kjéüúZÙ/½v®*ºá.ìÔÉÑÙÓŒƒJ1ŸEVƒ¤’ÓØvšhÓRÒ‰#D›—RHKXÆ1kŠØÂ�ƒ+“ž<Àé‘�‰m{Ä:@«Ž;€„€0"û‡yµ�>iª�ËÉë9<þ0Ùt³˜@‹4cY>ìÒi¢ Ë(f¥üŠZ�/Úéž<²mû;<´™byÏ0à‡ÙÿÞ2¥Vž¤Ú¶]LÝy«ýùºù‰ä§GQT ¤Z,{ Y  擞ÜG¤±!\»žéä!ýí½;þtû½öý»‡8iYHpFÒl¾rêÕr¿"ÇâœÙÚ2o¥ióùƒ„ã+HMŒâQóø—c;àñÖ!{/sFßÙyj`0¹uÝFž°,\@Ì�;gARegÜÿ#þÒÑ6pKçÍ÷]›N¼I°&E¼µ›ÔX?ÁØÔ€j�îÿ½ñzi˦Çù`Ìô}6Ûc¤”Sï¯|yu&41ï¥_Ä_híøR]>} E‹9“#;sút2ù×]ÅW{™Á|0Ë*UµF¹­ô�¹^CO9põ1TŽÅûé›hîY-=`–°ÆO‰á­ÛùGßS•´`V•f”€ÒÕvJuà*yÊ>¹¬ê}ÜU *ðõÀ “gÈå¶úVWT œrp›YîÀÿÝþ ÿ §‚1h"fIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/formatextlink.png000066400000000000000000000123711506556630100221720ustar00rootroot00000000000000‰PNG  IHDR szzô pHYs  šœ ïiCCPPhotoshop ICC profilexÚ�VwPÓ‰Þ_z‘P#éU¥…ÞDšt ¡j1DTÄDiJ¥( *"‚X(F@QAQ)*EŽ.ÈQòþàÞ»™7óîÞ÷×·ßìîìîìÌ.Ï ™N§¢ ”Æd8Z˜ÝÜ=ˆ¸>@@D` l#SÂ鯶ð?±ø€·Êd:�¦5dZÜ’7\äÍ&}j…¿ÃÍÝ!>hƒkÞoƒ[þ“Î@¼O &û tPb8;’�<àÚà·€ßoƒ?þJéÀn¢ù‡ÐpŸÐüþáîȦÐLžs`æÀÓònîÄ�2=�h>ÀÞÿK gÜ'H,ü¥Éeˆ ܉ùK›wBgx †: ¼&ƒlö¼,.`-�Í^)b³×ŠÐý�TÊQFÄŸ3BP8€²7úühÀ)ÍÃÇg-,ä,ŒÂ'8DüDooYÛ&'æ"N“ˆß~�˜»#K2G*^:V†,k-§$Ï-?¥Ð¸3W1TIO™_¹gW¾Ê!UEÕ9µZu¦†ŽÆ¢f¥V˜öNía�]7=~½Vý˜Ý»'öìu6à5h2d)}1Î2±#¡Iu¦ ³ífOÌ}- ²E³¥Œe¢å´•�U¾Õ´5Éú’õ”�™Íe›Y[+ÛBÛ;W»&{ ûÒ}bûÒ¼÷«8ò9�Ó¢óœË¬ëâ�5wn�­žª^–Þ�> ¾wöú¡(jþ”€œÀWÁè�=‡‡Ë©ƒ´Ma&tú‘td”ñ-|‚ùãè�ˆñc#‘_¢ú£ûŽ¿=Ñy²=†uª1¶átÍo•gnÅ݈/8{9!ûÜ…óI‰qI§’£RÂSi‚/RÒ¼ÓÝ2ögÚf™gç쾤�«vYéŠ\žd¾ÄUÑk›  yŠpÅèböõ•K% ¥³eS7'ÊÇo�Ýþ|§¿¢÷î«JÖ½†ªªû%Õy5Ä×F= ­#×»4X?2|¬õdçÓ�[š„šyZ°ÏP,`±[‘6ŽvžÂ/‰ʯŒ^»tÒ»RÞTuìÁõj½£¼Oë{úaê“x¿Ý@Ì`åÐÈѯû†FšF׿í�ùþl‚oÒã÷ÛÓÈŒÏlã¼ÜBî¢ðRÖ²Ì-«´uE6ÐÀ  . ¥ð ! nH2‡Ò@9£"Q×Pm¨y´$Ú}Ý€^À¨`ü0)˜:Ì8‡(‡ÇIŽ*ŽïXI¬6Û†]Çiáh¸›¸QN)N?Î"Î.y®P®j®Unsî4î¯<k%k�ë*è©è«ê¯ïîÜ“¸WiïƒPƒfCQCšás# £H£:£ŸÆjÆ4ãÛÆ?LLBLnš “ÄH®¤4R‡)ÎÔÔ4Öô±)ÛÌÔ,ѬË\ÄÜ×¼Ô|Æ‚lÑoénùÞ*Íú– Ëö³ÝÊ>‚ƒú~GšSŠó—N×Y7¼»®‡¯g¼W…wŸ/æ ù _å™ÿ¯À]A�Á…!‡Å¨Þ¡´1ºò‘HÆ3¦ðÑ€ˆºH�¨�hÖ ©“gbÆbmOWŸÙ—¿œr®?Ñ!‰•b�ZQ7­>à “•í�3˜v�wùªæµ®Bz±ðõÚŸ2ΛշüîU4U2«dï¬I©5z8_ã‘ëާUM^-èg¥Ï-[GÛO¾ÜÔQüZ½³ñ�]÷Çž€Þ™÷Ñ0Sú ׆ä>W~Õnµë÷ù>>>ÉžJžÙ:{s^¡cÑwia9iEfµq݇Íظwh,@N€ÛCc€äÍòe|Îz€<™¤– ±Ð ¨ÿ\Ѐ> €h�=„B´"Ä)Fq¡bÐt>ÆŠƒ“£ËÂ5sör­òèðÆó�8 ñàq"ƒÛz· —L—V“y)wP~vgŒ—rºŠ˜j™º®F§]G\÷ƒ~ùž ƒ\£§&‹fzç­Fmíì›÷“œÞ¸vòdùÄ‘ü‚!T6�;|G„YTĉªS+g¼Î%þ–j”NȆÜ_ù«E˜Þrþ ̽±šŠ:—Go··xžÙÞ÷J¢+ðmÅ»ù�š¡Ÿ¯7�õ}˜|=]6ü“{)iy|U|]–Íp�0H�.ì‡#�ÏࢅG^ ¤Q‰¨t4‹)à°Æ¢±¸œ¸ÎsgðTð¾çp¬Üäˆ×'¸‰^Ú:,.¾]–øM²@ÚKv«Ü'…Å`eM¬ê€z½f�vªîYý¤=yOŒfH»Ì",Ú­emS÷ÁþÎ(× weÏnŸX²e%ðyÈjt™áxÔ6rßq�Ú餸ú„•$»ÔŠt±¬ìÜ-y× 4‹ÛJ½Ê§*¢ï±k¢Ž>2|z¦¹�µÜnБÐùö-ñ]臇ýìÏÆÃÑcåß_M~™�ëýy÷WØ ~í › ™(=Ì]\&÷1Þü%¥‚ŽB to“Ÿ°€ð¼ þÇfææÂa ˆƒH»¨£è¯-m[{Å´$€è!á$£IÚ�eøÓx–4o¶jÉe½ÍVÕÞÚ!Ð1޹ĵÝmÒSÈ[ÛדK¹Ð4qˆ�º‹fO§2™¥-‘ƒÑœ$œR?ípæpüÙ„«çk’^¤ \˜J[ÏäËÞvIî²fžáU›‚E×ÃKâÊrÊ+n·WŒß㻯WC­-«›zdðärº…Éšh ~1ñ*¼ éÎìU|ßú1h€g¨ê«×(×·º‡~Ÿîš‹û©·4ùǵ56`ãç¼-É”H £†1ˆ25Ä�Aöû÷¾ãÁH` D @P! @ �� !à ƒ?„ýSšÿÌ€H&)ŒÅ f�étjÑŠFÙ¥DTWUÕýûø�Ÿ+�ç Ð(ûß~ÿ×±š¼$EöügAMAÀ­è¸hV cHRMm˜sŽá[†+|(ÎF4|ÿéÂp tIDATxÚ¤WkŒ\e~¾ó}gΜ3sæ¶sÛ�ÝeZVJ„¡Ð-ˆ"È^þ(((—”�" 1�ÁD�DÑ_PIHŒš@Lª‰ XÐnïKÙº´ÝîmfºÛÙ�ë™Ë¹~Ÿ?z¶�ݪhýN¾Ì{NræyÞ÷}Þ÷ýÙ¿?„!ÆÇÇ% €€~ÔÒOrÎ×rÎ�Bþ`@åºë®³FGGñïÖý÷ß��ZL± L0„�õŠ¢|›sïÊp8ìöõ%Y»Ý¾}qqñÛ¶·Bö�ŽŽ.pð,æƒS*€€‘@ ðeJéÝápXêïï‡,ËL–ed³Y�LJ'&&~Ê9€ €_0�ññq ê‡z‹ª¿K)K æc2\×E­VƒmÛB"‘ ¹\nøÄ‰ÛƒÁà·˜:ÄðÁ×éºþ¬ëº›u]—úûµZSSÓçÜК��MlÚ´‰ ±………›MÓÜB)m(°/„€ §ëúO,˺>—ËI9B0;;ë‹¥ª$‘ç)¥_£”n#„öîÝËMÓD>Ÿ‡çñïXç –^ÆØåÍfsc4eŠ¢@’$LM�äÍfó€ã8÷ �W¼àí@ ð”aîìì,‰òù|¢^¯o0ìkè' (Ê ¦iBÆfff¼z½ñªã8Ûì0 `À)BÈ�x<þâ‘#¸­V ùüE4‘èÛhšÖÆ �㜎ãÛ¶á—¤$„˜óA7n´;�ÆÇÇMóŒ±7u]ÿüØØØE›7o&kÖ¬‘öïß¿5TÞPà-ÿùÎ�;ÿ#¸R·Û}#‰t ÀišH&“BUÕ/HP÷íÛGEY~‡p£§º]“[–MSHYAä£<B€s~vK Œ± Ãð�¢Ñ¨”J¥òî� }:›N§µT*EÂá°�Ç¥P(¶mû¦N§ó.€ºmÛ&¥T¬öül<ïŒn²Ù¬»°°Pð¾¦i÷I’ôCÃ0>^¯7dÆX- þ¡i›>¼~íڵĶmhšŠr¹ Î9!H&“PU•d2™d«Õzêoúë{[Zuƒ�DÀÃæÏkD®ëžU«?Pʬ`0x_0Lø‡@<�]sôèÉd2ð<ºA±X@©d™„gnnN]¿~=‹Åb4Ó®Ó[‰¹;®¼õâß�øý!.ñç< ¾¢‹E”J%”Ëe!„뺀%“˜ÐÕ4m;côŠÁÁއeY°máÝn÷u×uŸ „L���ñN§ƒh_„p¸ŸIåSD�"HÀ�|‡ÎâLcè†iš¼ÓéX~9É�@àNÃ0.Îf³ôÚk¯�Ñj‰‰�ñJ¥ŠZ½Þvç×vqοoY–577‡�¦AKk²éµé“7>rÖú˜Ûý)¼< 8XMÄO‹ âºîg�cŒ¡Ñh 5+(î²Ña;ѲíuímDI²YPiªKG'åÁ\¦Ÿ\9²–0�€KOÞôð§üî¯ÞAÀ£^Xq&\IälÓ ˜mÛ:c œs¸®ëÙ®Yt.ov½éë’z<ísЃî_<8ð„ GXgB-Qö�¿yÛsïýòM? wø »÷Þ{W¨rÇŽ+º)€cl²V«õY–Eb± *Ú:É£G]ÙTæÝLtࢇÄ"\œ8% ‚ô‘¾zë‹e—?kv2BV°—_~¹÷ÖóUû Îù¦z½Žt:�t&¥«EýÒ’[ ma )š°„åð/qÎ>C€A#âR\zðú/ÞòÒžßþ€ÌV•%yà�VõA™o³e»R©PÓ4E__ŸˆD"KÕjõSZ8Hj¡y e5æà …0àÁ…-L˜Â„ 2‘‘4DºúÒÑÉÂ8€Ç,-ƒI= çíJ¥B !"�;ñxb}q®˜Ñô ™l–P+qØ%R%²�‰€¿¥‰ÀÁ¨£ÇÔŠ’¡°¤"ÉbH[éêì‰úÛ|ß[yµ×=¿€äyžÔh4D(ò‰ø ¹MíÆ#â Œà \B¯BÞ¹ ‰ê0j‡ã¹CYeíÖÓlF¹$§çµ¨’²ûÇ?lð{—5Ö~Ò£�ó–išœsî$ '™L–J¥ù[,Ë‚ëº0 SS3¼T:ÕÕõðs®k¿T(&Ú—,lÚ¼&Y†ÆñöXqÏؽúËHøå&zlÒ³— …‚355UŒF£oö÷gŒV«óøääÔ¥ÌVÕàû±Xägõz}òäÉ“ó‡j_}gF䨥äèÂlAp±ƒP²kµcÄ�Y¬:ážµ¤-[¶GFFbÑh4BBÏ4Íz»Ý^oîÙ³Ç*—Ëüž¿|â5"A#„t^½å�»¾òÖÍçZÿ9ˆ5;©"×ÍIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/formatfontcolor.png000066400000000000000000000022121506556630100225120ustar00rootroot00000000000000‰PNG  IHDR szzôQIDATx^µVMh\U>÷Í›7?™Iš˜!Í$QK B*.\t¡"»PÁ… ¡ÙÙ�‹B»PQw‚¨`)Šˆ èB¤7Z J!iŠñ'RÛÄ1ÆŒ™yó2ïïøÝKî0ŒãL^&=ðqî»÷ðÎw~îyOübš¯ÄŽ}&ˆ Ã`"#d¦x^¨ÖDÄЋÉ3 ”A Î�´[.þ¤ï¿MĤtz²çôéi², J%ª­¯Sà8òÅĦ)Ò##nH>‡¾O»·osP«1 3F&C â~­FÞÍ›?RD1%{¼[·¨4;û¦ï82‘•©§çõ#¹Ü9e”——ßõçä½ÈÉ0Th"jɪVϰˆÎÀ lûç�k׿™y©ù°î˜Ye@‘i�åë•BaÎwÝ•ÈN¸î[ÐÀ%Ô©×= É´°{šyê@Ìv‡õȱ å:I¤[,�¨@:�¡ bÎ>%D¦LÔK݉ìöБ3«ó<º‘HÌLœ<ùâf„0 ÁÌlbèp=Ï«A €Ù—ta@¤ C²kkkì«€"/„ácŸœ´îI¥huu•WVV~ßÝÝývS©Ô½SSS£X+{¤ïض]‘d<Îçó#¹\Žj\ëëëÉN%P‘ëa¥µ$³´´äÌÍÍ=“+ØS½™Éd.àůê+‹Hissó£J¥r� aÂé ããã—úûû-f¦ýe@¯‚ªÕ*-,,¼ÏÌ_Q“€œ&© sŇú8�N?”Íf_&ˆAm¤Ñ±ŽŠA X,R©Tú²É\;ÖPö­¦³ã8ŸîììÈŒæ>h­œÇ+•ï¾½zõ ¶ô‡§SZa¹P(¼‚?t$£ºv˜é±0üæ�Zí j-:j¥5™™ªB]ì< è—6ÔôÿJ 5컟„ {I®}@K‡¨[Àmí;7!ë�QÀ¬³Á�2 �wŸ!â̬kª1Õ)°­rð Éä4HPÐpE"1}¹ÍwÓO—A"z¾â¸H&_–õp"ŸT:­çV.÷ˆÇ<Ù²®ž÷Þ ó¯ %ÐQœ"žHö÷Ÿ#Ë \Û.‡aSCš™ÌÇã'½ím9 íT—ÏÑ0󬽱1ªP_ÅÀ¾€ú«U#ÏÀsÌÔŠ.:r­£ˆŽÑww )zàð³ut!Ä€î~�칫�½@FŸ���S?�cï>,׆„‡��þûmxxøíX—¤îZéëëûDž½=Pu]÷þ�Ü­­-¯©ñÔÚ0 : üMMò/_Ÿ¾ñ·Þ IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/formatfontsize.png000066400000000000000000000030601506556630100223500ustar00rootroot00000000000000‰PNG  IHDR szzô÷IDATxÚí—{PÔUÇ¿‹¼vQ�R"Y%•— ”Žƒ¢! Š`8P2:`6£Mêd(J”Žƒ(ˆ •ùÊA¥ ƈ >Q!DyÇòXö½�ßîZ fÐêÔÝ™ï?÷œß½Ÿ{ï¹çÜ ÿrc½‚1Ù÷U¼ì™ùþx1gE r°´?!W£g¤UPôgCÖqâ«•Ô!Ä_ÇÀ08�^dŠ õv´°xI‰Yho­«„œß -£qN®oGG‡‚ÏïGáå œÏ¾†úºŠ$scèë6’äŸpÃ}}=“6¬÷¿»aaÑ�ÛÏ\€BÐJÖR´-í¬&û®Þ±3Ê@ TÀx YYEøîðÁ“åo%ŸÆç@ €àKf¸ÎÌX² mí}¨.ç!ó‡ýeßøš¬yꀀ¾w¸³›GÒLw{ÈårÈd $%¤ö@x6…¬§H¥ƒ/žæäš°Ê_ p¿’‡ŸÒy°›¬H­ÃFCÇî}° ýižÑʳß(Q¯žsœajj‚šš_Á»Y;‡‰}îsóÚaË‹–ú \ÊIÑ@Õ8�›‰egPð"XX˜¡¼ü>rÎ^Bú  òÎG�ÖÔA›;‘käïµd)ZéÚ*Qp^SUN ~ÏÒw黨­kFì âÞ®ÒrH*˜|ߤޅ&èºLáÚÍßóòhr7ÇÜÖ ¹C™X€=±{»™…P«È㩚ԬŒ ¶Ï<®­cÆË`/76=¦nwü&£Â_š`?Å qÑûÐñðX¥V& _"Ý!uâÉUdûG¹xxÄÛ8ºA(’iÀY±%`¥OŒõ{Ü©é›Õ�ãGâ[ º˜FÖIסº®á²xoßEQÚF–ÐÓÕÖ àóíQž%w”×õÕƒ®‚øæ7dÍ"ÕàéZÏ äEn\ëPXú¬ß2Ö  èã�á×*ÊÁîݺŽâ‚oK )O$ëyõ¹Šî$ë\æü3rªááÓWQV‰Îöæ.HnW@Z}›Ì ´{aöÓݬŒMŒ•þý‚~°9l$q2ù¥î+  -¨ ‘t]C¹íÕ-1I@’Bz¯ŽVÕG>$&9ÝS;t¦EЊíé*`,Iq1SE™Ì™Oº6¦é‘LHãIo€yÿ n"õv6«“yõè¨ý­”GÉ1UëSîSIUÀÃú/ÐQO®ûT?“ûñì?s„l¨*é“qÅjÉP‚ðeµÿìÏésÛïYzÍ?ÑÏIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/formatintlink.png000066400000000000000000000034521506556630100221640ustar00rootroot00000000000000‰PNG  IHDR szzôñIDATx^ÍV{lS×?çú^Û÷:ŽóÆ�Já±V¤°Õ¶, ¶2ªB¥²2˜:êêÖA¥ihk5ÚUh];Œ“¥-P²tI`L}ÀJgíMJ(ÄqœøíkûÞ{ξ?ªnS&4õ“ísîýŽÎ÷û^¿Ïè -�7ïæ¶noÖ7no–6o}Ü`k|L÷1ü½}?Éú鯎îüMk盯žï~µk`ì¥7Þýç¡£ÇûŸÞ´±¡ÑòèF¾¶þã’Ï^¶`Yõq1;¯œJ5J1¡ið�”­Þ‘}övì“CÞ gZO)w ÀþŸýrYÅŠG:1/˜ £ŒšXÓ{4¹ÆcrØy¾eWÈsËî°ŸŽe €Km¾ûäSYåK«�#��­j«„`U#(ð†ÜÃ×nø=£žáè(¦:CÖÜ•›^DóŠÚºúŒkƒOmòŠgÙŒæÜ¹Ì8Fgw{‡ëú'@=ÈΚò‹,ûê#ûżâ{YT�`Ì*ùÊ· v·öƒþÊT¶lÛÁn9÷æ+=“—»¯Ó£o]#»žú¹½¦¦f^mmmÚ;Ø P|O·ô >ûº“|ÍIžéè'¶íO<ÆÎeœMUx)wÚB•°S†°�&<¿ÞÖÖ¦¥KæŠ1v~zùüA8FSµa.™¿Ô¦ŒÀ]<Á:Œ#…ôŽ�³°···Oß±{/þá³Ï×,_Óð^Ð/º†Î©Še_¬Ï™VÇ, šJ¢‘°W… �Ñ,}®>¬3kî¯\{Òb�µôÁuMv^0Ü]%4Ñ!˜72ï wÅëîcUÏÒ ˜ó Å<ëòÚº:Á¶y«~Î’ªÃÂPÊ)ºgéº�Ç£Q9GÕ4ÄÚU�ËQæGÆì­'5÷`3_ÊÖ™Ë>  _RU…^êxyO8ôB‡°QÑRh�Q˜�Âþq htâö0¥(tGDT¿a“eî7·ôˆ%„NFÉ>÷�ëý®ƒa×P§hÉ«ZòpÓK‚ÑdNT(¡7GÝtâmÇ�¤ý¾xö‚ût‚¾TUâ(ù=#M žjùƒö?ÔÔÖa£¥`eÙêm¯q¼1‹0#ˆ‚ ¬©ª¬Ä"QÂ^:½ëx!ÁŒ  z=±ÈÐß.V|mõR�^̆w8IÛHŽ„<7œïØo:ß~N�Ç>a‘ž’Škëë)Ʀ’¯o8‚õF3Ø ìBX@h40�K¬V”1©'J Yt ²ä0¼ÿ>;p$èèjÝžp�=sº56å0‚Â3ð’eEÑâÕ‡DëœÅ©”„õ{hqa¾ÆL<`Lè•(2s"·ÞàäAé9¢Äb²óÜ+M‘ —ÃqÆ®ü7iI²šU°®–¦ÏHÈ)*Ç�| Z/î߸0}î¢U¹ +¿A9NT¢t¢ï­‹X‹ d̘5mÞ’JÎ e�DJ‚^÷À¿]C”ø•¶6M˜B€ŠucS’d ,â°†ô¢‰VoÙmÜëËb SŽŸ4À>²oôÖíž�$.÷ Féþò•¶#RaÉB’¥däj÷éÑþÞf`Ø@@²çG‡VT¬ÚøgEQ¨{Ì�CX¢,É@à˜ßýÉè…“u$&_DÓó×îú§- @<ðýãõç«ÛŽ÷<��p¬Õ4B æXΩo çJ\ù“ÔLo,À¿€•¨�^õ||µ=5;8Ñœ£7繦&1¼øLhŠÂ 3cs˜ÊþË#½'~]TÙð"%šÞsñÔsšèJέiö¢÷àì6 ±`Ê-‹<<ÓeœJýo`Cë–Žßø°ÛÝÛbCD+Õ"þ³`Ë•Ž˜^”˜÷”&;#8ã„€áÉè R>«ð¼9‹+]]¨†}]ˆ–n3ÛÎïóâ´{¿CM*RÂþ1P‘Œk€-8òÑe;›œ*aóX2ͪÚp†bx›>×Ðü$Ÿ5cÞ^CÁÌ*-~—ƒa%0æ„G5ã.`²¡¡±¬ü¡y)»¼J’�ì÷ öµÇãïqQ‹f¯5–V±¼'‰Œúz»]j‚( Þ€ºúGuÆ\ëº{ª7Ã:½ÄP”¦î4/ôÙsÜïö¸»�íFDý#ˆgœ&@§š<1rv¨ëXS4äs³"K¶a’~Ñçè8æs{<—ì¿ã�)ãGàó´]'`^X”S¾ìæÙ|‹õyªØXLT9 ^y'tíÝßQMé„Öœ˜be&ëׯÇÇ™áº2HFgÊ)ƒ½ FücjpÌ hþÇ>My~×L1Èxvwrv¨à5A_Tù¥ ^Â…NxyIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/formatitalicfont.png000066400000000000000000000016701506556630100226500ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœZIDATX…Å—ÛOÓPÇ[ÙÖnm7:Æ6PœQP"^bæ ¦‹!šyõŸ}óÍDå?ð_0êÓ|1N%A1xá6dMprqD¡l]7ÊÚ]Úú F²ƒ„NOrÒôû;¿ïï“ÓüÚ€ÿ< Zü®2†’xTCy[ òz!£q¾—"ápXÞ®Ñ `(•¯ç¨¦‹yG‹Up¶Ö–kl*üœÊú"eýj—'ÖÈÜ\W>„Ã÷Uúi(.~¸å¶'·±�ñ]šðq+?£V€�CÂÈ£ª)n‘RP÷m4غø_ä Ïq‘ô ºƒ� 4?û`;UJ&è}EœAb ;‘TiLWœ¢:¸ú#ÞJÝ\àÁ–ÿ>7<<¼¤+€`k f]mÎJ�äªIJ?Ù®OÕ²É{�NÇ“D~yDW€®®.ߪÃW¯`f$VÇNñÑh4®+€l«ósÞÃM•:™�PäZ¼ªé½³é*=³J­&¶ýü«…Bt#J67s®Œ.Ö¼Ó ¨ª‡ø†chûI°ˆé/ƒƒƒ¬®Ùt*ëjCÞ>d泊‹©ˆV?Í%Ì-ˆ^›Š'q‘}­+@OOÏÞ5×>Ò~ª öåinhhè½®’Ùáç܇›+u2; hk¿ªDÊÓ+8}X¥Nss4?£©ý4„B!ºŒÛÛ6k?fijÑT(Lë P�åÎ{tG¥nÓ`^K%FFVtì»Ng]­hûqŸU«ÄVµýšÊFK·À _?G*þÕ”g_é ÐÝÝÝžõ´»£ ‰ÙÙ8×ÙÙùIW€<å=—n<±»RÇ×–“ ïúûû•Íòþ @  2Ìþ³YO;rŠ"„%0ÉÒËj‹üá\à÷û «ÕºÀää¼m7'®Ûl]ÆÝ^ùd0X6(Ê‚ ¦#‘Hþ¯ä�Ÿ¦(·O°7:ržC$�Iü ü:ùl˜_[/t¥SíTnž·ebp^ ²­}}}X²Xs“Uä�gK#E1–1ó³·�ï'´äý÷ñ�hF|ÊÄ[IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/formatselectall.png000066400000000000000000000010601506556630100224550ustar00rootroot00000000000000‰PNG  IHDR szzô÷IDATx^ÅWÝJA(‹ïÌ$×ò÷¾êß$‚ (‰^¤Wè&_@Í.–@°\½©‹$¢w›Y†=ë”3Í4Kû çâûÎ7gfôßò/..ædò™’0‰³™õµz½>%먿HÈ��N!†&ÏS½^/�á `âãã];±ã8(‹4S£ ÈIR<[‹Î#¸î>i ö:ØJ"±Mä¤spAZ@«Õž[«ÕªPçD¥R¡B�€ˆŸìf°Ãw@£Ývœæ |®ô¶£L’^ok±# ¸¸nkÊp¹ >²)»R�¦P,ïgôLy`à–>Ī׷Ö>N€,õ*}£%Ê^ó¹w¸³oÿžiõï/\rŒ"‹ bKGDùC» pHYs.#.#x¥?vtIMEæ µ›tEXtCommentCreated with GIMPW�ýIDATXÃcd äåå‰?~<êêÕ«.bbbêOžJ±åfff¢ÌÌÌð`wrrj§^KKk L­ŒŒÌbì`Â'ùõëׂ¿ÿrÁøÊÊÊ3ð©WTT,efff````Ó§8 î Å+A ««»•õ8Áýû÷9ÐVYY™!}‘Tq€­­­!ºøøø ésss`bbš©©©¹ˆ"èèè¡;€……åkaa¡=ÀÚµk9°2¢¢¢_ôôôéâ%%¥k¸J;11±k–––iÑÑѼ4s€±±q ¡bWDD䫦¦æ2mmm[ª; ..N‚››û1å?´¤<ìèèhOŠŒ„hjjfÞ»wÏŠCcccÍ™3g7Ã�jjj_‰ bjc55µ¯Œ—X™©Ož<áËedd¾1 `hhÈ%##S ªªú[\/_¾\š.±··—±µµ½�îMMMc²$¤‚ƒ>ùøñ£—¼¼ü/dqqqqÊ£úúúå¤h’——_ƒÓ§Oç¢ÈRRRçIÑäéé oÈòóó¿"»MÏž=3(--Õ"Öïß¿…±ýúu„b0000œ× ša w0Œ´˜ o’ÕŒQÖ!̇ا8¬á Ž×L7 ®èqˆ½û±Ž¦'Ÿªª¾'| ö@€!~DüM¦½ªb½'ÛÀjÄ×IXv¼-À0âK™�OÁîn S @Q  ˜�î(ª‡J5°k{–‚Ý9 €è:®£b7Es­0ˆøRf`¬Ò vê¥1ÑSt-€…ˆo"à`°óm>D|ÇNû¾-À«ˆï´šj®Q†Ë¡ÿ¢E8"/Äê•|µÅBL_þ%ÔZ#‹8·N\†ù0Ä¥”ääü:±ŠG8ƒmáÙŽ¼F.b.<7ÀµÔä…º¸‡Ÿ�¦lÙÿg7yYS¸)/¦^dïp_¾D�.®”Û­ˆ›À^ùNêËÏ�èi÷W«<3ò}¾z‰'Uçsñ"Ûˆö¬HZþg4+þ)¾šÝ¤<ÿ€~IA’ý5™ÞIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/helpabout.png000066400000000000000000000030501506556630100212600ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs»»:ìãâtEXtSoftwarewww.inkscape.org›î<¥IDATX…¥—klUÇ3ݲÝݶnK·Ë£Ø­´… -”¶c|R¤1!QÑã P!¾‚LübD >0‰1€/Pk0ÕQ1•Õ‚�FÚ…¶¤»¥Ý>öÑ�î\?,fwf—M<Ÿî=çïÿÏœsgF"ÅΟ65�€`>P ä¦â²4ð^­b”=RT�ô_@,¶3²ÙÝê Ý߆oèqUÁ–ë¤Â¹ˆZ÷ÝLrðœSk<¥Ò7>¿x‰m€|%âˆä‹?ŸçX÷‡¨"nˆçÊ6šÊŸ`ù¬—±æä§†U!±ÞS"½£ ¸tò¯²!F{xûøí\9}%(.{%kë¿Æ�?Û(îö¸¤6©³SäÉùüCi�Åü~´‘óÿP0©”;«6SënÆfq2=ϯ½{9äÛND p•u*Ï-þ‰û5©ÛõÈQª$_@<ìH%ú¹{‡ñ‡:˜l«@Q#´ûÛ˜’_úEßãÌ›n:íåý_Wrvð(3‹xæ¦ÃÈRNN•|ÑÜ5á¼0ršwO4s1Ò•6Öœ|6-ñš�J³±ñ^;Ú@ÏÈ<4‹ÊL…µÉ$Z €°2Èö“Ë’Èó,…†BZêy2#9€ÕRÀªy;µù�o˜ÁæYHô9»Þb ì`fQ#ÌÛ‰;�ð¿œìý„ã={XZ¾6#ù„yœ ©*^JÇÀaº‡O1öQl/×C¦Èè.™“½Ÿ�+çñØ‚}9€Ë>“;+7³eé_Ù®ÎJ@­»Yw N çjmQ‚ô�þ @åä& ­S²&Éd3 ë´qø¬!n™ �ôPœÃXeˆ�,R´+ ÖJ°Ÿ ?&ê¸Â±Ï·is³ x¿Û�÷»Ý8ŠJ©\tso¹�iÕu‚5UUÒ˜¶KW¿xJ¼i&"ØçãÛ7×Ñ}æVG!öª7³äÁM´ø˜ö÷î'24@dd éQ––1»±…ú«'Þª�Xç)‘¶CJ_uÄ2Þ }uªñqzÎüL^a1W¹Ê˜d7¾Ñ’2¥Æ „ûPbQJ˯կñ‰ÄÏé·Z&S7èìy’ƒU’D pàæÿýž÷¿ ÁWÊUUIczÀb=õw®:�IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/helpback.png000066400000000000000000000031311506556630100210460ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs íÀ,tIMEÓ *•IMöæIDATxÚÅ—]Œ[GÇwî½þÚ¬÷#.Iv6�P%¤‘6{¡D "¢ˆ– )/-m +ÈCߪ¾TBJ‰‡"õ¥È"%´* UÔˆ ‘ºÞî.]ª¶†lƒãMöÃ^Çö½¾3<øîÚŽílŠ Œôð�3óÿŸã™3çÀÿyhÅxìÌô.PGAŽ£(Ù´‡šAɤwÉâ|�étZ},ÆÎLŸžƒ$ˆˆXÝ@:8ÍK&�þ+–úù9ÀK§Óò?0vfúšx%¿ˆÐ!Ò‘A"Ñ8;’%>¿½@Ù�‹×F°j‹à,ƒòe8O[üò€ÓIˆ¶�×çˆo%²é|ûÁû?µ‰û·'ˆEDÛšÜR�¿þ}•ËïÂ[×L¨Ì×'÷5‹—¾”Òé´¿¡€ur= ÉûyôÀ¿xè`Š�MF×h©;¶º<[äg—Ln.,€_éÍXêÜW�ÅæHè]É�;vlãéãeŽ}nÓø’¼ñv‰l¾Æð}Q©Z0œŠrhÊ>×5PÁ–¼Ú÷Ù!¦gY–ŸÉdT›€±3oíºÉðð0ÏœTìÜÃóU®Ì•9u$Å;\¸Zà¾>£ÍÆÐ5öïŒs«$¹¾  >“÷v]s×CÜÓ— €ä~ž<´L2‘ Zk¿IsóUNI­ÿ>u$Åì?«]ÿžoMró¶Éÿ(C¤ÿ,’)À<½á}æ4¨ïâ± ìÙ„¨6¼ŸsZÈׯµ›NG{/P(`gJòf¶¼Ò¶¼Ü[Òf¦,ËrPò 4“-©^öŒ8Tœö«»Xô:’í›G²Çä£K¼6a‚{ÉË€mŒ}ï­]Àab›ùÒîeü ?Z lÙ•üWWîJîùŠå’‹B‡Øf°F'k'öZÑ …µ 2H*Y¢b·{Ó�üÕ?/u%^XqøpEãjn¸ñ1bƒ½fßA`jMÀ(ÀÖ>‰ªµVïOßrÏäÍkWÊWs#-ó‘h@Döñ†=Æ@Ü¥|‡÷O=¼­«‡Ý¢Ò<·ž^&]š "Ø�$Öȧ"F2êR©ÉuÜ�ü£ŒËß­9Q= ”˜FsJ®xnÛþÿ²�k( v C¨ÿÛzüJCÁz18kQòåÞuœø±÷±z.Œ¼Ï‚ò@yY@ašAÓ©Ø>¦Þš�¿üCÉÅgÅ]7Þh˜M/Ží¸á]Ë¢ãÕw–Þ%Üe„m8ö£î‡ë^†.À]®t Àa 7�½ˆ©yÄ�v|ý'Þ=‹ˆ{-XÛÃÔ<°Aú³VüOóë©�Hÿ_(—øôpOG²Ç_°9ÿT²£ˆÇ_(m‰l®RÿÿýòëèT[Èd2œÓfóÂúŠ_+oO $é�ÄŒvüq²Ê׬DÛæ—¦ow´_ƒ]“äo\¯{¯½üSà&Pl>]�ó @v>GÌðè�ºñìùmºÙöF]b†Gv>W7tò/Å�z “ɨ“–‘Ï« �Ç—Š5vEˆ˜:¦®µáÍ¿•9¼¿€ü*ßÑÆÔ5>™)Pu>>.€Ä¤ÿÍ#DúÏ¢écQSðÉ­ ö IûÐu³eMx¬¬¬òÎ Á‡ UjžéÏâä_´¢¦ÂCw ¨6—å]“PD ˜T�>‰{M]›�G ÕW¿ÅK«>¶Û´Xú³øå×-ýÕ߇‡m (têŽîÚš���k€ôý“µ{1û""{æîðI Ÿ/KPËâ2a’©«¡€ àwjVï©9 £a†‰‡ˆ…ßÄz2«—Ú`‡p6jNÿ ÍJö‡WÞIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/helpbasic.png000066400000000000000000000040011506556630100212240ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœ£IDATX…Õ—kŒUÕÇûœsÏ}Î�{‡��A™á!P¢©"$¤5¦h4Ÿ}È#U«iH“Ú¤i5¶IÓmš´U©©¦‰‘—-õ…ÁÔM-Õ*h­P! 3 Ì0sŸçœ{Î~ôÃ�¹Ì i“¦ëd:k¯õ_ÿ½ÖŸÿcŸÅyÁwþ—Åp¹1f™Ð,À" `0Ý6¼•ä[‡ž¾=ü¯èØðÌbTì{ÉlæŽl¶5•H5áÆ“X¶€RQ-À¯–¨–Ë^¥²Í’ò×Ç~ë‡ÿ€‹îÚÑâDñ_4·L¿sZ[‡ˆ¹‰OUUXóú¨Ï‡Ï>f,èÝ|Sá3è\»sy,‘ÜÙÞ¹hf"™@F!^¥€c:¦YäR6CUMß�BYIÒ™¶ ðÊœî;Ò_ ‚¯ôn]óî§йþ¹ë2™ü®Ys—¸–e#eˆ_<õ])nZ1“¥�Y¬ ;µ6ìï)ñüÞ3üåP@2ÛŠíÄÐZqªç¿Z-]ß»eÍ«Ÿ`îúç®Jeò¯Íê\â ~µD׌�}u>í-ñ 6Îú~²£›#ƒ â©&Œ1œêùÀ÷ª¥•™ࢻv´$EóûÏ_:Ó²,¼r�¯¯H²qubÄÓxóhÈ›Ý!' ©aZÚâò91V-‰“Ž×µ�‡wç™·’™f´Vœì>Ð/Ë^×±§o/Žæ´ÇÈw­}¤½sÑ�XŒš_æk+’l¼¾£ólYóàs%ž}'àØ€b ¬9WÑô+þqŽãOf²Åò¹tñ_;^šÄ@džgg³ÓµÎš'´’\:#à‘»7*÷BÃÆ-Cœ.(b6,½8†c Þëñj0Äc‚ßn˜Æì¼Ý`bãcpx(‰eÙ žì1ÅÊÐ%'¶Ü|Àj”¯Å}Í-³„Ñ”xà–¹€Á˜úÚ±·Lÿ¹¥"\[òèú¤êKÀ°dN†GïYH6å„z"vm4fL£ RI,˦PU#Î;Ml×[g(”}ÌJñø·?GÒµðC5¥?ÀPUb´F+ ˆB€�£2ªsô ÔPÚ4èBvôT},Á°ášvR®…w�Ê”6ô „­‘Qˆ€nC!ÄÛQ­>"e_rø”?i ÇŽ”1Жsëc©Ëå¨�4æD¿QA:xÂÇ $Z+š�f_ƒ§ÙÝç{•j<™N £Ù½¿Ä¢öäÇ2ðÍë:Y8;MçŒ$3ó J�j€&�ÛËJ(bŒ! ýœÞü?{FèÞ´º¦ÂÚv%C´Vì~wˆ3…°!ÃS­ÁRÀËïœä‰ÝG9v¶ŠÒ=ÖgÌsr8ä•C(¥�Qˆ í{ö\#G ´ý+¿Z4Zkª¾Çoþ<РTO±~ùô!^ÜÛÏ oœàágOR¾ý6½t–ªWÅhMP©h£õC£yŽo_sÄóýßÉ(DKɇØöÚ0zb/Œ$’òüœk­Iºö”žÜ3ÄÛ‡ÐJ"£¡ 6õ=uë±Ñ½ã¾rK×ÿ]EÁ:Çu›”’¼ßï#,—®9“ûaIgŽ�†|.™Ýăßè"•ˆQ“cF×Àæ¿ óÔ_OP <´ÖxÕb_LÇozo{­ÁüÄÀóÖí¼Òñzª©9Ž7‘båÒvî]ÕB[³3Î×¶éx�ÄJ Q# vº yìåAöVï:6<Ÿ’ŸÙŽu¯‹ 1Rö']FkTi­å#q×úñ‘'Ö”/äû©~Íæ¯}a�B݇e­µ-;+,«~£�ùT6˜ºÌ*Y6c=Ô·íÆžOŠý™~N¯¸çñØ`µõ !¸Êk>Úä±0 †-cº1fßœþ–wGEæÿÂþ 3GÄw×N¸IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/helpforward.png000066400000000000000000000031571506556630100216220ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs íÀ,tIMEÓ é3€rüIDATxÚÅ—]lWÇóµ»cÇkïfi;©“âV!‘ã� T�""ªJ}i¡X`É­úPU$¤ @H< JWN ¤BíC õ!%J•¶)•êIm·)_‹’¦ÎºñÇ;³;3÷ò°³ön½k§Ä•þZÍžsçüϹgÎ9þÏKù8Êã“;@1 !EÃ;äRL!¼³'3€H§Óò†�|¸8 F@�Õ„ �Û¸å<Â?eÉñ€—N§ÅD`xtr/ŠúR|UƒHD’D¢&ÛâK|vk€¢ g.õã¸U¨Ì�»Ò¤Cà>fñ›_n+"Ê:^ŸÀÜLdÃM<´o†Ý·là¶­Ä"êª=3óþòn�Wþ o^2 t¹&ª/X<ý-`)�NûëX6®E!~÷î}ŸcûS$6èm£%?òªW¦óüê¬Á³³àAxS–<ñU`®1Z[ãzÛ¶má±;ŠþLCWñMøî©"§'«Ü!² }©(!Wô¹4§€ 6eå®Oõ2ù˲|Û¶å*ãoíåE4ƒ¾¾>?*Ù¾)†çËU8þ\™ñ±$Çö™<:^às·j«ttMa÷v“kK‚+ òÖ¬·ãõ^õâ•�=ȧ!€ø p‰wè”+²%ÆÇ’Ë›ÆÇ’üäy§¥ž�ð�CqnNÔ”#=Ç� 7E`xÔ~ä·1{¹o_Ž�ýðÙ[SÑ&æÇö™|ï™ÙÓ¯¬Ò•Àö”à\¦¼¥-Y±3ß«L]°,«º)î�M©.û;)¹bM´ZãcIžú³×R?Þiðõ¡(h±»€ÀP†¿óæà ±�|i`?€r%Xzc±-‰g^mÖ-”|þ•-#Ñ ¶mh¢rd'«W‡jç“$_¢äˆë*ÍϾ<Ï=·§Z’xè—‹ìé-óÞ¢Â3}+ˆÎ,Ýû� uC›»’š÷¯þÃX—Äé·›²™üm¡Y‰šTÔÈ `®Ðb$Ì*ÅÐû·Þ�¶|ñÇYãcIü0L±°-i*µ†¶”/ÿX4t»æªíÍç¼–q£¡ã8n5lÑ• ^Íšð΢iP]@U·\—guë_Îüúª.„¿9Wg¸ó8sЇ©·‡ë�ë­mük?óH˜+¨ï5œ9þ´ež¾ 8õx „ •Ï/åçùd_g[Ï1€“Ç[Ê¿ù‹%±Ö{33¥ÚùûÅ—Ð(Ž`Û6G‡•é¬j}ů·¦qzÌ€˜ÞwZ« <òÔ|[}§"È^½Ró^ùíÏ�€|ãŒå¸�£™ç2—gøÂžO`h×ÿI~ÿäUº¢íòE!sy®öàfŸ$JÈÞr~Ú¶-�Zz6+?� „zÇ|¾Â@o„ˆ¡ahÊ*œ{»ÈÁÝ]üèwÙ–:†¦ âóÚT޲ëA5÷„eüþ �òét:hÉ,Ë’½LNfå®B5P_™«ÒŸRé0£èš² ç/–8±ÔR¦k ®SæÌ…%'4®=÷<0 ÌUÛ¶›gBÛ¶±,+¨“ð„vøï3.žPÙ¶QÅÐUt•u¡HŸ‰–yý�<ž/�g�k€S¿5µ¬Ò###*Ð1áß};‘žã(ÚpÔP¹ys»zÉd7šÖܪƒÀcq±À;WUÞ›-Sñ7û¤}ñB˜t×€rãXÞ¶M„$b@bBÞû Zì.m¨.7#�ê®åð|ÁÇ©6lþ4~ñ%K{ö�a²Í¹V·£5¯f###J8½v=•#;1º÷£FQ��°¥†µÚËT2TsvXdJ@!$PüV—Õ뺜†Ñ0ˆ˜!báêr1p'„»Þåôß»2F©V~LIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/helpfull.png000066400000000000000000000040671506556630100211210ustar00rootroot00000000000000‰PNG  IHDR szzôþIDATX…�—[ŒG†¿ªêËôìÌŽ×ØÞõnÖ—Äë82 F–’BDÀy   ( VÈ–"Ä8âEˆ(b !Lðå!ØÆVnNDlÅÁñý¶v¼ÞìÍ{›ž[÷LwÝÓ;c ˜´Tê®ÖLýÿùÏ9W nòxpû&Ð÷!Å:�Z^(t,�[ªk­‡5áñ(ð ýí±�@D7³®ø  €gòyçéþÞE…Þž.ò^ʵ�0ŒPtP,Õ˜ž+35ãºu¿übeüèó£G~3 „ŸŠÀÀ¯lÊç³X·vE¡¿o1Ÿ\ó›i09´ýN'÷œ#Èš�1a®XbbjÚõJ£[†ö>±¨ÿ'EnH`à�WWݺô‘»>—Æê �ú4Ýö Dû„ˆ‰Ø2bjv†’;öÚù]ßy¨ÜH�#0ðÀ«ƒw¯x¤¯·‡Ï—)VÂ4J­¡îGõ�Ä#$–ÂÌH¤é²R€#¡Zs™›¾¼ëüî‡ÜëI´h÷„K#Ð)¸_ YØ¡øñ·ú¸kmŽÞEZkÜrÈáS%¶ï»Æ‰+N§Ù¶¨! î•(Í\Þ}nçæ\OB̓¿²iÕ­½Ï ܶ¬ \GP)6øáÆ~»uk–;ä…Ö­5¦+–ÚlübK o|àbfB „h!�¦ Ò\ã,ºãêÜ¥g€F3‹ âjÏç�·¾|ÏÚÌ‘3ª~”F^-ütó-<þ�´&Žm÷Õý6#ãu._k  “H†aeÀÈÞ[w¯îòç®Ì·*2ÁyfÝÚ…K£õöœNÎ`÷ÛÓËQEš‘IŸ#§ËÉ;�¾×Zóí ]4¼!%´ ¡ œü¢Ü’;¿û�o/òyçé[ú34ê·�#R †gž!Š4»ßžaó/.±å…«|ýÙ‹œ½RK‰"ͪ>­BÅÿmf6G¦kÅC@`¨�·oZµré#¡p›i´�‹ä®Lɹ«5Þÿ¨Ì_Íaå ÌŒSòɘφõù¤Kât¼¼w•1#Ò�HKÓ² ˇ‹—ß8 ø¸¯·»‹ñ¼ÙMpDc£š©’)[HˆêHcÛ!:ð'ˆ¿‘¡ux|¶X¹§î)j~Ñļ„B´�Iæ­Ñx‘ cȘ€!SÅ„œÿ\k YS„ µ™!â=BhèÐ;4:á>iÊÎyÀ6pÒ¹2c³¿ßWŒ]RJ„Œ‹TµHŠU¶) éÊi&GêxÓŽ>Ê‹¯?¶³R­º¶@I‘tB³‚iQ ³uÁ;'½$µšýÿôqòf hÄD Sa˜Ã’–°¶­X˜WL\+W>>ðó·€*Ð0€À÷Ü=¿°µÓéÀõðy-Ê9‚ž\D.Í7¿ ùþï\¤± -£éhXœÓLÏ”qGOíIÀ+@ �¨2þáóÕJÉÍÛS¥ÔÄOGjîù¬“‚ä2‚•‹Uܦ-$ 3QÂRäsŠ%8}vº2üæ¶@¨‘=òüd­ôÉÏwÉ[qô-&–:””‚ñ™öm]ÓÒŽ‘"M‡a*2ÅÀRÅÉÓ.ãíùuuâÔ(0›Ô@º‡ö>±Ã¯^{�¨J‡J*!Q"þ2Ʀô� >GH)0MÅá‹ç¦uš"™•RbZ‚;úÃWÊœ=vêàÇûv˜JI¶mß$�[½é�ƒfvÙ¦Pä ‘–ÂHó*©W#î¼Å #e(tg0íXnÓ”–A>§X½Tññ•2ï8zðøK¶cÀ(P&Ù¦«¦ÏîÜ¿pàþÛ•i­AØÐ”X%vl2Y…«%ž’drFÚûR CÒ]ôuFûh–£ï;xâåû·Àx+øõš$Ógþº¯£{íU»£ó^„²„²P2iS)[¬yþ¹Ó‘,Î úÜ™ ï½?^9÷Οu~Ç÷[Àÿû¶¼åR@GaÅ—V.ùÜÃOY n}HZ¹œe;8–��Q˜¶Â²%YG’±AQ,×™˜(UܱS{®¾ñÜŽÊÄÉÑ$çÓÜìÁ亚°ˆ7�]Ë¿òË�ö‚þ» §k@YÙžL¶³[H‰W«LêПhÔ¦‡¼© ÇZL¦H\í%þߣ٠԰‡x•Mæó) Ÿy“©%óOw8½Á%0`Å|G PH|è¸éãù¿­ç‘TrIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/helphome.png000066400000000000000000000033101506556630100210750ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs íÀ,tIMEÓ  ¡3•VUIDATxÚÅ—ÛoÕÇ?sfç²»¶w×qbÇÆ‰b'M°=-R›„’ŠŠ�Ú¢¾ Ñ h­6}¨„òX‰þ¼‚–†ñÒ>ôÂB•¨„Jx�mQʦ6©³I|Ù]Û»3»3sNv½¯CHR©#}¥3çüÎù]Îïü.ðþ´;!ž<3{Ôi�ãÀ8J¶œ¡æPré_p8Ÿd:�Vÿ&ÏÌ>< < � Lv�@zz­[>@o8êwç?�NË»`òÌìšx %¿�ÐÁL‚Ù‹iEîYç÷åØôཅý¸^*Ëà­‚òåz/8¼þ{ÀÛIí6ZŸ :€Ùµ‡Ÿ=´Ä±ƒ]Œo‚H”ÒN¸’K¾É† .Œí‹a™âžóýèLŒÜrY4‘ôÈ»6Q <¯ÿÝ#fUîÓyúTüŽÿê|s|½Ðth‚RÓ�b"ôN*�ªMå6›s5žÞ�ɩ߶ÿ_üMsüñb'}D€RKÕÊÏ2RBsh:%7ÀÐ#ýðÞ®ÁhÉ8®W­§èJ¿vÉÒ¿@u!D4qo¾ ‹&¨®Ö&«ù à €z ÷î2†æ�´ÃÒƒ;fšŠú l�ch>¸Ë ƒy'ú·EÀݲ·Do øÖza…û‡Ú®ÛÔ›îÒòL­o›i¬”ívÐg—Jµû6ßA§¸ �N«Z©>t‹×��Oª67v¶@+Mª~éš |ÜⵚöúÞŠ€×ª–Oè�E�¾Ÿ]\âäñÝzíI7|^}ÛoæÖ|<_Ñmµ ôêÛ+M«µä‡ÙÅåÚ�—{‹Ph«2™ŒzÒ‰ärêkùPŠÇW  š˜†Ž¦Á¦'Ð40t­­4[s‚€Ìå){>Tó/9Æ_Þr@!�N‡ÛÝ;p8ÿ ¡{v£\åÝé<~ÅÅ2Ä]Á¯¸¼;�g£\­1×ÿø'à�‚Žš0“Éà8N8ÈìlN-úRìó%_ †w Œˆ "¸-40}¹Ì¥O ø�ležnîV×´cY>55%€ØtðãG0“/¢é“–!Ø7ãè ¤·7�®·×~aè³¶Vä“k‚/®—©ød0�—{Ù±Þš©k~(·–å·lLêBØ@jZ=ó<ºýš>¾µ5¡/Qóá•b€Ûúd0O°ùNÝÛ ÀJÝìÝÑ—¶fSSSZ=Ä�ätå‰1ŒÄ „yaª§Ôz:ñ³„•,Õ|¦dJõ§V¨�ƒ�šÕ¯ÔœÖ­aÔ-­Ã®Ï‰F0«•ÚàÖáÝ®9ý/ÐBŸ6zº:IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/helpnext.png000066400000000000000000000041321506556630100211260ustar00rootroot00000000000000‰PNG  IHDR szzôgAMA±� üa pHYs × ×B(›xüIDATXÃ¥—il\ÕÇwy3ž{o¹÷õÃ8^°}ÒÿËÓ=÷üϹ÷üï9‚Õ~m»4ðYà‹@'Ðt`lÇ��ý¤wû«ÙV¬Âqðp;àT­$�ˆC`Àu¡\cÎXYà9à^Ò»§>�¶]1à~à{@Œº:hmA´·rñ†uœ·&Bgc �…cce&‹>ý±q�\À%½Û®ž@Û®fàeà  èÚÌ-7^ÌŽËÖò¹Í)"Z ج ±!T|ËxÁgßá,ϼ>Î{ï ‘cP(¼|™ôîÑ�'ж« Ø4Óµ‰îí[yæ¶N.;/A&d<ïã!^`ñLˆ%ÁÑ’¸#qËßfùáK§È¾{†Nd�Ï�Þ}èìÚvµ}HÙÆÖ-ܹãRžÚÙ�–‚‚kx¼ÂDáãïVD R1ÍL)àû/�¦¯oúÞk?® ½;sf­Zä< ü¸ˆK¶ò�;¶±§·!“Ÿñ¼� CÎ_¥¹V“ž,Q2à™pʾe¦†ð…- –§KÆÆê�’ÛŸ#ÿZ°”@rûƒ@/pçmW²§·/91Uaºà!›Î©am­C]LÓqNŒ£C3d�oB¼`9Jž%[ ض¾Žw³ŠlÁ…™™ ÿÚ« ª—î·$â‘aï·»02%ò‹„øÆr~c)ª§&¥àÂÖZŽž˜eÆø†Iœ¹+ÝmqÌ:˜áðým$·?Kþµ‚œ‹ÿG@‚®Í<¶ãFKÌ– E·Š\År|Ü]rÖŽ–츺•Zã‘+\³"rƒ‚KΫƒ®Í‰¹òDÍ�ýóÔÖF¯»å*vÝÐΩi—“Ó•ÀR ,åÀ2Q80˜§5©i¬‹Ì“PR²e}’ÿN3á†+Þ Ï„¸�¥.ªxwFÀhµ¾n¡þÅ}7uòÐï�s$ob¹ÎÅIX[‹ŠFÀ˜MR*Ý$bqš’'§+¼|pšcãÒ3SÅ€©B@®bÈSÅ€ö¦éÊ-!Gòà­PÅò2›|ÅÌ"â ¤ÒíRjÕ,b5¤bšÃ™29×�_%¦K÷¿üoÏ.!¡¤äæË™ÍV–ÙøfŽB<†Ôª]K­�PkB =ëQpÍ*Þè…ÏW»BªOO”)ºJT+݆0[˜,RJ¤ÖžVZ Kk6Nä}& Ç2¢Ž$©>,Ž©ù?ûÒù\Õ™\òßXË odðu”‹†’g)¸fÁNIœÐ"´ÓRëaŒÙ8YHD$Z Œ çÏLˆj‰ …¨²s$Oìèàê —:¯x†¯>~�¡²ÂÞB©ÎræWÖ‚ÖcRjuTJA:“C+AÄ8zZ LâÛ×T…É„!{z;¸vãrç½�ÿ‡ž® cÎ’}]Ý;êH¯R H«~-µþ3ð 1›e<çÓW*ö¬i�jÁ³·o gSý2ç·ÿâ ÒÑxä,¶ÏXD>O¨5À+ZiµÂY‘ͧúÓe67Åé.-«û3ΟÞÙɵ›–G~×/ûy}Ä'�®Üû HD¶&›#Ô*üKföÝåI­'|Ÿ“'&HD$©„^–>G ~|cûŠÎ¿öD?oŽyD‘í-HÅ«•¦òy„ µz.³ï.WH¥’JÃÑINM»´¥ꢊˆóHÕ(n¹tÍRç¾áž=ïñVƧ&]²~1’5ŠúEh-áÈ$Ré¢Tú'`xoï¨ÔêÃÔÐ…Š¥5å�ˆVËÐQ߆œšZxŽ]ßðÍ'Ñ7îS“ˆÎ¯û0j£’–¤CÑ3˜ÑI0©Õχ÷öf–tDkº¿ò–”òóaÉm1J¡cQZë#Ɔ()88\bmT08Zà¿9Â@6$‹ ¤X©¸¦¥>ÂL) 4žÃ�FJù†”òîÙÃ/šeMiç­jÞFˆs“�ͤÖÕÒœt¨ø!^FCkR~¤@5&jA&ç3=š¥pjB›±mð…›GÏÚ–_¸ó•nàP?'IêÜ5´5D‰9’¢k(¸–¢·HÓçÕM�*’QE,"ñK:ë13½»4ðà“À X ”�©¼<ìg|w¸”´b ÄmÀÝÀõ€7% •‚T"¾µs2Ê{�;ß=ûÎôîJw_´´@O7¢¯‡ k;X¹,Æšö&" ÃS5f*!‡†²¸©i˜˜€b À¾ ÜÃøn»t½»º€Ç€‹I¥` ŸO_½�í-g[†˜HÖ�µë Z¦Ë!ûØóÏi^zá(†rà9àSŒïž<·€Þ]À~ ‹�u nÙÄžëÖpÑʈŒcºâGŽ ²Æ¡„@Ið´$éIüÈòôPžo>zŒÂ‹/ÃÈཌï~ùìzwu‘²—M¹qû…üâÚÕh)(û†×¦ëœ(Ÿ»·bZ�IhrÕˆ¯?zœƒGàà `í›ÀÅŒïΞ\«Î �ÖsÁ&n»a3÷íX�‚™rÈt)¤ìrÕhþë�Ã8ǪåMôw6Q)ûLW"B µÐ’«F8ÙØÆÑšâxUÀÔT+°•ô–½”D�Ò[¾ ì`õ*n¼îRîÛ±š r¼1[g®D! Sœ(‡„Æò¾µiVw$HÄ}í ††g)ZIhA䨖B=bó»Zx± (”}Èåº�ˆÒ�gN ˜oºH%cƒ×\Γ_ÀXÊV)Õ-~äð#K9²…�\5âª� ½mñ†Òggk�ö±RDó"NöÊ`o’góflÂp3é-¿¢t ,b¿¤èçÞí«𬒝*þ<ʾetÖgtÖçƒ2¬XÖHn­åÀÐ,¡R”}Ó€bÝ „à‚•-0Ð�ZØžè…=ÍͼÿÊ~.??Íè¬Ïx!ÄX‡±ŽÈ:òUÃñ9Ÿë/igU{Sy~úøE£)´gmÎM½Ižïî‚–(•>Kï®Û´�ò  Å­èãÆK;¨…–¡‰*µÐb,DÖÇëÓ5nºì<Öž—XD~3RvÄ“qÊusV OÒ–Ôäz{ïe€­Zju5€ìéäŠw§žª1[�ˆÌü—GÆ1U ùü%¬ëz yhùþCà -±dœÀ7çÜ¢}m1òÝ]È‘€�i¥Õ&´fc' Oñïcy†&«TBK=°xZð•+»ìI."ÿÎïŽ0”·x‰�o—t§%=‰knFÅc`Ì:-•ît‰$�i�ѹ:�ýgwFÀ�Ûº¹`Eª!‰Z¾±wˆC³�ˆQ¯›%_ª's‹d Q­öi©U—M4‘IhgkÏ(cK“bkæ-ä†Ûù /œˆÐM1ð—Nš É2ðû´ÔÚsZã€ñ|@Ù7§Îç ²ª!­I¯±üVPG"þrë _‹˜)GRJ¤Ö�TZ�yÖp¢2SŽÎÖ� ˜.Eä*†Ç_Ê7$Š{Šß²ž —)ê�ÅÝYQ sÃX.dxªÎt1ÂZˆ)‰ç,J«))µSÆ0SŽHÅ$Z Œu”ꆩRÈí�²o(× ¢ÉSüì–õ\Ô®¨†J`)û–b}þ®˜)Gd‹!…`áî°xJà)A\Ï¿•µH­§¤ÔêU)ãÙ"Z bžÀÓ§a\·÷èb1Åž[7ðžEÉ�¨„†Zd ¬Ãà’†<žžÏ÷$^PG �Z’Rë?K­ùÓÅ�¶¤"¦Dœƒ›ïáo‡‹x`çF¶­ŒãIŽÍ15ïJ%¤ÖH­ŸP鵟8.¥ø’4¶)Z¾œžLŒ™r„”u‚§† lìJ°ªãôQ¬•ä£vphxޱŠEIÙwZ šãŠÈoN ¬-I)wÊì¾›©õïE2úÆ R1I&¥•ÏÓ |á¡Qþ~$¿¨¿Ý9È /zÛ8O 2Éù�¦J%D!µÚ›Ýw“/¤ÒwI¥+nr†cs>½�–¸zÛ2âàËã¯D(%¹öÒN´5‹bÒMŠÖ&…³71ƒTº"•þ€{rǤÔên"ÃìÈ庥'㑊ËSÝ{&pû#Ç80Ü(âÈxiÑÚæ¸¤;íQ frŒAjõ£±'wdѲÁÏýKJùaWõ»�RèDœžÖB€±nÑ?xúp�É\�¾´æ×ûßä‰W xÉø©5™¤¦»5F®Q�.âOÎ!¥|NJysþðƒf‘)]ó™?uÏ#ÄŠôš.2Ít¥=ê¡[°aîìg¼µ)O™Òö”G“'ÈCæ& ”��gÇAl>ú‡k&ÏjËÏ¿ö‰AàY 5y^šÌŠeô¶ÅIxò”3ªf‘˜˜$ãŠt\‘ˆI‚È2^È�å)Oä²ÀÖ×î¿úð9“u7<Õ ü¸L7y¤»[éèl¡-©hŽŸö±fa(ñÔé4ÕÀRªÆ'Š'òD~ð<ðñWó¡ì’G³õ7ÿUwwq/á‘Ì$Hf´·%ð”@K�BàGh,sŸÊ\•j®FXWñà‡C{®ª½£átðÖýË�{†S ¤@{ åI„”D~DDœa$Â…áô«/ÿ|kîÿ›ŽOÊ�ÏxÀV`;°蜇kF@ŒG�G€}‡~ry´”¼ÿëÆ×:ÀãIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/nodeaddchild.png000066400000000000000000000015541506556630100217060ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  šœtIMEá  ) ¶™luùIDATXÃÅ–ËOQÆwh !Xi4&“žRÂc�‚üºpaÜ« &4jLÜ9W&hþ&âÆ„1,LåÑ4$ˆºb(/‘:L︘éƒa`2ų™¹3÷žóÝï|çÜ yS)zÕµÏù¿w& ÎU@:€«@ I` Ĩ3…yÞYEQð—À T‚4ZZêê5-{)“Ñû„uÕœûÉs†�{@µ9–45�#ªaww�ÉÉ%¶·ÿ΂¸k2á�)Ö³£Ü µµŽP¨†ÞÞ‹44èê:�ß_Ù zÐk=T˜‚£Ý¤Ý$EÓtjk«ØÙј›ûÅúú¤pã3¨+^ðä¶n¥ds3Ãää‹‹iæç7Ðui€hÎz�‚~ YЃÉÂöö_¦§S,,l¢ëxLx @7Kí >·¶2ìíÉbl PÓ^j 'Â!`öÐ"1í© À[*V˜îØ@¶ào½Þ½S'l‚@ h³ržØO}yZ2ªZÜÝ^„áÕ5E­*÷Y°Ï Ãx�¼?ø?š=W´—3¦Ï6^ãz6+0Œœ>�`9(¶q�Ãy’NÜìÒžéÉáÛH ˆxZß?N½"LIX6¢7g“nV=f8ä®uÁRRPíue»‰Ù`ñ‹ðÌqÊðˆ)ÝüøJ6)YDUHæW ]æE-1ÞTû@Ô Þ!ˆ[+:n¿5 Ð[zÐà7€®ë466"¥DáÆ�ŒÇãD.·£ØH’H–•R©”åÙ=ßt]§§§g­³³3¼Öú7t;9‰Çã\á¨ÅF.×RC‹}e®� �¬£])Ò_BØNÃçétúB6›õ+J~7kÖ³Ûº°4ÛÖ< SNÀnÉÛcï3ø @?amÜ��¿ßÚ¼®°wÀ2Pe«¢ï‡—€TÜÎ_ÑNB$�y�(E+G÷�ã:pY+Jf L-*Ó„Ó„œüÊZ³v—IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/nodedelete.png000066400000000000000000000023361506556630100214130ustar00rootroot00000000000000‰PNG  IHDR szzôbKGD¦�Ro pHYs  šœtIMEÖ  % ¯«–kIDATxÚí—ßk“WÇ?ïééKj¢³?æ´ êæ…:ñ²·ËQEØ.DjZM«ÄYë�Âî4kÑt*ˆ¼³V/¤H»•9Ü”^âE‘*Ý.², ïÒ×7çÙEÞÄ4MÚ(c²±99ï÷<ï÷¿zÕªVŠWì_�<)LMÑÑÑ�,,`´ÆòM-/5b‰ Æ ]—ßòyšÃa~™ŸçíÁA>�Ç­Z½`Õft¾§G¼ÑQ>hjâOÀ2 Q¾¹‹»D)”1˜ÅEÖ¸.�=�.9ùk(f†wù2;´&çy(¥0Æ,-(þZ@kf=Ý×GüÒ%kµn¨ë­ïk€�¿Aù�X$QŒ~|¬ûw݆{{eÃø8f³äD°ŒÁ*ψeµUáÏÖ­ã×J‘ÿZ.¸žLÊÚ‡Ù95Eºµ•©ʶ ý¬b_T @pq‘ÙHgÛ¶ƒ�rå’ˆFåHƶe^)y%Y(›×Z›WJ2¶-·@Ѩ”ë®:ÊúúdÄØ¶¤•’ ¤8WJ2J‰§µxZ—þ/Á€¤•cÛ2 ’è핺\èë“; Fkq•Ä1e¿®Rb´–I(õ±¦ë±¶-w@†º»¥’@Õ,pÊV”X”BkÍ®ËÏÇŽ`_¼ÈnÛÏ+Õ‡"VBIgÍQî‚¡£GåkÓØ(ƲĀ¥ ⟦ܯ‰h´`5Û~‰+î±mùä¬úJ ÔÌ‚ëɤ4=xÀGÓÓ˜@å8X üè8ü~æ Ÿ�:µ$”o$“J$èAår¸mmØ©ßïÛ·,êÊ‚âÉÆ@œövÉk-ß64ÈÙ²`ª”³½½òH¾±Q^h-7›š–e@]Y°„Dw·ŒûÁ6TfÆZ2ÔÝ-“ ã ‰øWþ2>|Xü+Õª7éUð¯ÜŒþÿ4ûOø «‡’·mkIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/nodeindent.png000066400000000000000000000032061506556630100214270ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs : :ðd’JtIMEá -,¦‚}¢IDATXÃ¥WklUEþfÏé-}HyتøŠU)•H"DcˆbTMˆ5š¨üP>cÂ�?ô1*QñEˆñAL4‘D¨¥Ñ`«ÄЍ¥(·½·÷yÎÙìî9{Oou“íΙ�»3³óÍÌ–˜¹£w骻å´y·úM>™UPB“ùCfŸ9X9âdÏÊé—œ:F¿¸þ^J.}lýº�sÎ�R ’©€2´b@BOfFÄ€dË'½2C�´ zJ¢ø[ï÷÷íÍåóyáÃx›Éøð=%Ä À3Ê=ÖzkÃkã”QÆf��†á�bc$(6BÌ`f}8³r=´Ö岑rœ½r»ñ :^ÀX%;WÇæGöÚ‚"Ö{DŽœQ`bnϰ|&¡ù¤ (‡Çô^6÷Ó�Ýï—áÍ.î·1.‹œ= ÐxEƒßéU nx7ô`×Gïý`ĈFÐáN1iìܹsV¥RñðÆÀÀÀXgg§ò-ã•¡Û`†7÷¡º¶~  ýL‡lÞµ÷ƒ®ž%ç1'éÈBÇݦ"'áä|5à±rÀL„Ü�ñŠݻ¯õ“ã4,òòø;¯­9¼îü7Ûkeb;×lä§w]ì÷,\Øn�¥\Бþ¯IŒCd+!ª­f @ w²œ€Ǹ$(È™¯ ß9øhׇݎm©˜&H·@U0µƒ'Ê!þ8UA>T ]Є])Æ‚H.€ALX;ï%øÈœ Fõ�ᵃj�!€dgU�QÈq J¹j„=Cyü4\@>”Z‘HOSaÓ7à‘‡Š*âúYàû±íÓ"®aëðýƒvní—�Û;ÜŸÛÇ¡dà óèDI‚€ ‘öœŒ· M:¸?ln^ÌÄ̰ùèêQ«æ<�š*¡$Çq¨²£ÁQD\Ã�³¹æ‚æž ¿> I=ÑôÉ¡lðÅËÏ>7) j\„T50‹ÎY�ïÆÞÀØqbÃî»æ¾´Ò:b ¹zÉUåÜüñ;¸ëŠÖ$ÎÂ�¡‰OÓ¥ý{F³Ùì&áb€Á¨¨"*\@U•q ¡*c錵`0$Gí8¾q0â’CHâÉÎ$3šìYn¬;¥(:#òñËÄ®XjÍœç»#&ÞõÜE>9È· ô’4ôÝne5�}DL|kÂM‹§¯¹)âÀ)ENY"ímœbV¡—¦­Q QU‘-KüUé³ÊÇ—L¿ëƹ™KJ‡ ènhǯ}Zgþñ3Û§êš•õØmN�C¹à¼µOË8 _>²r.hé1áïj¿5*¼¥cc�¹7ý«ÑÛ~óä4€PV� Æ‚—·,])ã˜ëKßüú½{޵¾¸±õi'¨®ðÄ<“žÅß? ³Ÿ¼µ|³ÁŸ–Q[Ô¾jÙ즋&$‡q¼@ßQõpÐsÃ�RF¹gS zõDÒ\ÚUÉö‘)š@ Â‚¶åËÛ¼™e�øT‘3)5 Õ‡vY×D]3òÔÎM‹ÚWÞæuÔàˆCÔ—>ˆž£À£)šOƒìH7£e3î逢<´z33ºÏ5ªpÒ£¿ûóu±µñu=´Øð,6œqä@”º=Ú½ŽÌ™üÔCó7äOlú?Y Ô…c@ÌÜqÛ}�ôŒTŽÞRÿÈL?Lí¥¨©�†|ý»Â¿Ý¶åmúG k®¼ç™Ç[2~ò¤&B¶a¤áô F8Îð¼)hçœê¾}£Ûâÿ ÎmmB[sSünW†Ëò,•Ÿ…!“ÎI•b ªS®@ú='NsÀ$ÃÜš�Vž>'•�lG5™-¡*�ñ*’ô²½V,tÒùe»‘ÞS"É·OƒbYrë@›'íßµýká Ýdˆ ™¹YJvËgÃÒj–zó5žŽLöˆ7ãºûÕ?M=—¿>/IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/nodeinsertafter.png000066400000000000000000000017101506556630100224720ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  šœtIMEá  .÷r€UIDATXÃÅ—KhAdz)>J›6�ú@Ôƒ¢ô¡mJ±EÑÒ‹Oz(ˆ ¬P¬Áƒ{A HAâEPïŠôT5¶µ¾{(ÅÔƬm�q3ã¡»u²nšûø d“0ÿï7ßcæ h¦”B)Å|šÁ[‰¶ûS>ÚuýúÕt(Ì&“ÖRG@ Î ðÔölV ”ž·•>¿Ëÿ“7ïm@+˜½…fÑÌ @#PïD2 gR ƒ9”¯·ú(­/Âùyàà䮩©êê–7TV.iuC³.€_¾ŠØyPæf°¦f¹X»¶‚ÆÆ•”—/®UJÝs³_ 2>Š»�š<í*€n@ï’Æ?Λ6­`Íš ¶m[ÍÈH€X,QkYãa?€Å>NV9¯|ö\½Î÷î]ŠªªRFF’Œ�gˆÇ-~üø”DÁÜæ�0êUoii)sÙ××ç>·¹½ëD‡oßÒ<~ü€xÜâíÛ$¶-ˆÍÀ2o¾zÕ;::ÜÇGÀ?  ˆæÖ�àû÷ŸÅT’’¶-¢—� !qz äªÙF „D�‹jãÂ? af£=!ƒÆ4ÎuÆÇxçþZxG^ï8–ãtàrùsÎ÷|Ïãw@)%RJ²)ÿYr”诽|9|ª¯ïÁ¼Û]�‡õ� .�Ë àÈ㉄@Ê$1Ò³)럷ßj1aJú¸’[@‘ƒ s“Ö'¬³çÔ€LŒ à˜ƒþP6»À‰"ï&í›éPk î ?T¤H•|Àت‚[¡Ý´~/�rpÇVl À§Èup²×zR‰'EÁ­– qáĦG0e×655¥¥xhhhÉûA/š�(“)í;¡P¢éçÀo»²­­-yœ $e>‹‘d®Í8ñÀ{>x™à2TR AÀ»q—Ëõ´µµõƒåü!Pi»;¢<¾Ó°fÈœí /Ì-€@P–Å×c`—]ÙÛÛkooïú­åÙ:èÓrEvu­açtç95'šH“‚2»rttô¹ây¶æÀ€ƒþÍ&í‹tSw«ïŸÒªÁt2.7ŽŽqÿ |ù²†'z¦ˆžž¿Új·†ÿ3à$ÐþuÛðG†ßê€#ÖÔÀõˆ.ð¿uªÌ]t~¸°5E`ʪªoQÑŽ��„ðW9˜Ì`ä+™TT”ˆ ©«+%??·RJùü5öf¨ ëVœKª«÷°!ÍÍû02ªÔõ˜g#mÂÚV îˆúÉׯŠ‹ó‹Å™œÔ™›[rà?¯(ý‡�ȾE�TvA0==Ï«Wß–r<©31Æ0L ¢Ø­ˆ†Ayy9¦i"„Øð>`I‹ÅšWeaff�ׯCÌÎ.b& pV|4 ƒÆÆÆŸõõõIçÅÝ,"NÙŠDæ-R–ƒ ‚_ÊÝ~]×õ½‰D¢@Ó–SþÓz7ïö�‹n·{D©€à‘ý[›t÷ì¼@>àJñ'Ç}@1cPùèSü’�·íSßð*a³ßŠä¤Åâƒe6v×øàë;¬l,³²ºL­^' C„û)ŠJL�piü2Ÿõå_+‡Âä~3zöc‰Üô(É ×Þx—Ñásäξ„�"ËÝiš¦íƒû¥oÛÇ+4úÂ{þìôÀÎlYØŽÉãïVÚ�xZø�­�-6 ›A€¢(Ä�81=Æ¥ñËÜø�g>;³%ê[ ‚r€f«R?tÅ]¨¢g¢Ü¼}“;nI;³erÓ£Œ äxûõw872FÚN348„¢(èÑ(Š,“Mgùòûû{ðM� `;¦¤%›^??ô*îôÀ…ÌEa;&k?l±XXàÃoï±¼þ„�í ªµ*g†Ï0¿8O­P߃»!¶cJ<ð×ÄÇc¸ U:Û!sQØO®±T\âî7ïS©Wøeå«ë«ûO\�vó.^¡�_ Ðlµï*öŒÁ+vóþwLŠn‘ùµ<€°SÝ¢˜_Ë‹k¿%Fß̈ìLZcºPâ²Dv&�1¦£<¿KlÇl~òßþI«] êUùyu®µ¢mÙ™´HM%ºáqùxðö è˜‡Š˜ºîô…�\ÀÓQ­cÞªmn½ÜaOXB1zÃŽáØÑÙ‰NO �Ë'û„µD$'­¶ˆìLšÔTâÅÃÛ"&¬}"¦®;§ï剖»O ~pE[ðÎ1œZôéGçþ�düˆÂXņÏIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/nodemovefirst.png000066400000000000000000000022001506556630100221550ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs þ þæ%xftIMEÒ246µÝ IDATxíV]he=ó³³›jTÚZÛƒ ˆ(D”¸û "BõA%ï’¬‚`À‚�úPP,⃾íCiikš4âŠ(VmjbCÔ4»³;»;ÿ3ŸçNY%“Ýt7‚ äƒ³Ã~3sϹ÷»çî[k«ÿå Üöö¨¢~�Ðþõ<„ü�ŸßUW?=""® ŒÍˆõ}¯òÔ¨zö®ç°h}‚‡ÇË ˆ&ƒ f¿ÁúVýÐÑ;Ô�ò‹ø§Y{%SÇΛ�%Kð>¯½J1‘ö*¤¯ <9=¦žß{‹…Ù,~»ðÒ*Š¥!ìÙ_•JTyc�è¹= xüÔ˜zfìe,”f2ò’™ÂGÍØ�ÿŽ’¶ æ×_j»þ$[ÛÉô¢ox8É÷}ç}žó~ïs¾»±[�Ý üÇP6ò¿ð}�htjÐ4‡@E-Áe‰\¥€l)�d¡€Â’…lÊF)ä“ òq XòB)zË`Z' : 4�Wþö6"1ü¥ƒ!Vx9».à¡–Nt;0¡�…èÀR3XÔ&‘WÌ’�TÎ@Á´Q̹\錅ØBÉ…,Ìù”2 -BŠ)øÍ»BÒÂ/i¢@TE¨+3ÿ\µáCÃmg.�F“Ø¿nJN¶†ê‚Ç¡Ãeh¬àr©ðº5´øT*<ÍEˆ†,„³èäÑJÕJðé�1a;á#X®åØ(@Ž*ßœìÄè8"†àPÜpˆ&Þ„›%uªèÂÏq?\•f8ì܆Ÿã>†¶.KNe*92A^•y›î ÖmûF6äˆØ¹�_N\èÁaëèpÀm·¢Ñ¼zY湺b@U4ö `è¬ûG©�<æc?%ù›\Í2 AÄ™_òT£–î,f‰é¯Žþ|ìøXwU„&à3šÑTº†€"h$×(O[Ë* ¤“6D”ó >ÄCá·˜g‰˜‘ù™Wæ_°®œ@-ü5[ÆG]£8ï|ù’‰™Ü#>˜ÌÙïyòF)¡øfð+"õÍt·>ìu€ò²24>H:ãpø¹£…¾{k�ª]å%:ÿ–Ϙ)O€wI�ؤ'3¤§Üõ°ê—ê¿9fMxýØ+ Ûµ•uœæDß©ëã�=÷>Êí7m]áÓoÞðÀÿ/þÙN!¢ù>pIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/noderename.png000066400000000000000000000031331506556630100214140ustar00rootroot00000000000000‰PNG  IHDR szzô pHYs  šœgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÑIDATxÚb;ÄÀpΗ�áFƒÛ~!Ž  ¨0±æ ± AÑ´‚dàá]‘xÄ??00\ÚÏðûÍ †w⮪ ‹@xKŒ¹ÄDRp]ÒÀtm‡ÔG å@�_@üˆ?ò0¼xÇÊ ßÂ7oõÁÃÄš @L$§Z Æ… Œ@ÎK6`¼°20|àË�û¡ÇpêÆc`‚e›±ò(QÙ €Hr(þ\YÀÀ!ÿ”�á+Ðò?@ÌÄøÝûÂÀæYÊ #%Î &*Æðæ (nŒ ™ @,¤¦X¦—­ Œ’@ï?cƒ|†;Ãsi{6 y†ÿ3021m&@‘ä€?�0°«ãþ'àÅ,À‚áƒÃëW_~2°³±óå†?ÿˆw@‘䀿�»ØÔ�ñý š?ÁÈÍð„QŽ�KÛ–á°púÏüŸ�éñ1 @D;àßë Œ¼7€ÁÀÍÀðhó`(ð1|ÿö“á‡N '+3ÐŒ  ”GŠˆhü~2—�M^‚�á5°LfâoœÀ áe¸}ÿ'ƒ€¿/°˜þÏð÷Ìÿ™‰v@å€ÿŸ00þÚdÈ-þ ô"0îð2üþó�á§a:'330{ëPyðèFB! r!0°þ ‚øJèwV0pkèÜO¨›�zÿð3Ü¿v›A4/h'ÐÒÿ lÊ–ûû›äA‚ì@ÌÁÿ�q(ÿ €ð:à/ÈòO8XMr@á tüWn†ßÀªñ‹Œƒ(�ÿÈ…>###Ð!Àlw((ä8–‚½ûTý˜‚ÿñ^üº‘ùÁfi9ˆåÿ�Nbâ? /ÝgñËWPŒŒÌà4  ›�áû�_ ?¾jàH–¢ #@átÀ¯ÿ�b—áÛnFvPð¿ºè‰_ÀPdã`xýCŽAŠ_œõÀ%䟟ÀñƒáçÏ_ÀÐ&Ú_¿aÉ—OÙÊ @¸CZ’ÿ} òß< à `šõŸŸáÙÅ‹ ¢þ} ~ÿføúõ;Ã÷Ÿ?þmý÷¢‘‰‰øâ €XpÅ=È[ ŸýüÊÁÀù׃׀œ— ™þ1<ÿ«ÊÀÃÂÇðûýp ”AÁõXCš‘¨bŸ¿^§Íeø ŠJF Ï9ô~1ÿe8±bƒ€wЮ¿�@d„¸Øjúœ¬ç^Kÿý€˜úGÿˆOèƒéû_D€éŸáûû· §Ob�Mèd`åæ':� Pʇ(€Ò�fü�ßR(¹ó?@±`³üÿDõ{öú{†‹371(›>ʹÓÁrÿÿ!œùªøÿ?ä6+(íýüÄÀðüº¥ÈöÁÔòëóqÞ' Êi ÐD öÿ �|s-( °s;; ''(ûÿùMR8c €X°•|°øÿóç/ƒ‘™ƒr@ Ã�Ÿ¿jþ!|Ï ´��h)++$tþƒÊFlFb„ဿHÄ ,åL“K!¦üg€ZÌ•À,÷XJ1K!p¢Űàùm< ˆä6!,ŽÙ€qÌÄD–v@`~üc0@à(˜0cÓ€9 €`‘eLC;Îâ“ FX>(`ütþ°¡örIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/nodeunindent.png000066400000000000000000000030761506556630100217770ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs : :ðd’JtIMEá - êëmüËIDATXí—]ˆ]ÕÇkï3_™›8iŒõ‹hÒª A’XSƒ”ÖB+H”Qi¡)ø`óPü@(´OmAúP¨–¶HEЈéCklpF¿J0Nb':jM&ãÄùº3÷ëܳ÷êÃù¸çÜ{çvZ»‡s÷Þg­Yÿµ××^GTuÓõ{÷ßë/¾#è A$™�´Ö’üÌÌ-…*9>IùD!¦%t‰7)?"4.|&͉ï *!W=pèþÛ.Ù²ï=NÁyÅ>Y{Gü¨*Ë ‡Óô½Äÿ£ŠGb¾„ßÓ#m­ðö¯ÎMN¼hà+—_ºu°¿? °oQÅ6· ´@5ŒZ`9pk÷^C2T¯šœ"9y ’¨â”X`xj�µ€G» Hü7õy™…ZÍNŠdÂ5y·\wx”rÃáE²“û„׋Þ»d­b2š*a¤™ûv}ýoÇ�=9O>ÐÒ)¿>9;]˜œú¤’*O[€vÎy¾dö‘BQÕôš!Höó±™¶‡Æÿ:f‚50Užœ>¸ÉÍþ àÐåG6§„�·Üýòöo|û2UÐ$ÕÄq�^7 x]¨5ôÂJ]U>|«Ì«Ï\D>ÌT@T²ýïÏ�¾æqÛºi¶iÛµÁî=7mÈ¢?MGÀIsõˆÏÊ!g+Mª€K X�r ˆ4ì4x2Ÿ¾gR�m'äX ài&ˆp~%ääl……Ѓ1­Ç&sš†NC"B²™�ˆ�Ÿ�D©ôo½ø×±UTÛè¿P‹ûx�W>]*‚Û¸1q…Í,�—«ÊŸÏœ´ÈÀà¾�?¤æW0b‰Ô#èô›_¼ä›Nk„ÎëùÅå(-ÁÙIE²’ž­?}×DÄ.ðDr¶~zýøüÇ`sÿ\5t3CSkxun¨žxá–�O¼À—q ¨ªŽÍ?q`È^ÄÕC7cÍOèj8¢^rJ\÷­_10ìãS¶.�Ö“Ö€d]Y4LŒ !ªðÜìCÇâ ;×ßN¤ ¼¯à‰pb»an¬pÓ�qå ¥ØßÒtíûSã³LŒý,ˆ4ä¹ÙG&SI߼蚾Š#Âi# ¬ö¡½È _xʘHClùÅ×â*¯/=MÝWh¸ ¡¯Qóe*Ñ<)}uR`Û n»ì i¨!»Ö؃²¬ª¼]>BC+„¾Bè*Tý"ªŠªö¶@j~kº[!SÄf" Q„­ý;–öl¸ëÖ–�+:òÞÊWí±„¾öŸ\PâÍçÿÂ;G»!’\ü¹€\Y0@$'—�î(åèÜc§�>A¸lðzT”³µS_‚­�uÃç?aˆéiȰ©^7ü�}@Yiýe¿¸ínÀÚâee MòkÁº‘à«å�¥ýû@^HCY%×Sá=3@Š—‘Çõì†ÖÙ‘ú ¥ï?U²›žÍ^.~ðÑñ…Ì¿&çßT¸äf+ÅËÉL�ŠÈµY=GÉnêÏï»÷¶ƒ£££Ëÿ—,øão_¹æƒ÷/ì-4��iL[š9RC¶í¬t4š=Ó¶5j:Μø]pòLýöKððO†úTZíõL5â|%j™ØjQ)öe¨m¾–Õ}_ˆ‹„ï­£³üò¾?©ê×õ1<Зõí8Wuð¢@í&½ƒÐ´Ñ[&q[•÷KM_Ì_# & ¬5Z`µ:�fÁ­#?ž_þâ¥zèJ„Q_ü%$BÝÁb=Íù87ñ·ÙU€Ú,$9 [75ñ×§þa¬A“ éê€sk*�ÎB9,öyݺ éÞŠÀô”Ü¿§ê­7¶IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/printpreviewdouble.png000066400000000000000000000015011506556630100232250ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ  8ø‘ÓÜÁIDATXÃÅWËŽA=U] �tæåΙ…2î4&:Öš‰¯•[ý@p'®|Ä8k„É8Æ%MÔ4q1 3˜tC×uÑtÙhûa27!ávÕé:Ô9u눗úÆ ¨Ýéâù³§¹'"p/©ìí ²·“hñz­ £gÂè™h4[ùY=Dùþ=Ãá�f+’çÞ�¸�~ãü|¢òr¹Œæ‹W�<+‰D„¦òÛ·nB×Ëhwº�< FDèú—îO°_?Ïp½rãñÓÉN>ÁèìõZ•˜–-“@XeÀ¾1ÀÖö:Þ¼ýlÙœz­š&ADî1\¥;çܯ³9�NéÁÁ=6™L0½°ÇŸNãÍ…Iðºïêz¹ÿîý!ÍfŽ æiñ�f‹`¾‘ÍMÛW6P½{§²µ¹ñõc÷ˆÖ „@¼Ÿ„ˆûŽ3G»ÓE»º{7v÷¿ûq”`ÀÑJrqGfñ›_n+"Ê:^ŸÀÜLdÃM<´o†Ý·là¶­Ä"êª=3óþòn�Wþ o^2 t¹&ª/X<ý-`)�NûëX6®E!~÷î}ŸcûS$6èm£%?òªW¦óüê¬Á³³àAxS–<ñU`®1Z[ãzÛ¶má±;ŠþLCWñMøî©"§'«Ü!² }©(!Wô¹4§€ 6eå®Oõ2ù˲|Û¶å*ãoíåE4ƒ¾¾>?*Ù¾)†çËU8þ\™ñ±$Çö™<:^às·j«ttMa÷v“kK‚+ òÖ¬·ãõ^õâ•�=ȧ!€ø p‰wè”+²%ÆÇ’Ë›ÆÇ’üäy§¥ž�ð�CqnNÔ”#=Ç� 7E`xÔ~ä·1{¹o_Ž�ýðÙ[SÑ&æÇö™|ï™ÙÓ¯¬Ò•Àö”à\¦¼¥-Y±3ß«L]°,«º)î�M©.û;)¹bM´ZãcIžú³×R?Þiðõ¡(h±»€ÀP†¿óæà ±�|i`?€r%Xzc±-‰g^mÖ-”|þ•-#Ñ ¶mh¢rd'«W‡jç“$_¢äˆë*ÍϾ<Ï=·§Z’xè—‹ìé-óÞ¢Â3}+ˆÎ,Ýû� uC›»’š÷¯þÃX—Äé·›²™üm¡Y‰šTÔÈ `®Ðb$Ì*ÅÐû·Þ�¶|ñÇYãcIü0L±°-i*µ†¶”/ÿX4t»æªíÍç¼–q£¡ã8n5lÑ• ^Íšð΢iP]@U·\—guë_Îüúª.„¿9Wg¸ó8sЇ©·‡ë�ë­mük?óH˜+¨ï5œ9þ´ež¾ 8õx „ •Ï/åçùd_g[Ï1€“Ç[Ê¿ù‹%±Ö{33¥ÚùûÅ—Ð(Ž`Û6G‡•é¬j}ů·¦qzÌ€˜ÞwZ« <òÔ|[}§"È^½Ró^ùíÏ�€|ãŒå¸�£™ç2—gøÂžO`h×ÿI~ÿäUº¢íòE!sy®öàfŸ$JÈÞr~Ú¶-�Zz6+?� „zÇ|¾Â@o„ˆ¡ahÊ*œ{»ÈÁÝ]üèwÙ–:†¦ âóÚT޲ëA5÷„eüþ �òét:hÉ,Ë’½LNfå®B5P_™«ÒŸRé0£èš² ç/–8±ÔR¦k ®SæÌ…%'4®=÷<0 ÌUÛ¶›gBÛ¶±,+¨“ð„vøï3.žPÙ¶QÅÐUt•u¡HŸ‰–yý�<ž/�g�k€S¿5µ¬Ò###*Ð1áß};‘žã(ÚpÔP¹ys»zÉd7šÖܪƒÀcq±À;WUÞ›-Sñ7û¤}ñB˜t×€rãXÞ¶M„$b@bBÞû Zì.m¨.7#�ê®åð|ÁÇ©6lþ4~ñ%K{ö�a²Í¹V·£5¯f###J8½v=•#;1º÷£FQ��°¥†µÚËT2TsvXdJ@!$PüV—Õ뺜†Ñ0ˆ˜!báêr1p'„»Þåôß»2F©V~LIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/printpreviewprevious.png000066400000000000000000000031311506556630100236300ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs íÀ,tIMEÓ *•IMöæIDATxÚÅ—]Œ[GÇwî½þÚ¬÷#.Iv6�P%¤‘6{¡D "¢ˆ– )/-m +ÈCߪ¾TBJ‰‡"õ¥È"%´* UÔˆ ‘ºÞî.]ª¶†lƒãMöÃ^Çö½¾3<øîÚŽílŠ Œôð�3óÿŸã™3çÀÿyhÅxìÌô.PGAŽ£(Ù´‡šAɤwÉâ|�étZ},ÆÎLŸžƒ$ˆˆXÝ@:8ÍK&�þ+–úù9ÀK§Óò?0vfúšx%¿ˆÐ!Ò‘A"Ñ8;’%>¿½@Ù�‹×F°j‹à,ƒòe8O[üò€ÓIˆ¶�×çˆo%²é|ûÁû?µ‰û·'ˆEDÛšÜR�¿þ}•ËïÂ[×L¨Ì×'÷5‹—¾”Òé´¿¡€ur= ÉûyôÀ¿xè`Š�MF×h©;¶º<[äg—Ln.,€_éÍXêÜW�ÅæHè]É�;vlãéãeŽ}nÓø’¼ñv‰l¾Æð}Q©Z0œŠrhÊ>×5PÁ–¼Ú÷Ù!¦gY–ŸÉdT›€±3oíºÉðð0ÏœTìÜÃóU®Ì•9u$Å;\¸Zà¾>£ÍÆÐ5öïŒs«$¹¾  >“÷v]s×CÜÓ— €ä~ž<´L2‘ Zk¿IsóUNI­ÿ>u$Åì?«]ÿžoMró¶Éÿ(C¤ÿ,’)À<½á}æ4¨ïâ± ìÙ„¨6¼ŸsZÈׯµ›NG{/P(`gJòf¶¼Ò¶¼Ü[Òf¦,ËrPò 4“-©^öŒ8Tœö«»Xô:’í›G²Çä£K¼6a‚{ÉË€mŒ}ï­]Àab›ùÒîeü ?Z lÙ•üWWîJîùŠå’‹B‡Øf°F'k'öZÑ …µ 2H*Y¢b·{Ó�üÕ?/u%^XqøpEãjn¸ñ1bƒ½fßA`jMÀ(ÀÖ>‰ªµVïOßrÏäÍkWÊWs#-ó‘h@Döñ†=Æ@Ü¥|‡÷O=¼­«‡Ý¢Ò<·ž^&]š "Ø�$Öȧ"F2êR©ÉuÜ�ü£ŒËß­9Q= ”˜FsJ®xnÛþÿ²�k( v C¨ÿÛzüJCÁz18kQòåÞuœø±÷±z.Œ¼Ï‚ò@yY@ašAÓ©Ø>¦Þš�¿üCÉÅgÅ]7Þh˜M/Ží¸á]Ë¢ãÕw–Þ%Üe„m8ö£î‡ë^†.À]®t Àa 7�½ˆ©yÄ�v|ý'Þ=‹ˆ{-XÛÃÔ<°Aú³VüOóë©�Hÿ_(—øôpOG²Ç_°9ÿT²£ˆÇ_(m‰l®RÿÿýòëèT[Èd2œÓfóÂúŠ_+oO $é�ÄŒvüq²Ê׬DÛæ—¦ow´_ƒ]“äo\¯{¯½üSà&Pl>]�ó @v>GÌðè�ºñìùmºÙöF]b†Gv>W7tò/Å�z “ɨ“–‘Ï« �Ç—Š5vEˆ˜:¦®µáÍ¿•9¼¿€ü*ßÑÆÔ5>™)Pu>>.€Ä¤ÿÍ#DúÏ¢écQSðÉ­ ö IûÐu³eMx¬¬¬òÎ Á‡ UjžéÏâä_´¢¦ÂCw ¨6—å]“PD ˜T�>‰{M]›�G ÕW¿ÅK«>¶Û´Xú³øå×-ýÕ߇‡m (têŽîÚš���k€ôý“µ{1û""{æîðI Ÿ/KPËâ2a’©«¡€ àwjVï©9 £a†‰‡ˆ…ßÄz2«—Ú`‡p6jNÿ ÍJö‡WÞIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/printpreviewsingle.png000066400000000000000000000015471506556630100232460ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ  (ס:çIDATXÃÅ—?sÛFÅ»w”Ž&’cwI‘QÊd’8v&½»të|@«Œº|�äqÒ‹J ºËX–m)&pwëx ø_œñ6��ÛwïÞîÄÌøœá.¯×zéäôŒßŸ?»ur3CÌŒ‹Ák¿ûš)2·’fLR–ÀÌœ1³ÖïÁùÐ6�ÁùÐÞ¼yg/ŽŽm]W²PFF >|¸éàåå{®®®›çûýþp ÝD^QÅ;×Aï\ë¹øþ›½½þÅ"kD�(Ùh{|uoŸG¿<8¼{°ÿï<~ÝÙ«b0jwåè�#ÆÀÉé'§­×¾ãCàå­4J¨v0†ÀÓ'�IѸ¾¾ææÿ¯þú{{˜«ŽÎUšŒF#Ê2V÷U7¢M–ÁL:˜DˆÑ(F%e¨*;½"²Ý*ˆ!cìàhTR)¥ª*¼â¼âý$Í‹£ã͘Y•($’e]Œ±j¯"¨*Þ{¼sôz½fœ»û-~Õäµôe™(Šb¼¾mL©^ï–&¦­ãòíÕú Ôõ_–‘¢(ˆÑPÕªœ*Ný¸2hî×ñàçŸ6[‚PFB“F4v} U«Æ¤Ò¢ 2é�Ó¡+¯ŒY¨[r3É�lè\É„¨uPÓ„àÄ„Ö2áF›ÑM¸;Mf%µ±êÙ™–º˜–½Yû<ÐÌ^Æ®^JðÞ£fÍõÆaw·ÝÅ. ÜöçüßþúÀ?À—ÿ¹‡o#š�ÓÏŸ•m%å¡"IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/printpreviewzoomall.png000066400000000000000000000035651506556630100234440ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGD ^š“… pHYs  šœtIMEÜ  (" NõIDATXÃÅ—kl×ÇÿçÞ™ÝÙ·íµ��mÖ^;vH,‚ÈÁU(��XW Š R!ß‹¾TúøÒ­©ˆªm*EªZá¶Jû±FD­ZySZ(ŽãÆØ�.±×ÀڬػÌ>gæö³îtcìµú¡WºéÎÌùÿι÷Ü{. !ðÿlÒZ/‰ˆlP   € € `À €xNoÎÿö9�â—Ò†Lá­Ç�?tàÀ�æ–––-UUÕ•�Ç�H$žÌÌÎÄ>½{wú;ÿüQ_áÿåÝ�€ù‹÷Ö*œ"bvìÝ»÷ÍS§N½ÞÞÞ¾]¸§"|üÉ –—ãøÕüïV´¶bÄ?S|ç‘#GNŸ9s¦£¡!Ø|ããü­(2“‘czI�ª»s_àåÚ£w^YM8/^l[‰@~¾ÛÛÛOŸ;wîD PßüÇÿ<7ò(Öëv¥ªª7;+}.Ÿ]–d�Ÿ|°·i5ïó≞(E¬pk8€]]]ƒÁÆæÐ߯ÍÝÊ”ÝrïÜ)«+6—{ŠÌ\B€À�¿:’øî{;<«MôD¿lÚÓÖ`ï›:;;íÞýÒ¶©éiÜ^baGp{¡¾¦®ºÔÕ`“X™n@1Y�óâóï­x�vvvÐdÚ]À|Ö·µµ5ÛívWøÁ\$îßši®ÝTUâ�«!`·É•¸ì(s)øÞ{ÛW œûfÖ*úÚe´µµ5¨·Ø_€¨ik39 sÂñ¨¢b“Ræ¶W„Ý&q”8íð{”{••Ÿ/tß‚B>ß=ú8?–Ëå kÔ˜v‹Z@…ßï/Ïær˜3¼ñZŸ³J"8ud“9œv ŠM¸üÎ}ÄS9,$RHe ’9Ù¿õ•þÁÉÛCsÙ\¶Ãï÷—¨( àæœ»ˆ1ÌæUbŒ�8#ä'”ÁÆ8˜,K˜Ñ*c œs·i·h€T,Sv;êK$éü¥Ý­œ± #‚fè8öƒ¿†4C «ÈB Ê¥5RKeY±+ˆÅb*€ÔF€¥™ht‘Ð:q¾ùn«×i“²gúâR,�ŲšÁR* Mסظ–5ØÂL"ûøÅ2æ%"D£ÑEK«� k̆Ãáh&“ù¯íõìÏ[mù�ßýúmÌ-%1O!�Ñ 1¦ &Å¢ª™_Ž'_¨Tj³Ù ÂápÀìFt‘ÁÁÁɉ‰ñ¤u�σüâI=k@× ºf€s)�Ф™‰eºymZ½ûª?Qâw+MãããÉÁÁÁIÓnQY  „îl}xrµÏþl«ó‡Ýᆀ�K6í¡J³Ñ”>9ôðÉýƒîXéžÇÎééúúú>oÀ�0ºÚþ^Þ݈ù‹÷pcÁ¸ì”¹-“3ôÉÅT™8{»þIýK¶—/ÌW]¹r%yýúõ¬iË`y#‡‘ä9½9Wxž¶–=]ØSixÛ7‰êçKÙsvÒŸCoooRUU§ÛíŽ÷öö^ 8Úè¬ñk!D¨ØÃH·zkmïw\@kk+œN'$Iú¶¦iH&“»9†«W¯&ÇÆÆÂSSS™ýû÷·¸\.ï[/WÛåHK—ÿ¥—Ö‚X‰€÷­aOôD¿`{ Øçóùê\.W•¢(e’$95MK¦ÓéEUUg———ïG"‘�¤|>ßkG·m:º•MÚ¼N‚G!ãOŸé¿ÿíMí—Ï‚�òâù�'z¢Üwø,‰L¨PbާÍ<d®ö;lŽl|ŸgI•#F`‡šx#èæÉ*¬hµšÁü˜�Ø-].Hݬ¥k^ÙVJgÔò¯“Èç¼N‚[!ýÃ{ú¿Ñ.èËïB±jQjRjD”IšQ‘L0fn³ÂìdÂõ�>v‰éê¾~ŒQ¾"üp?ÉtiX“ü€ADk—å&ˆND†™ª†)$› yf�Z.�í¯ãG‰ž”‘à‡Ÿã'…ëÑȄХuóô©ÌôÞ@1Ÿ6sŒDn- §]~u “ˆ=…`_já'@ ža þ"S¸š�›ÂNs!Z×D!ÜY"]zm ï ‚t¤™wÝ�3býŒáb`�LÏ /˜ë i|xAÈ€Î_ðƒd–3âýŒ€¥bþ—6<¼ @7Þ¨çoŒÎ7þpGÀ'ëÞ ¼ÑÍTËš^çÇž5²p¯/ˆÔ|ZŸ½¯Š€~q­ww°,By‹°À0aÝf��2¬,s=·lL’% ¥g¤¡@èr–®ÿÅd÷xŒ±BDIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/printpreviewzoomin.png000066400000000000000000000032401506556630100232700ustar00rootroot00000000000000‰PNG  IHDR szzôgIDATXÃÅW P•UþüïáV„Xn( ¨”Êfˆ b¨¸ƒK²¨¥ ¨áhZ*Æ–’(‹ È"È"©‘ 3À ˆ ˆ8¸å0ÓÔ¸ ££ït>º3™=,ëÍ|s8ç|çÜsÏ]þ‹DDÒÿ‰ç;%IÁËpdx2>dlÒSØáWü«ˆ�Ç0-Y²$1!!á,ÿÚ[[[ïvtt¨!¡Ã?x‚¯øÇðO‹aåààœ””TÙÒÒr�AÇ�§àà` è–Ða‡<ð‡ø.@ >ÅÍÍ-¶¸¸¸­¹¹™RRRè=ŸUW­æ/-å¼6�ûŽÃ�Ða‡<ð‡ø¾ñ§õ¶³³ ),,lkhh !¡�Ó¯9¥ï•¦ç—?î“ü¯&n-J‚„;üà��8Ä÷e_ô.@fxÄÆÆV555QLܾN›U[ó¤•)1C6�Ü;ó@CüÆ’k9ág:ŽBB‡~ðÀGâ‘ù4.@ÌÞÔÕÕõPUUÕý’’Zö�ôAæ^iSEجŒ[Ñ©�wO¼».Ž|wd$tØá|Ä!y�O“.ô Í˜^Q__O{â⯎\—’üúŽªH«´Î�É-��]þE}Ù'²–|ân$tØá|Ä!y�y5-@ÅX�••u½ººš#Π½s3;bBk¥7ÿLÍ�è¶Ë×Èe?$tØá|Ä!y�y5- ?cKiié½òòrZ¸-%{RT]ôöŠ;’éïAök hÚö²ÙIÝ:ìðƒ>â�<ȇ¼š0€~úôiuee%� :rÐ:¾5:úüÃ\É)ŸTËIÍu2ê¢1ŸQ·„;üà��8Ä#ò!¯¦ dlåÖÝ«««#Ϙo2,Ú¿ ­}œ.y\ É—I«ï÷tØÙøˆC<ò òö¥룢¢nbÅæžúvè®æç¢»#ÎSZâEªÉl£iù}’|8€%tØá|Ä!y�¯/Àðð÷÷ÿž�•UV_™°«&zxâOÁ6GÕ!³ó¨tc5K‹ÚIòä–Ða‡<ð‡xäwAÿ¾œ‚·­­­³’““»)¶°²H ¿ºU:ðp£I*%ÏÉ£Ji/Ç2` vøÁqˆGäëË)À=ðÃ×ËË«žïuª;áv`ö¹$)ò‡O‡'? µÎR§»£³ �Ò9Hè°Ãøˆóôôl@‘O»/7!–ÁÆØØ8Ž[x½¬¬Œ/6ÿ˜|¦©`RâµH´Ùúȃ0‡ÂÇ�Ða‡ÿBÓÅÛàûùùuÕpžŒ‘ß„½¾º gSSÓ ooïë¹¹¹téÒ%jhikÍ©l- (¸œh%:ìðƒÇü.wwwòññ¹£««›e6Lë0,}ýb/è3\ ØÛÛ7p7ºøX>4ííítãÆ�n vø™×ÈüZ Î:m˜7áQº›ÎÓÅå’¿+âYïQ„#ÀÐаÀÌ̬ÖÖÖö–££ã}'''5$tØá�±†gž³jÆøG‘3•”°@E™î:O½Í察WÄ_½ˆTb9 sĽދe7c?#бMl¶¹ŒÑ “aý™“eõ¶©JÚýŽ’.TQ–‡Î“2–cÖ³öÄóÞ„²Ø˜ØÍCÅ xhŒ# |Cp1˜é)N|ÄEÛ(i�£’’œU”ÍEøXÈb2Z"¿BÓW±¶ènËWzb‰†9XØôÄßnVúм@3Yýù4%í�¥ê."g±Î“•–r¦øLË¿¢Ñ«å�Žôc¼"Â̇‹ã6ŠaÈ0ð²¬(2—Õ!¶JŠž­¢C.*Ê]ªó”——Ô†²» ׃ëöZñêy‹1™aΰè_‹ÁŠâ Yf§¤Ø9*JuUQþ2õ K9[!kR€–˜ý@1kc1¨%c*cc:c†89=€¾ÁR_qb“¥¬Ÿ®¤}N*J[¤CG¹-¼ ‡iZ€R¬ÿÆñþ·á¿£Ù 'q"zà$6]QºÙJVGØÿVÄzke9öJwWÿƒpü>æ"Nn™"«—™jãÕì%NP¿—½ÓE¡6 ÿQ©â;a"&¤z™›Ð\Ø'2ÞdŒ�!Žì�6á C#¡�­! "&1 çþ Ñû‚þAÉnIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/printpreviewzoomout.png000066400000000000000000000031761506556630100235010ustar00rootroot00000000000000‰PNG  IHDR szzôEIDATXÃÅWyPÕUþ=x‹[‘ˤ ¨!æ‚!²H¡Ršâ@¸Å&% ¥è((5(bF¬ï¹ ‚�Ê¢ Ãj! 0ˆ!»:˜Ø`ŽÓ-Ȩ…ït¾ß\Œ™Ê–õf¾¹œs¾sîw×ßE""éÿÄヒ¤`Lf¸1|¢õ~ÄÿªÑñ$ÆÒåË—HKK;Ï¿ÎŽŽŽŸ»»»õhaÃ�8x‚¯øÇøgİsuu�JOO¯ikkëaЙ3g(**ŠBCCå6üˆƒ>ò�ÿÄDç³<==µÅÅÅW[[[)33“Vù^·[¸¢rÂâ÷NŽðŠ>Š6üˆƒ>ò�?Xo''§˜¢¢¢«���{ÇyYP™‰OB–䟡•Öä$Këòå–mø|ä!0ûb %Ã[«ÕÖ677SªnχÀÈiufª´áô'RÄ…X)º%Jн²CnaÃÏqðÀGòQõ  Foåááq¸¶¶önII ½½eç9éÝìdikõα©]1+‹ÐE]¸wdó¯haÃ�8xà#ù¨ƒz†ÌB¿cÆÂ¸¸¸ê††JÒí¿>6äð!¹xü­Êîët-ú¼ÔÊélø—E2yÈGÔC]C¨krssoÔÕÕÑ–ø´ Lï´´›»Ãªï§Ÿ¿EU•·¨º¢›¾ìlø|ä!uPu 0”ñAiiiOUU½¹=3k¼©üÇÃ’UY.ÙE.:šã›B>)r ~Äeó‘‡|ÔA=Ô5TÀ0F\yy¹¾¦¦†&‡�8ˆ�–Ôpï„ä~’Ô+›ht`+™®k£Iï·Ë-lø—yÌGòQõP×PÑ>>�¨#êæ&Ä28XXXèx oTVVRSKëwÍ…–{¿Ù-/‡®g«´ï~¸Ü² ?â—›[nƒÜknn~‘ë0^4ø&ð-0a,¶²²:æççw#??ŸÚÛÛ©±íjÇñšŽS¡…WØì¿�6üˆƒÇü^///ò÷÷ÿÉÄÄ$×zœÑQÚAEIn*J_¬¦š£¢äy*ÊX¢¦Ë4}«m•Ùâ3­|$Ä WËï32„ñŒè#A· 3†¹€/‹( ³QêcU”2_M™j*X¡yÈË�KjC%‹0°scѹɀå˜"^=/3f0l3`­í(Eq¸­R¿ÓIEÚjÊb'Whôþ¶Ê�˜¥Ô¯šjŒW³¯8ACžö8 ¡Œ� ÃYâ;1E Hý47¡�ðOgLcXŠ™/Žì0ƒ6áCsaOS=^#1¬ÿþ£¿k\nq. IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/printpreviewzoomwidth.png000066400000000000000000000036071506556630100240100ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ   -?¸IDATXÃÅ—kl×€¿;3ûð>l³ƒŸ»²vÔ- µ©Á hxÇ.¨A›´ÅV‘ZUí¿*ýQõWÕý×U‘R µ 4©["•¸!�¦Â‰i–‡³C�í5¯�ñkÙµ×Þ™ÛžEkÇÆK¤ªWºšÝ;sÏùιçÌ9#¤”ü?‡ö´›B”e@!àœ@� W~EKÄbûLÅk�ÀáÇ÷ïܹÓ_QQQ¶fMa�ÛívÅb±ÇƒÑÁáÛ·n œ={öö©S§>Â@ß³‚| @¡/ÕÕÕ½räȑݵµµ/J‰«?áÒå+LLL’ŸŸGuU>oŸ?ºvòäɶµµ½tJ)�¯t¦ò�l-„ÙBh Ý^[[ÛÐÔÔ´·¤¤Ôÿî{ï?ìJöèå»§¼…EŽ‚<çj›E³H$±x21662øI÷å¡»ƒûê÷ìô7651<<< …Æ…YÅE¦Tà¥`0¸«¼|�¿õÜç¯'=×]7jå…«ŠVºsVÙ-ŠSJT€‚|9=µjÅd®g°·¿«ûÜ…Ë•Û·ÖøƒÁà®P(ÔD€ÔrJ†õëëëë÷WWoÚÐ?0À�q¥'§¼JiùôÛu…+œk­šâÑ ìXt‰EárÚ-ëŠ Êþ~ãçÛn?Öz#w©®Þ´¡¾¾~?°Þ”»<€yõÕÔÔøm6›³çÞÃHóí_mii­ß€ÄfµhB€2'Vè›¦äœ ÿò›ß?õCl6›³¦¦Æø2ä/{*P¼¶¼¼dÇïê¼+º€‘cw°j*ù.»U$g bÓ³LÄ“è†nH?oîß›rõ¬Ü�EÇüÑOeQþ“߯­pP´ÂsNy22ö7çS�A¸‹ä‚�óÆÈ±;óþŸùÍ=ü¢„%/ºò­û‹‚(é -5 )#û—],·©X.y±œÀ€ß/fMÚêñx’èxbÞÚbÞÈÖúÌ�@ô{ކ GŽ4nÞ{ìÕyô½Ñ‰Y�ÚÔ¬þDÐdbUQt©¨C@ÑbŠc'8¤”SÙ¤¡D®\¹Òwóæ‰s?û�_:u&-h_m ð×ÕÕ9�‡MÓH¥R$ Âá0mmm‰p8ÜÓßߟܱcG…Óé̵öµÎTåôkÿø�þÁ»7R¿}ļ†Äì,€ øð¢×ëÝž——Wêt:רív�¦iŽT*•˜žž�Çãщ‰‰»‘HäS`*//ïåCVzA鳿:n»0>êÕ›ÿ|-u|)ˆy ‰”ÒBÌ1àЉDn^` �äÓÀ80d–ÝnÀš33¹Ý=·ÄrŠ�(eÿz5¨tÓí {„/5¥0\®6Ó;™©;“1SÑ)ùög÷tÏÎu¯"„0!Ô}ëÔïJ';SŠâ¬ùÞAJ)íŠMÊ”"­$aÂjf…SÌ"#Í™ŽŸ‹]cÒ¦)z|{±úE¤;©X¯¾®Ä[) ø`!žÞ–› ºÂ0=b˜Š,&HFÉ€ê¼úH:‘º²£T=$Ä\|+BªžW_—åDgJ˜º¶lžÎÙ ˜ÖÛ»yµškʯܸ:*ºå[eê+Š@(sJC…úq¢#ð‰–EAæTMÅ33cb!@wç¨ÌB×^.S÷ BÄA¿¼õоxÏèв¬ªiÍ´Üž .82 Ü�¤tu·WÝ%ÄÜýöAùï‹÷ŒV`\ã?::Itc�OÝÓ5b\øk·þ3»È@ši—2³BÍX[êdFà†:É©‘i=z7.[�‹À$`ˆå¾2‚Ðò A¸À0a]@˜2 ÖŒÈæ[Ò„HÇ@: µ%Ò0@.Ð�ÙŒ©ÿê þÑ!0ŸÝIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolscolors.png000066400000000000000000000024641506556630100216670ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœÖIDATX…µ—[lTU†¿½ÎéÌtfêLEZ,XJ‘‚-·i@M¨\c )Ñhbâƒ1ˆÄú"Q_ `J$ñÍH$\½Ô# hCE –¢r,ˆ…ÞgÎÞ>Œ�v:g˜)Áÿ霵Ö^ÿ?묽öE–¨^þê=^ñ.2è*¥U…VcÈ‹{ÍMA�7b"¢iì&ºÿжM7³É«2Ô,_=ÑuJëgñe“TC—¶ÇY»ûú_ïHÀ¢—×ø­Îö÷´â5+b)1ƒlôté·wî¬ïÊZÀÓ+^/5˜Ý ewF…SgáÍ e)@l¥T€ZºôÍP¯§÷Jº!£”¢ö± ‡;=g.�£\Óv\½ÄÅÃ_ðí4ĤӠM§ñZ#ì^Ÿ³ÒO¸çõóÔ´¸[¼¹|r'Žbö°3®]�s(Ã×}Óz0DùUÔY ]•.aU¹�…Ó ËüI†i�ßÓ È-*Iòçc®ö1.PZÚDPç; ÂvFùvwŠ­ ò c¯´¸Æ‡qRˆn±�˜ˆB% s“vzôCc0N¼»ƒ] àôQŠ.7ã÷z]ã�Ëye b‹¦Ñ/ t4_îfbQnêŠ8ûG‘­›¨¡�ñ¾œ´ä—tê°-�ÒMt¿†¤ëÒ¾nÝ–`ßñv|Á0¾`˜fO¿uû£äXlP_iÓ™ÓÛuÀjn:Þ3±¼²ÅÔ„Úë1<âðÐîz÷‘|õS‘8é5ca9½YîßîۨŠ;/ÿ6ïúäƒO-€’I³q^%"‘s´üÙÁ½A›PÐÂц3»ùè`+_Fz°súË-bÑS\Ž9ä)CP@´p°Çâ„ $ÅkMT,Yv&rôF¢5jV¬Z¯à���X”X´'Ñlʲ±=^,Ë}›foX»§áý·ûMç×H×Íj…Lî³Yv–�y& %Þ@¤Í &߈ú°¸ve‰2rT óf®ZŽS¹ëã�‰a‘4Š÷6Ô7+[Í3šÖÿƒ\Œž?�ÛºáÜíB³ûGÔ¼¸:OE�S¥ Âh)6¢C?Õ”èÑÒ˜ÓÛu`ÇŽÓ_›à_Ò¯2ÙJ ¤IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolsfiltercondition.png000066400000000000000000000036721506556630100235640ustar00rootroot00000000000000‰PNG  IHDR szzô�IDATx^µ–{Œ]UÅß9çÞÛ;3-3wú|̃@-Ѐ`E(µS*ÔÄ(©Qñ‰ Bµˆ�‘¢‚”¤FE­$ð�¨ �B[Óé¤Ðµ´!ÛtÊL§tÆÎûνs^ûsÏvnfì$%âJV¾u¾ý%k�}²÷½ÂÿBÖoyöS*þZ�xÞ U)ˆ' ªœRÑF»EtÕÁ¼eâðÙ¶‡o;(ç@oýù4Ùê_jr‹—ªi(T±¬®Š9YŸBU†Bu£ŠAQc0ŠÓWQA<ÇBJ¥Èpf¸LÏÀ§‡Ê �Eï¿ÝúÐçžL%@þú_*ÝuÓ%Ôä÷ Ó_Š9Ò;F68SŒIðÈe2d³�íeÈe-­öÅg<މ-Ã(&J&ª�&eIMàôÊUòV-™K©œò»Ý ßßxøéw@ÞCãŠ&®þÞSÔT穞“sÌç2ä'Ì2Y_Èx„Œ(�€/êžPKA}aKßHÈ¡®÷Æ'ûË”£ƒG¢‚Qží„‰!NÔÕh’�/| ¶†(ŽY¹p.…|@&ðQ¥ÐÊ8©öõ õùE\²Ðç#«.fiµà‰°¸&UR£MI­NT5¶'[°‚gˤjl-q¶r «È™¡w®¿�I(ÀTŒ1 — ÿ <_ðK±’$%ž`œ’¤N;&iâz±Û‰‰`Ž“Úàfcƒç�L?)Óx"„QȆ†991¦‚ A娸0 V â*–¢øŠ(–JŠ’  Š XŒª%dÄ "4·l¬;ÙöL_%€¦Åþ¶§Ûßmyä–f>ÑðÖPJ_ÉÐ[J‰F#%J<Qúc3ý[".ÇÕMÔíf§Ë1÷l¸ÐíâOw¼If´�5Pæ^s÷öm+¯ÛÐòÍuM,©‚½Ý! x€P7Ç£Æâ”r˜0¥ÔÑñÄ2bÄš —"ÂØ'1Q’NÌYÞ±f9¾Ûv#3ØÓöÊc_ýÐ Œµ@£ ±õÒµZ¾xm#ek²§{œê¬P•õðÁ�s÷Ý÷]IÒ‰ç‰Zé%n} üqßIL_×tóA �~tzˆ¬ 1šV,©¥>/ô•Rw¾U+Ž ÓÍÕ™“eMó<á…×OQî9iÍ¿<ÃüÜÌ ñÁKGrõMM . .ç1‚@œÙ'Ÿ�ÁR¹lq5ˆ°ûH/C�'Ú^}ìK3Íg˜âTûs.D9_ß´Ô†¨É@16"˜sÞÜ`©ÐX›Cðh?>DïÑ·[÷mÝøÝæç 03Äþÿ†ˆ« M ëç1'"„©7w4PŸÏ žÏ'Šœ<ôÏڷݶè>Ÿ9€03ÃÕ�×Þ³}ë•-7´¬ºh)BJh IœTnF<ñ9Þ9ʉ£O�ñÌ–7rµÜ¨Šƒˆ¡ÕŒsÿΟÐè̼wˆÕ×ßÐrQóÀ`ÜUœ§� �ÝE:;n§¾v7]õyV5®%—© ŒËéz�¿þ3Ã#¥ß¿üCî¬ìŠÇù‘ƒ@×þÇ¿¾éàî]­m{ñ±†a¸ruA8pðk~3˶rßg¶Q[ðÒñÍü¶ýkXZý}Û3Ü{ëc,ž?ÿ7=Ä€Ï,àó�Õk~´CGSÕ÷ ëêÐwúS]³åQ½múj×Ïô‘½Ëõ¾¿¢wí@'á´íÙµ;ó ÝøË]/-€xÌÀyw¢OD‰ÁV�þ’àOðÉÕ_àÐé'íó)D¨ÀiÛ³kÝvf»�ÝH®ÀÃ@ƘEˆJQåR(*ž×ÁÒµt�%Q D–8íz‰bgÞdÉ‚j$`-�˜%<`4,…Árêz½å À#7*çâ×7Oõ6ï;{Á!ë1{PŒÁ“É(ÅN£.|�÷„�q³‚ƒÌ6€3-Ç®"ƒå؇½ä³°e·°ùïÂ=/ XízvÍÍ �÷ ‚Ãlh:ÖßöÚ±Ó�Êeà  —�ªÔXVe©Ài×˹ú .ñ: ³ 0þÊ£·ßõ⎗ÛNuŸ!x —J˜ô[œè_ ›Áö�Qä\Ï­¹™·;¡ç �‘0+Lýy¹nÓ“[/¾juK¢>}Ý1c=W>Óp9×\ x'–)ßû@ßIžoý9w§…Ycêzþè}OmË×-»êØùÀ‡6ØËeS}#·¬\‹Aà�$ÐÛ Ç: ¿›÷<ÊýÀ;À¨¼�K'k èªV|œu�×pgvW 8 �ðFW;¿éØÉ^ RÞ`.°`2D˜4®nptÚõš'g|þO \0l¡£Ó®—„iøÆ¿Z•?LÔIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolsfiltertext.png000066400000000000000000000035271506556630100225610ustar00rootroot00000000000000‰PNG  IHDR szzô pHYs  šœgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFÍIDATxÚbøÿÿ? ÄÄÄ899Ù˜˜˜x˜™™ù¡˜ˆ¹™ˆ5f/@1r¯¥¥¥SZZZyÿÜuëÖí:yòä9 ¸sþüùGgÏž}|âĉ{¸¼hÑ¢} ‹¢¢¢j ¼¹¹¹… 9 �sh0Pp6@´1TT¢Á`pÌ€Fb~Ò0A¼²7ÁZëËZû´ÖdÎÉZ‹1µVJ)¤”!à½'ÆHΙ¡÷Žˆ°s8ç>cÌ«”ºO�_2ÈÐ` ¢¦¦û€$Á ±„9P8$ÉH$ŒÀ¨ŠÊןÊÖž¸{÷~¢÷,¥Ô½÷-9k­w¨ÖJΙ”bƒ#Þ{œscÐZ#¯QJB µÆƒ9'½÷ËZ›¥þø<PA†6ƒLªHà@3 Å,Á¤+Áâ:“])ª¯ïîBˆ³Öz¿à·¢÷¾7Æ µFΙ”1FB8ç6ØZËz ­5J)¤”¬Œ1[|ÎI)ïýµ0ÇWà€J26„a`ƒñÀÞ&3°¥HÉ>ÌÀf�t ¸J µÒK§€ªÞ'ÜÌ|Öµæœè½£ÖêME9gI)aCƒ™caŸ!ì“SWk cŒSà)¥\_€WÁ²²²ò@ËÞþýû÷ÿ¬Y³þïÙ³çÿÅ‹Áš-,,þãñ?///ØR±ùùùÁä “9 ä˜#Áæ�¢ÒÎÎnPŒf/@Áàâââ{êÔ©ÿ_¾|ù_UUõ_QQñ?ÐQ`A¾âããû¯¤¤ôßÌÌì¿››Ûÿ���ÿ±±±ÿÿ§¤¤üONNóA–€£˜ À9h×®]`GxyymŠñÃì ¸tuu6oÞüïû÷ïÿ�Y ì#XÂ0(hA†Šˆˆ€ãäHP<«ªª‚'--ý_HHÿÀ2®äØgÏž�ôÀ /Ì^€‚;�ÀÔìõë× dv±––†#HÁ '$$üðàÁÿ÷ïßÿïêêz t\4PŽf/@¡$Baaaý‰'ÞÿôéØïÞ½ƒ¥ÞÿÀ‰(KAñ.''÷?)) \^|üøñÿ�?@9é·‚‚BP�4r" Œr˜Âí�Yîåׯ_ÁaàñãÇÿ7nÜòÅÿüü|°Ï"##ÿGGGƒË…êêj°c>üX†üÿ÷ïßÿ—/_þóæ 8Jõõõç�WEφ„µ$Ƨ?°¤ûrÄ‹/þƒhbÁŸ?ÀÙT2®_¿þÿÑ£GA‰v#ÐXl@á,еµµã�éàÈò;wîü¿}ûöÿ§OŸ‚ã”PAÅ3ˆ1(�‹ìÿ{÷î\ Âgúôéà2$..î(Ð8;P¼c+Šoe,åò�;Κ—/_þʦ ¢Ì ‚eÛ¶mÿ7lØ.´æÌ™óêÔ©ÿ»»»ÿÏ�;ìèòòòëÀÜ*x¸qÕD°6&ÀFP�ò)°)(NA Ì J ä`MøÚ´i  \ŒkÎgÀÊóøjC€b ¢=Àäçç7ñæÍ›àÄ �@ÙXnüVÏ`€| ª/ž3³shÎ�Å³ÆæÃßö-ņ¢å ‹ŒaùÊ šFÆPÛtœRNQD9€Å3‡&m½4f’ËRç –ž×»Â5ú¨ÙFßö/°|rŽjù"GQÛtœJá b3üXÕE(¦{‚aTkĸ—¶ù$­v�V»NSb*#bmŒLH¦(+´Ôž§Õ®3äÉz+�Íðã�6b {[�wþ+ÊbA”×É“òåÐü¥FÑöàëéí“dÐÝ ï¾�ºw÷F=ÝTt PŒ·{¼c&Jìã±%ïøpßFdù5A³ž†$û5Ü%XF\‡¬xƒÅƒú€‡±¨) !æ@_õ·¶{ü·J €¹_»þe'Óo>äMdÐÛžùo¹úûW%é1—àÊ™À@›ÒBO9†ù_NÀjµÿyan½Œ®ŽÊ·÷à® û 3t-jÊBV‰eßeGˆä)Ý™Vôà jì<¨Ñ¿@�m}ðáÿvýVJmhš¥áIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolsfindreplace.png000066400000000000000000000037151506556630100226420ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœoIDATX…å—YlTçÇw›ñ,žñ`<Þ†h,×P .CÕb'}€H]©‰»¤ª�Ú¼ô¡Dm$pQK©PD«Vj«ò*¸MEÔ&U‘‚H‚“0„âb¼à}¼�gµg½[ðŒÆxl©o=ÒÑèÌ=÷|ÿs¾ÿwÎýàÿ]„BÃ4M¡»»ûúººFQEÃ00 #ç“·MÓD×õUvNsÿiš–�Ñ××7pòäÉÏ®)'Nœ�:::ê=©T AE‘T*Åøø8Á`I’�e™šš|>‚ð(‡Ü¯išk²4M«ÕJ<o|ü™\Ì9›Í’N§èïïÇápÐÔÔ„¿a3Á%|ÞRôl’žžü~?^¯7 ˜˜¦‰$IE}Ö(ÌæêÕ«´¶¶IKœy£ŸÈ²Î&w ¡XŠJ·…o=·—hpš‰‰ êêêÖPó¿ª@.ó¶¶6æ—MºßŸä¥CÍxËldT�å”ÊÀd˜Ÿ_ü?ùF3áÙ †‡‡±Ûíkðù|‹Èd2H’DÆP8uœï=ÿ4µ›H’€ È’HCm»·UsòümüuõŒŽŽ®›ùFÛ³¦š¦111�ßïçÍÆèh©ÃfI«:†a¢é&&Š¢Pç+çíÞI|ÕÕX,l6[Q‚ %hÑ „B! ËTylhºAVÓIg5ÒªNFÕYŒ?"©Ãfa`*‚ÓédzzšÜñÍéFÙ­€iš¨ªŠn(’ˆU1 u@V3‰'U¢hº�dU�T*E$!‹­Šçv»7܆¢œN'†®ã²É̇–©õ:Q5ƒØr†`<Ã|$…¹RÞX"CµÇF08›_¬P í\3+”5[`>Ÿ�……öo÷28f1–bjq™@(A4©!É2Š¢ ( ñ¥$vV3<|誨¨`jjŠ@ @KK Ïï{Šà²ÁØlœ¹ð2- •4Ô¸1ÒºººèììÄb±¬ ´æÁ»¿åÙÖNfärÆ÷ïgÓ… ô—gÌ%�ò—ó—¢ P0 OŸ>]c±XÞ«©©©Ï5¿ßO<Çáp�N§ñù|Øl6¸sç555>|˜²²²Udèû'#œãs»ÑR–4¦v¼Àâï_ã¾uúÜë—£ßÍù §N�Úév»ßóxŸI’P‡Ã‘ðá•s¤&ßa×ö­¤£“$æ>&–™OîgVÎ$~ü‹‹ÎÂJÉgΜÙ\QQñQmm­ýúõëx<¼^/@×u‰‚ ÐÔÔ”'WnºI’„iš‚À•?ý”2sŒ]Û·’\ø7©ð��Ê`ÈAû×�`ŽÆSpqÕVÉš¦íinn¶;�NÂá0ªªât:Q…D"€®ë$“Ib±X~QI’EY–‘$‰;ÅgìTVÖ²¸A&>ËðL–ñåJ¾öýßQã߯½Ñî5„—S©Ô�»wï&÷ìÙcSU•h4šliiqD£Q4MC×õ¼*Š‚,Ë«Ô4T®]|•g÷úq:íÄ'¯“ND¸;ž!*Ôsô䟱–8ן†]]] ³³³[/_¾ÜyïÞ½½.—+mµZq¹\Øl6œN'¥¥¥¸Ýn\.N§»ÝŽÍf#½äú¥q¤µ »M"6þ.ñX˜#:båA:_½D‰­ôÉ­øØ±c3ÀùãÇ�Ë‹Åt8Èò£š›bÉd’d2 ÉIDATxÚ¥–{lÇÇ¿3»;{?Ž÷#Dq €E•ä ˆ–H±|U ib¨dúG ˜ÚD­HH TP”¨<"9&JI)˜Gh¨À(U]G䀠„˜GM«@LZâ`gƒÏ>ßc÷vfw¦œï87Ló•F;;šÕ|~�ùí�à6jkû¸�RG©õùÌ�ÏÇàº2 J©ãJ©VÍK—>œÄ7HJU[˜7<ýèôj|6RXÓÿ÷ƒÖÖµ”’ÝýÜ_åèBe¦²aæ² ”Âñ›PĨå9QkÚ™ÍG�žlz≚-ƒN~Ò‰ÞžÞâû¯¶í‹’Ò --ǶxTß<À&àÞ ãƒ:(¥ùAJ)% àÂEÚv‘ÎBfìãRª+W.I~“Jµ¾ñÏÑÞX?Šo¿Ý¶%K‚›½Ð8Ì›( ë: ]ƒ¦i „€‚œÃÁ T£Ð5 ¥r9ŽXÖõT§”2²jÕ²ä­vh�Ú9Ž�ÁaìÜðd~ð³ç£Þzëh­%Ôf·2„y|&C à+Ÿ�Áçc(/óÃáÜáàÜ¥ååATÝ; fÈÂÝ|+k_?t" éŒ !\üâåÝQ8}pG„çbwªrFñp¿ßDÀïC0èG0àGY0Ûvøª,ƒÁ hº)% <èÇwfN4oÝ®]ï�rù+>ˆZ9±¾n$†0œÊ ¿ŽGŸz9 ´©é�†!TTÍž0âvf€±¼Å~ÓDÀd˜ ÌÐá8eÁLfÀÙG)Õòž˜5w„Ï”dsn$†1”L!‘ÂÐP–e#•J(ç¢N¯,G¥�@Ó4z~0]Óuøƒ�1Ì€”²x¸iÞ”RÌÀÔ©“áyöò­[›C€Äà0Ré,“àœ#—s�Ëå`g³yÇáµ3¦A)…FóÉVÈ|MÓŠVJ)a fÀÐ 0]‡¡i04 !Mª€ëzáÀÎ OFâ}7 „€.lÛF&•ÂùÖ×"@MÓ5Q4Mw]è#…úP JAz.G$1FéIXBbÜßp*‹ÊŠ Æ�¯%´èr ÀÊå �äF€ )%º»{Á9ï+uq¤¯?Y´ÆÐ5XVÉá ²– ËÎÁâ®ëÞt=¥Ð�N)t]ÏÇŸRp‡£ëÒ—Â;ç¢õÒ?/ƒ  3Y†R¬ýWÖ ·¤Ô#?»Ë’GÞ|sã˜C@÷í{±¹ÿJ¼û‹+1(©ŠÙMÉ-6—ÌG�‚œ�Ã_ßÿ;²YÒ„»I õ§Žu ™Lü~³hñ¨KÉ\)¥\)á)…wß=‚rTWWÕÝ5@KËÖ#©„ýê‘÷Ú144 ¥ˇBIUðX¾¼*p#[Ñüض[C�±Ä©¾þ…*U#ùrüvû<³àðœðìåáŸ>qíx¬7äID—,�þîÒÕðÌû!âçÁc±3øø\ÿî/k~ö�®µ£n×µž>¸cT8Æ¢mõyˆÇ~2-üà²Õ�¾™àñ!¢ŸÚèºVÖ¼ép×Z"¥ª}ýЉ¨•sp}`™¬OJüiãÚȨXÝ%Ä–Çç†<©¢ËWL /x|5¤øµÎˆ´Ÿ²ñYO°™lßß®b} $‡Óà\ �ÎÀu]üí��‘BbizŽà.õÛÍ )…èÊ•Sà ëVAúç=Ñû¯3ØÓæ½S×zêÓ Åļ[mÿàrR‘ƒéëüèà^P« lÚ| ªYh9Y�ñ‹Ö€üzû~Ź@ìZ?8çà\€s;›-6ŽÿOJµaÉœ€èÂEÃ�Ô=Š·ÛðЊçÐvâ‹$‘RÕÖýfGÔqp.`YìlvTãømJ!$1Âã­ÁW×E2™L¯/Þ‚HÃmÃg½ùZÉ$øV·Óì,öqõ.IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolsfonts.png000066400000000000000000000034151506556630100215140ustar00rootroot00000000000000‰PNG  IHDR szzôgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ŸIDATxÚbüÿÿ?Ã@€b�1ììì”UUUg©©©Yýýû÷µ,`ddÓLLLŒ¿~ýb>vìØ�ãÇ�W~üøñÈóÄ"@8..nñË—/ÿÓì۷ᅧŠÊ: ›D@ö<tÄÄÄ`Q‚L#cd1tyBêYYY xyyµ€ÂJ@ü €àøýû÷_ûß¿8-ÂÇFׇ®µ {@4(^8@rÄ‚gØ ¹ÙPP¼ÂØ K‘Å€ñÌ€œ°Ñõ!ÛÄ‚Ë×0  ØõÌÌÌ`q�€ø0ðóçOnnn===¬Q�-¤@ €˜Ð€¬dÁãÇ�^¿~Íðýûw†³gÏ2œ8qŸ§OŸf8uêX¤öÌ™3à@!\¡D0>|ÈðèÑ#°…ZZZ`>ógÏDEEÔÕÕ?yÂpóÖ-IIINNNpáK˜È &\qÌ·à`½{÷.ØÀÀÀ@WWW~~~†÷ïÞò€ÁÚÚšÁÊÊŠAVFšá1БJJJ`}@S@áô5rhÖ€X‚244d�––fxúô)0*¾1üúþ™�éÿ?I1a†??�øƒ´„(ƒ‚ŒÓ¿_`9 • LÌL ¿þà€bA”è@Á ŽŠ?þ0<þŒáë·ß ‡?©1ð 14`bøñû+Ë? †ÿ¢ -G¸þþûËÀÏÊ ˜¼g(pæc`egš÷%çÀ@1áK 1v f�C@¸çóÏÌ Üª bJ —o†É>¿B4ÿ1üýÏÄpæÒs†4õ§ Kb8EÞ2¬Ýû€ÁTú?/0Áþýû#„a €à9¶ r ÃëW/¾|ûËpæ ?ƒò�ó e‘º *š w¿Š0܆ÊÇׯ¬ô¤Däع¾>yÌ`(ÏÁ,=0²82 €˜°Õ`Ø‚êæÍ[ ÿ™Ø~f7ç`à–d¸~ÿ=Ãå×, /ßÿe�bù ).Èðù30AòþbÈ·þ Ì ?ÿÅ™@ €X•ÿ æË—/ ÷î?¦ë o¬LuþþþÃpóÙ†¯ì" ¿^`ЕúÃÀ,>©™&?ƒ¹–Ã`ôÿùóÃcÈ!@xÓ(Osqq� �oß¾1|ûú�A\J�ATL˜¸þ0œ¼ó›á' ëû§ &êÜ ?ÿ2�óÿO`Iýã7#Îâ9g6e½¯_¿‚óþþýûáé”Þ¼yÉÀø—™áè}F†ïÀ¢@ñÏ %U†_ðàþ-‹0‹aô œÖ-[¶nÝ .z988Àj@eÿõ+çTõüÞrØ3|ý†ÁZé//×ï!¥ š…¸Ú @,¸r¨µŠŠŠ¨†iPA³ì0뿜 |Ÿ0˜¹ñ�³"Ь Ý!È!@,¸ê�"$—ƒª` 5ß0œ~ò†á#°pÒþû‚AENüØ"¸(0@,¸ªc•~ ú"ª‚�ÑÁÊpüÌk†/yþ³~g°–ù,…Þ¼ƒ¨�¶9ðfid6@±àk !;Š��‘á ›w¿fX�“á§°òƒáø>†–žû ÎÀâX˜~þÚ`-'ô( ‚E1ŒÍÊÊÄpãæ†eo10|{Â`öe/ƒéï# �YsÍÆ«à’”C°¥zlÍ8 ¬Q€­uôõë'Ik3.†ÿÐ8«ƒü?“,+PÍ/°ïq5ð9 €XÅÂ`©È¬ �5,�ƒó” *ñð%6\l€BFBmþ¿@Güÿ‹»¥ƒ«ÄÖ¦` €ài˜âqu«�iF¤dŽÎGv º:X½kiÃ@ÁCØg;Ć&&&à0¾è ”ͰÉ�,•¦½½½ "þÈÏ 9€b„)*�¹íRRR¦@1&x^"Ðé$€*¶?~0›ùï�¥î& Ð" =Ù JˆU�˜›†=r�ÏŸñc Ý ø­J ЀŒIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolsgenoptions.png000066400000000000000000000035601506556630100225510ustar00rootroot00000000000000‰PNG  IHDR szzô pHYs  šœ"IDATX…­•kP”çÇÿçÝ]n».¸Sî¬Àh$jŠb6a `¹¸©�vÒ&-“ޱMZ;“Ô~`ژ̴‰ùàÔ&Ô±%Vmf¹8‚r ©¤aµa4ÜI¸D„p_.²Ë>§v¹˜Éùò~8Ï9¿ßs{ÂwÙÙÙRMÝ�'™E¤+%æF²ÉMeeÆÁ¥j軂ëõiß›–ÉNðÌ¢Ô4J™ø�•EŸ-®“@bjÆV!èƒ ׺Ñ{F£Ñö(ð„ä}16B1«¢·ïÀÛ¢!Iº;»ðIe…||l<…˜$ÉvñI™OF%Ç OCbjæ‹eEùwV P@ùâË/ãû»cçr�‰l¿wT/ Ûô€°ƒ©�ðP;£ãîø€³‚‚µì¡Ž­éé1‰¥à‰©[Át• ʬWaÇ®�s¹ÚêjüóƒœYx\YqáçCµÒ«U ÍŠB ¿ õMÃ4iqnª‰xu쇎$’’ ëác¼ñÊ!l�‰™ËõõöâÄŸÿ"lÂ6"dÐ])*¨ŸÍét:yHdô«ÁÁ›D[KÃ×ÒZ7Ù ×\¿Ù‡k¦>ÄlÑ åi¿™ÃIÒãKÍÞJ"‡þ{÷e.€@iÑELMMI,è§•óÀJ¯³`¼Ë„ÓH2�6~ €õĹþWq;僀)!Ho2åXÃã’Ò‚ˆ�Œ”ôt;¹¾ž^àq%•ÛÁ�çˆ6íyÖ°Yí-�ýÁaÚé)‹ˆ¯o�¬ 8aÝZõ® ‹· $<ò×tû÷Ãÿñ�v÷zzÐÚÔDÎV(·n‰¨ÐDD(�Èõß2C‚¡OMÅíÿ}�h•f‹z¼ßPM fK €OÞçé3x.::K1ÀBl€�°P‡Û“˜’Œu 3øÕá Ѩ˜] ü0L«Åk¯¿Žˆ¨¨™> Ð9“)ÇjÐYÆU�W._¬s•Yõ%ÎΗ ‰Ô3_i1 T©pôÍ?QLì.Èdò`µÚÝ}of&^{ã ¸¸ºÂÉÙi¦³bÙ?aRÒõ´t¿@ ãà=¯&SŽ5>9ó(ofýê0¶=õÔr-ÀÌx°çsQ[]�S= €�8žÂƒ()9;*.I3+ƒ§ÏÀY�N'P 7®__À>:2‚¼sçˆ&T¸¬À| ×0(ܼ ˆpœœ\V˜æ‘Q¼{ì-’ øw—òÛW˜•� W=&RÁ‰KLÀÏýBÜ©¯‡Å2µ"ü�cÇønw7�ñþÎíQ I’a—îi<“�ÕÆÌ£øï§7PQZÊV‹…ÀôöÎ푘…¯J`><^¯Çs?9ˆÉ‰ ýÍo1f6ÃÕÝZýAô·ÝFgÝU^Ôƒˆ†~¡¼8¿hqÿe·Àœ™q>7cf3\Öx"<áyÈ.ð `�NSšø&€/™qaÌ�.×ó&1–p'"ÔÕÖâÆõj¸º{A«?¹âáMðÑn F×­O\A`³M¿pµäBÛr“tx –‚@˜V 777Ü7Á|¯Û®Ö7bü¶ì˜×Ë$yUBª!`9Ù£ÀÀÙÅ.n®¸}ë;› ôÔÀEí¹ Ç�‚¹·S =40ôBkkãðŠ+ÁàËö6œ>ù>O[§fÛ`G)½}ÈeÍÚãÔ�ù`˜{»ÜY’ÒÃ# Û›¿YR@—úcoI×V‚?ö6ߟœ?#A§áGCM’ÊÛ×^Bãfs_·iaAáù­­ £óÇÌ�…°¼÷(ðòKù¹å%y%#ƒ…ÍÖüq�ô|µpzDðÛ ߈s€•¨êéé^@”ö˜¯ïªá³¹òËyÅg²°‰æª|½×a'á¿e7|´Û@„ ²HoÙ dggKÄ�ËdòG‚ÏÆ•KAl`›M4_Ícs_—�ÄÆ­:(\U `�#!ˆ+îvw¡æÚÃ'v5ð9‰â‚B"Þ/„M4Vy¬oáefÛ4/þù΀àp“$ÑK·>«S|ÝÙ…–¦F|”{†§¦¦V„ÏF[sÃÁaÚ&œ9ÐѵƟœ”jŒ®›ÿ�¹·ƒÀø°½¥¡tnqæ7ˆÖE$þ z&Iƒ‚9«âr~þJð…}2ž'¢3 ’<|`™0cbø€¨ƒïӿРãÜutôQ\Ša½dšq•ÔXc4:ü‡¯(‘œ‘ ’> æ ²€E�Ur>\Ut¾ÿÛôû¶A{öî]o0œ–ðR²V Id»õIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolsshortcuts.png000066400000000000000000000034341506556630100224220ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs  šœ¾IDATX…­—ml•åÇ×u?§çôÐsÚ"”Vg[j†Ö%2jÂÔf Ì%ÎdfÉ\Ì^·‘%ûàq�éÈ˜Êæ?m‰ÓO̽8‡fq²Á&" ¢8ÇšVpÒòÒh¡œsžû¾öá9=í¡-Ÿ+}r§Ïsß×õ¿ÿ×ëʲm[wSl©Û$ˆc AÎoÞ¼ù€Öu[1~I¸Û:×YS=*È·úÿ¸ñ xæWÏ,i¬«Ûý‰›oiD'Ѝ"@00ó„fÄÅ¢?pàÍ=>ø�Uík·î¬Ï²fmWKÆeR2§ñû� \ê=Q,JIÛ#€“M]ËW4§RQ”BUPUT ÃB ÃO}¾ÁJÅ==�¯~zwX·î¶ÖÔ7ï»]Ož _—™G±XâÂ…QîüÔDz_ïù{–´uE…B±ÉÌ03 ÅqB0D@ÊŠ #ù3RQ CÃgPÑ”�€fÓ5:0ð_®»®bœ*`‰ÌŒ\]â¡8K\iiù;>.!"xó –œ®<‰6ÃS\1Uj3µˆ` ³²ñò #1¹ººªs àñ”| ‘:TÎ%�÷ Tq)FÅÇ%¼�«ù™÷Yö¿±Ÿ?üîEîÿòý8§”â@—f ¨j…�ÎÎN …ꔎ:’¬š‘±/Ið©hå&éš mmm;vŒŽŽÅˆÁdz0 U †‡Ff œdlt ItŠDUhTQÑDY¹¨(7uÞÄâÅíRù>“$1+LÔ’B±À÷7>Ì¥ñq.^¼H>Ÿ'HuðVÁñ>‰n#IIÌØ·o{÷ìeý=ë“÷’¤ÔŒÖµ\3Ìhm½žù��,ZÔLsK3ÁÁª™«bàýŽsã’Î ¥˜Ðµ¼‹®å]˜%)ècÏÐÈÐ4ûCCC47]Kä"T‚`X98E úûŽÌ >ßÀ[o¹ª×“—H§3d³YÆFǪ¾åsyþÓûn¥hÍ$¥¸ÄüÆk­99•T«�™PœYIš6-XÄÙ‘¡¢sa4\*–B}¾AÏ�?KaÖ³™L-èx¢K$€íOoï¨�R¯-¸f~³FaÆ(SUð>”†GÎíÙðІ5ík·îÌeåî•·4djœ\E7T÷ž½Ø7X*J¬íC·~éñ;Æc},xß0— oÄ‹: ÁRâ¤Ó„…b‚„�8=LˆE(N”C…lP5ïõïÚ¼_Ú×ôÜ(©øðµõ²zeç D¦šü…ã§-u)¶7{_Üt;ˆ-^û£ï³îc»Y8±?p‘ÿZ]Zô—�Ý›>yzð£Ø’ ²æ�:o|ï©×?}ýšž›ß™#&dÄ´0uo@Âl¦ÆN�9IGû 3–Ù)ÿMÜuòÖSkƒCCgÈlj-rm+»3ä«¢öûi&$]“æRaœ ãIŠU*cy8‘dH˜4\ž!BÉÀb¡R¤:w² (¬e^z‡r©`ÝSmεR1^,éë�b¡XîpÑ䪎CW�º¤‰Mg a“ÀQ̯èÝõÈéYHØKnz`ÿAvî|�¥K?Iß‚>š[ZÈåêèììDÊåø¹_?Ïò[—#•°M‘|˜5«û^zxïôË^ éhIÃyöÙçxêgOP“ªAUÙðíï’Éd¸ç Ÿg÷k»ùø’%•SÃLªx Õ àJ ¨:D§ŽT”*·WÇê;WÓÚÖÊÈðK—-ã‹÷Ý˾×÷¡šLñV6.fˆØeî˜]ªvMÐ/"ÔÖfxç�0::ŠSGˆjqê*3€ˆ–W©z>4€„EíÞÂË»^á[~È?â3+ïàÕWÿBsK3í‹ÛPçXµjUyxI²cÒ8Ó�٤ʥ8&“ÎÌ“ËÕ³åÑ-¸² T•žm?Æ•†àyà�¯àƒ'„T²ú€A(foh³ˆã˜£½ÿ&7oö0eÞŸEBðÉ|y^˜`F>Ÿg`àΟ?7÷É9dQS3µµÙ«P2}{x4v§‡ÇhZ¸è#þü�w½TRô϶OZÖwgk­fO0YæDf>¤˜�UlcßK›{®`åÊîè½lí]ˆý_(1“ ûÿ´é­+íûuýò¡Ýô ´IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolsspellcheck.png000066400000000000000000000033271506556630100225020ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  d_‘tIMEÓ  ;gž¥ÑdIDATxÚÅ—OlwÇ?óg×»ëÙq²v6¶ã¸¶IHB-ZÓTM ­‰¨þ( . ‰CÏ\9pAzB�…U$%-©¬&4%�#§)$$nÇj;îz×^ÏÎÌÎÎìÌpØg³8¶iK$~Òhæ7¿7¿÷}ï}ß{¿�ÿóP6ÌS@°(+€+k9 ·I6¼&¹H†|Ÿl’ùpd¾í8¼Ü~ nZ;L5]ÀYà»@+ �À×�óÀ?�w€ß_Ò›)Ô6Ì? <+×2ððž¬= |¸$ω°€ ð<ð .ߺbTX7Ð7Ì÷=À¼¸¼úœÆeýûrÿŒ8|8ÌÈ~ß’{/pý¿xhþ<&›5�PÜSßvÊóç$ï‹»$öÝ[Å| @èv‰ÛΑ:ùRIOCB¶g�1áLŸ„mI”ú@ø›ÈÚÛH‰µíÂÔšÜMàQ‰ùgˆÅi`Ÿ(�Œ(ù°‰íU`v;Ö¯ȈËs¢ôⶤ�ojC¦Åª. |þ“Ö�f‡€’wI!Öy‘ € ÀUYŸ�ô7L—¤$@‹Ô•¯ 'NoÀÅ$MnJ ÓÀ€äp^6 Eé�•õOIš“¬Ùì9x8 ÜY×úlÚyŸ½ºär§¸ü5ž2~ARYåÍJ øš¤Q§X¢È¦;„ý‡äyIêŰxò8pEÂyB¾¹Í8:Ó$¹K/VCNQ•ümºa¢ì§üûµ•J©Él[¦Ey®n´_n}R‹¬³AŒ‘¸ƒä°9¬h êm‰ƒJ:êÓaGd ÅZÜ Ù2+¸Lñ!Ï$#xÛ·ã¡{^m4WÂs¦|×Ïm‰–.³�é…½mÿÈ|Á.% ÊuEÓv+ŠrLÉ(ýJ6L“ƒÐtt )àañw\Σò2&÷ÁÙ®ü{˜ŠÚ5í¥ë~¦Ø¾s—�Öa§¬®ìÅÌ.Çq†µ´®f:“‰•þ•†«=É…2°ˆG‘T~ƒÉk˜¬Ð·õYðApK-rTOkx»<Å¡Ú^US�¥’ÙÕt2ÐìV»QŽ"Q^,æp¹†ÊL.ÓI™Â�Ò ›ßØô$o¬•¥ì¼O¬j66¡â÷ù km©…¾Üm|ŠѹÄ^ÇäÏXÛP#>€¡’Œ¯¾R� ÜÀ‹•jk„ ÅnÓµF§e`›:—éæ%N®·î�uxp˜Ìã2«Íh‡ô”N�úºr¥¦{qÃí67Q¹@ŽÓtsëãHÔ-W"f¢È¿—™0Q-uÝJU!vb(RÃâ]T^§ƒ3 p•c>é‰h³1ÆákÙBÛ©5š¬qÇ©3M�ßÓÉ9Nrã=’m6æÂZ8ú!Z=^#_Ì.ï s“st¯Ÿ2C)Å-Á|l«K‘šTÑYÆÅå¯èŒÒÍE:™äØú¿ãCðTàħYd%¼Ã2ûñÑ)p�ßÒÃ%N<ø›õ°C ¬ r•2 `ž$/×X ô°~Ïÿ#wjKAmÉ�IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/toolstoolbars.png000066400000000000000000000032301506556630100222030ustar00rootroot00000000000000‰PNG  IHDR szzô_IDATx^ÅW{LÓg~Z.¥X�ªˆ- (æ Al°©è&Ó|™[4ú™Å ²%3‹Ä,J4f—dqKÜ%‹qîsÆ1M6ã"7ùƒð‰šÔH`ƒ€¹ H¹´”Rvž7yÒ°Dñ²“¼9má=çéyÎy~§†ÉÉIü›ˆ°†††5^¯÷�‰‰‰Dñnñmâ+åüšŸŸïÆ2#þÁ\.×—‹esttô²ØØØ9[BBBNÊç÷Ξ=»ù©p»ÝûïÝ»çX°`l6²²²°lÙ2k@@À©#GŽ|ýTäääœéïïß~éÒ%_oo/<Ø/aaaXµjýûÅÅÅû CÐS@+(((íìì|§¦¦Æ×ÕÕEZ`4ˆŒŒ -{âããs b� ªªê»óçÏß)//φŸíرã¸T ¸¶¶}}}ƒPRiÎËË{@üã`ÃmŽŠŠ²�ŽŽVíÙ³gÃ4¾ºÿ~KSS†‡‡!ÁJÌfó"q3­‚ñÌ™3v-ëœ9s���`Y²dIiaaá&L±¢¢"¯4å¡»wï*ããã¡¼Ü ``™  <±xñâY©©©'$év¿©Hdù™” )¯Y9¾7kM™ ÒÃ²Š‡Ì9æÎ�‹”””Y‰‰‰ÇKJJþàÀ�õâ?’dÛ„&NÂT¬@Ë?SJŠ>\/IŸÑQÍE@=‡Ã¡<ãÇÅÅÁn·“w‚P4´µµáÂ… hnn.ÿ®€é˜I²¼Ç™l``wîÜQfÏž�´´4¬\¹R7¥š.I†ˆˆäæær×°-ãTϹ¸¦Á?}�ü¨Sð½4˜ƒÉÉíàà ¤ëát:AcÇû|>hªô¡èk/ÛQ¸¦/Çl{{‰/0¶øÏŸ–&$BšÚîÝ»³¤³/I³ÌLHz¦;¤„€xÌÞV$Ž#*¹–¨å0ŠFŒ¶|‹[Çoÿù¸ã-‡cÒýPJxèС:áþÕË—/÷^½zÝÝݤFˆF¨£_« 7b¡ûÂc_‚{d­5_Àëq!4é=,JH(øe_ì)Vâ¡¥øèÑ£ÛÛÛ3¯]»ö?iªûeee…DEENŸ>�êêj †‘&ÄŽükô €!ÎÎzxdžà¨ýæ‘@L·�°ÄF9IBE†pl—±sKâAiÄeÒ_É^ˆxïϰǥÀ“Ÿ×ƒñÑ>x\ýâû`² aå{ 6OO‡?€“'O¦±Ÿàg2jÆÛ·o‡ …Èë@£Øpwýg¯¦ö-Z3‘¶ça ‹�×í”3ˆñ1åÕû€ PÄ<·I¼  ½óAMƒë�’°0«Ú€[ÀyÞg³ÛŸ‘é+Rê¬f½§§‡�=• < «¯¯çH+Ñ#J°JvóæM%04jŽàümD:>&&4Š¥™÷ø° …¿Éx«Gø¼yó@kll¤~(ÙWL&´ç²AZ(H;wîÄTZ´§‚zÁ ¬––lܸQ­obrŸz1)ñ ¬´´TçQ9‚‚‚XyƒÀ ð…’ÛSï™°¬¼ýCزÅM«F¯ï(ïpDy篿†qìX´K|#ãª;bz«¢ô‡k  ½ì�\2¸ýPlDœ¸~}»vEêà MMÌ{üFüŸ�ªI¡Èˆµkƒ±oßmìÝʼnÒ Àx³¦V@±Z­,©â­¹Ù‰c?Œ )iŸ|Ú šÝ6�­[ç31ïÑë€ @M�/º@ÂÐÒjÂï´ÃáÕy€¹x|€®»“à4Çxý57ºº'ðßí–©Ë ë 0�þFX¾<ˆGUâÇnäç çÅHܸ1®)ЀÙCCšÍ%“ë•‹HM8W6‚ŠÊ~¬]¦w&ž–ݬ­­LøëÖYÙМ ¸_ +!êèè¸"c•ÍæÓˆÌ": ð¢VHî ܈ððpÔÕÕѳz:ÆT/}t6l­²²Ü®233‹ü)Зœ—TRãܯ^½š|Œ‘žžÎÀŠ #�\hü+À÷¬y¿"«W6Ÿ~Ϩ¸ò+V¬("rºBv€m¢d]>±'$ÅŒ ª*!�B�KŽG_HNNn[ºtiõßß_½ }¤IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/treelogo.png000066400000000000000000000030501506556630100211150ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs»»:ìãâtEXtSoftwarewww.inkscape.org›î<¥IDATX…¥—klUÇ3ݲÝݶnK·Ë£Ø­´… -”¶c|R¤1!QÑã P!¾‚LübD >0‰1€/Pk0ÕQ1•Õ‚�FÚ…¶¤»¥Ý>öÑ�î\?,fwf—M<Ÿî=çïÿÏœsgF"ÅΟ65�€`>P ä¦â²4ð^­b”=RT�ô_@,¶3²ÙÝê Ý߆oèqUÁ–ë¤Â¹ˆZ÷ÝLrðœSk<¥Ò7>¿x‰m€|%âˆä‹?ŸçX÷‡¨"nˆçÊ6šÊŸ`ù¬—±æä§†U!±ÞS"½£ ¸tò¯²!F{xûøí\9}%(.{%kë¿Æ�?Û(îö¸¤6©³SäÉùüCi�Åü~´‘óÿP0©”;«6SënÆfq2=ϯ½{9äÛND p•u*Ï-þ‰û5©ÛõÈQª$_@<ìH%ú¹{‡ñ‡:˜l«@Q#´ûÛ˜’_úEßãÌ›n:íåý_Wrvð(3‹xæ¦ÃÈRNN•|ÑÜ5á¼0ršwO4s1Ò•6Öœ|6-ñš�J³±ñ^;Ú@ÏÈ<4‹ÊL…µÉ$Z €°2Èö“Ë’Èó,…†BZêy2#9€ÕRÀªy;µù�o˜ÁæYHô9»Þb ì`fQ#ÌÛ‰;�ð¿œìý„ã={XZ¾6#ù„yœ ©*^JÇÀaº‡O1öQl/×C¦Èè.™“½Ÿ�+çñØ‚}9€Ë>“;+7³eé_Ù®ÎJ@­»Yw N çjmQ‚ô�þ @åä& ­S²&Éd3 ë´qø¬!n™ �ôPœÃXeˆ�,R´+ ÖJ°Ÿ ?&ê¸Â±Ï·is³ x¿Û�÷»Ý8ŠJ©\tso¹�iÕu‚5UUÒ˜¶KW¿xJ¼i&"ØçãÛ7×Ñ}æVG!öª7³äÁM´ø˜ö÷î'24@dd éQ––1»±…ú«'Þª�Xç)‘¶CJ_uÄ2Þ }uªñqzÎüL^a1W¹Ê˜d7¾Ñ’2¥Æ „ûPbQJ˯կñ‰ÄÏé·Z&S7èìy’ƒU’D pàæÿýž÷¿ ÁWÊUUIczÀb=õw®:�IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewbreadcrumb.png000066400000000000000000000024441506556630100223040ustar00rootroot00000000000000‰PNG  IHDR szzôëIDATx^ÝÖ[lÕðï9gn»Ûmi Û ¡´…„c 6 QˆMLª½HÒH Fj b^šÀƒQhù—ü}ðÁ”ÐHj«¢!o�1Fä¡á¦ h�ô¶ZÚÒ¶Ý ÝÝÙ9ç¸�P²!J² …„Ïã¼Ìwf¾¿ß<´©ýTÃPZ×±mm]gpÍŽNkÍk�-€$¸_ÛÑQ½þ�ã±Öo{äG'ûeyÉhi]çÜÅ=R²³Ý£Ú±µr•EÃdXà…gVjŒàÀS¯¶¹ñÜ#'ûVe Òœ8så%xzå",^èV†Æ° @Û¼½�’­í.FiýúÕyú•‘ $!$†}a”¬È1¨Jjæõè:­öd¤—C‡/dbÖ„?м¬T@’Ò¹°GªQÃ]HBÖ­,ð¨ãþ(…M·K‡à<»´®Õ9‡’,­hn MëÓUMÁüªƒÛð/(%™šÎh4ƑȔØ�®& ¿ò»3Ò{ê_,cµkStE9ZXy°wàBxÁˆ¥©‰t…"±@@xá$BIX±á�›q ²l•6p-Él¬X«B:–•·x�€çG¦,·CE"Ccðù§A)éÿì³M<©Î7y2Ò”¬…©¸Ø;ŽŸ.\EJŠ�._lX ߇Œñ³c7‚†ÆÁm‹Ruü18n !?Oº„¬¦hy®ñçÐ$¸�RâtÏ(_]¨SŠú¬òn1…#Ä…DÌ·¿ùÌÛP©Ä¥Þk ¥h›Ë”æe§cpÔ�YÃ!0EEN¦›8˜•ÐK¥”`†¸U¼B� ßu_1¥�Çδ¾Ô›T€Üç�RŠl§SCpÚD"ïµ–ä.T%ä:{ÿoo/&Rœr;4˜–„�›aàêØ”ž šf¬!é³Àª�ŽP˜wŒVÄ´À£„²LÄQÆö¸ µ¸x™‡ûÃ1h EºK�yz.¸ÜyñØ+SIH/ I¸�ÓP‘È¡)ˆ_· …qŒ`ÃægKðDI‹o>»x—ûÇåt$¦ø5»|I@|d(hÿ¸/„4—†D) ×ý–¤8ßn*ç2WQ~û;€HŒcQš•Í>ˆÈŸK›âó�¿ÆÌœÌÌ"04ŠëS!ƒƒŸUt—qB{ëÍLÇ3¥¤Œvÿ|dsÿœPÆÚ¼#ŠS£Huj˜Á¨Ý p. E”Й÷¶¥¾±É›XàT‘éÖ�šè¾ä–%ìòÍ9ÀÀ×{{9ÇÎþÚgågڣҏ=fŠC±ËA@Þ=u¾?¢3 X1|y²Ç´8ßÿËÑ-§ç ‘m½ôù¦ä’,7¤„½Û�3#Çc§–V*6r²›¡è‰ã]Ä?ö„Ãaó�óG¶4á^)¨8¸±¨æpìõÃßËu»>‘ßúR>·»Ý*®9,ó+›ÞÇ-e/``^Ô~Êâ7’å»?µo%Ÿ¬ÿXîúÿr{Ó7² ºyÉIþ‡dIÈk�’¦0,HÑí^쇅2·´´U�×C]{û)!ݦÅÅT(Š8ûÐá\b†ß3ê˜Ï6!HÀwD n!ÃmÀíÔàó‡@@|}]��yàíÚwš ¹ÿòï}¦J8R оÁ«ïâþ‘$>voæW5O/­jâU‡:ÊÊ<ùe�ÿ¤Ù€v¾ÉIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewcollapsebranch.png000066400000000000000000000020551506556630100231540ustar00rootroot00000000000000‰PNG  IHDR  «hbKGDÿÿÿ ½§“ pHYs ý ýKœY tIMEÒ$,$lNºIDATxœí–OhUÇ?3³™Mó§)I5h þ#‡‚SÒôPöàÁCzK…žD$<„  ^ ¼I¡ÐCÐJ�Ú¸©¥ i‰(ZZ©è!&mÉ¿ÝÍìμ™yóÞó°[Ýîn6Ä/¼9|ïÃïý~Ì{ðþ³½>jÞºþªR€µ·w"y}ê53ÐÓO{ÚØ ìì ¸µ#ÑÑ©ƒæÔ‘sôvöâ8Às@ÇÑ©ƒª/WVúl5ǦÌg‡¯’±&p]Ð}lzàFþ$°ô¨¢-‹Ž_4Ÿ]c&õ ®Q(;æø¥Á¯ëq MéĶ.ª”$Ä$¶ÀÂCI=žIYð÷0l*ª”(Ë'´—ñÈróJ–z<±"¢’è±4�¸æ®�AÇŠHFäÜy®^,ðÁá“5<Ñ!‘�IH!Þ¢hh²ÏŒ¾òwtÈéU|g‰™o–™82Qå̃„ÄŠbENˆÍEÎö™wûƹÍ@Í)M>µÈ…éc‡jyh eˆ�"”QL‹œí3c‡Æ™wgqH'kI–‹7J’j.lÐ4¡ÊÍEC!¯kD•ë—?µ½wjœß–—ñ#�'sdE�þ—;¨Ç‹EMj¢Èà‡1B(|_çkÛáTIÛÄ\þ«·øv÷~P¶‹—dñe–ý­|ûÅïTsc Ö R)!(øŠ¥{ ïrø%ðX”S%¶�´˜Ë·èš7 Ýw)ú)d¬ÉS/:\;·J5¢„8ÐB°’ÓäîYˆ›AC‘@‹¹|FîyzÄ |RiM(52Ñ´=£YÌ´Rͽ@R(Æä³šd¾ñc¾¡È”E�ˆ¹|¦¹ë¥/«)ÚE@³îIÜ.A|ëªy\Tˆ•4ÖJ;â畆¢ÊªJ²;‹™–g{GtäZIl�‘ÂÚcýù5<Ük­ˆÛK�‰6º� ÜþX›œ¶Vvcîï�° ÂfHlH)êrÒ56ºøje~<膠µ€í²69ûa=¾Q­ìLfw� :0N \;“­Ã·%ª‘eOŸÆÞN'ØM°�=}~¤Šo[´�Ì…¶vŸRÓ«¹)/ âÜbR@;Ð<t9à×re{)=J:Ëü6°ÄõÆ»Q*G_–×:¥GH*¸¬–™ÞnE••µ­”ŽÇBJ­¨æ0;QÞôQ�ÿôc#þïä/¨ÿ‰.JǼ#IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewdataeditor.png000066400000000000000000000030001506556630100223030ustar00rootroot00000000000000‰PNG  IHDR szzôÇIDATxœÅ—_lS×Ç?÷�¯�?¶b…¤@¦¢QZ@Æ6è6U¥"´CíºNÚ¤MÕÐ4UÓ¤=ìmš´I“öZíaÛË^6í¥UÿL*ꨤ¢)%)iÚ „Äı1Nmc;ñõ½÷üöà\7Æ+¶#éÜßïüÎ÷{~ßß=ç^ø?7íàK;^®Oý/AÛ-ïØÐ_Ž> }û¥Ê3?;|ßA=§J¥\ÄsN½2B1Ÿîùø�ßæMa©P¾¯àJy8Ÿ'9êž§rc’Œ8¼5y@¹Þ}%P)ùVáú—B¨Ô&^V7ØÔ•Ûñ˜5~7”¸è¢Ðó³l]7‚£¾Š6ïàx3Ž“0ï1ˆ€¦ZÍäVé¯L²hdøcÉaps•ñ Û8Ýñ@Àô\�7’÷_M«¨ÞœççÿâO\br~+ÚÇË ¶åk¹ËüsÿæÜù#‡�<[Óu×øžëÖdžibÛ6£'x~í4˜!úlú·íÂÌ/ ½ü‡=SÓ�¯lŒ²~]Ï]�‹®ë""躎a¤R)p_£#$ˆ0‘ÜÁÎGw‘?û‘íÇéw…º¢)¥PJ!R“Àq®Æ§y´û$:ñQÏ[»v¹F¾�“ï}ÐÒ>26ŽmWl"©‘³u ”âÿ`}� ÁïMmàÁ�½´µµ5Ä5¼õÍg<‘$™¾ÞD`.•æò•8†iÔm®ë23› ™¾Ž®iÌ%fù~߈@°›±«óÓƒ˜ÏV'ð“žmp¾v잺ùšxûÄ»|gÿ>ÚB¡úîmÛæõcïðÜეJ%F‡þÄöM ‚Q¦>_‡ØF$i"pÏjÀu]„Z!¦Ói6ò:#êæ|zk×õbšÍÇŽ H]»†&­íBm×¾Ïó¼Ú³§(—ËÌ]fps‚ë¹^ìÆê:@‡Ýã7�‹5õU|Üòìº.Žãà*�L&C·ý z[‚]|šÜF_ÿ&tÝ\o$PË€”Rœ>ûaƒs.u�wÏŒ6e`&‘Ä4M�ZJ«Õ*¶m3;› “¸À/$!´ž•0’}­$JdùUmA@IíÞ¿wwƒ3›[h²”Ê‹ìÛ½“¶P€b±HµZåâÅKì^3J{¤ ¬(S}zêiÂ]Ýœ|ÿÆs¢Aÿ¹µK�õêvÇqp]—¥¥%ò¹4� Ä!Ø…«‡)ªo‹Å¥¾ˆi΀§ð¼æo%­í¢Ïóê½R©�Ífé�Ñ ƒaür˜�ýÛ±,‹ÅJ ¥jkÝJ@_)Á�d@Vd ¦ÿ,‡ödÁŠB �äÂnz{{ñ3ì¯u« Eøê[Çœs©4åÅ¥¦ \»>O&›Å0 lÛ&;?�Yæ…#`…ýÔebj‰¬}]×±m‡¶ŽŽÚ¤…žª¥ò{ƒO68ß>yšÁ'o"pêýQ¾ñØN‚–E¡Pàܹs<*‚Ã"µ°•ÿà9zzj7l¾p“á3ã5 ¼ü 4i-··‹ù|žÂüGì B �Ä5!ÝGggg=¶¶óÛHЪ:¿ �jµJ.—㑾K`…AÓ™¸²‘-÷aF=V”Bü:»�£“d²ù† on"ðïá3(¥HÄ?ã÷¿ú¸cLOÏpöb„äâ'˜f >×õšÆ—`ëÀƒléßÐpµv3Ç´:Q�ŒÇ7pèɽD£Ñ¦y~Fš$Ý?ÓÃíwîy¥ÒM�üš#ß=Ä×ÿ!±X ]o}ɶºŒLQJ»#`¿)¥H¤æØ³w;©R/'>˜X¼�ˆRõIæÜÕ™£W.N®±m;躎)Jé"¢šúbìï@[h"¢‰Rºã:�KÓJ3Í®aþ±)š¦‰ˆèJ)DÓuà XV%ÒÕ]XVÚ_S, ƒåëÞ_¨E÷ãVó  VŒý¿ÿûÍ\  ðè1ßjË JAIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewdataoutput.png000066400000000000000000000022531506556630100223660ustar00rootroot00000000000000‰PNG  IHDR szzôrIDATx^ÅVMh\UþîÏ8‰J DZéJH$mÅ�¸š(*kÚ¦±®Ä• HQ¬�íOŒýIã$13M&“ùOf’¦WºÑMi2U n*ºÑ…º¨Jç½ë¹çMßã†8º™ôÀǽç~s9ç}ß½—ÆÜÍýȱ¥R]ÈnnÆ´¾¢ÚøÕŸÞÛÛ«´×!»‡zž‚çû�- ßJJ]üºÛÖÖÚ<ãcK\á­ê�ÐJ U=BÝ3í~¶¦­­ÛÕÖ¸ÆÎmmˆIÑ2l�Û¾áZ4ØÚeíZá¡ûÚ $Zž®å5:Ѐí xv{œ°›\3j Ñ jµ5@H>¥…1ˆNò¿pv+O£<Œà–ùèèè kjD­c�JB 5Û=ÏãQJ^9ß÷ÌQ8¹"Úï{NãŽãZ)ĵÂÓ§~Æ�ß!�Î`:™B"1‰3gÎ!¦5ãÊ•/péÒeT*U”JeäryÜ£5#—/`yi± gnq±‚••Ëv�k85�ndðÕWßÙÁVtvvAD_Ä ØèÞû<«€HÚ�Ûß÷ŠÍYÎ_í  ¼îyÑ>W$J2”FÉ£ƒæëî~Zˆ£Ü©‰(˜Œ)…ŽÀõëß"™šÅDb çÎ_ÀÈÈ(´VPÄ_Z¶ò/¡\^D>_Äìl&äÒsYZ¯Ú9c–l,K¨V—¡¤‚üo ¾ÿà1<ÞE×¢ÑÓ³w# ˜ë­€Í ôïa½^‡ØØw¨¥¤Q:sÃ9ç*yîò¼7š»ût³H–rçÑ5Ôj5L|žÂ…ñ>9{Ÿ e®TV°°PA._Æ\&�ÔLJkæ/ÎÌ¡XZ`ù)g.›+Òï—x�j4³@qO7‡wÃÐØµk¿$¢aA�e6èí}!|Ü"pè`?(90pð€ó)6PÀ„ dËáÔtoA`ÁÃoƒµÚ*“tÆèŒžÁðG'ˆÓ,c¹²Ä2gsy:õüXYŽ‘L]D¡XjX ™›ÏæC[¤ÚÀBÉrý2ò [°{לCX™ƒS,)ß×û¢c� -…XöõÃë,pDwp¥R Îÿ¯5¢I¢é5Ô±˜Âo~‰ÕÕk|>=?†“§G0t|:¦¡ˆ/Ú¨XF&›åS>9=Mëšù©dÙB�æÊæÌ¥çç[ø5lò �¿�?X ö<éü�â‡/ï{ɵÀ°4G;·à�#ƒ�ðÃǪ™ ¹‚KA¬·(¸ž )$7XæÚ¨,'„³¾>Œ¿[1AxßÜ?¸bj×®š±ñ„=;fNœ:mŽ 7w"_(›l¾`Ò™¬I¦fÌg‰É�KLL™¹Ìü�”¸ 33›6Ù\Ápø>¶¦­í4°Ip�` ±ÉÕäbJbs#ª© ¦Ý»UÛúþrÇmχoZþå\¼íïß¾ú0”b aaAas¢Nø•pS4T¸—'lNÂ_„?q·ã9T‹=ò�4IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewexpandbranch.png000066400000000000000000000017641506556630100226370ustar00rootroot00000000000000‰PNG  IHDR çœÓbKGDÿÿÿ ½§“ pHYs ý ýKœY tIMEÒ$F”L¼�IDATxœíÕMhUÀñÿ›�Ý4&iAõãTÁƒB´Es°âÇ¡/<‰P�€‚”(zEO¡�F9„ –D=¤Å x**ĵ6»M²ÙÙÍÎÎ÷¼yvV2;³uôÔƒ»û‡}¿y3;;ðÿ¸­Ç«WžTóWæ`Ú?õ²ãðÄdUçÔñ“œ¹ôLL ÑÿbèºàÄÌ >9ý%Ï^z䘪#zi(³“JEñ‹~‘Mã<Ÿ?u•/Ÿ²€é½4”A¤R1%Sò}õ#>{â*/óXcD/ e.b¬"b­ÛŸ„¬ðéÜ7n÷²P Tľ¾EGÛÆ×ëHáü½àå�Ÿ {(ƒ8ÒÃm<ºtµnì#4ø¶ú!çæ>æÇ «°¿òÝ­¡ b‡.~èâ'=Üħ%®Óq»¸¡ÏÏÚggßgýk»°?·zr$”AÚžGÇ‘8A@×M°¢Ê_i8»8nȵd�ùGßcå«›…}ny¶Ê ^/ÆóOâýiÇ�d›Žï³Ó ù!XçõÙ.®îö‡¿ÈCÙÓÕI\ðv—¤óVýöp‚oDêúwøIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewnextselect.png000066400000000000000000000031571506556630100223560ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs íÀ,tIMEÓ é3€rüIDATxÚÅ—]lWÇóµ»cÇkïfi;©“âV!‘ã� T�""ªJ}i¡X`É­úPU$¤ @H< JWN ¤BíC õ!%J•¶)•êIm·)_‹’¦ÎºñÇ;³;3÷ò°³ön½k§Ä•þZÍžsçüϹgÎ9þÏKù8Êã“;@1 !EÃ;äRL!¼³'3€H§Óò†�|¸8 F@�Õ„ �Û¸å<Â?eÉñ€—N§ÅD`xtr/ŠúR|UƒHD’D¢&ÛâK|vk€¢ g.õã¸U¨Ì�»Ò¤Cà>fñ›_n+"Ê:^ŸÀÜLdÃM<´o†Ý·là¶­Ä"êª=3óþòn�Wþ o^2 t¹&ª/X<ý-`)�NûëX6®E!~÷î}ŸcûS$6èm£%?òªW¦óüê¬Á³³àAxS–<ñU`®1Z[ãzÛ¶má±;ŠþLCWñMøî©"§'«Ü!² }©(!Wô¹4§€ 6eå®Oõ2ù˲|Û¶å*ãoíåE4ƒ¾¾>?*Ù¾)†çËU8þ\™ñ±$Çö™<:^às·j«ttMa÷v“kK‚+ òÖ¬·ãõ^õâ•�=ȧ!€ø p‰wè”+²%ÆÇ’Ë›ÆÇ’üäy§¥ž�ð�CqnNÔ”#=Ç� 7E`xÔ~ä·1{¹o_Ž�ýðÙ[SÑ&æÇö™|ï™ÙÓ¯¬Ò•Àö”à\¦¼¥-Y±3ß«L]°,«º)î�M©.û;)¹bM´ZãcIžú³×R?Þiðõ¡(h±»€ÀP†¿óæà ±�|i`?€r%Xzc±-‰g^mÖ-”|þ•-#Ñ ¶mh¢rd'«W‡jç“$_¢äˆë*ÍϾ<Ï=·§Z’xè—‹ìé-óÞ¢Â3}+ˆÎ,Ýû� uC›»’š÷¯þÃX—Äé·›²™üm¡Y‰šTÔÈ `®Ðb$Ì*ÅÐû·Þ�¶|ñÇYãcIü0L±°-i*µ†¶”/ÿX4t»æªíÍç¼–q£¡ã8n5lÑ• ^Íšð΢iP]@U·\—guë_Îüúª.„¿9Wg¸ó8sЇ©·‡ë�ë­mük?óH˜+¨ï5œ9þ´ež¾ 8õx „ •Ï/åçùd_g[Ï1€“Ç[Ê¿ù‹%±Ö{33¥ÚùûÅ—Ð(Ž`Û6G‡•é¬j}ů·¦qzÌ€˜ÞwZ« <òÔ|[}§"È^½Ró^ùíÏ�€|ãŒå¸�£™ç2—gøÂžO`h×ÿI~ÿäUº¢íòE!sy®öàfŸ$JÈÞr~Ú¶-�Zz6+?� „zÇ|¾Â@o„ˆ¡ahÊ*œ{»ÈÁÝ]üèwÙ–:†¦ âóÚT޲ëA5÷„eüþ �òét:hÉ,Ë’½LNfå®B5P_™«ÒŸRé0£èš² ç/–8±ÔR¦k ®SæÌ…%'4®=÷<0 ÌUÛ¶›gBÛ¶±,+¨“ð„vøï3.žPÙ¶QÅÐUt•u¡HŸ‰–yý�<ž/�g�k€S¿5µ¬Ò###*Ð1áß};‘žã(ÚpÔP¹ys»zÉd7šÖܪƒÀcq±À;WUÞ›-Sñ7û¤}ñB˜t×€rãXÞ¶M„$b@bBÞû Zì.m¨.7#�ê®åð|ÁÇ©6lþ4~ñ%K{ö�a²Í¹V·£5¯f###J8½v=•#;1º÷£FQ��°¥†µÚËT2TsvXdJ@!$PüV—Õ뺜†Ñ0ˆ˜!báêr1p'„»Þåôß»2F©V~LIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewprevselect.png000066400000000000000000000031311506556630100223440ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs íÀ,tIMEÓ *•IMöæIDATxÚÅ—]Œ[GÇwî½þÚ¬÷#.Iv6�P%¤‘6{¡D "¢ˆ– )/-m +ÈCߪ¾TBJ‰‡"õ¥È"%´* UÔˆ ‘ºÞî.]ª¶†lƒãMöÃ^Çö½¾3<øîÚŽílŠ Œôð�3óÿŸã™3çÀÿyhÅxìÌô.PGAŽ£(Ù´‡šAɤwÉâ|�étZ},ÆÎLŸžƒ$ˆˆXÝ@:8ÍK&�þ+–úù9ÀK§Óò?0vfúšx%¿ˆÐ!Ò‘A"Ñ8;’%>¿½@Ù�‹×F°j‹à,ƒòe8O[üò€ÓIˆ¶�×çˆo%²é|ûÁû?µ‰û·'ˆEDÛšÜR�¿þ}•ËïÂ[×L¨Ì×'÷5‹—¾”Òé´¿¡€ur= ÉûyôÀ¿xè`Š�MF×h©;¶º<[äg—Ln.,€_éÍXêÜW�ÅæHè]É�;vlãéãeŽ}nÓø’¼ñv‰l¾Æð}Q©Z0œŠrhÊ>×5PÁ–¼Ú÷Ù!¦gY–ŸÉdT›€±3oíºÉðð0ÏœTìÜÃóU®Ì•9u$Å;\¸Zà¾>£ÍÆÐ5öïŒs«$¹¾  >“÷v]s×CÜÓ— €ä~ž<´L2‘ Zk¿IsóUNI­ÿ>u$Åì?«]ÿžoMró¶Éÿ(C¤ÿ,’)À<½á}æ4¨ïâ± ìÙ„¨6¼ŸsZÈׯµ›NG{/P(`gJòf¶¼Ò¶¼Ü[Òf¦,ËrPò 4“-©^öŒ8Tœö«»Xô:’í›G²Çä£K¼6a‚{ÉË€mŒ}ï­]Àab›ùÒîeü ?Z lÙ•üWWîJîùŠå’‹B‡Øf°F'k'öZÑ …µ 2H*Y¢b·{Ó�üÕ?/u%^XqøpEãjn¸ñ1bƒ½fßA`jMÀ(ÀÖ>‰ªµVïOßrÏäÍkWÊWs#-ó‘h@Döñ†=Æ@Ü¥|‡÷O=¼­«‡Ý¢Ò<·ž^&]š "Ø�$Öȧ"F2êR©ÉuÜ�ü£ŒËß­9Q= ”˜FsJ®xnÛþÿ²�k( v C¨ÿÛzüJCÁz18kQòåÞuœø±÷±z.Œ¼Ï‚ò@yY@ašAÓ©Ø>¦Þš�¿üCÉÅgÅ]7Þh˜M/Ží¸á]Ë¢ãÕw–Þ%Üe„m8ö£î‡ë^†.À]®t Àa 7�½ˆ©yÄ�v|ý'Þ=‹ˆ{-XÛÃÔ<°Aú³VüOóë©�Hÿ_(—øôpOG²Ç_°9ÿT²£ˆÇ_(m‰l®RÿÿýòëèT[Èd2œÓfóÂúŠ_+oO $é�ÄŒvüq²Ê׬DÛæ—¦ow´_ƒ]“äo\¯{¯½üSà&Pl>]�ó @v>GÌðè�ºñìùmºÙöF]b†Gv>W7tò/Å�z “ɨ“–‘Ï« �Ç—Š5vEˆ˜:¦®µáÍ¿•9¼¿€ü*ßÑÆÔ5>™)Pu>>.€Ä¤ÿÍ#DúÏ¢écQSðÉ­ ö IûÐu³eMx¬¬¬òÎ Á‡ UjžéÏâä_´¢¦ÂCw ¨6—å]“PD ˜T�>‰{M]›�G ÕW¿ÅK«>¶Û´Xú³øå×-ýÕ߇‡m (têŽîÚš���k€ôý“µ{1û""{æîðI Ÿ/KPËâ2a’©«¡€ àwjVï©9 £a†‰‡ˆ…ßÄz2«—Ú`‡p6jNÿ ÍJö‡WÞIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewshowchildpane.png000066400000000000000000000003331506556630100230210ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDùC» pHYs  šœtIMEÖ 26>îhIDATxÚí—A À “Òûé |òöXÁ‹UK'·Ýˆ´j…æÉ’th±ÎÖ2â½ lWóòö¬à‰ër$"ï›ÜѤgh*À@D)�9R "@„@„@ôµ ~õ;¾²DFÖ‘PIEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/viewshowdescend.png000066400000000000000000000003411506556630100224760ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDùC» pHYs  šœtIME× .—/kÖnIDATxÚí—Ñ À C“Ò…� tGŽŸE°”«‚É߉p!Áµ„q"˜¬³u(ýÉjžžÀš b\L% 1u‚Á ôaNñl¼²n ¾ñëÛ�/p6i„‡œÁÉ9¥¸™±èÌi…òàõz±£¶*{kSÛÑgZ–¾¿ýáKñþ\"̓1†AJ9Ó4¼QSUEö×í<ª%(9q+.œ¿)þ` É8t]·!…yYx½¦jù‹M­�jã@ZW0%ÿõ\Áõ�A(ªyTŠ¢é^L÷zjzDàP¹”é‹@p¹TøòoAF–#Â…° Ñ%‰b(áX¬q,{äUüpÄo¯“ ë÷ }Žï{B˜4Uåpk* âŸtW¼�Y§äc¦ í§È±LUÎ�88¦V‚ ábìÞ选 @Nª6ü�q|ZZÊ8�XgIZJàdþÝaÿø™Û`sÚ‡X\ Ò/»µ¶¬Ýe%Úë|{šW²½m/”qS�I<ßöÛ�åk’ûûØQŒð5¬/=Œ?ÚÏed1þ×/磾¬,U RfþÍgþñ3§ÉÞ�K?Õãþ{ïB�{¸¿ýÃc\ÕXéùŽsŸpòJ¯ìñßQæƒ?ÖS;·Þ{·Ï››¿xíj J@Ð%'ñœ<ä·á+OîÓ²ßApýçzÌ*˜ŽÈ•30—Á"!TÜq[>[·ªká†Õ.¤(AªÌOô'ËÜ�¼¯bè2Tw˜§w_èñäh+ì³ ½²;ð£ð«�ˆÜ¥ù äÎÅ¿ýÝœ‹EåO¶ôLÔˆR5þà±>>�Ž��v¡²|ôk$ûpÜj.Ôìbtö†àÍž¶¸|ÍÞ§ ‘P‚ÔMÆYyÀ“yäÔVÌœq+ôë”ùðUhî\(ÓŠÐäx¯cêë7Ùp»i’�à[0kf!"¿Ý€»5‚gãâ0GAÕn F4È Î[vÊß÷A{¾vû� o¤ªJp�dpÏ.0 ƆÐL,Á¤dwŽ×pà*JæU ³bzÝ�Á�Yˆîacá.H ÆB$W1 ˜²S橚Œ ¯ÞЀÃ͵ ‡àÑüŠûÐ{®3Wïóðs²ˆ@X­˜Y—o9%hû4y“Á(œÀK—cý³°ãÍ�é(©\¾à#“E“sš@& Àˆ 0rdP¤$k‚+ham$À. ³ê:Û‰íþ]ðÎ.GŽ •¬¤¦ˆ›ï ñÿ—�‚ØP9A™µ±ãælhâãî��›êlev·NC…ªèz4Q�()ðtÃp1³ RB�¥ IÖ~û kJjYò„tÖæšüe!¸ õü"ãÿ>‹×æ.�½¯IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/winclosewindow.png000066400000000000000000000033361506556630100223570ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<[IDATX…í—Kl›YÇÿç~/ûsj;'¡‹u*К‚Lg�Ót !N= ⱞ+ ØÀ±±fU¤6/;íŒÓ´QiëLªtAt"•èP ¥µ¿’Œý½ïeáÇXy5#!Í®tõù»ß=çÿ»çÜ{�LB|œ�}¬êÿ ï5˜˜ˆÇ ì'BˆOƒhÖÞ¯R“©‡Åq"1zœ˜ò3.xœIì¯ðÄ[SS³“;çÑÎM8~atH÷µÍõõõé¡Pkkÿr¿,Ó[»ôv!z‚áŠÅÇA6—…åXˆÅbº¦ Q÷§††bðôÙS8Žƒ­­M�Á"Ï ¢¿<{öŒG"Ý " …<ÇFlxx_ˆñ £CšâKÅb±1ÂúzŒ1º»{ðï§O8�VŸ à ï;÷ïß7%ÆÐÛÓÛ„Èòð\#gÎèªâûm+D-ç¾ÔððH@’66Ö›v½½Ÿá÷÷ÿ`¸Âûþ®ïuŽ¿ñµ×5Õ?5tú´ÎG>¿"c ‘®dEE:�6×ú&Þ¶*ks##gu‰1dsY!À9Gw¤ÃââõŠéc³“WñDüœOÓ&c±!]�|~£ÒH¤’,#ýö;&ýì9]’%ärYpÎ!„@WWÀ�ÅëUôǒÓÉ{éì çÏ�}Eõù.ŸÖ>„`Œ¡«³ >¿Bpx®‡Üz®¹òÎÎ.ÀÂÂõªmšñ™™Ôõý4¨§ã«šæ¿42<¬6Z t=ÆªÕ 8ç5ñŽN„ùùyÃrÌøìÔÜÂAþŸ ñD|Ô§ª—FÎŽø§¢‘"‚BtttH§Ó†iÛ».�½Ú¡jAr:yÅuœo\»vÍPªªÂ4M†˲àº.4Mƒ¢¨Hϧ ×q‡ö©{5ÁH”Ëe”Ë›°L\ðf$,Ûc2ˆH&è°~�ÄD<®ÊÚÅþþ~ݲMØ–0‚$IÍ4X¦ Ó¨"ÔUE›LLÄÏýWñ¸"©¢ºÇ=”J%c`DðûüÐu½ QÞ,Ãu ¾¦«òá Ü„MñÁA]x. ÅBó[8Ü¿ÏÀqm”ŠÅÚ´wt@‘ܾ}»j»Ö…éËÉw>2@C|0Õ=!P(ÔŽ„Ba(²‚;™;†\D£¯éD@¡Pч€Š¢àÖ­Ûǵ&öƒØ3 ñSýýº'8ŠÅ|S<n‡ª¨¸“¹cØŽû¦íØod2·ª‘HT'(•аmÑ�€"k—÷KÇ®ŒMŒ½¬‘ò§Sýý@ X,4wz8†,)È,e Ûqßœ™œ¹Ôj‡*k“Ñ�P,›wC0‚,ÉX¾»\q,óÔôôÜŒ€ÄéG/?¦ÕÕrÎ9G[Û2KôìïÎNÍN‘DDRrúÊ‚i__Ê,U\×C(jÞŒår ®çâäÉÏéL’s` ˆˆÑùžž^y{{«9~äHD„å»ËF¥bü05“JÐZûÜìÛ7·+[ß^^¾[q¡`¨i¿µµ‰p{˜„ÀKuè¦.£ZcD$ðsÎ3ëëë^@@Qƒ!1¬¬¬˜…béÇWç®Î·ûZº–¾ºðn>¿þƒ{÷îU=�# A’$lonB€oPˆH&"& z$|ü¡öp–{^ÜçÓ( ³\6ë½·úž“ËmüüæâÍt}.õß�w€öþ£ÇO;#�Ëår´­-(‡Ã!ªV ¬®®Ù\î§�ÿþ�ÇõÅ{ !P‰€€ÿ•/¾ò…O=ú=EU¿dæïþöþ£‹ÿüð €]Z;Ò©5 h'>â3Ç�ûcì“€(esÙ_./­Ü`ÖûBÞ<D¤´8QQ«RÝ9àpêÂÆÎÍT�DÃ^©÷Ft¼{@Uá{Ãú^Pê�¢âÕ�]!ßC¼Õ^j±oð8 áæüÿùÇÿ×ó`)$5IEND®B`‚TreeLine-3.2.1/icons/toolbar/32x32/winnewwindow.png000066400000000000000000000024111506556630100220340ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<†IDATX…Å—É‹\UÆçÞWõ†{(c'�f�JŒEˆ8€(âÊ…‚.Æ•€ÙdqáÖ� &*BЦIÀ !£!¦ÓCR�tÍï½{\TwèJ•]mw‰ßö½s¾ï~çžsïUåÿ„7ºT3P X–l£ú’‹­s§)�bѶáç&¨»;JFá@µz°†­Rš2nÕ�!Gê<UCÇ8­'ØÅB!w¾oŽPÀ3^½¾0 ¦:®bTÆœ‰¸, *¶-JMঠs©è¹Ü¯óÐ%î)ÁþW޾ÚRù¨ÝÖÒ0j¥R~ŠÊX“í“u¶M4˜(5)ÚD~ÌÞ]/péêIÚm�ZÓ£ºPk†�•úñ×^J�G³}짇žxØßÿàôеg½:ù`‘bx�|0O>X nd:Œž£\|‹ÝÓ·k_Љ�—¯ùÑÙßôx§àà-˜iô¨·RÿÉ{8}n‘8éÛ/wàÙ„bx‹måë8�%ãÍ“gß[¤A©ðÅÜëX>c¹y“Ô�±÷þí\¹ºì‘ºéf3~( åt_~† ð ÖY}”­1žoS)6˜,Ö™,,1Y¸Áx> ÞA¤¸R§?8†1à{¿ÐŠ3TÆS¦HÓ*‹û~ï�ñÌPû­Mð3M¢l�m¥2»§^$À¬¯uË{Ïû„0lÑI~bÏôçÀåIEÆ«ÖëðæÓŽ—Txv_¸½"âad ‘,ÖV‰¢ÇÉ­¯Z2ÞãÜ[þT‹b$ïû:Ñ·\k‡Í¦ˆ�ˆQ½N§}ÞÎqç=œ;‡ ¾sê»XƆûÝÛK¦JŸ¢Ó~ݨ$ùš$þY›IlcV„x(Y� iòͺQÎÍ-ÒÔ"j::Fäæ@¿‡MGUŒ�‘Ñuð ëëvMDJ´;Y·,j뱘êŠë?3îBq99�"†2pÏšï œ»€È.Dò+Y;@…F³È ‡.äó¥A@Ý0R™ÄRÅɘ:ªIò#iúiü-" XïQ¬}u!b¦¨×ç™3&û|—ô PeZ�ÀØêb4ž#‰?Dd Œ�¸6ˆ!mŸA9‡Ó2~v'µZ±ælž¹ïŠêÀÊŸ²CŠ5Šª‡Jˆ˜2’6é¶*ÝMªyT‹ˆÜÇÜÂa˜�YÍÑït@=R·grãc$�è2B‹î¼È ¢Zsˆ¿þºÌÄÿ(ݸ«p®‚Hcna¨"f !FÅCÓ2NË8§Ä"Ò»©6“Ź P¡;®ªvhÜàüKC€Þ<ƒ–µÉ9°YôK°FåÀ†ø·Ø[ç\#Bš¦ýŸ¶€î1?¤Öz×.\<¿}Ï®FJ¾ŠóÏc­�‘PU›=D$:üöá#'Nž8¦ÎMý' Df/]üó]  "ªª­;ñ€<�£{à·ØÈ5gƒÔ+yS  Üꪪ}/#éŽ* ¤:¢—ëšœNµw‡�äm¸lâJ6Zü »cõÃ&ýuTIEND®B`‚TreeLine-3.2.1/icons/tree/000077500000000000000000000000001506556630100153055ustar00rootroot00000000000000TreeLine-3.2.1/icons/tree/anchor.png000066400000000000000000000006321506556630100172660ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA±� üabKGDÿÿÿ ½§“ pHYs  ­#½utIMEÒ 1- ‰µIDATxÚ�ÒO+Eaðßq‹QlowiaORÊBù ÊZIê®}eeå+°²ñwcé–Ý‘¶¶¤Ük3G¯ãþ›šÎ;gæyÞç�™Lg«c%ÎW8lWTé 3¨â¶\8Ð� ¯…+ö$(Ûl§D™`4¤ža­ðI\`ƒ�Èr|£þž<á+<�ï¿&>c"ä6ñ‰‘È51çS<â¼×»÷[Ý sdmþׂj›|†¼hâ=ôou¼¤ Ú¨¨vQ�æWÁ¶c\Å8k¥çŒ'ñN`T°ŠÇx.cÖ±€×ëvq„½¸ÌǨ É×h$qwIÜ Ì[(tóÍ´å�ßÀ2¦ð�áX²±�~“~cLM !¢ÞIEND®B`‚TreeLine-3.2.1/icons/tree/arrow_1.png000066400000000000000000000004451506556630100173700ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ÚIDATxÚÍ’AjAE_UwÄ d§—¢7ЕÇÈý²É²½€ADGQ\ gºÝÌBeº‘„@jSPüÿêCüeÕÚ]ÿ¿~m<…hÈ<'Ì7)ÍÞ1ˆ†Ì³$EDxm´£-3¯ßT+ç@¢�æåþˆ5Š÷÷ÚÄ} ÐiÕøèÏÈr‡+¤‡Åˆéçû]R@n´Š�X£d¹Ã¨<&–[]ð Yîž¾u)À¨`�þp:_¸dùS[6N¶¬’-j,§t‡}©RöH‘…¿«+>HQ´½ÀmÅIEND®B`‚TreeLine-3.2.1/icons/tree/arrow_2.png000066400000000000000000000004611506556630100173670ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“æIDATxÚÅ“± Â0Eïk«›ßà/ø®ââèêäèæèâà7ˆ«ˆ(ÄÍ¡ÝAŠcTJû’¸I‹©ÕA|�%œ{H. ðï!Ížú†·tÔÌõàŸ®¸‡ {µG!ý¦Ö¨„,‘³L ÂýrDp=§I+0  )ef†Öj—˜J*¥@D Tl½¼pqBÕ»”KEäsXH°�ŒæOà°ß`»&rñ+аUÅÄñ„ Éua]4îÔ0u=D,že¦…ÓJ$»×€³óq ¢·á¬Q•ö@e<ílÉÏãIfP`ŽIEND®B`‚TreeLine-3.2.1/icons/tree/arrow_3.png000066400000000000000000000004521506556630100173700ustar00rootroot00000000000000‰PNG  IHDRóÿañIDATxÚÍ“=ŠA…_w•âÌŒ <Âb`à!ŒM÷¦›yC�`¦ÙF⊠˲ŽÃ.Š‚ v÷”�àìü€[Ð�tÕ¯^UOŽQÚN8“,/è8¸?ò3Iä8øëw�¦D]·{x¶Ø€IC)& ëB�VØî ãí×ú•å{xâ/QÈ3öÆÁºÖ…'©¤a¬Ã·D=(U^dð1Ç4X�Iã`,Œup¡€IƒédUŽ š8ZÇE�Wk X®$š¶]þà½ûög jÜ눇[’Åç0êz.ŸÚñj ©6[rî@ÜJO’u˜’&Qý ‚Gp5a†à6ZKIEND®B`‚TreeLine-3.2.1/icons/tree/arrow_4.png000066400000000000000000000004421506556630100173700ustar00rootroot00000000000000‰PNG  IHDRóÿaéIDATxÚc` ø�O’‰RCˆ2 ºcNC˜ÐlÁ†œ äÖb5„Ù€­'ï0üúó��™‰‘�…aö»Ï?~üúðå䆽) ?>¿gÄjÀìmXY˜þüýøÿŸáÿÿÿ l¬, þþcøýç/ÉÏ–úÀõ¢„Á·_þýûÇ LLLp9ÙYÌÔ¥|*ýÂlÀŽ#¾}|ƒ7@_ß»ÌpmïR¸ P øóûÃ�/04qð`ÕŒ-®±bûÔŽÿZÎÑÿ %*œ‰ˆÍÈ.£M^xÔÅoÝœ ®±IEND®B`‚TreeLine-3.2.1/icons/tree/arrow_5.png000066400000000000000000000015031506556630100173700ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs íÀ,tIMEÓ &0ÖNQþÐIDATxÚ…“ßk[eÆ?ï{Þ“œÄ¤ibHÒŽn¥ ëæ\ ›cæ�õFa‚¶”ý»ˆ»ÛÍØ•ÇUEx)½ÚdPeÂì¦]ÙÅ"]°«¥KS³4'ÙYÏéyÏñ¢è&úÀsóåû<ðýñþ•© ÂI¢° ‘€°®t÷Öœ}Ì}ºW<%L�8‹až’±�ÌHv‹¤ðGÓ"ô6:B»ß+ÝþìWûõåg *S %„œ-žŸøðÕ Gö $ ¼­ˆßï»L_ﱸÔü;¡ïýòùñÙ¾AeêN !oW^ž8ó¦E:¡( šüt·Ãþ‘$[:äòÕ6WçÖZ)ïÞK?OðК€…� ø‚O baa)¤U› XˆM¬â�E¢&f=¢ÙÍŽ….xÁ¦›ùæŸaþP1@ž#ô«âó�ÙXìû1$4 Š‘š•»L\nç$±2,ý½õeCdsuRŠ×;bëbåãrs4/k aÇÉ+¹>èNWO·Ö€ˆ úÚÐ*Tꘈ6ñÖÅ[@rj´ÕûÌØ.¯ŸÎ¶zƺsÉϱñh�šÆN\’E)��¹Ö1Š�Ããµq¹Ý õ78K~ôÐjAU@y˜ˆ•FQ Ú›=TWia§ÈíÌÞôO�Dtìâ¦Ö…-¤xB©TļÎp{™&Ÿ½"Tõ0 ,»Š³ùÄR_m#MÇë«åþö”‚‘ÆÈ$±M ãü�Â�M6Û)XNÀ“Íg º®Ë‹ë+'¾¾É͉엗üÝ/Äø·z·­ TPsàIEND®B`‚TreeLine-3.2.1/icons/tree/book_1.png000066400000000000000000000004241506556630100171650ustar00rootroot00000000000000‰PNG  IHDRíÝâRgAMA±� üaPLTEÿÿÿÿÿÿÿÿÀÀÀÀÀ@@@@€€€€ÀòœªtRNS@6:™öbKGDˆH pHYs  ÒÝ~ütIMEÐ \m‰_IDATxœeα€ …á— ÌE=-� Ä ‹Ø0;°¶±2EI@ €&`Ñ $ ×Aâ;‚„qŽžyq£tüŠ~¥XaUNꀭp:£�êžs¾íôšÙ¦ýЦl _IEND®B`‚TreeLine-3.2.1/icons/tree/book_2.png000066400000000000000000000012111506556630100171610ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“>IDATxÚµ“MHTa†ŸïÞ›óã$cZMSJX´2"jWÑ*¨¡íZ” ´Œ�D�-Z„‰mÄEA«Â�iá„ZAE`‹iLR fÊÆû7÷»_ �Q$¨E8›Ãá9ç=‡þqÆ· êO »M¬œo FÆnö’M§(:.Ó¡ìVÐ5�¡ièBp-õz¹´0òòþ]^�óÃr(˜Ӧ且—Ÿ–ƒ¡ f‹eüµ€3íÛ›± ”lGJ)©(¿Ö`hJA¾eÀ@ �ôv³09ŽåyX‰íyø¾@ˆEBÌ˾išê^òä#cp1ÙÖŠ™ÿ΢ea{ËÓ]¹:]AÀÐyC˜¥y.?Í$�ºê}=×)f?áxÇ“¸žÄóWñ†é/ßèèèÐn¤3pp5àô•CûÉx‹µ´„+}\éSñJ­Èö$sÑÎdªJMW%<¹�<«J_²¢>ÚÈÎP˜ŽMÞ´Q+WúLii=ÀÐð„0ôÇ“Ôn�}&R¹9ÙmЃ†€åI¤ï£ Á]Cµ£ýó;†á£ãɾÚguœÚ×[:¯’H$PJ �R233ÃÔÔ]ýýè]£ ½-Ö~˜™Þø<ûuk`:³TI�ÖE¬2Ú®=5P.—#;x›¹y€s¿ó@Ð )`PGâ1÷Öñ„÷~ðNP›Â¡î¿1TlåE—¶DꇪæÙ»¹qŒÿ¿«Ð5«eIEND®B`‚TreeLine-3.2.1/icons/tree/book_3.png000066400000000000000000000011661506556630100171730ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“+IDATxÚµ“OHTQÆïOÎFÆ¡D%˜³À�¢Ò¢M¸kÄPв —í"I\„Ц•éØR$ ‚6.R'òí DrÑøÆ�.4§qòÎ{óî}·Å8£HP‹:pvçü¾ïÞÃÿ¸"ékéi@ÿ©ãÉø(`g÷b©ØüäûIr_søeQT�ª¦�e[¦ÁòóeË<˜Ÿ]šÅÙv¨ü¨ Šq ðË>~ÙÇ+y¶Ai§¤�ë@xp§£¯ƒb¥ˆ_öQU…ª*B6LË„ºDÀg€:ÀÞŽ¿Ç)8•€À«µu;a�hKPÚ)…B�y‘Y8 xÐ{«—½Ÿ{ˆCÑPW�:ñg€ÝdÃ^>dáñBhª¦Ç&ÆÈÏ£|…ô%Ò—h©ûÉ‹I¶�mÌÜËœ ܪ6p{ðá ë»ëˆŠ@5åP…h}�ž¤å …ÕæÕðØyÀÞeîgt¡X0’‰$±h OzˆÇÿ§Åþ·}º»º™››3íˆ=&}IÀâÒ¢áæ\•º”²ìˆÝP UX»ý9‹þX?[W¶6¤/'êÎl€hs”ž›=ÖHßCCCh­‰F£5u¥( 8ŽÃÔè<ãäeXíWÛãkoÖšóóm›áæÑJq¥É‹ytF: ×u™ù2ƒûɸû» œF€,° ì:=˜®?–ÙÕlèx*þäoÕ~|¢G‰ ‰×õð´v·~àÔ/$& ¶žŠu‚IEND®B`‚TreeLine-3.2.1/icons/tree/bookmark.png000066400000000000000000000003541506556630100176220ustar00rootroot00000000000000‰PNG  IHDRíÝâRgAMA±� üaPLTEÿÿÿ€€ÀÀXXX000­wðªtRNS@6:™öbKGDˆH pHYs  d_‘tIMEÐ  ÚA¼\CIDATxœc`À ÁÈ`46VVV±„�@@$¤¬¤¤¤2•A@DH ¤3TÂuu ¸¸ Çf'?1ýif”3IEND®B`‚TreeLine-3.2.1/icons/tree/bulb.png000066400000000000000000000014751506556630100167460ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ÏIDATxÚbüÿÿ?\IcQì3ø°°2D² Ú1±sq�¤ÿ|ûøíÛ«/‡~übXÎȰ¨î§åˆ>€ba@î¿& * Ç‹8Ä3sªØ10rñ20022üÿôšûÛ�CÁÏ÷­ xyãÍBf†< ú¯ M7àÿ_†b ‘$©˜Zi†¿þýË1r‹2pËè2(++13ÍmNzzíÃC pH €à°²3ŠÛè20ˆŠ30|< 60230JÈ0È9h0¼¾w¢f@!¼ÀÆÀÃ,tÕç3 O3`yX?20²2ðÀ„nе¿þ¿»ÊÂÈõ‡��™è‚ÿh.ò· ÿ>=bøûŸî<€‚ðý3CÇË+_›$.10°°3001"4ƒÌø÷'Ããó¾}dè�Iܦ?=Çpþëk  X€^ù÷�ÿ1ëW†Ï/þ0<8Ép¨vL@Á øÏÈðæû;†Ž�l xA Å@ö6†Gg�q÷–¡�o`únÀß@W³1¬q†aÏ×@>¨!¼ö—÷ ÏN1ìafgX�<„0à?Ø¿}fØýéÔA(²?<&? #Ãoä° x þýe03\øx…á³°./(™ V|¾Áð}þ¡E@± DH?Ëÿ#·hݾ2OÔèåË ?}føþã'û‹··-„ŽüA3 €àœÖ,…ç·¿¬üÌÑé 7oÞa¸sç!û÷ �­…Ì 9þ}ƒùÿ.T5@Á ¸òø=ÜTf¦,7o_fxôä×oŸ~]𗉕åÕ�ÿ‰ €aÙY^^‘nþÿ·ÕÖÖIVUU 9pààÏÇ�ÍÿüùÓF Ôa˜š? �`(…Qò.HÝIEND®B`‚TreeLine-3.2.1/icons/tree/bullet_1.png000066400000000000000000000011721506556630100175230ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC» pHYs  šœtIMEÕjþktEXtCommentCreated with The GIMPïd%nÞIDATxÚÍÒ?nAÇñïìøë¬Œ‹H‘,9Ešœ#gð(@¸àp€”ˆ‚Ê 9Gj'–“ c³Þ?Þ�™G)X©áI¯i>o4¿ÿºÔߟÂ0¨Öj}ã\¯0¦›¹1CcíÀ9|Q‹�/ív×÷ý£rµÚÈòœ(IøÇ$YFnÌȃƒWÆ ×€ÏÍfÐj6��'aH©R!N¾O&|›Lø9Ÿ³HS kGU¥ö_³(Ý�0ì‡aØy¾½M°³››<],x|r‚!].IóœÜÚNê\xwð´îùõ:õV öö`w•e4|ŸgÓ)×77xqŒR +Ò[œs]A´Flm�j<Ư×ñ´@'Ò½»÷H—KæQD2™œ�A€RÈÕQ‘NY!k@’¦ÃÓé®�iCp~Žáú₯——ÄIBa Ö9€áú ²l`EÞ.�áf6£zzб–y1�͈oÀ‰ `°ãÇZ-@ëc]*ut¹ŒçyçXYž“C~ Œ­÷_¯b¼·H*•®UêH”êàëfÕNdTQêà�sÃWù}¹ä"}+Ò³Ð]}ÜP`ðÈóï&ÿ?õãBÆ?_¯BIEND®B`‚TreeLine-3.2.1/icons/tree/bullet_2.png000066400000000000000000000012501506556630100175210ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC» pHYs  šœtIMEÕ ÇØ�ñtEXtCommentCreated with The GIMPïd%n IDATxÚÍ’»nAFÏîz“µsUbŒ/qÁEÂJ‡¨x�4<@"***Ê$€' JG�@B¢ËÐR „D@Æ+o쬽ž�Ù™¡@&"5|Õ¯_úNñéÀ¿ŽsñqûAy±_/ìJ×ì$膒 g¤Bw’í¯gO?½ÿn=in&µàÀ)ªX)R’QÂ8#�;VÝå¾Þê>ï§ozÜyX_œÜ\}»T[¯V.W(¯¯S*•p­4™RHc„gï6kÎ^ôQ§¹)`tma7(¯TëõÍz“Õ £tÄaû«-é$E …ôuõxÕÝÿ0…ÜN0P.—i•ZÜà:ÂÌ_�':‰è÷úŒÝÊc{�ælÃZ‹çx)Rá C{®MxžÎ¯É¤ÇÆ´w)ñYÌI¯Ç×…6Å\€ƒÃÑäˆø,FI…Õ¬{>üo@vš„Q>j´½6™Ìè¬u°Ú†!Ýo]’qB–iŒ±äq`b±?ðOe©d øïéí^H$Ó

    Àì F†1 Âí  F ¯€"óî�ø–ÁŽÁŒÁÈâ @¼…aC/ÃGp€r000r10 0`^1Üa8Åph€:P"œA™� ˆ%Á^``˜ ²S ý ì •@Ûÿ¢@1ýÃÀð…á4Ã% $Èì@Ì Ä�xïjüÏP†M3 Ãg ù—áà³õ€ÞÅó°³0ÜfÈ6›Or °¹n5]ex4àØ¿ï�U ôó|i €XÀþüÄ?�Ž=L Ï^5ÇSÝ”(ň\ `…ÿ�N~Î`Îð /, {Àb,HI™f†°�l€b¤47Ź ÀÃQ‹ôÓU!6IEND®B`‚TreeLine-3.2.1/icons/tree/check_3.png000066400000000000000000000005341506556630100173140ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“IDATxÚÅ“1Šƒ@†¿]Ò¥!��'x›4ÓmŠt)-µ›v-¦‘”IjÁÎ+Ìl¼C x«­"ºAaa_5óÞüï3ÿ�ÅårùÊÚ, Ã|õ’(=Ï›¥ìû­õ70`šæ[ñívöm´Ö|.ñ«”âx<r«¹b)%MÓ ¥\�R¢”¢®k¶Ûí 6i!Ë2Îç3mÛ¢”"Žc\×�u�ç9§Óé9ÐëõŠeYìv»ÉîF€4M¹ßïTUÅápÀ÷}Ç™LZH’„¢(0 € ~�Ïä7› Bº®£®k„ó}ß³^¯Ÿû(Šˆ¢èí ½öZëòñÂfÄþO~ãˆP"ºmj IEND®B`‚TreeLine-3.2.1/icons/tree/clock.png000066400000000000000000000020311506556630100171020ustar00rootroot00000000000000‰PNG  IHDRóÿa pHYs  šœgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅF�IDATxÚbd@*ñ»þÿùðï÷oû¿ÿ*üûõ›áßï?þþü}ðߟ?^Mü€¬ €‘9ª‰{þÿý;ÿŸ§€©¡8ƒªß¿ÿ®=úÄpæÄ#†_ן|ø÷ëO⻋™`zŽÔ’÷ÍWË<ø?mã“ÿ·?ýùÿíïÿÿK¯ÿ¯™xâÿ£ïÿÿŸÿðïîšûÿE¬çýçSí›Ó@0ÍêY‡þO½òåÿËŸÿÿ¿ýõÿÿ; ¾pÿãÿ“7ßý¿ÿíÿÿŸ�ü�ÿÿwžýô_ÐhÚ.©¶�^€bVMÚ+Àðïÿ~'?uŽx#!†ÿ@Á@ t9';'Ão @yF"ñû¼~‰ 2\Ù~Ƀ‰Õv&@1ýÿû/€KŠO ÒBœáPáÏ¿ü„A| .KOdؽiƒ±³Ã €¬ž,Ÿª„À¿?ˆéÿŸ¿ö *B ,L` üJƒ )jÞÔ\0m9Ã_M;†ýO¾2Üÿø“AÎQ;öÄŠ*1aN†¥ëo2Ø›I2ÈHó10㦯²��íû† K0¸gU2¼øÉÈ ôÛ¯? 7Þf–à @L@‚�(ñæõg†7_ÿ�ÈÀðˆï?xÀ`ooä�ÓÚæ¦x1püúÊÀËôŸ�õëWN -ÿÿ3 (‘|}÷•Á2Ȉ�hõ‡Ÿÿ8˜ÿ3ôÏe¸vüü·xE%€ÞùÏðã? 7/3ƒC¬ÃñµgAf?  ¿Þ:ù ÁÒZŽ��•‰�<¬Œ ¢‚ A K€±ðŸáÛŸÿ Ÿ�ÑÁ é?ÿ®m¹2à @½ðwãkÏ?¼¼ýŠ� è,^ f>6&~6FV0æccc \@ žœ}ÀðàÌ}P’Þ@LÏ÷Eƒ“çÊ)‡þýø 6„›™�èR†oŸ~2|z�ȉƒüý÷ë†Ek@¶'ƒú@1ƒXßžnºñ�ÓYáøž›êj" ʲü@¯00¬Úp�áꙇ æær@g30œ:|—¡*rÃë'ï'5Oé ”ÌÄ«ÜÌ}ó� ¥"BtTäøþþýÇpóÞ;†e‹Nƒ øµž™ˆ=SqŠ·€SÐ { VEóÿÿ€ äg�³‘Õô&ŸF‘ûð¡IEND®B`‚TreeLine-3.2.1/icons/tree/colors.png000066400000000000000000000015311506556630100173140ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA¯È7ŠéIDATxœ…“]L[†ŸóÃ9ý›´•Ž•f8aíf�"S$Æé † †+5Ñ,±jÐ,‘‹eÆ]oŒQã4&S/¸0F5Ë`ljeS·±Œ°©Á L¨@…‚‹ÐÓ–ž?/: š,{o¾«ç¹xó½7HGØÚÞò˜/äë „üQU•W“ÚÌÐðÏý‰Ÿæß/À,€ð°3tí¨óŽÅn! zc;ø½~Lí"k„Y]˜`<ñêü‘Þ“Ïέ™§¥�𭊲£ûñšã-ñš'ÿÚq,ûëXZ›£¸2µ‹+é é\%Ïă›ªÄÕØ—ßýrâ_Á-*µG{¢'ŸÞ_ÓðAñO>Ïj¤s‹¸Ö‹ì©¨àÌX-ŸU2·`ÙªÑþ ×=Øw~I¾Îû^´öã'öù#¸DZVÞ˜>¶Í=Õ­(J#åÊ ›Yu�cï] JU„·êe€îö͇»Ûw6›Ó¤ÑYU½¡ûð”¹(  Äc#<Ü4…ǯ"–yÁ²q8%Eöù¨îÞªÆÅc3P�е Ï»i©¿ ”¹À2@‡ÊÀ:Èe`ZXy�•ÌJFl‹ø:÷:Ö)ÌDZäwÔíNÈçAσ¹¶ ¦º† ’ÀbrŠä\fTÞs§ë~1$bÖ©d7�¼Hª]äë d–$Ö?×`bø²>žÒ†äm!÷vr&V“ç#>”JØØ˜fIboÈ"Æü4}ç/®\U§[Ä„²jų¿åͱI3� –$¢‚UêA´A4¸têký“³©#@QLkJ Õ–ÎädNèÐÈÁΞ¯º–2Em¥H!g‚C}�‰¾^yçÛ·ÒYNÈ_œ�íßßõ@æ%X>7‘.¾ÛZïn+wXÊ÷‰ñk/¾7ö¦-‰™»ï¨h¶ 9wbxq`rÙ:¶ñƒ=Ÿ½ÖzÑž>`�ö6&ß~*øÒ̇�W‹ß´ÙÍaçs7ÛR¡9z°iP9`ÛÉÛ‹ÛÇ_Žþ nÆn\£#Z­tÜÝÒªë†Ôaþ£kY.ÜLð7q~MC¼H IEND®B`‚TreeLine-3.2.1/icons/tree/date_1.png000066400000000000000000000010221506556630100171430ustar00rootroot00000000000000‰PNG  IHDR�‘h6 pHYs  ÒÝ~ütIMEÓ 0-æI!Í>tEXtCommentCreated with The GIMP (c) 2003 Jakub 'jimmac' Steiner'3ïXgIDATxÚ�Q½Ê"A¬Þie5XÐM430301ð%|3ö5Œ4SÀGCC…ÝA`q‚Ù¹`Ä]üŽãî:êž®š®®þ1Àn·ûèõz�Ífì‹óù €ˆþ@¨×ë@·Û�¢¨Œ&¢¯’™¥”oÂ`0PJ}&|ÐeZ†Î¹7áë×râ[Bˆ Â0|ЛÍf4õûý$IüËp8l·Û¯×‹ˆ¬µÅ6Ƙ,ËN§“”rµZÕjµ,Ë.—‹w/MS­µÖz¿ß’ˆèx¶IDATxÚm“mHSQÇ7qHôm RÜr�æ²LÌ@Œ$Ê6X.µÚÀ&¡Ò D¬³TÊH ÑÄÒ4‚)Bz%?æËL$ ’tsnW7·»íÞ9ïýw¶Š6çÿs8ç<Ïï¼=�€@§Ó  E”Tª³ z}å­V»¯¥¥åªÉdªŠ\Å„bÃMrr² dññ¢„´´ŒÒÒÒsuu�?»ºŸòãŸ'x·‡Æã'}N¡P(üµPL )))³¾¾ÉÓýh€}3†ù…E¸i›�ô>L™¿"%%¥|G@Óí;#ã“3X§ýXql`Éj‡ÓãƒÃjËl‚ t€C™Z=¼#€oÚ²æÆšÛ‡ÊÖ<®£hlßÐvrÞM §�Ž‹‹Û¨©©í´¸xd'jÜÝ{ðÏÌÁ»¼ ÎhD°¹5¼fþñ ‰D(,,T¼ÿ²‹?b¸pï¶Rà øŸ…Ç?�ò Í;/ŒH¥Ò]Íí}ôŠ—Çƒ°Ö‰ó–N®L ¾¨þ‡]áùžgìH$J�ù…¥ºob9@vÁ¹7áðn�­¾>+ ”Ý�©Ed2™1@TÒùjV/`‹Í�ÑW‚Ë”cÕÉb‰.^¾2KüEQòº¢K×Ûóë<,ÄÉÕ;¶¼ÁÜ<å‡@‘ÜÍ/y€Þ—y¹\~"&�æ´õO2a'û蜭àz�E*€ŠÇ‹o[0½ @wߌüüü1±X|ÄÐ6†ð�hÜÆ£×Ì¡v$EƒSF3Nžo÷e/þ�žž~&²:¾zïíÿâÚÿÙÙÌŸ�ôÈŸ?ÿøýáóo†ï¿Nœ¿ÃðàÉ+†¿±{íõ»Ï _ÿaààäâñì…¯_¿1|:•“õ?ƒ§ƒ>ƒ�¥6ƒ¶ªV~üøÁðäác†ß¿ýñbÀ7�?1<ûõ‹ÁÆDhû_†×ï¿2<{ýÌþtÍïÿ¾|þÊpòôu†OŸ>1½6 ‡sŒ Qôßÿ–T†Å˜�°£!®“ß½ÌÜ¡—RÏÄĘÁ=ÿ*áàrÇŽŽ5C!žÜZûŸ‚ õÏ@Cþ!;++#3#à‹¾ÿûÅÀøó';Ó!^.†W@±OŸ?Á  °ß@Ñöù;ƒ’ ƒ©¶4Xèr`àþGùò(úŸaáê= ×.]�@Ð@„ÄñÏ^½ü tÐf`”|iŠƒ øúõ' ÐY_�ýøö�–â‚ï?>èã'v†?AÑ O80€Â‚™ hÀׯ ?½û ºà;Û7Ø�ÞùæÿÑ3èû÷ï LŒL@þW`@~ê‚Ä@Acá0éˆ?ÐÀPÿô¬d ƒ 4ìÏŸŸpbÀ§/¬^¾axÉÎÌðSEœáׯO@ ŒZ`èÿFé¯_?€¨é?#Çׯþ}ÿÔÅÈ Ò @Œ Ààç÷¸ÇÄø_ˆ�ñ7778‘üýûl (IƒÔÀÎׯ�©ð3�Åú˜™”ˆ‘Òì `°“Þ2¨  IEND®B`‚TreeLine-3.2.1/icons/tree/doc.png000066400000000000000000000005351506556630100165630ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA±� üabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÒ,"o …×ÚIDATxÚµS1 „0œ{_cå®ó ×ÝÇ|„…">à´Dlޱ É^qDrq£6·0v3³³|#@pC ÈÃBkMÃ0PUUV$ ,Ë¢®kRJQžç;'ÂÀº®¬½¢(ж-æyÆ8Ž(ËrãJœ!IÄqŒ÷û…®ë~ê;Ƙ ô}�4M7nä^rÉ–à×ý|ä8’ï"(À]°g7ç�¸Ak}êâÐ�”’íÌåX¡W¸¼!Äaçÿ-±i(¥Ngž¦ žþx�‹ßÙân‰]�D ë~IEND®B`‚TreeLine-3.2.1/icons/tree/euro.png000066400000000000000000000005161506556630100167670ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA±� üabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÓ  8‰ñ ËIDATxÚ­“=‚@…¿ÅØslhmHô&–†SPr/`mméì´ðÜhh±X›³X"á%¯Ø7ÿÙXÖÚp  ¢EUUu”e©ÏLì[ñé&p‚Õ1BÇ-MíY’È©¼óL¼ή°Žž–-pNc§‚Û‚¶ÿ7VsGHÒœ8ω"oà1d€`€ ð}/šòÖû…ëX¥y{à,ÒüM¬ëº¿TÞ[P=Œ¦i0ÆÇ1‹"Is¯ý $Ñoz'm>úIEND®B`‚TreeLine-3.2.1/icons/tree/folder_1.png000066400000000000000000000005471506556630100175140ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC»IDATxÚÍ“MJA…ß .\(Ñ�àQ"žÀ3¸�­ài<�x÷‘D4B˜ IDGIÜÔÅĪzYôô�IÁŸ� EÿÐß«Wýü§VÀ¥¨ÿ~Jìt[ìt[<=;ù–Hœ÷�÷�7\4Ï1y}Äx<ÂÆæ:ŽŽ QáÌGå|~¹G­¶ƒétR¨›â8†¨¸Md±ž¦#ìï`ÍoÞÞÚÅݰ € Ì F…©Â P]Ðо¹,•€,ûüÕÉE i�Ùg£îÔ¤,@¢_è!_ûb‚’€™BDÐCÎ�IƒÚ’AˆÌp1iÐ|œ�Ì2¨JVA•ƒ‡>®®›Î.éœä×WÕz·ÃÒŸÛvðWúQÂ*3Ó‹¥t!`õ n¨,,,!ûl¼^!rT˜–…ß_�e ›x¸OÑÕ9èjå"2PÕ@Á6ÑN®Ðõ$ÉÃc*ƒ$I/V=P°ò¹<-­Íž9××ñ� Øßߢ�/°¾¶Åîî6FâK¤Éš_ü ‘ãðà”�ÞÉùý4T5JOO7Fâ‚dJÿvpшÎ}" €T<<=ÓØÜØ£¿¿K¤ËF–ÍšŒ�N„\Àeô’‘á!Ò£¤í÷¥Çn‹ÛUPW_K{Gñ;µ¬8|¬11>SŒò-…Èy !LdO q#ZR|®]¡(š{ûOϸ\ÿÏ|Ò›´ŸÝ»E‹IEND®B`‚TreeLine-3.2.1/icons/tree/folder_3.png000066400000000000000000000011461506556630100175120ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÒ ('Ž¿°óIDATxœ¥“½kSa‡Ÿ÷Þ“ØDmФbÄJk©â¤’¸”ÒE!Ù\¬‚]Dðpܬà (¶JAj¥H2é’¥DJ¡n×%ÚšVÈWo?roÞס&Ñ&é ÞåœßûüÎ9p„RŠÿ  EÓ 9Õ-öûX56´hZ•'Ï’ÈÉ¿1¡Íà@"'9³ øZ¬0ø “l^’+V°6$å-‰³½Ë,MO¨j÷F•d¶ç7{úÙrƒó)÷2K;�`o!„¸®”бáï â½cyJúÞGº”áS¼®3š‰nÍm³ZTä,Ɇ%¹Ÿáê…m_'j:­ºƒ‹^�ÈZ’Ù¬S/>U ˆÓÖäÎáq nVÛÁÞˆü|Kï�ºË怡s<|ØárfÛßQøâz#!hM¯äJ†r“RóU;yù©ßl;±. û—•cC mWsÉg2¦`�–0ç*Èš‚×Å\ö« ÙÚ¯,9Wÿx;ñæ¿�GjcæÖF؃³l*–�¤`µ@– m´ïhDý»J¸ï»íãG÷�­äÝ?VL4Ö + |6U–¦k‹¾ç, ¿(©¹Cá[ôœjl�*`è*Jã=ݰC×ñåcœ‚sBhžhßÛ÷ ×ó÷}ø½½c ý{w2/ºOW…Ù[öG³ñÇXòò¼ˆó�W(Èíw?xuÀÅý»feÝÙ½5:·¡ICÄÂäã±Ízcçs²*kÆGP�ùÖÖÇù<õÎõSþܵ%¯Fõ/tCEr$Ì+S©¹S«>Èf�{ÿ®êÀËíJY*P�BŒ5µ~¼ã›lϳǗâuˆî0™Í@¹ »ùŽØÓý»×®ÐÕ“1gôHzLk0ë ‚ÛÞwsDÑtÅ+ºRÇ¥<†+ÌäÅóå¯ïß©¾xrÎ6LŠ@0ÀÉHŒ4•�7¸ÞÚÂ"L\j2€ï‹A;]LYÍ[¦¦§-¹ wâZܶڈ€hr–Pß™#å³{zÖÞj)멉ívïéw'ÞH<ÜôÃÈ>3S T·FÄ)ÂV6xZ°\èæ×ûÚ^Kmnè_\ ÄÆý©©Ø£Ÿ�|•öB‡gœð_Ö¼Rÿ à{ÁBÃÉ+_êC¡{Ý3G•†?=aYewôp~e²ïPæ*t-ÖÕ?YÌ1Ï 9†IEND®B`‚TreeLine-3.2.1/icons/tree/gnu.png000066400000000000000000000004201506556630100166000ustar00rootroot00000000000000‰PNG  IHDR]RgAMA±� üaPLTEÿÿÿÿÿÿ   ÃÃÀ€€XXX000Iæÿ>tRNS@æØfbKGDˆH pHYs  ÒÝ~ütIMEÑ& �˜ aIDATxœ-MA €0 K°VÑóâ¼ë âYð#þÿd;l)ICÒ£Ðò"*WqðÕU«û£ÉwN¬n@ÇLKî·Â3Gp8x…)dS„ÜÖvÔl¾‘\šÇÿô?�ø|]ê/Lkµ@IEND®B`‚TreeLine-3.2.1/icons/tree/hand.png000066400000000000000000000012431506556630100167250ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“XIDATxÚu‘ÛKÓaÆ?¿Ó¶ßÖš§y( 1P².Š„ÃÈÙMÐEtUA×AÿAP‚!AfeTµ +-ÌcX¦ÖMÝòìÔ9;}»X�ÎùܽÏû}>ï÷áåí‡V')¤‚@jŽ>÷u°ßÝû©Ë=ômPY7ø¾³MIšDÿó[š›n‰¢$`žžîmÝ|ey•¬5,àíëíãjýer²² ç™›™ îÒrÝiÞ-v3ùÁÿêþØ®æç`š&« X%DZº‹ÐüÕÕ5§6hš–8ÇÂÄ#ˉ‹;¾|ú€ÙÉ©+)]mЦ¨{âáPÂŒGùx€ô4@ÞZ€PZZ⩨¨òj ”²ª:9}æ,ˆpâø1‘†®±ÉoÁø˜Ï;?:ÀÃ{·þþƒÙñú`y Ó™ŽîÌ¥öÐÁÍ�@E3¨,ßGû»ÔÕ_c~q9Qaq 5<‡nXS4wfF °°r´¦ÖƒÓªP¶»”™‰IV£dåæWm348LËãgÄà⺠¦ffï74\ÇçóáÈÌcÇömí"ËåÝÎJp«ÅïK]˜Îp»«ÊöìgtÄ�áÌÆ°è8L;ñhS~þåU{Q8Ÿ²Ë—þM…™N§;˜©›Q†Y¬Å©¡ÝÐèÇ)‚ØCBØaÎA{ðØÍþƒRt ’èÐ¥ ÑÕ@j×ÝÍ�†Ý\v¶É´VÇÙyºÌH‹%[ô�/_^Ïáy¾üÇD�1à ½Šzå÷SÀ] ßGŠ·Žªª:vçxÛ„µ_–ö:Ó/ž¯|(% #CE¥+|(ÐÔ›züèË�l%enº7�[ ªªjòÞéȼ»¶Ò à:š¦104¼ÕHÇ!ÿqöó¸¾Úõ¼T��‡#Ç:ú:öœq ÷›…S)!ZÚžó”¤öc•šeR[6Øé ñµ2÷²\íS€KWÏž*o.e¡½Øù®eb[&´´â:®eÖ]–c,RD7Ð/€'£pØÂ~ìÔÌ6ìÇE¶x·˜Ë­×6ª ?—Õy„Ù•�ï€.€××ßhÍÁ]»ÂÁp„÷é,·ók­À3,±Ã÷'Qöw£'˜NeHÌUbÀ¼ðö4ÿ�¦Þ“Å?át:�ª•}¬~3�ÉB"޽˜Ù†ã3Ëux§‘–…D\~ºÐ-�kåäàÁ_G»á!ߟ—¯þ×ò¯¸áüŸ“ÆPÕ;¾ÛIEND®B`‚TreeLine-3.2.1/icons/tree/home.png000066400000000000000000000011401506556630100167370ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA±� üabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÒ +Jˆ²îÝIDATxÚ­“O‹RQÆWÓÂ�ƒ^ºNŒ6îîîJÁ0 à-$$,Dù=„V~ý9Юf1-Z-‚ \‹q 炚¨sÓ¼Ïóœ—\?üšÝÅìüw‰Oó!Q(D&“ÙJrexz @.—C×uR©²,S©T ­ö»V�êÇŸ†A$A×u²Ù,Õj•M›¬†A>Ÿ'›Í2�ðx<$“IJ¥ÒÉE Â4MŠÅ"Á`p1x±‰Š¢P(ræš„ªª´Z-Úí6�FMÓh6›¨ªJ<Çï÷3 ¨×ëlÛfÉ“Z­ ,Ë�Â!ñä¿�NG†!„B×uˆYï²étI’p»$’áŠï*Óé”Á`@4e2™,õnŒQˆe£G£årMÓ°,‹X,¶=·Û½Fà8Ãáp‘ÊVÇq¸áõðòÛ Ýó?ôz=¼^/’$m|‰sÔ<0÷_(¡ n—‹³N›n·CÏþÍÉ÷'è÷ûØg6Ó¿S”› G‡Ç’àÀÜÿòæõÛçÖׯ»½ðî½Ñù.|×dü;;|úðùÙí;·ødòu™£ÃcéR¾ï?_¡·×Ñ{16IEND®B`‚TreeLine-3.2.1/icons/tree/lock_1.png000066400000000000000000000013311506556630100171610ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÓ 5%å®_ŒtEXtCommentMenu-sized icon ========== (c) 2003 Jakub 'jimmac' Steiner, http://jimmac.musichall.cz created with the GIMP, http://www.gimp.orggŠÇGÎIDATxÚ­“=‹SA†Ÿû“Ö"²\ãÂ6jL·ˆ?!�¿ ­•�B!…6{Á¿ EºÀÚÅì f¹ºÅbt—%›•û9™±ÉÆÜÀALqÎá<̼ïøÇÐê�€‡@n‘G@ ø¨?¯–J¥W­V+ Êqå8Žêv»²Ùlže2™€‘8�ÏçŸÙ¶-z½žW«Õf–e–eõz]t:eÛ¶ wh\˜°ê‚zýò ÷ïÝA-tŠBoÙ"Ä;9boï-Ïß /4ÍÕë<Ø-ãN�™ýøÂÑdJ…K·EàSÜ�” 1´@Ó4æÁŒñ©Çíò]ÂÀ_4Âw9 ‘r¾:™k"ù.…Ë)†ƒ�„aðû �ËÖ†D×ãk R Æ3¸UÝ% Ã¥R2ô9ùüM7“ �K™,ÛEÉWgˆXÐ`üäz:CzÍà`:ÞÇ=ýŽï�sz€a(¤Ð˜žû‰‹ØX|”¿9Où_ñ  ΤZdwêIEND®B`‚TreeLine-3.2.1/icons/tree/lock_2.png000066400000000000000000000012651506556630100171700ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ„p9ùŒtEXtCommentMenu-sized icon ========== (c) 2003 Jakub 'jimmac' Steiner, http://jimmac.musichall.cz created with the GIMP, http://www.gimp.orggŠÇGªIDATxÚ­“¿kSQ†Ÿ{ojbª%ÒÐbBA‘jLK–âÿ¢£“�A!ƒ.w¡àà¬C¶@;š!þ"HÔ¡Bˆ¶”$•ûóäû¼Õ%1E=p–ïå}xÏ{Î�ÿ¸c`ìÖy�—Ëåò^³ÙŒ{½žm4“L&ó p–º …Â×uM§Óñëõº–J%m·Û꺮<\ ¨V«GÝnw–Íf?ŸÍjµšiµZ¼Yæ·EdMDÔ÷}9ŽF#)®¯[Àµ¿)ó^am5xùbO·JW5—Kkʱ5åØº’r41«Û7®ëf!§ÀýyMë«ç�ؽs M:Œ#ÿ—hL„|ÈþþO_÷IÍ‹pw§‚7>búí#‡£1q%Š… 6òB¥ø>`Y³pÊðÄçfå6Q$‚b�É—>"³Å!<Š«+ô{ð÷B�ͼ`ÛH€D Ã)l×vˆ£(Ix‹e§› ™,[§A“°`~çJ:C:¹ô¹€ñð=ÞÉWÿ”K€±cÇAmc1> ¿@ϹÿóþúŠÁg¥ DVIEND®B`‚TreeLine-3.2.1/icons/tree/mag.png000066400000000000000000000014571506556630100165660ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ %Ï;ÈD¼IDATxÚm“KHTqÅÏÿþÿ÷93×™;Îè(¥5¦%…ºh•InÚdP$¸‹˜UPÑ¢]›¤Eh ËÜX Mˆ(ÃB¨ìaP9ê(3Žïë�ç}´Ìäžõá÷�Ã÷}úûŸ©œÀ:$I¸Éñô(åÀ8B6,ÓËƽb?º»Ïá"Ò×7¨ò½æÓÊâªß§É²Žãpl [_6WÖnë[æHoï%k/€mó´×ë‹Cš¦Tˆ"�bÉB>_¥"�ÜhKwŒìò4€ß{`_hešß¯¢<èGX @` Z@…¢ˆðù<¤²*|@‡[ÄnQ<2D�A0ÊÀ…"Ið*2dIB¸2 Ó,´¹eD¢”"›Íciy’ÀÃëQ ð ŽÃÀ[àQ,ä½® ¶¶ ƒÇ(G ð <£ Dž‡$Š€m#—+l¸V3ë“Æ¶˶`Z6l–mƒR �ç!ñ<¿g¡ë¹1WÀb2u÷ëô÷EBŽ#pÎ.C:•ÆÄ›ØÖÍŒ€F*3…BvӲ̖P8èUŒr „ ™LâùÈK”JµAZ~£i¦úB³'9ø^ß©C æa]¨³¡6ã}{Ê��D&ò¥Ìúš1¨4ö˜çêÈdgƒ6o/Í-¿X\ãz.¤Ò;1ä >ÞŽøx»[J<:¹òiè¢n|¼åÌ>nv†{ÂÃ÷ÏDj€ÆÇÛÑjFw̱®(b]Q¼{úïèNÖùÛº®¨U±H}cáàff³ª>T6Ic]Qש»£3Û¹#~2½�Ôʪ¦ý��²×JžKf›è¡äÖKP4°ú+‹�ùW>sÿ}ßëŸz¡‚�©•…E:PÓÊÔ°ðy–E ÈO€«µû?hs]÷ŽºŽUª÷ù‡ÄP]G"WóíH´`•¾âIEND®B`‚TreeLine-3.2.1/icons/tree/mail.png000066400000000000000000000015131506556630100167350ustar00rootroot00000000000000‰PNG  IHDRóÿaIDATxÚ…SMh\U=÷½7�É›Ì�3“d^Lh ¡bƒŠK©¨!⦴ ›lD¨(º¨»Š¥fÿh7­PA20Ä)šE:4MÂ4¤y̤“fÆñefÞ¼¹ïÞïºh,­¿ßòƒs¾ïpÎaøŸ9þû¨”4ÚÕe¾Á¹x¹Ùì¼ÍyðÍÔÔIÆ¿/\ø1,‡õSCC}/ØvüÉJÅeKK›¯ììt~àý�àâż&%YŒ±§5�½ÓÛîС§2étJºÎà8Õ‰­­ú‡Š�LOÿÔ§”:–HX¯Ûvâøðp&ÔÛ…®3H©P«y… ìßoGnß.¿ à}`33??A¤^³¬Ðøà`ÏáþþDܶcÐu  ”焵µ ¢Ñ0„P¸t)W¨T~{éÊ•·J�&“‘��9pâàÁþ¸mÇ‚@J… ”Ëu˜¦�PHÃÈHvˆH���¢iBÐ}ưÄêu5”Juxуëí6‡R R‚€08؉Dº^$¢´FD¥R='%‰L&†TÊ‚çq,,1?_DµÚ@½Þ�„ÝÝa ¤ž1ª_¿þ¹–—Ë´¸¸î¬­•¾‚`:Ÿ?W2±«U.׿uœÚ3ñxÄètLÓçŽSà_]-_®Õv¿$Róùü9ñX‰H¸ngöÆ�õSûö¥F}?@«Å17·Ò(î.ºnó£v›Ï1†v.÷�úÇíÂääŒ `jbâÙÉííßqëViåÎ�­O‰è»k×Þ­þSéØ_§Ov,³f|ŸåºÍËW¯ž)üWÝÿ_™ ‘Q� íIEND®B`‚TreeLine-3.2.1/icons/tree/minus.png000066400000000000000000000003671506556630100171540ustar00rootroot00000000000000‰PNG  IHDR;Ö•JgAMA±� üabKGD.p›´ž† pHYs  ÒÝ~ütIMEÑ à(í±tIDATxœíޱ Â0Ï‘%ör“M,±[˜˜ÁE@´H4tÄŠ‚”Ÿo3Bôû\ýN÷`Ç„èBlV±æä|b»^ΛãEVDQåýùr‚æÊôc¸=Yµšêàþx1–ëwpè�MDMbÍÉ[;!:*<}±3IEND®B`‚TreeLine-3.2.1/icons/tree/misc.png000066400000000000000000000021611506556630100167460ustar00rootroot00000000000000‰PNG  IHDRVÎŽWbKGDùC» pHYs  d_‘tIMEÓ 2ñþIDATxœm”ÏkTWÅϽ÷Ísæý˜7oâä%™Æ1h¤%ATJ]dè";ÛÚ,Ì"‚` "ºÄàJwfQ¡Ûlº)H©!EHñBÚ‰3N2?ïÍÜ÷î{ïvQ±=«ïY|ÎâËá|¦……æ8Ž—Íf�0ƾ „L€Öz7I’RÊ¿9ç½Ç�'ŸräSsñâÅl¹\þjllì[×u¿ö<¯œËå,‡½^og0üÞh4~ÞÙÙùãÉ“'òË>KKKÅz½þÝäää�Õju.‚QÛ¶1F¨ÖuÝÂ!ÏóJŽãœ¶,ë”išjjjê¯çÏŸ?]¾|9[¯×¿¯ÕjWGGGO0ÆhEÃiz€LF€s ¥(¥$—Ë�™¦9MéÔjµÍ���˜---±J¥r¡R©üäºî””’! „ç„ XTØÞ>Àp8„”J)b†G)­j­_?~ü­A¡P(\p²Ýn)%Â0„R qc|<ƒlÖÅ»wïA)…a0 ¦iBÈIÛ¶/ù¾¿a$Ir4Žã �N‡J)!¥DEˆãišblÌCF·Û¥ôó0š¦é…$IŽÒ0 OsÎËív�Ný~œsLO;¸sç2™µšƒ™wïžçý~ý~ÝnBˆ²Rê´¡”åœç@)…$I µÆ³g ¤iŠÅÅo”°¸H°¸ø+´Ö ”"I’ÏÏ¥i:jôz=jYl;‹bÑD¸¨Õœ93‚Ré€s{öðaн½;;C¼xÑÁúú;t»aSƒÒ%„DŽã¢”¢ÕÞ¿çX[àÔ©6æç ` ׯ¿Dš¦ÐZÿ[Bfƒ�0â.%„¬§iÚÌd2p]ŽãÀ¶mœ={óóãXYùÀVVöpóæ—°m¶mò,0Æ I)]7c¯“$YÍd2ÕJ¥B´Öˆ¢ͦ£GõzI¢±µ¥qï^–eAk�$I0 tÇ«„�׆ëºûBˆå~¿?ã8α HLjãQÁ4ÛØÚj¡Z­B)¥¢(B«ÕÒBˆ7Œ±eÓ4÷Ùêêj:77·Ûl6©bzrrÒ™˜˜ ù|žç!M‡h6ߢV;ß÷Q( ¥Ô¯^½jpÎø¾ÿËýû÷%€§OŸF³³³[{{{Bq„1Vô}Ÿ‹E†‘Ãøø1„aˆíím½¹¹ù¦Õj=ÈçóË·oßnÿgF®]»æìïïÏæóùÊåòy×uýR©”€F£1 ÝÝÝÝUÎùòÈÈÈo7nÜàÿ»GpåÊC1’Ë妴Ö3œó8ŽÓ°.¥|mÛöþ­[·âO¹>뤥­æºIEND®B`‚TreeLine-3.2.1/icons/tree/move.png000066400000000000000000000003301506556630100167550ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA±� üabKGDGnKl™– pHYs  d_‘tIMEÐ *$sÙsgUIDATxœc`ÀþC1NÀH@3Aµ¸ Àe+> q„× L¤šˆÏ¼6¡¸Z&tR a$S3P0€+´ ŠÃ\@rü«‡öé€â¤Lqf"†<8¶iIEND®B`‚TreeLine-3.2.1/icons/tree/music.png000066400000000000000000000004201506556630100171270ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ÅIDATxÚÝÒ±JA…á/¦Ôé¢EJ! l·äÌØY™éí-|!¥V¦ôlÄ6i°É¦™Yfw›€.w˜sþ{­fÅÝ îqŒÏ¿ 0A=\ÄÌs¼aŠW8Çú¡vTò¸ƒ6®ñzcÜá{—†ýŒp‹œb�—ªå.ñé?" †Š#<`RR¼F Î0Ã{,5K’$C~Z‘½|üN/*'X…:F¶À徟­Ž¬VedÿE[G-fJQá�IEND®B`‚TreeLine-3.2.1/icons/tree/note.png000066400000000000000000000010261506556630100167570ustar00rootroot00000000000000‰PNG  IHDR�‘h6 pHYs  ÒÝ~ütIMEÓ : èDÇ>tEXtCommentCreated with The GIMP (c) 2003 Jakub 'jimmac' Steiner'3ïXkIDATxÚ�’=K\A…Ïsæ‚ZDBüÀ"M°J)’@¶6B�¥U¾ ó4VV�Y„6©£AÙM ›]A‹ F×p×\‹{ïîu‹€žbfžóžÃ0Ò5…¤æñîÿ¡ÛÃâŸS­½;ƒ³[Qzô£úlçkÁÖøäëöÑt¼Ó÷¬Ô�ä,(§mÛºBÿšŠwúŸo4߬ïu !)j›(£ÿ~tþyàéÆïµ÷_¶7$EÅ„t*�O.Ÿí?<« /¾=,•+õêR«Õ.V :Ø’TûöøÅ‡z©\i|}€®$é{Ës3#÷Ÿ¬HÊiR23Ø&‰°H*:ªW—èHÈîzT;xÙÙ£¼R„! Àù¦¨ÞJ€ò{ P§]ÃÐÝùí 7ñ1ú%¥™Ÿf†�åÕ§ùéÿ0’,ÔyÖ±Ñ[y°°³�XV$ NÎu]ÜÒÔ¾ �À úëÍ"ä‚,BKHæ9"ï@ôBÈøºÕ�È'pú+HUµª*úíÖ�ÙŒêºV€(ŠŒqF® 8Žiš†¶m$Ëœ€�Ý’�”eIQ|; ! ÆÍó\“$Q†=z^� âÆr®&D†<Ídúg`?æîV%,@`üø1lðãXúÁ˜Ckàa<{Sü¿kž?qt¥õIEND®B`‚TreeLine-3.2.1/icons/tree/person.png000066400000000000000000000014341506556630100173230ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÓ *àè¦tEXtCommentCreated with The GIMPïd%n€IDATxÚ¥‘Ml q‡ŸÿÌÎîÌvw»E?Òvƒ¶)­D¢”�–6uàä@$n.„8ôæ".ĉÄ·•ˆ~4´úµmuIwg§;óŸ'¢=¬ƒßíÉ›÷ÉûË kÒÔÔx¸ L?€Yàpž%�nꬨHÞrÝ]~wWGÕ€"0–JÕ_^»£ü Å¢}´P°ŽwwuÄmñùË7, @Øjšæ±µ‚Ðß ¥Ó9Q‘›exø#¶�Jªš ¼ËXFI�º²h5×jÆÅ=yØ]�€ ,|žçÄȬ™(Y¡ÂPÕÚ¸"b𠬋*$"Mχt¥FI�¦éÝ ¤t‘ÒÅ.J¤tñ\Ÿ½�: �,YÁÐD6g»v® D'î¿É£‡§v–±­Fc}TˆR%áÌ£·ÖóžfÓã‹�žrl7àÞP�ñE›¼íÍðçõ·(wÎËø­ ¬n£tÝðÏ|‘ÁI‡—“KøF%ãvuÖse‹+��ÀÏßèkL7ßí¿rms˾ވ_ÑÀèØ–– ˜žŽHÔ±£ó‘duMU*Ýò=3yØwåx_EUMݹuªnô_0F§ó(ªÂøÈkvµ6p°½ Ûqy5ú…©¹%æ²9TE�]Ì0øìÁ´S\éS#ºþðBÿ¥ÊSÅ*:ø¾�çùDu�Þ®ÄådW|òœ?y„—ï§ñ|�²x2–ÍLÕ)Bˆõa£œÅì2ŽccÛžë13¿„YXajáyÓâÄ¡6æ¾/Óº‡�ž º¡UUBÚþPX�ÆMO%3¿°ê=& g¯ßùÃO^ ­šm C¤¶üG~NŽØ€Ü(GIEND®B`‚TreeLine-3.2.1/icons/tree/phone.png000066400000000000000000000060421506556630100171260ustar00rootroot00000000000000‰PNG  IHDRóÿa CiCCPICC profilexÚ�SwX“÷>ß÷eVBØð±—l�"#¬ÈY¢’a„@Å…ˆ VœHUÄ‚Õ H�ˆâ (¸gAŠˆZ‹U\8îܧµ}zïííû×û¼çœçüÎyÏ€&‘æ¢j9R…<:Ø�OHÄɽ€Hà æËÂgÅðyx~t°?ü¯opÕ.$ÇáÿƒºP&W ‘à"ç �RÈ.TÈȰS³d ”ly|B"ª ìôI>Ø©“ÜØ¢©�™(G$@»`U�R,À ¬@".À®€Y¶2G€½vŽX�@`€™B,Ì 8CÍ L 0Ò¿à©_p…¸HÀ˕͗KÒ3¸•Ðwòðàâ!âÂl±Ba)f ä"œ—›#HçLÎ ùÑÁþ8?�çæäáæfçlïôÅ¢þkðo">!ñßþ¼ŒNÏïÚ_ååÖpǰu¿k©[ÚVhßù]3Û  Z Ðzù‹y8ü@ž¡PÈ< í%b¡½0ã‹>ÿ3áoà‹~öü@þÛzðqš@™­À£ƒýqanv®RŽçËB1n÷ç#þÇ…ýŽ)Ñâ4±\,ŠñX‰¸P"MÇy¹R‘D!É•âé2ñ–ý “w ¬†OÀN¶µËlÀ~î‹XÒv@~ó-Œ ‘g42y÷“¿ù�@+Í—¤ã¼è\¨”LÆD �*°A Á¬ÀœÁ¼ÀaD@ $À<Bä€ ¡–ATÀ:ص° šá´Á18 çà\�ëp`žÂ¼† AÈa!:ˆbŽØ"ΙŽ"aH4’€¤ éˆQ"ÅÈr¤©Bj‘]H#ò-r9�\@ú�ÛÈ 2ŠüмG1”�²QÔu@¹¨ŠÆ sÑt4]€–¢kÑ´=€¶¢§ÑKèut}ŠŽc€Ñ1fŒÙa\Œ‡E`‰X&ÇcåX5V�5cX7vÀžaï$‹€ì^„Âl‚��GXLXC¨%ì#´ºW ƒ„1Â'"“¨O´%zùÄxb:±�XF¬&î!!ž%^'_“H$É’äN !%�2I IkHÛH-¤S¤>ÒiœL&ë�mÉÞä²€¬ —‘·��O’ûÉÃä·:ňâL ¢$R¤”J5e?奟2B™ ªQÍ©žÔªˆ:ŸZIm vP/S‡©4uš%Í›Cˤ-£ÕКigi÷h/étº ݃E—ЗÒkèéçéƒôw † ƒÇHb(k{§·/™L¦Ó—™ÈT0×2™g˜˜oUX*ö*|‘Ê•:•V•~•çªTUsU?Õyª T«U«^V}¦FU³Pã© Ô«Õ©U»©6®ÎRwR�PÏQ_£¾_ý‚úc ²†…F †H£Tc·Æ�!Æ2eñXBÖrVë,k˜Mb[²ùìLvûv/{LSCsªf¬f‘f�æqÍƱàð9ÙœJÎ!Î Î{--?-±Öj­f­~­7ÚzÚ¾ÚbírííëÚïup�@�,�õ:m:÷u º6ºQº…ºÛuÏê>Ócëyé õÊõéÝÑGõmô£õêïÖïÑ7046�l18cðÌ�cèk˜i¸Ñð„á¨Ëhº‘Äh£ÑI£'¸&î‡gã5x>f¬ob¬4ÞeÜkVyVõV׬IÖ\ë,ëmÖWlPW› ›:›Ë¶¨­›­Äv›mßâ�)Ò)õSnÚ1ìüì ìšìí9öaö%ömöÏÌÖ;t;|rtuÌvlp¼ë¤á4éĩÃéWgg¡s�ó5¦K�Ë—v—Sm§Š§nŸzË•åîºÒµÓõ£›»›Ü­ÙmÔÝÌ=Å}«ûM.›É]Ã=ïAôð÷XâqÌã�§›§Âó�ç/^v^Y^û½O³œ&žÖ0mÈÛÄ[à½Ë{`:>=eúÎé>Æ>ŸzŸ‡¾¦¾"ß=¾#~Ö~™~üžû;úËý�ø¿áyòñN`Áå½��³k™¥5�»/ >B Yr“oÀòùc3Üg,šÑÊ�Zú0Ì&LÖކÏß~o¦ùLé̶ˆàGlˆ¸i™ù})*2ª.êQ´Stqt÷,Ö¬äYûg½Žñ�©Œ¹;Ûj¶rvg¬jlRlc웸€¸ª¸�x‡øEñ—t$ í‰äÄØÄ=‰ãsçlš3œäšT–tc®åÜ¢¹æéÎËžwç|þü/÷„óû€9%bKGDÿÿÿ ½§“ pHYs.#.#x¥?vtIMEÞ 5)Zkö6`IDAT8Ë¥Ò=hSQÆñ_ú�ím¥ŠS§êäÚœ$”\ÄùFp4ºêX7/*A¥Ò­í ¢drt fu² .)Á¡h34”Û$סI4ê-}–ó¾‡sþ¼Ïs=Êf³Î­g´K,¥=ŸékÜ�YJØmrç—nPÿ` [òæ�é)ÞµPe=Í'€øxI¾²°|À½†R†;–b®_dò �¯Ñ< à3ì=äA½X,¦±0ašÜÞÖâöAž/¯ö÷?ÕjµôÏ÷‘Ë+$Ë$OI R©¤q–ŸclA“ä•\.‚ ð·@z›GÜéÔ æK,@£ÑPæ¨HøO@>Ÿ‡«C�V§´ÁâsZã<‰)¯ÿÉôk“ð;åöq$#¼Å�˜ÂS{Qô-Š¢þxÉÍ]>´N!†Ù8d|�Âzµ:3S  xÝM¯MáﻗϤ*sýöÙXdÛúI<IEND®B`‚TreeLine-3.2.1/icons/tree/plus.png000066400000000000000000000005771506556630100170070ustar00rootroot00000000000000‰PNG  IHDR;Ö•JgAMA±� üabKGD_޾óóö pHYs  ÒÝ~ütIMEÑ  ØŽž üIDATxœcdÀ˜œÒþÃØÿöÍbÄ¥«Æuw_þ_w÷åÿ¾wþ#„ Xðrýñ[¼–àÕüýÇOJ4ÿ&¬—Ÿ¾ÿøg£«ù·o##“SÚÿ5³›14žºöˆáåÛÏ ¬,L R"| ò’B œì¬ Wî=ghë™…pöªÝçp;Ÿ��áÓ—ï 7¼Ätö•ÛϾÇï?l€‘����Ý=óÿïßQ$ü>ùÆÀÈÈȰg÷. �ÿöÍbda```ø¹s:J brJûÏÇËÁðúíGÅèàŒªoß‘ÏO_¼#.ž±�ç/ßãÕÈÀ 0l€˜\ІfÙ¥)—ñIEND®B`‚TreeLine-3.2.1/icons/tree/print.png000066400000000000000000000011111506556630100171410ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÓ  7­dæsÖIDATxÚ­“½nA…¿Ý%ÀJŽÃOIÙ&ÔÛÑ!…8e\˼}^�Ž:"©PHMÉb)¤°9ÿ‚z½Níèðm$}0ˆïû""ây^´ú¾/¾ï‹çy²\.Åuçr|Ü—O? Ñ#‹E‚ àââ�Îjµ£Ñˆt:Ír¹ f(Q¾Ç•;'›É�Ëåî]øq~γí-‰$o˜M§l?ÝÂ÷nB"J¡i:Ãá�l6Ãx<¾'H&œž}çÛ×>óùh†!š¦¡Â�P)t]G× ^–÷£aŒ‚0`gç9¹Ü;¼… B…*Äó|žÄ Ã@ÓôÈêˆàìôÇq0M4X,·ƒÁm7�ËË"B\_/V²6ü…+ñzÿÕûß™�q®~BYIEND®B`‚TreeLine-3.2.1/icons/tree/question.png000066400000000000000000000013521506556630100176630ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ­#½utIMEÓ 1q,(wIDATxÚu“ËKÔa†ŸïwgFS#aF³‹C:PØ@�—¨ iU”îܹpá^Z†ä¶¹p•m¤Y¶,#Ô$hS"‘É[:::·ï;-tF*=p6çò¾çœ—£8ú†$$BTJ†Ô܈JŸV§þ Üy*} ]‡XS]¬lºH–4có£jâT€»ÃRm„ÉP­Äw ]­Š\¾€1àº6Ë¿ ¯Þ[|]uÚлðRíXe#L¶_ÒñáGpµ¡D¡XàZ“�¶fõAE¸NxÖcó –�‹0Yî³Êc_¨–øÃN‹í=M$d ûØÈÀÏ-8´¹~ÙG¾`¸;@´QÇ#ÒWP0ØÙ*ìçù¢p¾Æa÷¦àË2Ì,æ¨ Ú¤w vE#0àt Iȱ‰Õøëðl‡• ø¶ ë@¸Ñh˜]2¼ý¬0âQ]E¬¹_BŽÑ€gØ9´àðhž×Ž÷39žtCKØÏâšajŒݽÊ-u´céßÿëÛÓQ¤%\CjÕð| ÚBë&8FHe‹ŠÌ D!F µÉ#_„ïE­p킃œ€HÊšQéýC’Æ K�m�kÃ̲Cb´Qx6G„�¬$ׯ�´  c[{†s*^S¥ñÛ9.Ö© òWnu³„ˆ«È8?ª&~lÚ‰ÝÌa¥¨Ú§¹×¤£Í%TÒ¼±�e)MbmÜ›pÊ;iCïôwÿäÍB.~+bã<Þ|ÏÇ‚ “çÓ‚fvÅK€ôžùL-ÒçY¥ÁHC. ø!³Ÿe1]•Ì•¬±2ó™ekî—�‰b�ÔÚ¸sê;ÿ‰î¿Ù*µIEND®B`‚TreeLine-3.2.1/icons/tree/rocket.png000066400000000000000000000007051506556630100173040ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA±� üabKGDþ›60»—Ë pHYs ?@"ÈtIMEÒ .NJBIDATxœ•ѽJÃ`ÆñÿIZPĽEÔEp è�è*HuR+~@up.ŠEq¨ »Þ‚£P‡øAºÑ©ÅÁM’ ÍqЄJÛ¾�éÍïpÞç‘eèc ‘2†…«3Ózü´ÂáÖ,™apåÒÂëø¼]4ðÚþàX‚žªâu|¼öÏwó˜ÅV¤ï€¿—çÉ—œh€Ój aˆ½Áôžpí|Éáyy’©«6D°�ß ,Ak5‹À Üuö*N„�šì<Ä1€1^šÀkû1…X,Ú}ñÙm'†3HÃ@
…ð2 — s©-ÅjLÂf.½í @£n*ÒENÆØØü zý acÜLßஎJ¡K°d=lEÂç„ØÌý3€¯> ÔÈF¶"ûÕ&fÎd{÷>1@ÑuÏaX\ÿûSØLø�þÔ¶HÏïRIEND®B`‚TreeLine-3.2.1/icons/tree/round_minus.png000066400000000000000000000057541506556630100203700ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB7ÇMS tiCCPiccxÚí™gPiÇß† C‚D HÎI$Q�2Œ0$LÈâ ¬ "’AD\]‚¬¢"ŠQPÀ€î ‹€².®"**Çè¯ê®îÓ}¹ºùxûWO?UO‡·ªU €ìx"')6 ‰—Æ÷u±g‡„2±£  V­Nj²—Ÿ³?X‰°üKÞ�Hx¼§ûïÏÿǹI<.n…ã¹Q©œN[áXnWXrfZòJ v\a:åW8XÈ‘ß8QÈ1ßxç×_‡.GŠùÊ„£BŽüÊÔSBæÄò“�íZéWû6÷kÄ5…7ÁŒã¥Eñy‰Zà¿�š%–*|à‘éq‰iºq¼ÿÑ9Âýò�ÞX}Ý£â{móÊ;`¿)ù^S; e7=ßk‘Çè,@ú)'�Ÿñ­†.h@@2@¨M  Œ€°¶À ¸oàBÀFÀ± ðA&È»@>(%à ¨µ 4�Vpt‚óà2¸n�»`<0^‚yð,A„…È ’�” uH2‚Ø�5äyB¾PÅ@<(Ê�vC…P)TÕAMÐ/Ð9è2t‚BÐ,ô7ôF`L‡` XfÃv°ìo€cà8 ΃÷Áp=| î€/÷àX¿„€¢Œè"lÄñFB‘h„�lG �r¤iEº‘~ä"@æ�( Іb¢tQ–(WTŠƒJAmG¡ªP'Q¨>Ô=ÔjõMFË£uÐh7t0:�‰ÎG—£Ñíè«èôúƒa`X3Œ+&�ÉÆacÚ0—0C˜IÌ‹•Áê`­°ÞØl6[‰=…½ˆÆNaßãˆ8%œÎŠãárqå¸f\n7�[‹ãÕñxo<¿_ŒoÀwãïà§ðK ‹`Eð'Äv*­„«„qÂ"‘¨B4'úãˆ;‰ÄÓÄëÄ â•¤Mr …‘ÒIûH'H—HIoÈd²Ù–JN#ï#7‘¯�Ÿ’ß‹ÑÄôÄÜĸb;ĪÅ:ĆÅ^QðuŠe#%‹RN9K¹C™Ç‹kˆ;ˆGˆo¯?'>&¾ A“0”ð–H’(’h–¸!1CÅR5¨NT.5�zŒz…:IChª4‡¶›Ö@»J›¢cè,º=ž^Hÿ™>HŸ—¤JKJn‘¬–¼ )` †#‘QÌ8Ãe|”R�²“Š’Ú+Õ*5,µ(-'m+%] Ý&="ýQ†)ã$“ ³_¦Sæ‰,JV[ÖG6SöˆìUÙ99ºœ¥G®@îŒÜ#yX^[ÞW>[þ˜ü€ü‚‚¢‚‹B²B¥Â…9E†¢­b¼b™b�â¬MÉZ)N©Lé¢Ò ¦$ÓŽ™È¬`ö1ç•å•]•ӕ딕—TX**¹*m*OT ªlÕhÕ2Õ^Õy5%5/µµµGêxu¶z¬ú!õ~õE –F�Æ�N�–4Ë�•Åja�k’5m4S4ë5ïka´ØZ Z‡µîjÃÚ&Ú±ÚÕÚwt`S�8�Ã:C«Ð«ÌWñVÕ¯Ó%éÚéfè¶èNè1ô<õrõ:õ^é«é‡êï×ï×ÿb`b�hÐ`ðØ�jèn˜kØmø·‘¶ǨÚèþjòjçÕ;Vw­~m¬ce|Äø� ÍÄËd�I¯ÉgS3S¾i«é¬™šY¸Y�Ù›Î^Ç.b_7G›Û›ï0?oþÁÂÔ"ÍâŒÅ_–º– –Í–3kXk¢Ö4¬™´R±Š°ª³X3­Ã­�Z l”m"lêmžÙªÚrmm§í´ìâíNÙ½²7°çÛ·Û/:X8ls¸äˆ8º88:Q�œªœž:«8Ç8·8Ï»˜¸d»\rE»z¸îwsSpã¸5¹Í»›¹osïó yøyTy<óÔöä{v{Á^î^¼Æ×ª¯å­íôÞnÞ¼Ÿ¬c­KY÷›Æg�OµÏs_Cßß~?šß&¿f¿wþöþÅþ�4Òz)�a�M�‹AŽA¥A‚`ýàmÁ·BdCâBºB±¡�¡�¡ ë�Ö\?f–6º�µaˆe7&n¼°‰²)bÓÙptxPxsø§ïˆúˆ…H·ÈšÈyŽçç%×–[Æ��²Š*�šŽ¶Š.�ž‰±Š93k[;çW÷:Þ5¾6~1Á;áDÂrbPb[.)<é�ÊKàõmVܼeóP²Nr~² Å"å`Ê<߃ߘ ¥nHíJ£¯|˜Ò5ÓHŸÈ°Î¨ÎxŸ˜yv‹ÄÞ–�­Ú[÷n�ÎrÎ:ž�Êæd÷æ(çìÊ™Øf·­n;´=r{ïÕy;¦vºì<¹‹°+a×í\ƒÜÒÜ·»ƒvwç)äíÌ›üÁ凖|±|~þØË=µ?¢~Œûqpï꽕{¿p n–~*âÝüÉð§ŠŸ–÷Eï,6->R‚)ᕌî·Ù²T¢4«tò€×�Ž2fYAÙÛƒ›Þ(7.¯=D8”~HPáYÑU©VYRù©*¶j¤Ú¾º­F¾foÍâaîáá#¶GZkj k?�;ú Î¥®£^£¾üæXƱç � ýÇÙÇ›e ?Ÿà�œô=Ù×dÖÔÔ,ß\Ü·¤·Ìž ;u÷gÇŸ»Zu[ëÚm…§ÁéôÓ/~ ÿeôŒÇ™Þ³ì³­¿ªÿZÓNk/è€:¶vÌwÆv ºBº†Î¹Ÿëí¶ìnÿMï·ç•ÏW_�¼PÜCèÉëY¾˜uqáRò¥¹Ë1—'{7õ>¾|å~ŸOßàU�«×¯9_»Òo×ñºÕõó7,nœ»É¾ÙyËôVÇ€É@ûm“Û탦ƒwÌîtÝ5¿Û=´f¨gØføò=Ç{×î»Ý¿5²vdh4`ôÁXؘà÷ÁÌÃć¯e­4Ý4c4s~Öyöî‹õ/¦^&¿\šËÿSâÏšWš¯~ýËö¯�ùàù©×ü×˽‘ysâ­ñÛÞ…u Oß%½[Z,x/óþäö‡þ�A§—2?a?U|ÖúÜýÅãËørÒò²ÈD. r‘ ˆ\@ä"¹€ÈD. r‘ ˆ\@ä"ø?v�¯ÿnV‚—ccøgày€Ê*4¢ „ýù`â|ŠzTXtauthorxÚsÊúV”§•š—�Z!êP,ÌFþIDAT8Ë…“KHUQ@÷½ù?9y~Ð,B  ŽB<�fO :ìC5qê A”3 ÙÀA� �“âÄo ~BÄAE"é³ûô¶ö}ûÕE÷aÝsî9gÎ>û8rJ&¥ºžnjàœÀ'Xƒg·dý}x¿R̦{ ÷á.غ I8žÃC ù  œI§–¯ØÜ4LÀ;ˆ@îB“Û‚IºÀ\…}ˆ±Ð oÀã—Ð̸ <¸OTÑÅ{Œþ¶Y޳qQÎÖ&éAÜÓ|¹–0•)6,Ëù2n ý­¹PKUvΡc¼P‚ÅnäNùŸQe¨Õ.[vXÐÌ'ì<›÷m¼ ¯Ì¦ÐÄ—º¡Mªœ_à»z ­}ƒ¯P¶”2IG§¡~†h(—õ9»�@vR¡ ó§óÐGª«lX‘<È fÂüóâž4“VÓYÓ]�­xÚ?Je¬PŠhÅÁ7-…RQÉç„DÕÃÔ5ÈÕÒvVÐÝ–ªV ZHÝm™M©ú´“€$y|+‘^&‡Ìîh‹¸ý΂ےŠ,&VìFr-ËZίí_Cî€: }oJ D q^¢ú˜†áŽ•pºüÐcÒ#�ã¹ï˜ˆöå§8«ì»(yœ.O²q6+™êeªÿóœ‡ãâ®a?!¿XðäNB”Vúæ.VIEND®B`‚TreeLine-3.2.1/icons/tree/round_plus.png000066400000000000000000000060531506556630100202110ustar00rootroot00000000000000‰PNG  IHDRóÿasRGB7ÇMS tiCCPiccxÚí™gPiÇß† C‚D HÎI$Q�2Œ0$LÈâ ¬ "’AD\]‚¬¢"ŠQPÀ€î ‹€².®"**Çè¯ê®îÓ}¹ºùxûWO?UO‡·ªU €ìx"')6 ‰—Æ÷u±g‡„2±£  V­Nj²—Ÿ³?X‰°üKÞ�Hx¼§ûïÏÿǹI<.n…ã¹Q©œN[áXnWXrfZòJ v\a:åW8XÈ‘ß8QÈ1ßxç×_‡.GŠùÊ„£BŽüÊÔSBæÄò“�íZéWû6÷kÄ5…7ÁŒã¥Eñy‰Zà¿�š%–*|à‘éq‰iºq¼ÿÑ9Âýò�ÞX}Ý£â{móÊ;`¿)ù^S; e7=ßk‘Çè,@ú)'�Ÿñ­†.h@@2@¨M  Œ€°¶À ¸oàBÀFÀ± ðA&È»@>(%à ¨µ 4�Vpt‚óà2¸n�»`<0^‚yð,A„…È ’�” uH2‚Ø�5äyB¾PÅ@<(Ê�vC…P)TÕAMÐ/Ð9è2t‚BÐ,ô7ôF`L‡` XfÃv°ìo€cà8 ΃÷Áp=| î€/÷àX¿„€¢Œè"lÄñFB‘h„�lG �r¤iEº‘~ä"@æ�( Іb¢tQ–(WTŠƒJAmG¡ªP'Q¨>Ô=ÔjõMFË£uÐh7t0:�‰ÎG—£Ñíè«èôúƒa`X3Œ+&�ÉÆacÚ0—0C˜IÌ‹•Áê`­°ÞØl6[‰=…½ˆÆNaßãˆ8%œÎŠãárqå¸f\n7�[‹ãÕñxo<¿_ŒoÀwãïà§ðK ‹`Eð'Äv*­„«„qÂ"‘¨B4'úãˆ;‰ÄÓÄëÄ â•¤Mr …‘ÒIûH'H—HIoÈd²Ù–JN#ï#7‘¯�Ÿ’ß‹ÑÄôÄÜĸb;ĪÅ:ĆÅ^QðuŠe#%‹RN9K¹C™Ç‹kˆ;ˆGˆo¯?'>&¾ A“0”ð–H’(’h–¸!1CÅR5¨NT.5�zŒz…:IChª4‡¶›Ö@»J›¢cè,º=ž^Hÿ™>HŸ—¤JKJn‘¬–¼ )` †#‘QÌ8Ãe|”R�²“Š’Ú+Õ*5,µ(-'m+%] Ý&="ýQ†)ã$“ ³_¦Sæ‰,JV[ÖG6SöˆìUÙ99ºœ¥G®@îŒÜ#yX^[ÞW>[þ˜ü€ü‚‚¢‚‹B²B¥Â…9E†¢­b¼b™b�â¬MÉZ)N©Lé¢Ò ¦$ÓŽ™È¬`ö1ç•å•]•ӕ딕—TX**¹*m*OT ªlÕhÕ2Õ^Õy5%5/µµµGêxu¶z¬ú!õ~õE –F�Æ�N�–4Ë�•Åja�k’5m4S4ë5ïka´ØZ Z‡µîjÃÚ&Ú±ÚÕÚwt`S�8�Ã:C«Ð«ÌWñVÕ¯Ó%éÚéfè¶èNè1ô<õrõ:õ^é«é‡êï×ï×ÿb`b�hÐ`ðØ�jèn˜kØmø·‘¶ǨÚèþjòjçÕ;Vw­~m¬ce|Äø� ÍÄËd�I¯ÉgS3S¾i«é¬™šY¸Y�Ù›Î^Ç.b_7G›Û›ï0?oþÁÂÔ"ÍâŒÅ_–º– –Í–3kXk¢Ö4¬™´R±Š°ª³X3­Ã­�Z l”m"lêmžÙªÚrmm§í´ìâíNÙ½²7°çÛ·Û/:X8ls¸äˆ8º88:Q�œªœž:«8Ç8·8Ï»˜¸d»\rE»z¸îwsSpã¸5¹Í»›¹osïó yøyTy<óÔöä{v{Á^î^¼Æ×ª¯å­íôÞnÞ¼Ÿ¬c­KY÷›Æg�OµÏs_Cßß~?šß&¿f¿wþöþÅþ�4Òz)�a�M�‹AŽA¥A‚`ýàmÁ·BdCâBºB±¡�¡�¡ ë�Ö\?f–6º�µaˆe7&n¼°‰²)bÓÙptxPxsø§ïˆúˆ…H·ÈšÈyŽçç%×–[Æ��²Š*�šŽ¶Š.�ž‰±Š93k[;çW÷:Þ5¾6~1Á;áDÂrbPb[.)<é�ÊKàõmVܼeóP²Nr~² Å"å`Ê<߃ߘ ¥nHíJ£¯|˜Ò5ÓHŸÈ°Î¨ÎxŸ˜yv‹ÄÞ–�­Ú[÷n�ÎrÎ:ž�Êæd÷æ(çìÊ™Øf·­n;´=r{ïÕy;¦vºì<¹‹°+a×í\ƒÜÒÜ·»ƒvwç)äíÌ›üÁ凖|±|~þØË=µ?¢~Œûqpï꽕{¿p n–~*âÝüÉð§ŠŸ–÷Eï,6->R‚)ᕌî·Ù²T¢4«tò€×�Ž2fYAÙÛƒ›Þ(7.¯=D8”~HPáYÑU©VYRù©*¶j¤Ú¾º­F¾foÍâaîáá#¶GZkj k?�;ú Î¥®£^£¾üæXƱç � ýÇÙÇ›e ?Ÿà�œô=Ù×dÖÔÔ,ß\Ü·¤·Ìž ;u÷gÇŸ»Zu[ëÚm…§ÁéôÓ/~ ÿeôŒÇ™Þ³ì³­¿ªÿZÓNk/è€:¶vÌwÆv ºBº†Î¹Ÿëí¶ìnÿMï·ç•ÏW_�¼PÜCèÉëY¾˜uqáRò¥¹Ë1—'{7õ>¾|å~ŸOßàU�«×¯9_»Òo×ñºÕõó7,nœ»É¾ÙyËôVÇ€É@ûm“Û탦ƒwÌîtÝ5¿Û=´f¨gØføò=Ç{×î»Ý¿5²vdh4`ôÁXؘà÷ÁÌÃć¯e­4Ý4c4s~Öyöî‹õ/¦^&¿\šËÿSâÏšWš¯~ýËö¯�ùàù©×ü×˽‘ysâ­ñÛÞ…u Oß%½[Z,x/óþäö‡þ�A§—2?a?U|ÖúÜýÅãËørÒò²ÈD. r‘ ˆ\@ä"¹€ÈD. r‘ ˆ\@ä"ø?v�¯ÿnV‚—ccøgày€Ê*4¢ „ýù`â|ŠzTXtauthorxÚsÊúV”§•š—�Z!êP,ÌF=IDAT8Ë]“MHTQÇÏ»ïcÔ–¹°ìC¢ ¬ÕL E­Ìm¢`ªEôA-,I‚–- "ƒ- 4#¡B(‚1ˆ6Q­2R˜Š"Òiú‚Tššqz¯÷úŸñ¯<æÂ�sß½÷œó¿çžgIÝØ:ܱ æ,ØZA>ƒ Ðÿ<“?oÅa.ƒã lî€  �¢Åpö`4ò*®=·ÁSà‚.pla°w ‰ �¡€  ”@ûÁ#Ì]ÃüØŽyø`¸¤ŽÙÓ°{¹ _Å®ø�jj{#0gø˜Ö˰`:îã@®®¦M`gÝÚ úWk¡‘ÚyÏk¬‡Å N¬À-,ê4’Tð�UgЩ V²ºcØÐCs|…_` hð ÜeL  …_nè1ƒJþ ~j¶ØÞð¬89À]P§2‹`ØÜ™É¿àkÔÆøpGY-Ö[ëê° TÕW¼a“œH$Œ( „=%<#žk‰m/öÝnúL¨‚ `Ø36°>Ý;4ý̶p0Œäå|-Êéd³øÕP ß*òàâꬭ¥ú~«Ç±$7Ô~“½ �t ûÑ}¢ñ£ ’Ð%˜ åwÉ—C;ÜSØ?O×GЦÏñ¼šTíÿ_äq÷?ËåK@²»v#¥¿犓e±úšlI¥šåêá¥ú3]GT6ïïð~&Í6ˆÌ§ÿÌø2ž›;©'qçî©088c�fÛlÍܧjdÇMj'kûÞ›2·¾Êò>_’ê¬/ÿV®Â[ê ÝIEND®B`‚TreeLine-3.2.1/icons/tree/smiley_1.png000066400000000000000000000015051506556630100175360ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“úIDATxÚ}“mHÕwÇ?ÿ‡ëÕÝkeV”Wºö¼í…’T£�9j!aE™”•[k½i½Šz5„Ö ÍA…/6VˆšfEOš…š(Ó9˜¨¥·{ï_ÿ÷Þÿý?þz‘Áj±‡sÎ|ü—0p¸X3q88Ó{ é�ú— >8tòÀj¶lþ5PnKï§µõ!§~ŠÑ?bÕ•ï¸}º²èóª¯Ë�”,œäVbIRP2¡däb'9w¾…j_Þ6(3Ë¿ž9º¦´ê›]¸ÆvjÏžB’}xV'9ÖR€’š\ú¨7½¨—�pѪœŠÃ•[qÓ¸fIR(?ùY 2õ(;Þ�$ûð, IöqxÏ¥±ÕbÓž›GÇshñÝNRz¬“–¶8Ç�ì ··‹¾Þ@-@¸pE¶xÞ¶CŒÞÝ "ϾΈ�—Äì *2|’˜Ÿ£Šš³Ädg•xr%$ª¿Í«B’V¾qâ¥Ó öWì[�“Á?§_p9Š>žCàâ$GèëúƒÑ ‡[wã\n±k€Ê[ùÎÁ­¹%'ÊddÎB’ýxö4ñ)ƒ¤!0mÁð¸MûÓ).6X÷€ÏÞ÷L—–,”÷ï, RX”E SÂ0šî18fó{³ÆÀW�ÝüaàÐØ@è.Å￲:`�M†IEND®B`‚TreeLine-3.2.1/icons/tree/smiley_2.png000066400000000000000000000014561506556630100175440ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ãIDATxÚ}“[h”g†Ÿÿ°›µ›ƒ/Œ“(¶zcTª%B¡Q¡V£ÍEJJ/E#Šx£^I{%‚ZÏ‚XZ,(Š‘DSÐhÌ6¤"³Fec jL6{Þÿø}_/Jkņaxç˜�ÿSìZw2®Û&µÿ ½UŸZPùÁöý[–°æó…˜áJ6n&JW×]ž':äžšß5 ãPsõÊ]»ÐŒ)ø¹AÜìšf`„Ê0‚¥x¹G�ßâðå±`5€1i>ûýÎ�ëwíiDXÃxùA¤—BÓH7ŽŸ‹ŠšO*1òoæÞë³g×u ¢ú£i[w4o@Ø#gM3hÚß�n2—4ìíEÓH7‰¦ØñÍ >œml*  1òsùºÐôe¸™(ºfë�;´w¾ ™‘<}Uĵ�ȺE¬©kÀ½�Q0�3C{·õ§ ,*œ]�“|è ™ü°¯–L^qìøIœÔ#z{{9rô ™¡_'V’ªòÀ—zyù¬&é§ Êgμ¥´µÝD8c8ã~o¹Bzð"nò/|û e3 €Mf<Í颤‡N¢'ù”�É�#(?ƒ’”Ê'›—è¶í\W~î³6ÒÏ"½ôD6JXºtPÊCÁ𨈘@[þuëÆàÔÅ{”Oçƒ4‡Ï 0špS‹M×–²yu%ú=úû²—M uýîW´]ZL6ïòÛ�!?Ïspï&VÕÖ€"ö¬�Ož'XTÉòªјKK—Ðn©‘qwN±–[²¢f>óÊ,ê>-fVÉkœñœ±NÂÁ_Ô5PRhò$ú˜îHŠŽ‡â4péß§üǶ ¥µûšÂCÅhzÒK“HYä,…ã)^¼ôˆô¤8ÓêÞ>{×3]¨š©ûUm!‹ª§iXŽ"™‘Ć=®¶'æàkÞCðpð€8Ðü,}»ùoŠÏc‹ä‹îIEND®B`‚TreeLine-3.2.1/icons/tree/smiley_3.png000066400000000000000000000014531506556630100175420ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC»àIDATxÚ}“khÕuÇ?ÿË™[Û@m‚¶ÙÙ /½hËQH‚xAÐ(,Ä`¢i#'Z"¾Ñ^E½ Á ò Q ‰--ÎJp¦s3ÎÂ6ØÙ Ιu˜Ç³sÎûŸ�ó¿ü.½Ø oø…‡‡‡ïóýÂßEØ \‚™:¼?Ã=ã¡ùØÒƧvxoÖ¿€]ÝÒ#pôô\ã£/ò$îÇ�ŽÇ\þ¸£eížÚ0¬*ÄTŠ 8‚aXX• °*ž&œJrøÈ¯|vnü2°ÀšŸüd÷Ë›÷|¸YN–R¨pÃŒ ‚b* h^]ÞˆUº÷ÜõAo>pÉ¢-Kæ´ïêØˆô2H?‹aXì8Ћi×�É)ÚöÅ1Ì*p0̻ީcqƒµˆZÀÖ¾3õ¯WÎ}…ÀM`ÚÕ´¼J×o£8®âöX-ç Ô²á�6ÊÙn¬Ys™e»tõ–oÚ@sMÃf|ç`‚aóéþ5¸%ÍçGŽâO �Ç9tøî�o¦ÖЦúÀ[f}ý3;”˜hÁ³Ï·‹ý‚ôÇñó}üxá;&S§œ~„w�uÀ&;—Ë�aƒ Ð*DË2~áw|çÐ-Ë8#‡ÐÂE+ Z€K ÓóüKZLý/VÒC‰"*œœîÒCËò4¯|´‘R’ÎJ€>ˆ•îþôfÅì—(É,¯d¸•(2–)`š± V/oàÅ¥ulZ‘g(24X8gÑæEµ©Øé×PÂ¥jÞ:"Õ ±*æ!C­Ðá�áçãüýW7Wû=¾ú6ÏpZ/±�Ñ?o»_Ÿì¼¹½ýÝeÜ>CMÕ}Õ­C´ôóù'#˜d8­�#ÿ%ñ‡+ýΪâx¶ie«Ä²#ÓÁ.yÇe¼à“uÉtHOï�±°xûqÏÔÙ4ßܾeM Í-UTW”}�ã*’é�ï»FÒœ¶ñD�½À rÀð%Ðúðò¿/‘q±öë¤IEND®B`‚TreeLine-3.2.1/icons/tree/smiley_4.png000066400000000000000000000014131506556630100175370ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC»ÀIDATxÚ•“YH”qÅߢã4“މ-Z9e{¤$Qe=EA˜íûbiûKôõA-QBDEeeš¥TЂ’æC¦4VN3ãè|³|Û¿‡,Ú:p¸ÜsϽpá^ø9@)pÐûxØÚWûÒoùÙqÞ~ÛlšÌÂãQ]^°âè½-Ô×?æàÉ -z9Pò·µ‡Jòç–í,FRœ˜Ú{ôH+’¤ ¤ AIÎÀÐÚ8~¢†£•_j�yJ_óùÃ¥S––íZ‰óaDßca$9 [`jm€`ú4/J´k䓦ø`àÀ­‰¹iø/zÉ8#Ÿ/Ig˪þØ©l]¥k&ý¡o_>”ÒéŠ ˜Ã'.c§§+1šŠ«Õ?Œ+–䓿²8u±‘êêoúúÅ™/ˆßß à‘²³³Œ×wW«‰p#¡H=šJX“ñxÜäs#, ÿ—Á`,�T§ŽÇ§³+ÊŒu>S  ©´¾ ¢%LÉËBRœ ©KCX1¤Ê¤÷KÆ6Mn×ùÉÊ0q:r<ž¸#L�¡U[üTÞz‹mF°�žoÑŠ#¬Â68}¥�öÎS§âó[Oeà~ôSnOk‹gq·^gþš{³ÛŒÐ òúMKw¿ ¦!ÄÞE45½¤¹)P �“7º¿øØP$>ÔÍþWûÄãªÃbB®K¤¹U‘œ$‰ÌtU”™)º^”‰g—²Å±=bl¶$€1ß/±âÐ&ï†Íë'cF;px Hr�BqdbëA¦ÖAóËë|ølò .Ä…£(ùù”n]”1gÿFÉ)©H²Ûè!ޡŠCÐÞiðôy˜sUú#`ößž©bÄ`yÃò9nòò�¸R$b Aw¯M›ÏàZu7­>.«ør€Ý@` 8 ünþ ÍBÖþ¢‰IEND®B`‚TreeLine-3.2.1/icons/tree/smiley_5.png000066400000000000000000000014431506556630100175430ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ØIDATxÚ}“{h�qÇ?ïy_»¶¡Ì‘3›?¶93·¡�°#Dü¡Æ\Ê¥„?ä?É-—C [$E[lsÙÈs9®sY›ËYçìÝ9{Ï{ûùÈ‘o=õ}z¾Ï·žú>ð7Ü@)P èÝU¬êžý©G,+=aõ¶fÎ�’˜–†®6q÷nÛµÓôQ÷%ÿ2¨ÛU’;uÝúEHr#¬;™>s–ÖJ^¦JõíP~ Cœ–�%¾r׬¸ÔÑèj%‘1žtž¿n§¬ìžd}8]v-Ѐ|„›J¬¢rý^×}�“4h>Ñ p€¤àVÀµÚzl#D4øˆË•Q›Ï ý?6C\½Š—kàrÛìÀ¡$�0ÑC�1ÔÛazsÛìlLí iýd€yJ I[GØõ¾÷œ¼ðŸÿ3ÁŽ(ÉÎFg÷¡xn ²e&�‘fM‹V 3Œ° vì{È‚Ò[¼k‹#s„‡¼¼QL˜0‘ì‘ãPí m~ÎÑŠXâÓæÐòÕð”|¨.Z @Âårýâ………¿øÏþÓr±uA‚èN,îœaNÑÚ¸PÏø‡¸g¥¤¤ˆšŠ£¢æÜZ‘é’0\BŸÛõÁ½¥°gËš|ò³,ÔN‹@È$j$ ’�æÎÈÀ{h'½Œ&Îx½Ôù-/Pö{”o®šÝwÊæå‰$¤fãÌBŽíO$¢!äT,ü¾KTWÖs¼Z¿ Lþ×3�2ÀQ¼xJ9¹ñ$ÆItEÃÉ˷߸x=È«ÎKùÜÀF 0€ð8äõª¤D’DËcIEND®B`‚TreeLine-3.2.1/icons/tree/sphere.png000066400000000000000000000013701506556630100173020ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC»­IDATxÚ}“Í‹EÅ]U]Ý==½;;cv3›‰fCED¢ñ&bÀ“àÁ›¹‚�üK\O<ˆ"ž]Ö=ˆ'/‰�€® l hf²óÕ=UÕÕ5âA6àƒw{‡ÇƒSPJ½!¥ÜB !\E8>Þ<­�N™÷.§ñ­›ÝŒ-Q«ÁXÆsdk¾(=V| |øT€”rÿ“­â�ëýª] … ijÜlN5›SÎ+¦¶a¿ªùί~®H!Äg··;¼{¡OûÜ€üü€Vÿ,º(P±ï¨}ƒqžˆš08^qøJ×®dzïã [äÛçX»t‰bç"éö½¶!Ѓ3Kc(Hˆø£ ϸ«€7; 2ÉHº¤[}ZçŸE¤-ü|J°3¡G#b)ÐqD¢$WW–œûHo]Ì4RI¤RÈ$AèŒ8KqL$%B)b¡ˆµF+IÞnóÜ™3¯ `GÕ5¾®ñe…ŸM©'�±ãõô„fQÒ,KB¨‰¼'QŠ,k±9t€÷ ¾Z`Ç#ÊႵÈ$¦^”,ÿbÇü¢$""Š5q«…n·ŸLÏŒß ÓÈ¿hœÇ=#¥¤¶–z2Á�Œ°Æá#EˆST»`i-À‰~ºoýîåY…ñž¢Z¢OÆÄB@h¨Ë g¶£3B±ŽÜèñë�;w%0?öáÆ‹2Âpa…±kvi1Öc¢˜eÚ¦^ß lžåQYñõ½{X¸-�ã9¼D³z!— '^*)\œáòßé6û̅⛃†p|úß/üòºàåW6:t{]Z±FK�JSD^ ºÏ0žLøöð�ûðpå©3߯Ãõ×òœÝ~ŸN¯‡NSÆðûpÈ�2{Òü6ÿƒ÷€}ào ù—�€àýÓâô&-¢æAéIEND®B`‚TreeLine-3.2.1/icons/tree/star.png000066400000000000000000000012621506556630100167650ustar00rootroot00000000000000‰PNG  IHDRísO/gAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<DIDATxÚb`À>U1Ì_Î0Ÿ€bÄ%ñ¡’A€‰Ÿýþïß ¿ÞüT”œÈð›:€bÂeÀÿÿ ¬ºòlzZÿ0àR@8 ``cŠgsÐcàrRføÇÊ�K@a5àmC³ª´#çcFîÇ ê OšDþýÛ-€® €ÿu1Ìÿû�Aá/Я9Ùþqó3€ØÜ– Ì"/ÁŠþ¼”cx>ãÃß¿ ß_|d``çøðñþ§ @¯= Æ¿� óÿ©ª'0;Y%ÞAÍ}ŠÃÁ"@ÌÎð÷é†{³N2¼<÷n@�cá{CÁ?>æ~Ž}Fæo¸ãì#P3Õi·>¿ü[h·›a@Á£ñ}CƒÇ|n+>LÍ?™¾ÞÚ¼ùç×ÿmw2, J:x?Y²à÷›—ý"îÂX ¸¾è Çç­w0l€  JˆJ« °~}ÅÀðñ'DàR<��“‘áß?Ô@(üzúÈž“” 1#ï�ÿ�ÑñŸ�MèP âfàŠ0=„bÀßO_Ø9ÿ3ü½ý›áù“ oßþ¿ð¥BŒ :L ¼@5ì‘õÜþÇpûÆßÞÿO4\Ë`hº‰ÁðÕ‹ÿ‰§výýðôö_�� �  x ÞNdPúï>05é :+PýºÏ�œ'€^¨&ð9'{û¡Š&EÓü@´çb!Ru->MIö»D|Í~Ã~8Ø“�SlÉ +òÍT{EH Ž#Âk¥¦ž\/©ŸˆqÞƒµ…V¶½ÐºÎ#Zé[žc£L /ÄœYøh<ÿ�²‰ÖÌmJ4Ò� ß×›9òB.Kr¾ß[¤rÂiv[“ö^IEND®B`‚TreeLine-3.2.1/icons/tree/table.png000066400000000000000000000003241506556630100171010ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“‰IDATxÚ퓱 ! EÑÍFA{ë0ã¸`B2šKq"Q)"Åqe?ä/û à`!6ïý�sˆÈGVJ!„p ´Ö�ª:Õ¯X±,`€#¥„ª~Õ˜sfß÷Ó™ö³ÖcœžY­õ"üMü�À6cüí±ßñ¹Y=ç;ÓhcŸžû¦ëIEND®B`‚TreeLine-3.2.1/icons/tree/task_1.png000066400000000000000000000004441506556630100171770ustar00rootroot00000000000000‰PNG  IHDRóÿa pHYs  šœtIMEÔ (9’DëÃIDATxÚí“= Â@F_0 ]Ø>mHk)Œ'¶VB<€½UjëTâ\ȶiD<‚MXRZ­Íúƒ¿XXø`x0³3|Í:\˜P=` �èÒz ,¹!Ìa¯Ì+¶ïhY ½�Ð ÆtÍâ¡¥”#`àž.ù¾OºÇ1é¢("Í›ðݱ6ÆʲäJ)’$9ïº×C­5UUÝ]ö<¯Ñ«B „àþ ~*�Ö¥Ÿ’ÙOòje|‹#uOotEXtCommentCreated with The GIMP (c) 2003 Jakub 'jimmac' Steiner'3ïX­IDATxÚ­“1HaÇw÷Þ©Xâ q •Š �D‰t0Xh@‡àÚµ8¸”Ø.v(¡¢âäàÜDÉàÒ±J…Ò’±á ikîëÐX¼k;øà¿½ÿï{ïÿøàßµ˜ˆV¸¡ò× ¾ïÿQ©TŠÂòW&¹˜-,Ìpðå„Í�]<Ï£R©P.—¹ÛÝÉhêûxñfyx°Y|ÇÖv‘jµJ, �cÛ6…B�³¯G¡þÀÈf³¤R©P“eYär9Š«�`Èdž2>>�ª R—*êŽ Åõ¦quPѺYPGh›{÷ú1Æ„úíðû *°¶Dûü{û{xï=Ú^Mb�ãôýuº Àu]zÊû´Ÿ#‘Hðx}ëâ{ú-n2M4›ÀD¿÷>Ví’Ž™,úó;öô-É4ªÚ|…Z ªxƒø½°j—ŒLÒ:œF\EE"€pˆÆàª0öd Íd’¢¨ Ný"K/Ÿñù°‚©guÄî´6|úø�êÅzº:ø�•!2ñÿ¦”ç¶êîy¢©ø6c¡IEND®B`‚TreeLine-3.2.1/icons/tree/term.png000066400000000000000000000007761506556630100167740ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA±� üabKGDÿÿÿ ½§“ pHYs ¿CfStIMEÒ49�^gK{IDATxœ¥“?nQ‡¿yXÞç‚(J°… ïq¶ âw@Ê hr±]:*áÆˆÒ@¡ ‘eß¿ŠÅ‹GÉOÍ+FŸæ÷fFÌŒ§hжí£(]×É¢m[ëºî¿…1FrÎSN)‘R¢i[Š6› UUQUËårö~Hu]ÿµà½çùÙ† }Èܵ{ÔÀÌø~wG_>_±ÝnpÇ€¢pþ~�)¨A±1+sF‹"ÎὟ:™ÔàöÝš——{ʈ”b C ˜"NX­VŠÂ«Ë=ß.Ö(pþæ†o¯ a „'Â3çf€Åá—½÷è�ž¯ëÉóíÇפéûŸ€àœ€È) ç Œí‚�¹(¹ú_="ÃÉ4ÚYª€fŠªÃ0útq8!„ÓL f†ªQJ&©‚�ZÁ ŒÌaõg€”ݧ'Ët<²c�꺞–ã_Å !Ìâ`[ÌŒ¦iuL»ÝNä©çüí[ñö{ö�IEND®B`‚TreeLine-3.2.1/icons/tree/text.png000066400000000000000000000003661506556630100170040ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ­#½utIMEÓ áªãoƒIDATxÚµSAÀ ÜøŠ�´¯ðÎ|ËGü%=1¡ZƒvgL6›M1ó� ^MN)AÉ 3ŸùH¢÷þ1¦2Ak]!„(IÆ´‚•@KÁZ[ŠQoˆDe5™ÐBa7�Qÿÿ;pÎUÓ–¯ó¿ƒÙþ¿w0Û%°b¿l¢Ü¼Þ�{sryJH&§>IEND®B`‚TreeLine-3.2.1/icons/tree/trash.png000066400000000000000000000014121506556630100171320ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“¿IDATxÚm“OOSY†ŸÛ{ïáRúÇ;P¨EÁl€Ç`bÔ¡Æ7ºPÇd’1î4nܘÌc\Íz¾WJB&3$# Q'Ñ` 4±b)­T�iKio‹ÜÛÛãÆVÞÍï$ç÷>É{ò…-B˜ÀqÃ0þÄ0 ,Ë"ŸÏ377‡" ¼·m;É÷B$ ïܾ) ¹7²¸¾"ó¹%ùâùCùóÅ3²~/„8[÷)_ÌC^¯wêï±?‘<|Âôtœäb†` ™ ç‡Ù½»Uõàñx¸|å7„lÛNzzzz¦žNÝ'éfÿþ^¢C'ØÓÙɦ‰hÒy;ŸÂ¶ÚÚLA�ü�mÛ @,#ÔÚ�ÏßN ‡�£¿ï0…B–üÚ ÙlÓÜ…Åb�Xl¾]«FîŽpýê¼-4i­È€Bk(¾ªÍÆF‰b©ÈÄãÇ<ñ’r¹Ò¨õé÷û¢³³q–WV ‡›q6-ŠÅ<–KŒ��299A2™fa!Í»w)²ÙµÛÀ„R'uwwÊP(DG¨�½]]††S­¡*›¬þŸ'•þÀBb USÐ5•Tú£òM„–ƒ7®1:z�é×ÓXV]×X\|OµZE×5ú¨TJ Ö¶´··þ~*úCC§qìO\ºt_‹Ž”.ÃÃ'q]‡��~Ö××(—7Èå ·<�B( F³—é stð$m¡0Ꮍ½ý˜f€`ЇiPÕ†í+`+HS=4‚C»Ð…ŠßïCUUEÙÖà@JÉÌÌ,µZ�š¬·ö[I)±¬ Rî¨V]ž=û�ññ™™‰áºncɲÖÈd–YZZÅqœí�X*U^¥Ó™_=šdWÐ�â©�H¤‰Ç@�xçø#<(HþIEND®B`‚TreeLine-3.2.1/icons/tree/treeline.png000066400000000000000000000023351506556630100176250ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs  d_‘tIMEÖ ,P6ajIDATxÚ¥×ÏoTUðÏ›tŠ F# ”jEÀÆÒDÒN“[HÑ [Ý™˜àЏšvãðo0º2èÐØh‹QŠ"?Š"¿â/\˜¡ÓÎs1w†÷ÞLg=“—7ï¾3÷ž{¾ßï9sù¿V¥ž_wTIìsqøM½�Óþ¹ÿÀ”XzưØéI½�Òþù¶;ËNž´Ï䌨&üwcBŸÆw ³œ9ŸÊD$ίxgYK.^³ ”¬ O—ñ+òöê³7ŒžÏf"ßqç¯ÙëãÆl0èOœù:航x!ƒuUYΔÑç°Øz|(2³<Ù�¯2Ž’rjôAUÃ8Ò4OOà×ϸƒQýúõã­Èî¼dYpü‚/°ÍÁàõ®Èe_zÏsˆŒ‰©®‘0�§°�9‡�ñQk6c~%«ÃÓO!ˆQ»m¶;ŒNšvÉ´I%hÀ“Ø>™Ì&ªŠx±#¦ýÆÅ¸ê¶w¬±` ,t…ûÏa•­†ÅŽà´Èåv2,®Óµôð[ƒ 2Ü©ÙÌcTÑ&Eôò ­¨cô<›RºSl›HÓ¸Þ4S9b,$2·ˆÍ^ jø@d¶«iùY7ÍšQ´%d£f a‘A‘}¸…Oq7Œç OZ·H¿á&µ^ŸA\7e&ß‚ýýÿáÔDõPçE¼ˆ;NúÊY« Yk¢á_ 0ìÄ6\sÚ)ŸЋõø¦9ÚZ“N·²2 m°û ‘ã^wÄFÇÚøMµWAÉ0⥌OÓJ˜übøõCbœ2äÛW²*xR1¨à}‘­H8Ò’ýutë ­ ÷k¸zÀ  gÈšUÁ¢aû ·SÁ78Jå_ØŸªuLŸÆV̉]ù!,z³Á•Q#c±XY´\OHVÂÓ8�€¤7ÀR`kCœ‘[©LÔõ¥2Öž—é y%9S©¾¾%ð ØRWÃ} Æ0ÒÜà‰‹¯ 'äS‹×ìÕ–*¨cúcb,Q¦n…ôÊ,¾‚ž�ïØ4aZ[l.Ü×…`æq%Á•Î=áŒÈ¥\‹П ‹iMßó¡«WB&Ope¹žðæq ‡“ñQTÉ,`ó²…h1ó ìA^ìjèo÷Â. ˆTU…n1\Uü�ŠMÞöø¯„uœ ;«�w²º_±v%9ðÆ›z@Ö–ë ¿;iÖÙ]ç mÌ™èêci;wW™¹X1+R+ø'Ô…Šn’…èpÛ�g1� ¤mö¬—0¡d÷�Ù©7š{€u”¼¨5ÞrÁ|¸–TU2™2.…ïÏ: ÖûÝ~CýÓäÿ©AÞÓáè“Ç›m=§œôTu¼¯àÖ±ÇÈ/ûØ:]#Û}ܯvàDBÝ÷º/(++<ó½áGï)vmaiG[L è®ô¸�r[þÆÌ´ ê|ö ª(zöšj‰é´Ž‡Ó ” è^¬e}C.sDYé!ºÔz³ùN?ü³Žvð,WW¤öæ×2gÍÒt ®ÜBIEND®B`‚TreeLine-3.2.1/icons/tree/treelogo.png000066400000000000000000000030501506556630100176310ustar00rootroot00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYs»»:ìãâtEXtSoftwarewww.inkscape.org›î<¥IDATX…¥—klUÇ3ݲÝݶnK·Ë£Ø­´… -”¶c|R¤1!QÑã P!¾‚LübD >0‰1€/Pk0ÕQ1•Õ‚�FÚ…¶¤»¥Ý>öÑ�î\?,fwf—M<Ÿî=çïÿÏœsgF"ÅΟ65�€`>P ä¦â²4ð^­b”=RT�ô_@,¶3²ÙÝê Ý߆oèqUÁ–ë¤Â¹ˆZ÷ÝLrðœSk<¥Ò7>¿x‰m€|%âˆä‹?ŸçX÷‡¨"nˆçÊ6šÊŸ`ù¬—±æä§†U!±ÞS"½£ ¸tò¯²!F{xûøí\9}%(.{%kë¿Æ�?Û(îö¸¤6©³SäÉùüCi�Åü~´‘óÿP0©”;«6SënÆfq2=ϯ½{9äÛND p•u*Ï-þ‰û5©ÛõÈQª$_@<ìH%ú¹{‡ñ‡:˜l«@Q#´ûÛ˜’_úEßãÌ›n:íåý_Wrvð(3‹xæ¦ÃÈRNN•|ÑÜ5á¼0ršwO4s1Ò•6Öœ|6-ñš�J³±ñ^;Ú@ÏÈ<4‹ÊL…µÉ$Z €°2Èö“Ë’Èó,…†BZêy2#9€ÕRÀªy;µù�o˜ÁæYHô9»Þb ì`fQ#ÌÛ‰;�ð¿œìý„ã={XZ¾6#ù„yœ ©*^JÇÀaº‡O1öQl/×C¦Èè.™“½Ÿ�+çñØ‚}9€Ë>“;+7³eé_Ù®ÎJ@­»Yw N çjmQ‚ô�þ @åä& ­S²&Éd3 ë´qø¬!n™ �ôPœÃXeˆ�,R´+ ÖJ°Ÿ ?&ê¸Â±Ï·is³ x¿Û�÷»Ý8ŠJ©\tso¹�iÕu‚5UUÒ˜¶KW¿xJ¼i&"ØçãÛ7×Ñ}æVG!öª7³äÁM´ø˜ö÷î'24@dd éQ––1»±…ú«'Þª�Xç)‘¶CJ_uÄ2Þ }uªñqzÎüL^a1W¹Ê˜d7¾Ñ’2¥Æ „ûPbQJ˯կñ‰ÄÏé·Z&S7èìy’ƒU’D pàæÿýž÷¿ ÁWÊUUIczÀb=õw®:�IEND®B`‚TreeLine-3.2.1/icons/tree/tux_1.png000066400000000000000000000012571506556630100170600ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA¯È7ŠéfIDATxœ�‘OH“qÇ?óݦ:Ù¦¦™3Ô™Ø!ÉH”(CT*T’‚(�b…xéA‚—.ê]*;ä-µ›•`�ÉD0rVÂ\Îþ0ßÍí÷îݯ“"ò&}ÏßÏ÷ù>Ï£`,SUUÕíîîî^¯·cnnn^Ó´€‘QùGÀi�Ç3‹Å²¢Ñh~8>®ªêÞjL3¢-ËÞ’’=ß9p°0åíF^³aiGjs¸p¦�_Ëkä¹…–\ÿ`VÄr}õÞÝD&ƒ<ˆ(7ò®`²:‹32®Àb6Žê»n» ÐÔù·ªþÚõëQ¹IÓÓÓÒf³Ià-`ß¶dffNúý~)¥”z*%…R×uéóù$ �;Û4ù|¾�ɉDBªª*ãñ¸—.—KZ­ÖE`‡ñ Û¥¦æc!H&“!X]]%/¿�ÜÜ\ìvû.åÐ:²ù ŽÎ£Ùu…n+À,„†¦ ¢Á)\N'ºž"�dÄõM úOàî­èö¸¯P¾ftt -©#„ !4⑹êÙö$§Jh©q¹7Jܺ\ú¼¥ël¤ÈwþaðéK¬Î}¸I$¿W‚d~åâ¹›*)/¢ìÝÄìDx•� ݽdÆ2 j‚t«ÊMŸ™ÅÔ<¡P f> ÓÓö%m´”Y¼¥sÓl0ù €®ö´Þ7ƒ,¬|$!"e y¿Ï»RSÛ’‘5ü@Èé9¯Ü�†ô{Bðyú ’×¢ìµIEND®B`‚TreeLine-3.2.1/icons/tree/tux_2.png000066400000000000000000000011121506556630100170470ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÒ ÚÔ»s×IDATxœÍ’½kqÇ?÷’ëÅ;ß’ �A5j�!•'+Ô![Í*„ nVÄÅU'íæ$®¢ù,6£ÖÒEÑA¹ÔWB{ær¹ÄK~.^¡Fqò�¾?žçûðáËþ«š�$K‚»À'@¶÷€½ã߬ý2 @hš& …‚Ðõ¨ ¤¶3ÉCú2prx¨( ®ÛBU•$pûOK’$ EQ², MÓÂwHŒ#0s¹³³gQU˲¨T*‹E"‘H¸;5z@ …ÝùùKÌÌäY]}I¹\&™L’Éd¨V«8ްô€2¤Ï躞ÿºñšÃû¾qbê•«·ˆÇãxžG½^x¼Ú–pÄ ÓO9zJa«û˜Gw¢Ä’]–”“bLÍs“5Ž‘`"ŠnšLçú$úˆïn‡;Ç…Ø­}Hñþ³Àþ(xóâ�õ[ÍÓ´û1ææ.bæ`çï2(,\¹yþGSÐÛx‹è$觯“Ê_£Õj³¼üŒN·cAà!jCáƒaiY–×VVjf»íá~ßd׋t:ƒiš4 ²Ù,®ë¢ªêfÇ€/Ã$Ïoß÷…ã8¶máyžð}Ð¥RiðÁ€‡£Yüsý£E¯î†}/IEND®B`‚TreeLine-3.2.1/icons/tree/warning.png000066400000000000000000000014511506556630100174610ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ 42ž” ŒtEXtCommentMenu-sized icon ========== (c) 2004 Jakub 'jimmac' Steiner, http://jimmac.musichall.cz created with the GIMP, http://www.gimp.orgôóºqIDATxÚµ“KH”QÇ÷Î7�Ïyh5Y&áhN`3�c¤Že0™½° m*� "¢6­"¬EnÚµ(ZºZô¢©*{A›H’¢ f3NšYãŒ3sZ8ŸŽ-¤E¸p9÷üçÅ…ÿ`&pø ä�w@7`ü�¸ x£²µ}…\<¹NÖ6” ÀmÀ;Ÿx!0¸Ôï‘GWº$ó|»d¯—Ô½Vé=·K œ¥"[ÉýºÏíÜ¿ÜIk퓪’'ï]ÔúÓ´4¸±šþ·ßëe:ö韀]ÀÙÞSíjçš4 ¸tk’#çâØ”kª 1èæS"­>&ÒQà�ÐEÈùȪjÝÝaBa ´ƒ±ñ ’©,"‚ÛeãBw ‹|†è±*ÐÀ& tú@?¦½…,က¦•´VÔ-sqpK%@Ðhö,^`ªQ_qØ€äØ1h ûˆEÊg¦‡:—à´kØkÚbÍË1Õøœ•Œþ*ãøþÕä 2Ç__m y­*Ѐ·¡Æ ’+ Sô=Lp¸ç%7û¿Î(­Õ–,@êî³!¾¤²ÈL2¡¹>ljÝUD‚žq¾ |úÉ«Áq€‘éTÐÜð˜Ú¾o£ŸmÑ ê*]Tøì˜¦A&�gx,ÃÐp†;/¾qÿõ£¹p ¸fÁÃÀÕânež“ú€èl³%æ°+O./-R ZÀo½+H)EÒ0Ô@vJ†ÿé×ý i™©=Æ`IEND®B`‚TreeLine-3.2.1/icons/tree/wrench.png000066400000000000000000000020371506556630100173030ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<±IDATxÚbìéYÄ --ÎÀÀð_���턦¦’ô¿ÿ¿}ûñųg¯&~þü}þïß¾222ÀÁ�¿LMµ¬¬ôˆéÇ�_ ~aàåådÐÑQË ó7WW[E` ­xñâÍAgg³Luu†�¿5²0¼{÷�áñ³÷Ï…þÜüäÌ»‹áÐ_µ�ZÃÁËÍ›XYéky{Ûj½~ýNKEE–áýû�@©ÀÀbfxýú=×oÿÄ=9÷ê3}¸ò�ñÃgx ³˜˜æŸÿÿ|54äDD¾}ûÅðïß``ýexôèÇ/ òœw”$�ûþýõïÏ÷ïÿO1r 1ÈÚ&³‚‚ A¾ÿ((9ÍØØÞýêêï:ÿÿööøêêí÷÷ø ìÆå‘øåIóöôòééÇñèØÿ ÿˆ14´”áË—/@ ?½999ìyy¹4¾~ýùBHLÒ0ÌAÀDæÕ$©ß÷D€Ö}ãdexÄÈûçîmæâ¯_Lúüí/@±€üÁÈÈÄÀÊʲÊ[?}úÆù�‘黨¿½æÿ/Þܦ¤õQˆ—� ì_îÿ ÊL?Xþþçì»r•����a@1kk[ƒÇ¿ÿ€^`øÏÈöG‚óC�ìé§_>ÿûÆÆÃæ*¡ÆÊÌÀÏÎÀ¤˜ÿþgåúÅô�‰ÙãùkÆ—Ä€üg`døõ—iÊ‘3 l¿þ3ô˜º±22¼ûÁÀðà ãŸÿ ºÂ¿ r7NÀQÄÌÀL[}ûŽ0üùùýGŸ�ê_f`â}ÿ›� ˜È¸™þ ^`†½6i׆ŸÏþ÷9[±03°ÿgxÿ’�áÊ#æKDÐpzZú�hÈ-N†{/Ô ñ0°ß{Ï~ýí¦€ïax¨`a&IEND®B`‚TreeLine-3.2.1/icons/tree/write.png000066400000000000000000000007541506556630100171530ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“¡IDATxÚ�“AkQ…?¥ vá"—%Ͻ‡RºuÓÿ!¸ô—¸ÒE‘Tê&HqHBL! �„) yÃLf¨†×÷® ™a&“h/œÅÀœïÎ��¿³Èt‡ #ιµ²ÖÊx<–v»�@v6â8^«N§#Æ©Õj…$×2‹¾ï§T¥�Fƒ^¯GL&Z­VòÊAPˆ&Â|>§Z­rrò‰ãã�˜`�__JÜzô¡˜`4åJ)|ßGDð<�Ëó˜Ï7x|]¾?ÝÎâ8ÎmÎN©Tâ2ÜÃô·yöö'/^÷îme "’v�lð<�å·]~÷nòôÝ’—Õ>À]ÀOXk™Íf¹Í"B¹\æâô>Ë·yòê+GõAî׳1�s ‡ÃTÖZ¾Ÿ=äù› GõAöù²­µE‘DQ$aJ†ÈÁ~9ýƒ �f³™<³1�µ6½F½yŽÖ­5ιB¹[«7WJ!"T*´Öi¹‰ñ¿€ÕWMιõ€n·‹1æŸf€ét 0X-qÿŠ¿s¢ÝÄøZØf«.0ö3IEND®B`‚TreeLine-3.2.1/icons/tree/x_1.png000066400000000000000000000003721506556630100165040ustar00rootroot00000000000000‰PNG  IHDRµú7êgAMA±� üabKGDÿ‡�Ì¿ pHYs  d_‘tIMEÒ  1Ó,»š{IDATxÚµ�± €0 O‚’9PX…A2Ë0A J 6 Dbvx LPPR!Þ’cùýñ¾¢²wæ`�Ý@Ër•µµ&:64ïŸBF+Ö oøV»<Ý#ÄZq¦%£)]ô1äègUrh`Löúò¡¿àŒí<ûù.‰IEND®B`‚TreeLine-3.2.1/icons/tree/x_2.png000066400000000000000000000014641506556630100165100ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“éIDATxÚ�“Kh\u‡¿û¿÷NæÎ�;“4±L f*t¡1 V›¦’(Á"­ˆZÝADÈN¢ˆÆRRpS7Џ´â¦"‚!±5�©vÆñÑFg2“y8™û~¹�‘*v¡¿Õ9œóý8çÀ‘ùSºâ˜B�ãx›ÿªt:=lè¶øP¶ß3 cáf}š¦�BäUUý^UÕ‘¿ z®ϾóôÃññÁÞØ0ŒWþ ëº>yWoôÅ §âó“bMU~鄊ue×vxq4Çx&ñªaÏuàd2yüŽŒváÃǧ$ic•ír�È�AøØ£}zÖ«”l‹ñá,mÇ›þÑ‹«©Têr·Ì·?1-_[[a³nòév‹õ¶7”ÀýcG>z~%ËݽĀWßádO‚»uõœiš?Ÿ?5#]»´ÆJu—w~ªp¡fMÄq| @ꌙJ¥^º]SÞ>´¯±C„„ÃûÙk7Y-^çÍ«%+ྠ.v8¹ø¾¿d ¥¸YkÍNå²¶…� [‘¨nW8�/S°Ã3a~pãqåß÷/oYnW©Ñ{äÈaÜ� Ži" ï˰n‡c¦¤lø¾ÿÝ¿(Š27 H§ß�Ÿ£ñõ2.q!K Jpø–$[î¬)É+¾ïÿf „˜?¸§{ñý¹'•ÆÒgl6mžÝ( VÐóPn�ȱèG{ty¹éÎ4oÈË’$-œxý�ÓJý«Ï)˜.‹…Š$’C%7(å«�é‰}ƒD¶E—£½™®OÊ­Ñ ŠÎɹTâ½·žšÍü¾ºDÑò9ûC5ø-`_»Ýnxž·Zª¹UoM>8ÃʽwIEND®B`‚TreeLine-3.2.1/icons/tree/x_3.png000066400000000000000000000015721506556630100165110ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  @¾áAtIMEÓ ",§á¢‚IDATxÚm“[huÅßfg/Îî&»ÙK.²hR)ÆmjšÒÔ‚¦-TôA�€Š`¨ VÑWT)*QV+¾}Ð Ú ´”–^Ò&©-6YldÍRsÙ°—l6îdgƇh´M?øÞÎ9p¾s>á6sy[¿ÏqÝ>º\\q‘ë]¼p¶v+Vn!š¯y\÷ù RáÆ�4|Ù,%Û)ׄ¯Jºç­}çÏü±Aàò¶þ¤‚“ÑD|søé§Ðv  …‚¸u‹ÚØ8ÕÏ¿`>;U˜õûŸxøÌ©“ë½ÛM%r±­wëfßËуæíœá¬6(~v„¹�/Nšæ½C§Nü©hm;–L>êñô�‰§¥+ŸÇ©ÕÖ¥0q´x í·é€ÌεGö�¨‹½}><çÝ·»ZE�FÑ‚AŒT k¾€5_ÀYµñoÚ„ âÚòÀ.BŽ3´e&ߦ}¦a„íæ&œB�ÒÇ ïy#‘àŽtµ_®Ü~?‹ß~‡ùɧ´W–p•2;+Õ�:Ð¥"…¢i ‹G¿&òøcx;Ú1ö&X:ü�ŸOà]ZŸ¦áéÒÑ, -7ƒbø 07o¾±v½ñ ‚G¿ù/7W‚#¢”‹\wÊe¢SY"W®Ò|iŒ@(„÷d¶¦áƒCÿèu§ÁŠH^Utm´lÛeA4…¤{ÐÞ}g |ðxéÕu÷Ã÷°~lŸ�¢í,_‹4�«Á gk5áȬ*8Ï>³æùÐûëuŠ÷tSü8ÃêT¹¯‡ÚžAf•°àÑ�åâ±0Ò?б£-;vt-ѵs¹ E2R)ª—ÆX8w.ÿS[ë“Ó‰Øèz•¿ØÝ™´¬‘p:}·ÙÝ�ÈÍd×…êä$¥‰‰üédâÀ¯ÉøéL&S¹ öåî[Sµ•×�À�qWÊô65P/±~Ï-ë;ŸˆžNÄ®d2™Ê†o6¶ÌäÛ:+Õ�‘.GD­ˆä¯EšÆsñØ `1“ÉXÿâÿö_&ûј�IEND®B`‚TreeLine-3.2.1/icons/treeline-icon.png000066400000000000000000000045251506556630100176170ustar00rootroot00000000000000‰PNG  IHDR00Wù‡sBIT|dˆ pHYsÅʼnÖïtEXtSoftwarewww.inkscape.org›î<ÒIDATh�½š{pÔÕÇ?÷÷ÛG6›Ý¼7!H ѦSσxãÓ»ØQ÷¬A^ž»�…%·S’9‡4‡�pì,'Nïæ“¦ jÞ€&c:}E¨¬¼x³‹¾gÛŸ‹JóÅŽ¸{¤`n2’§Ã ûÒO…üô2Ò~6½ÉšƒËtºn5ƒ•k¹xÂM–öÚzkx£ú>mÛ¬“«Š‹‡æíc¢¿ÒšŒ`÷”<1Oœh‘•ªÂ'VzÁþV¶ÔüŽM¯s:tr„ A^z½ÑNzú;‡È;|Ü;w;“3gY„D²ù‹'xçóGuò‰þJš·UqYû 2C½oÕ¯,2Sø¤é-žÙ»˜ã;GϘé�t‰…t²[/y“ sMMI (ÏYÀñÎ� y°¯… w¥YÖ‰!5š ‹Í*÷Ÿz�?ú.}Ñ`JD⸴èff\7ª6×”?–p$Žm'þd˜#Ã!‹“FV´õÖð·#·"¥fhäs�á̳Ü|®*{`´ÜÉ(,ŸþbØÖÔªåHóF»f“@áHéæã�Ó;«“U•ÜÁ’²Ud§ ø+‘´÷Öp¤åöœ|‰SÁjʲ¯ Øÿµ19Pä›NEÞ޵¿—�m}×n!(õmR—ôôwðÐÖ Ä´HB¶¤l7|å)ÛÎë»÷ƒ”LɺtÌìmx…µ‡W$ʹž~»¸ÖRß1RðßÎí:òéÎl¾Yþ«¤OÉœ=Z®¦9ù;Buœ7$"?ÊHAMç.]¹"o n5c\È¥‚lO1>w�Nv:ô¥¥¾Á�ΰ^9•µ|¼‘å.Ò•»ûš,u )”Q硼íbZ?1¢Hq†Ï[6�?K7—ãéUQ… Uqëè5Yj`p oçI¢õ À@x³šÃ¬>Ÿ|-Ÿ‰Zz7L3×1¤P¨çße\e3¸p(*N'ås®ÆŸ7�W¸© c"©F b2úU+³%?à€ñqCŠÚë?cïýE§¢j)ó¿ÿB1:^PVÉ”ÊÔÚ1Ä«/dЋCgaäVT ¬/$C$UÑaÎÒ;MÉÇ1©B³�¦O?Í?êE•NœZNÕƒÃåNÎÈ$…¤þˆ¥ƒ?o¢­¹Ø¥^êm‰²;¿ÕRWç€×�KÈ¡?…†£A<ÎLÛÍ�H+“ð8=öÏ'=±N4÷Ðx½y–ºº¡s92 W¸æ³ÇR ;º$C]÷>]9'½ÄRW׳@pAö×u G[ÞMÞ£Ù$°sÀ¦®#TGuë¿t²©9Ö¯›†¡›ž�®¼»á¥¤×JaýÄjºBY¡1x”>þ61mhCóºr¸0w¡eƒ•…7èRâL_3ë«oCb=jf+Šm �¨«ëÚÇovVðć39¬ÖÕ-œr§íqÞÐsÀ[nxTú¸q=ëÿÄšÐh×ÑP…ƒ–³Ÿä%Y—ñ�©Û¶5]Œ¿óÕg —ŠÒl»w/3FÙ4…F'ß;Õ R–=�ŸÏÞ„C±_ÆMð¹òù鬿'^Êsª˜7ùVK#B1Ù‰mR(¾KÇ‘æðãsÈO/cù´g¹gîvà šÁp˜‹£,û îžók¯à–™«G=Q‡æQjéõƒÊ—˜à›F®§$%ý8@`º³”f_ΣUÇP…¥ŸƒÍ°&n�é�k홚£G¬/œ�”<`:‰íÎ:ã �Š€†s5d¶ i}”°ÝäFÓ/4(l;wK&$mRÿ\Žº.$[5ÆÛã`ÊDd�q‚TÙ¨Š£Höœ‹!Å,ßíˆ�OvMÉŸ*šÊ}¶—Ô>ÛeYg¶í|åqª·½NWKýX»�U0¸”æŠ�ê[å+VØ·2"ÒbÿÛ/ä¦÷äAúç_¿s&•S±àF¦/ZŽ?`þþ9RðrI�ØÃ62­‡ÛT/¥ò­,Žp°‹·ŸZIk½ñÎ0t¡±·ÑÙpœ]ëŸf÷k¿§¤²ŠŠª¥ø“�é 3PLA™á;Ù5Äí‰~†×œh‘ŠÂÆT>·žØ¿…ÍÏý’žÓýÒý¹x2sðdäàñçpÃàµîG·¬'ì ·«�Pw=Ý„‚�hш©m ˜Ë—ÝËŒ«nÑ¥ �|Ô¯qýÔB‘¸cšÿÕÀÇ HVZ‘o¯ÿŒ¦ãÉ.º€Ìüb¼Ygêo@q„ƒ]œio »µ-Ú�‚¬ÂòK§æŽ¼,ƒüÂö¯Ãq²]ÎÑ$O ¬tþ�°W‘<89 L¿c']¤O6ËRá:)¸RÂÄÁojçíï64 É8Ø49GTÛ5øùMë:MØí²IEND®B`‚TreeLine-3.2.1/icons/treeline-icon.svg000066400000000000000000000146401506556630100176310ustar00rootroot00000000000000 image/svg+xml   TreeLine-3.2.1/install.py000077500000000000000000000373511506556630100152670ustar00rootroot00000000000000#!/usr/bin/env python3 """ **************************************************************************** install.py, Linux install script for TreeLine Copyright (C) 2025, Douglas W. Bell This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, either Version 2 or any later version. This program is distributed in the hope that it will be useful, but WITTHOUT ANY WARRANTY. See the included LICENSE file for details. ***************************************************************************** """ import sys import os.path import getopt import shutil import compileall import py_compile import glob import re import subprocess prefixDir = '/usr/local' buildRoot = '/' progName = 'treeline' docDir = 'share/doc/{0}'.format(progName) templateDir = 'share/{0}/templates'.format(progName) iconToolDir = 'share/icons/{0}'.format(progName) testSpell = True def usage(exitCode=2): """Display usage info and exit. Arguments: exitCode -- the code to retuen when exiting. """ global prefixDir global buildRoot print('Usage:') print(' python install.py [-h] [-p dir] [-d dir] [-t dir] [-i dir] ' '[-b dir] [-s] [-x]') print('where:') print(' -h display this help message') print(' -p dir install prefix [default: {0}]'.format(prefixDir)) print(' -d dir documentaion dir [default: /{0}]' .format(docDir)) print(' -t dir template dir [default: /{0}]' .format(templateDir)) print(' -i dir tool icon dir [default: /{0}]' .format(iconToolDir)) print(' -b dir temporary build root for packagers [default: {0}]' .format(buildRoot)) print(' -s skip language translation files') print(' -x skip all dependency checks (risky)') sys.exit(exitCode) def cmpVersions(versionStr, reqdTuple): """Return True if point-sep values in versionStr are >= reqdTuple. Arguments: versionStr -- a string with point-separated version numbers reqdTuple -- a tuple of version integers for the minimum acceptable """ match = re.search(r'[0-9\.]+', versionStr) if not match: return False versionStr = match.group() versionList = [int(val) for val in versionStr.split('.') if val] reqdList = list(reqdTuple) while len(versionList) < len(reqdList): versionList.append(0) while len(reqdList) < len(versionList): reqdList.append(0) if versionList >= reqdList: return True return False def copyDir(srcDir, dstDir): """Copy all regular files from srcDir to dstDir. dstDir is created if necessary. Arguments: srcDir -- the source dir path dstDir -- the destination dir path """ try: if not os.path.isdir(dstDir): os.makedirs(dstDir) names = os.listdir(srcDir) for name in names: srcPath = os.path.join(srcDir, name) if os.path.isfile(srcPath): shutil.copy2(srcPath, os.path.join(dstDir, name)) except (IOError, OSError) as e: if str(e).find('Permission denied') >= 0: print('Error - must be root to install files') cleanSource() sys.exit(4) raise def createWrapper(execDir, execName): """Create a wrapper executable file for a python script in execDir. Arguments: execDir -- the path where the executable is placed execName -- the name for the executable file """ text = '#!/bin/sh\n\nexec {0} {1}/{2}.py "$@"'.format(sys.executable, execDir, execName) with open(execName, 'w') as f: f.write(text) os.chmod(execName, 0o755) def replaceLine(path, origLineStart, newLine): """Replaces lines with origLineStart with newLine and rewrites the file. Arguments: path -- the file to modify origLineStart -- the beginning of the line to be replaced newLine -- the replacement line """ with open(path, 'r') as f: lines = f.readlines() with open(path, 'w') as f: for line in lines: if line.startswith(origLineStart): f.write(newLine) else: f.write(line) def spellCheck(cmdList): """Try spell checkers from list, print result. Arguments: cmdList -- a list of spell checkers to check """ for cmd in cmdList: try: p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p.stdout.readline() p.stdin.write(b'!\n') p.stdin.flush() p.stdin.close() p.stdout.close() print(' Spell Checker {0} -> OK'.format(cmd.split()[0])) return except: pass print(' Spell Checker not found -> install aspell, ispell or hunspell') print(' if spell checking is desired') def cleanSource(): """Remove any temporary files added to untarred dirs. """ for name in glob.glob(os.path.join('source', '*.py[co]')): os.remove(name) removeDir(os.path.join('source', '__pycache__')) global progName if os.path.isfile(progName): os.remove(progName) def removeDir(dir): """Remove dir and all files under it, ignore errors. Arguments: dir -- the directory to remove """ try: shutil.rmtree(dir, 1) except: # shouldn't be needed with ignore error param, but pass # some python versions have a bug def main(): """Main installer function. """ optLetters = 'hp:d:t:i:b:sx' try: opts, args = getopt.getopt(sys.argv[1:], optLetters) except getopt.GetoptError: usage(2) global prefixDir global docDir global templateDir global iconToolDir global buildRoot global progName depCheck = True translated = True for opt, val in opts: if opt == '-h': usage(0) elif opt == '-p': prefixDir = os.path.abspath(val) elif opt == '-d': docDir = val elif opt == '-t': templateDir = val elif opt == '-i': iconToolDir = val elif opt == '-b': buildRoot = val elif opt == '-s': translated = False elif opt == '-x': depCheck = False if not os.path.isfile('install.py'): print('Error - {0} files not found'.format(progName)) print('The directory containing "install.py" must be current') sys.exit(4) if (os.path.isdir('source') and not os.path.isfile('source/{0}.py'.format(progName))): print('Error - source files not found') print('Retry the extraction from the tar archive') sys.exit(4) if depCheck: print('Checking dependencies...') pyVersion = sys.version_info[:3] pyVersion = '.'.join([str(num) for num in pyVersion]) if cmpVersions(pyVersion, (3, 9)): print(' Python Version {0} -> OK'.format(pyVersion)) else: print(' Python Version {0} -> Sorry, 3.9 or higher is required' .format(pyVersion)) sys.exit(3) try: from PyQt6 import QtCore, QtWidgets except: print(' PyQt not found -> Sorry, PyQt 6.4 or higher is required' ' and must be built for Python 3') sys.exit(3) qtVersion = QtCore.qVersion() if cmpVersions(qtVersion, (6, 4)): print(' Qt Version {0} -> OK'.format(qtVersion)) else: print(' Qt Version {0} -> Sorry, 6.4 or higher is required' .format(qtVersion)) sys.exit(3) pyqtVersion = QtCore.PYQT_VERSION_STR if cmpVersions(pyqtVersion, (6, 4)): print(' PyQt Version {0} -> OK'.format(pyqtVersion)) else: print(' PyQt Version {0} -> Sorry, 6.4 or higher is required' .format(pyqtVersion)) sys.exit(3) global testSpell if testSpell: spellCheck(['aspell -a', 'ispell -a', 'hunspell -a']) pythonPrefixDir = os.path.join(prefixDir, 'share', progName) pythonBuildDir = os.path.join(buildRoot, pythonPrefixDir[1:]) if os.path.isdir('source'): print('Installing files...') print(' Copying python files to {0}'.format(pythonBuildDir)) removeDir(pythonBuildDir) # remove old? copyDir('source', pythonBuildDir) if os.path.isfile('source/plugininterface.py'): pluginBuildDir = os.path.join(pythonBuildDir, 'plugins') print(' Creating plugins directory if necessary') if not os.path.isdir(pluginBuildDir): os.makedirs(pluginBuildDir) if os.path.isdir('translations') and translated: translationDir = os.path.join(pythonBuildDir, 'translations') print(' Copying translation files to {0}'.format(translationDir)) copyDir('translations', translationDir) if os.path.isdir('doc'): docPrefixDir = docDir.replace('/', '') if not os.path.isabs(docPrefixDir): docPrefixDir = os.path.join(prefixDir, docPrefixDir) docBuildDir = os.path.join(buildRoot, docPrefixDir[1:]) print(' Copying documentation files to {0}'.format(docBuildDir)) copyDir('doc', docBuildDir) if not translated: for name in glob.glob(os.path.join(docBuildDir, '*_[a-z][a-z].')): os.remove(name) # update help file location in main python script replaceLine(os.path.join(pythonBuildDir, '{0}.py'.format(progName)), 'docPath = None', 'docPath = \'{0}\' # modified by install script\n' .format(docPrefixDir)) if os.path.isdir('samples'): sampleBuildDir = os.path.join(docBuildDir, 'samples') print(' Copying sample files to {0}'.format(sampleBuildDir)) copyDir('samples', sampleBuildDir) # update sample file location in main python script replaceLine(os.path.join(pythonBuildDir, '{0}.py'.format(progName)), 'samplePath = None', 'samplePath = \'{0}\' # modified by install script\n' .format(os.path.join(docPrefixDir, 'samples'))) if os.path.isdir('templates'): templatePrefixDir = templateDir.replace('/', '') if not os.path.isabs(templatePrefixDir): templatePrefixDir = os.path.join(prefixDir, templatePrefixDir) templateBuildDir = os.path.join(buildRoot, templatePrefixDir[1:]) print(' Copying template files to {0}'.format(templateBuildDir)) copyDir('templates', templateBuildDir) if not translated: for name in glob.glob(os.path.join(templateBuildDir, '*.trl')): if 'en_' not in os.path.basename(name): os.remove(name) # update template file location in main python script replaceLine(os.path.join(pythonBuildDir, '{0}.py'.format(progName)), 'templatePath = None', 'templatePath = \'{0}\' # modified by install script\n' .format(templatePrefixDir)) if os.path.isdir('templates/exports'): exportsBuildDir = os.path.join(templateBuildDir, 'exports') copyDir('templates/exports', exportsBuildDir) if os.path.isdir('data'): dataPrefixDir = os.path.join(prefixDir, 'share', progName, 'data') dataBuildDir = os.path.join(buildRoot, dataPrefixDir[1:]) print(' Copying data files to {0}'.format(dataBuildDir)) removeDir(dataBuildDir) # remove old? copyDir('data', dataBuildDir) if not translated: for name in glob.glob(os.path.join(dataBuildDir, '*_[a-z][a-z].dat')): os.remove(name) # update data file location in main python script replaceLine(os.path.join(pythonBuildDir, '{0}.py'.format(progName)), 'dataFilePath = None', 'dataFilePath = \'{0}\' # modified by install script\n' .format(dataPrefixDir)) if os.path.isdir('icons'): iconPrefixDir = iconToolDir.replace('/', '') if not os.path.isabs(iconPrefixDir): iconPrefixDir = os.path.join(prefixDir, iconPrefixDir) iconBuildDir = os.path.join(buildRoot, iconPrefixDir[1:]) print(' Copying tool icon files to {0}'.format(iconBuildDir)) copyDir('icons', iconBuildDir) # update icon location in main python script replaceLine(os.path.join(pythonBuildDir, '{0}.py'.format(progName)), 'iconPath = None', 'iconPath = \'{0}\' # modified by install script\n' .format(iconPrefixDir)) if os.path.isdir('icons/toolbar'): iconToolBuildDir = os.path.join(iconBuildDir, 'toolbar') copyDir('icons/toolbar', iconToolBuildDir) if os.path.isdir('icons/toolbar/16x16'): copyDir('icons/toolbar/16x16', os.path.join(iconToolBuildDir, '16x16')) if os.path.isdir('icons/toolbar/32x32'): copyDir('icons/toolbar/32x32', os.path.join(iconToolBuildDir, '32x32')) if os.path.isdir('icons/tree'): copyDir('icons/tree', os.path.join(iconBuildDir, 'tree')) if os.path.isfile(os.path.join('icons', progName + '-icon.png')): pngIconPrefixDir = os.path.join(prefixDir, 'share', 'icons', 'hicolor', '48x48', 'apps') pngIconBuildDir = os.path.join(buildRoot, pngIconPrefixDir[1:]) print(' Copying app icon files to {0}'.format(pngIconBuildDir)) if not os.path.isdir(pngIconBuildDir): os.makedirs(pngIconBuildDir) shutil.copy2(os.path.join('icons', progName + '-icon.png'), pngIconBuildDir) if os.path.isfile(os.path.join('icons', progName + '-icon.svg')): svgIconPrefixDir = os.path.join(prefixDir, 'share', 'icons', 'hicolor', 'scalable', 'apps') svgIconBuildDir = os.path.join(buildRoot, svgIconPrefixDir[1:]) print(' Copying app icon files to {0}'.format(svgIconBuildDir)) if not os.path.isdir(svgIconBuildDir): os.makedirs(svgIconBuildDir) shutil.copy2(os.path.join('icons', progName + '-icon.svg'), svgIconBuildDir) if os.path.isfile(progName + '.desktop'): desktopPrefixDir = os.path.join(prefixDir, 'share', 'applications') desktopBuildDir = os.path.join(buildRoot, desktopPrefixDir[1:]) print(' Copying desktop file to {0}'.format(desktopBuildDir)) if not os.path.isdir(desktopBuildDir): os.makedirs(desktopBuildDir) shutil.copy2(progName + '.desktop', desktopBuildDir) if os.path.isdir('source'): createWrapper(pythonPrefixDir, progName) binBuildDir = os.path.join(buildRoot, prefixDir[1:], 'bin') print(' Copying executable file "{0}" to {1}' .format(progName, binBuildDir)) if not os.path.isdir(binBuildDir): os.makedirs(binBuildDir) shutil.copy2(progName, binBuildDir) compileall.compile_dir(pythonBuildDir, ddir=prefixDir) cleanSource() print('Install complete.') if __name__ == '__main__': main() TreeLine-3.2.1/samples/000077500000000000000000000000001506556630100146775ustar00rootroot00000000000000TreeLine-3.2.1/samples/110en_sample_basic_longtext.trln000066400000000000000000000073221506556630100230560ustar00rootroot00000000000000{ "formats": [ { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Text", "fieldtype": "HtmlText", "lines": 12 } ], "formathtml": true, "formatname": "HTML_TEXT", "outputlines": [ "{*Name*}", "{*Text*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Text", "fieldtype": "Text", "lines": 12 } ], "formathtml": true, "formatname": "REGULAR_TEXT", "outputlines": [ "{*Name*}", "{*Text*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formatname": "ROOT", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Text", "fieldtype": "SpacedText", "lines": 12 } ], "formathtml": true, "formatname": "SPACED_TEXT", "outputlines": [ "{*Name*}{*Text*}" ], "titleline": "{*Name*}" } ], "nodes": [ { "children": [ "ed02751e95a311e79cb17054d2175f18", "ed02771c95a311e79cb17054d2175f18", "ed027aaa95a311e79cb17054d2175f18", "ed027f0095a311e79cb17054d2175f18" ], "data": { "Name": "Text Fields" }, "format": "ROOT", "uid": "ed0270d295a311e79cb17054d2175f18" }, { "children": [], "data": { "Name": "Similar to Treepad", "Text": "This file provides a single long text field for each node. This is similar to how the Treepad program on windows is usually used." }, "format": "REGULAR_TEXT", "uid": "ed02751e95a311e79cb17054d2175f18" }, { "children": [], "data": { "Name": "Regular text field", "Text": "The most commonly used field type is regular text. Formatting such as bold, italics, font sizes and font colors can be used from the Edit menu.
    \n
    \nIt preserves carriage return spaces, but not multiple spaces within a line." }, "format": "REGULAR_TEXT", "uid": "ed02771c95a311e79cb17054d2175f18" }, { "children": [], "data": { "Name": "HTML text field", "Text": "An HTML field allows tags such as italics to be added manually.\n\nIt does not preserve white space.\n\nCharacters like <, >, and & must be escaped." }, "format": "HTML_TEXT", "uid": "ed027aaa95a311e79cb17054d2175f18" }, { "children": [], "data": { "Name": "Spaced text field", "Text": "A spaced text field preserves all white space.\n\nIt does not allow character formatting." }, "format": "SPACED_TEXT", "uid": "ed027f0095a311e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "ed0270d295a311e79cb17054d2175f18" ] } }TreeLine-3.2.1/samples/120en_sample_basic_contacts.trln000066400000000000000000000143261506556630100230330ustar00rootroot00000000000000{ "formats": [ { "fields": [ { "fieldname": "FirstName", "fieldtype": "Text" }, { "fieldname": "LastName", "fieldtype": "Text" }, { "fieldname": "Street", "fieldtype": "Text" }, { "fieldname": "City", "fieldtype": "Text" }, { "fieldname": "State", "fieldtype": "Text" }, { "fieldname": "Zip", "fieldtype": "Text" }, { "fieldname": "HomePhone", "fieldtype": "Text" }, { "fieldname": "WorkPhone", "fieldtype": "Text" }, { "fieldname": "MobilePhone", "fieldtype": "Text" }, { "fieldname": "Birthday", "fieldtype": "Date", "format": "%B %-d, %Y" }, { "fieldname": "Email", "fieldtype": "ExternalLink" } ], "formatname": "PERSON", "outputlines": [ "{*FirstName*} {*LastName*}", "{*Street*}", "{*City*}, {*State*} {*Zip*}", "{*HomePhone*} (H)", "{*WorkPhone*} (W)", "{*MobilePhone*} (M)", "DoB: {*Birthday*}", "{*Email*}" ], "titleline": "{*FirstName*} {*LastName*}" }, { "childtype": "TYPE", "fields": [ { "fieldname": "NAME", "fieldtype": "Text" } ], "formatname": "ROOT", "outputlines": [ "{*NAME*}" ], "titleline": "{*NAME*}" }, { "childtype": "PERSON", "fields": [ { "fieldname": "Type", "fieldtype": "Text" } ], "formathtml": true, "formatname": "TYPE", "outputlines": [ "


    {*Type*}" ], "titleline": "{*Type*}" } ], "nodes": [ { "children": [ "fc702b0e95a311e79cb17054d2175f18", "fc703cc095a311e79cb17054d2175f18", "fc70413e95a311e79cb17054d2175f18" ], "data": { "NAME": "Main" }, "format": "ROOT", "uid": "fc7025d295a311e79cb17054d2175f18" }, { "children": [ "fc70345a95a311e79cb17054d2175f18", "fc703af495a311e79cb17054d2175f18" ], "data": { "Type": "Friends" }, "format": "TYPE", "uid": "fc702b0e95a311e79cb17054d2175f18" }, { "children": [], "data": { "Birthday": "2004-11-30", "City": "Nina", "Email": "bill@pinta.com", "FirstName": "Bill", "HomePhone": "(703) 555-5647", "LastName": "Smith", "State": "SC", "Street": "1492 Columbus Drive", "Zip": "35762" }, "format": "PERSON", "uid": "fc70345a95a311e79cb17054d2175f18" }, { "children": [], "data": { "Birthday": "1905-05-08", "City": "Harbor City", "Email": "jj@battleship.org", "FirstName": "John", "HomePhone": "(401) 555-8923", "LastName": "Johnson", "MobilePhone": "(703) 555-2873", "State": "HI", "Street": "1941 Pearl Street", "WorkPhone": "(506) 555-7413", "Zip": "86741" }, "format": "PERSON", "uid": "fc703af495a311e79cb17054d2175f18" }, { "children": [ "fc703e0a95a311e79cb17054d2175f18", "fc703fae95a311e79cb17054d2175f18" ], "data": { "Type": "Family" }, "format": "TYPE", "uid": "fc703cc095a311e79cb17054d2175f18" }, { "children": [], "data": { "Birthday": "1901-07-30", "City": "Dogbone", "Email": "jdoe@spots.net", "FirstName": "Jane", "LastName": "Doe", "MobilePhone": "(654) 555-8527", "State": "SD", "Street": "101 Dalmation Way", "Zip": "52782" }, "format": "PERSON", "uid": "fc703e0a95a311e79cb17054d2175f18" }, { "children": [], "data": { "Birthday": "1999-08-14", "City": "Undersea", "Email": "johndoe@subs.com", "FirstName": "John", "HomePhone": "(805) 555-7296", "LastName": "Doe", "MobilePhone": "(503) 555-8234", "State": "NY", "Street": "20000 Leagues Street", "WorkPhone": "(777) 555-9999", "Zip": "12763" }, "format": "PERSON", "uid": "fc703fae95a311e79cb17054d2175f18" }, { "children": [ "fc70427495a311e79cb17054d2175f18", "fc7043b495a311e79cb17054d2175f18" ], "data": { "Type": "Work" }, "format": "TYPE", "uid": "fc70413e95a311e79cb17054d2175f18" }, { "children": [], "data": { "FirstName": "Dil", "LastName": "Bert", "WorkPhone": "(501) 555-5612" }, "format": "PERSON", "uid": "fc70427495a311e79cb17054d2175f18" }, { "children": [], "data": { "FirstName": "Pointy-haired", "LastName": "Boss", "WorkPhone": "(666) 555-8945" }, "format": "PERSON", "uid": "fc7043b495a311e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "fc7025d295a311e79cb17054d2175f18" ] } }TreeLine-3.2.1/samples/130en_sample_basic_booklist.trln000066400000000000000000000123451506556630100230430ustar00rootroot00000000000000{ "formats": [ { "childtype": "BOOK", "fields": [ { "fieldname": "AuthorFirstName", "fieldtype": "Text" }, { "fieldname": "AuthorLastName", "fieldtype": "Text" }, { "fieldname": "WebSite", "fieldtype": "ExternalLink", "prefix": "<", "suffix": ">" } ], "formatname": "AUTHOR", "icon": "book_1", "outputlines": [ "{*AuthorFirstName*} {*AuthorLastName*} {*WebSite*}" ], "titleline": "{*AuthorFirstName*} {*AuthorLastName*}" }, { "fields": [ { "fieldname": "Title", "fieldtype": "Text" }, { "fieldname": "Copyright", "fieldtype": "Number", "format": "0000" }, { "fieldname": "Own", "fieldtype": "Boolean", "format": "yes/no" }, { "fieldname": "ReadDate", "fieldtype": "Date", "format": "%-%-M/%-d/%Y" }, { "fieldname": "Rating", "fieldtype": "Choice", "format": "1/2/3/4/5" }, { "fieldname": "Plot", "fieldtype": "Text", "lines": 7 } ], "formatname": "BOOK", "icon": "book_3", "outputlines": [ "\"{*Title*}\"", "(c) {*Copyright*}, Own: {*Own*}", "Last Read: {*ReadDate*}, Rating: {*Rating*}", "{*Plot*}" ], "titleline": "\"{*Title*}\"" }, { "childtype": "AUTHOR", "fields": [ { "fieldname": "NAME", "fieldtype": "Text" } ], "formatname": "ROOT", "outputlines": [ "{*NAME*}" ], "titleline": "{*NAME*}" } ], "nodes": [ { "children": [ "0bf4f2ee95a411e79cb17054d2175f18", "0bf4ffbe95a411e79cb17054d2175f18" ], "data": { "NAME": "SF Books" }, "format": "ROOT", "uid": "0bf4eeb695a411e79cb17054d2175f18" }, { "children": [ "0bf4f8ca95a411e79cb17054d2175f18", "0bf4fe8895a411e79cb17054d2175f18" ], "data": { "AuthorFirstName": "Greg", "AuthorLastName": "Bear", "WebSite": "www.gregbear.com" }, "format": "AUTHOR", "uid": "0bf4f2ee95a411e79cb17054d2175f18" }, { "children": [], "data": { "Own": "false", "Plot": "Evolution caused by virus begining again", "Rating": "4", "ReadDate": "2000-10-01", "Title": "Darwin's Radio" }, "format": "BOOK", "uid": "0bf4f8ca95a411e79cb17054d2175f18" }, { "children": [], "data": { "Copyright": "1985", "Own": "true", "Plot": "Smart viruses take over", "Rating": "2", "ReadDate": "1998-07-01", "Title": "Blood Music" }, "format": "BOOK", "uid": "0bf4fe8895a411e79cb17054d2175f18" }, { "children": [ "0bf500c295a411e79cb17054d2175f18", "0bf501da95a411e79cb17054d2175f18", "0bf502de95a411e79cb17054d2175f18" ], "data": { "AuthorFirstName": "Orson Scott", "AuthorLastName": "Card", "WebSite": "www.hatrack.com" }, "format": "AUTHOR", "uid": "0bf4ffbe95a411e79cb17054d2175f18" }, { "children": [], "data": { "Copyright": "1996", "Own": "Yes", "Plot": "Time travel to change history; discovery of America", "Rating": "4", "ReadDate": "1998-09-01", "Title": "Pastwatch, The Redemption of Christopher Columbus" }, "format": "BOOK", "uid": "0bf500c295a411e79cb17054d2175f18" }, { "children": [], "data": { "Copyright": "1999", "Own": "Yes", "Plot": "Boy travels back to Russian fairy tale", "Rating": "5", "ReadDate": "2000-08-01", "Title": "Enchantment" }, "format": "BOOK", "uid": "0bf501da95a411e79cb17054d2175f18" }, { "children": [], "data": { "Copyright": "1999", "Own": "Yes", "Plot": "Ender's Game from Bean's perspective", "Rating": "5", "ReadDate": "2001-05-01", "Title": "Ender's Shadow" }, "format": "BOOK", "uid": "0bf502de95a411e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "0bf4eeb695a411e79cb17054d2175f18" ] } }TreeLine-3.2.1/samples/140en_sample_genealogy.trln000066400000000000000000000162061506556630100220270ustar00rootroot00000000000000{ "formats": [ { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Birth", "fieldtype": "Date", "format": "%B %-d, %Y" }, { "fieldname": "Death", "fieldtype": "Date", "format": "%B %-d, %Y" }, { "fieldname": "Location", "fieldtype": "Text" } ], "formatname": "MEMBER", "outputlines": [ "{*Name*}", "Born: {*Birth*}", "Died: {*Death*}", "Where: {*Location*}" ], "titleline": "{*Name*}" } ], "nodes": [ { "children": [ "5086f03aaf3a11e7a6243417ebd53aeb", "959dd4e8af3a11e7a4263417ebd53aeb", "a19ee912af3a11e79a1a3417ebd53aeb", "a3ed3f0aaf3a11e799293417ebd53aeb" ], "data": { "Birth": "1935-05-04", "Location": "St. Louis, MO", "Name": "Grandma Jones" }, "format": "MEMBER", "uid": "0ec2773aaf3a11e79eea3417ebd53aeb" }, { "children": [ "4b6295b4af3a11e7beaa3417ebd53aeb", "7c6a86deaf3a11e795c23417ebd53aeb", "8630c54caf3a11e7b24c3417ebd53aeb" ], "data": { "Birth": "1935-07-30", "Location": "Las Vegas, NV", "Name": "Grandpa Smith" }, "format": "MEMBER", "uid": "1b0fdaefaf3911e785d43417ebd53aeb" }, { "children": [], "data": { "Birth": "1992-07-15", "Location": "Denver, CO", "Name": "Linda" }, "format": "MEMBER", "uid": "3096a564af3b11e7b9a63417ebd53aeb" }, { "children": [], "data": { "Birth": "1995-02-14", "Location": "Boston, MA", "Name": "Billy" }, "format": "MEMBER", "uid": "35eb10b6af3b11e7b0593417ebd53aeb" }, { "children": [ "f571c05eaf3a11e793b33417ebd53aeb", "3096a564af3b11e7b9a63417ebd53aeb", "35eb10b6af3b11e7b0593417ebd53aeb" ], "data": { "Birth": "1960-08-16", "Location": "Dallas, TX", "Name": "Papa" }, "format": "MEMBER", "uid": "4b6295b4af3a11e7beaa3417ebd53aeb" }, { "children": [ "f571c05eaf3a11e793b33417ebd53aeb", "3096a564af3b11e7b9a63417ebd53aeb", "35eb10b6af3b11e7b0593417ebd53aeb" ], "data": { "Birth": "1962-02-10", "Location": "Dallas, TX", "Name": "Mama" }, "format": "MEMBER", "uid": "5086f03aaf3a11e7a6243417ebd53aeb" }, { "children": [], "data": { "Birth": "1985-12-25", "Location": "Phoenix, AZ", "Name": "Cousin Jimmy" }, "format": "MEMBER", "uid": "7baaa7baaf3b11e7bf9a3417ebd53aeb" }, { "children": [], "data": { "Birth": "2062-06-23", "Location": "Pittsburgh, PA", "Name": "Uncle Mike" }, "format": "MEMBER", "uid": "7c6a86deaf3a11e795c23417ebd53aeb" }, { "children": [], "data": { "Birth": "1987-08-31", "Location": "Houston, TX", "Name": "Cousin Dave" }, "format": "MEMBER", "uid": "81d4264aaf3b11e7b17f3417ebd53aeb" }, { "children": [ "7baaa7baaf3b11e7bf9a3417ebd53aeb", "81d4264aaf3b11e7b17f3417ebd53aeb" ], "data": { "Birth": "2065-12-08", "Location": "Cleveland, OH", "Name": "Aunt Mary" }, "format": "MEMBER", "uid": "8630c54caf3a11e7b24c3417ebd53aeb" }, { "children": [], "data": { "Birth": "1984-10-05", "Location": "New York, NY", "Name": "Cousin Joe" }, "format": "MEMBER", "uid": "916e641eaf3b11e78c293417ebd53aeb" }, { "children": [], "data": { "Birth": "2064-06-05", "Location": "Los Angelos, CA", "Name": "Aunt Patty" }, "format": "MEMBER", "uid": "959dd4e8af3a11e7a4263417ebd53aeb" }, { "children": [], "data": { "Birth": "1990-07-20", "Location": "Bar Harbor, ME", "Name": "Cousin Susan" }, "format": "MEMBER", "uid": "9bba64f8af3b11e78b123417ebd53aeb" }, { "children": [ "916e641eaf3b11e78c293417ebd53aeb", "9bba64f8af3b11e78b123417ebd53aeb" ], "data": { "Birth": "2067-11-10", "Location": "Philadelphia, PA", "Name": "Aunt Jenny" }, "format": "MEMBER", "uid": "a19ee912af3a11e79a1a3417ebd53aeb" }, { "children": [ "a4371f0caf3b11e7ac8b3417ebd53aeb" ], "data": { "Birth": "1969-05-31", "Location": "Baltimore, MD", "Name": "Uncle Bobby" }, "format": "MEMBER", "uid": "a3ed3f0aaf3a11e799293417ebd53aeb" }, { "children": [], "data": { "Birth": "1980-06-25", "Location": "Wilmington, NC", "Name": "Cousin Steve" }, "format": "MEMBER", "uid": "a4371f0caf3b11e7ac8b3417ebd53aeb" }, { "children": [ "4b6295b4af3a11e7beaa3417ebd53aeb", "7c6a86deaf3a11e795c23417ebd53aeb", "8630c54caf3a11e7b24c3417ebd53aeb" ], "data": { "Birth": "1937-04-12", "Location": "Las Vegas, NV", "Name": "Grandma Smith" }, "format": "MEMBER", "uid": "d3b3f1c8af3911e79f6f3417ebd53aeb" }, { "children": [ "5086f03aaf3a11e7a6243417ebd53aeb", "959dd4e8af3a11e7a4263417ebd53aeb", "a19ee912af3a11e79a1a3417ebd53aeb", "a3ed3f0aaf3a11e799293417ebd53aeb" ], "data": { "Birth": "1932-09-17", "Location": "St. Louis, MO", "Name": "Grandpa Jones" }, "format": "MEMBER", "uid": "f0f4f1f4af3911e790383417ebd53aeb" }, { "children": [], "data": { "Birth": "1989-05-31", "Location": "San Francisco, CA", "Name": "Me" }, "format": "MEMBER", "uid": "f571c05eaf3a11e793b33417ebd53aeb" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "1b0fdaefaf3911e785d43417ebd53aeb", "d3b3f1c8af3911e79f6f3417ebd53aeb", "f0f4f1f4af3911e790383417ebd53aeb", "0ec2773aaf3a11e79eea3417ebd53aeb" ] } }TreeLine-3.2.1/samples/210en_sample_char_format.trln000066400000000000000000000057401506556630100223410ustar00rootroot00000000000000{ "formats": [ { "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formatname": "ROOT", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "TOPIC", "fieldtype": "Text" }, { "fieldname": "TEXT", "fieldtype": "Text", "lines": 7 } ], "formathtml": true, "formatname": "TEXT_PARA", "icon": "doc", "outputlines": [ "{*TOPIC*}", "{*TEXT*}" ], "titleline": "{*TOPIC*}" } ], "nodes": [ { "children": [ "14e55e4895a411e79cb17054d2175f18", "14e5604695a411e79cb17054d2175f18", "14e5616895a411e79cb17054d2175f18", "14e5626c95a411e79cb17054d2175f18", "14e5635c95a411e79cb17054d2175f18" ], "data": { "Name": "Character Format Examples" }, "format": "ROOT", "uid": "14e559fc95a411e79cb17054d2175f18" }, { "children": [], "data": { "TEXT": "All titles can be set to bold by adding <b>...</b> tags in the Configure Data Types dialog's Output tab. The \"Allow HTML rich text in format\" option must also be checked in the Type Config tab.", "TOPIC": "Bold Titles" }, "format": "TEXT_PARA", "uid": "14e55e4895a411e79cb17054d2175f18" }, { "children": [], "data": { "TEXT": "Font formatting commands can be found in the Edit menu and in the right-click context menu in the \"Data Editor\" view.", "TOPIC": "Bold Text" }, "format": "TEXT_PARA", "uid": "14e5604695a411e79cb17054d2175f18" }, { "children": [], "data": { "TEXT": "Text can also be set to various colors.", "TOPIC": "Colored Text" }, "format": "TEXT_PARA", "uid": "14e5616895a411e79cb17054d2175f18" }, { "children": [], "data": { "TEXT": "Large text and small text", "TOPIC": "Font Size" }, "format": "TEXT_PARA", "uid": "14e5626c95a411e79cb17054d2175f18" }, { "children": [], "data": { "TEXT": "Text in italics and even text underlined", "TOPIC": "Italics and Underline" }, "format": "TEXT_PARA", "uid": "14e5635c95a411e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "14e559fc95a411e79cb17054d2175f18" ] } }TreeLine-3.2.1/samples/220en_sample_bookmarks.trln000066400000000000000000000304471506556630100220470ustar00rootroot00000000000000{ "formats": [ { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Link", "fieldtype": "ExternalLink" } ], "formatname": "BOOKMARK", "icon": "bookmark", "outputlines": [ "{*Name*}", "{*Link*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formatname": "FOLDER", "icon": "folder_3", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "SEPARATOR", "outputlines": [ "
    " ], "titleline": "------------------" } ], "nodes": [ { "children": [ "25608cd495a411e79cb17054d2175f18", "25609bde95a411e79cb17054d2175f18", "2560aca095a411e79cb17054d2175f18", "2560b66495a411e79cb17054d2175f18" ], "data": { "Name": "Bookmarks Menu" }, "format": "FOLDER", "uid": "25608acc95a411e79cb17054d2175f18" }, { "children": [ "25608df695a411e79cb17054d2175f18", "2560970695a411e79cb17054d2175f18" ], "data": { "Name": "Information" }, "format": "FOLDER", "uid": "25608cd495a411e79cb17054d2175f18" }, { "children": [ "256091c095a411e79cb17054d2175f18", "256093e695a411e79cb17054d2175f18", "256094f495a411e79cb17054d2175f18", "2560960295a411e79cb17054d2175f18" ], "data": { "Name": "News" }, "format": "FOLDER", "uid": "25608df695a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.abcnews.com/", "Name": "ABC News" }, "format": "BOOKMARK", "uid": "256091c095a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.cnn.com/", "Name": "CNN.com" }, "format": "BOOKMARK", "uid": "256093e695a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.usatoday.com/", "Name": "USA Today" }, "format": "BOOKMARK", "uid": "256094f495a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://washingtonpost.com/", "Name": "WashingtonPost" }, "format": "BOOKMARK", "uid": "2560960295a411e79cb17054d2175f18" }, { "children": [ "256097f695a411e79cb17054d2175f18", "256098f095a411e79cb17054d2175f18", "256099e095a411e79cb17054d2175f18", "25609ad095a411e79cb17054d2175f18" ], "data": { "Name": "Reference" }, "format": "FOLDER", "uid": "2560970695a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://dictionary.com/", "Name": "Dictionary.com" }, "format": "BOOKMARK", "uid": "256097f695a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.dict.org/", "Name": "DICT" }, "format": "BOOKMARK", "uid": "256098f095a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://ibiblio.org/", "Name": "ibiblio" }, "format": "BOOKMARK", "uid": "256099e095a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://en.wikipedia.org/wiki/Main_Page", "Name": "Wikipedia" }, "format": "BOOKMARK", "uid": "25609ad095a411e79cb17054d2175f18" }, { "children": [ "25609cba95a411e79cb17054d2175f18", "2560a8cc95a411e79cb17054d2175f18" ], "data": { "Name": "Linux" }, "format": "FOLDER", "uid": "25609bde95a411e79cb17054d2175f18" }, { "children": [ "2560a4c695a411e79cb17054d2175f18", "2560a5de95a411e79cb17054d2175f18", "2560a6ce95a411e79cb17054d2175f18", "2560a7dc95a411e79cb17054d2175f18" ], "data": { "Name": "Debian" }, "format": "FOLDER", "uid": "25609cba95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.debian.org/", "Name": "debian.org" }, "format": "BOOKMARK", "uid": "2560a4c695a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://packages.debian.org/unstable/", "Name": "Packages in \"unstable\"" }, "format": "BOOKMARK", "uid": "2560a5de95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://packages.debian.org/experimental/", "Name": "Packages in \"experimental\"" }, "format": "BOOKMARK", "uid": "2560a6ce95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://planet.debian.net/", "Name": "Planet Debian" }, "format": "BOOKMARK", "uid": "2560a7dc95a411e79cb17054d2175f18" }, { "children": [ "2560a9bc95a411e79cb17054d2175f18", "2560aaac95a411e79cb17054d2175f18", "2560ab9295a411e79cb17054d2175f18" ], "data": { "Name": "News" }, "format": "FOLDER", "uid": "2560a8cc95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://linuxtoday.com/", "Name": "Linux Today" }, "format": "BOOKMARK", "uid": "2560a9bc95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.lwn.net/", "Name": "Linux Weekly News" }, "format": "BOOKMARK", "uid": "2560aaac95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.h-online.com/", "Name": "The H" }, "format": "BOOKMARK", "uid": "2560ab9295a411e79cb17054d2175f18" }, { "children": [ "2560ad7c95a411e79cb17054d2175f18", "2560b11495a411e79cb17054d2175f18", "2560b3bc95a411e79cb17054d2175f18" ], "data": { "Name": "Programming" }, "format": "FOLDER", "uid": "2560aca095a411e79cb17054d2175f18" }, { "children": [ "2560ae5895a411e79cb17054d2175f18", "2560af3e95a411e79cb17054d2175f18", "2560b02495a411e79cb17054d2175f18" ], "data": { "Name": "PyQt" }, "format": "FOLDER", "uid": "2560ad7c95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.diotavelli.net/PyQtWiki", "Name": "PyQt Wiki" }, "format": "BOOKMARK", "uid": "2560ae5895a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.riverbankcomputing.co.uk/", "Name": "Riverbank PyQt" }, "format": "BOOKMARK", "uid": "2560af3e95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://qt.nokia.com/", "Name": "QT Trolltech" }, "format": "BOOKMARK", "uid": "2560b02495a411e79cb17054d2175f18" }, { "children": [ "2560b1e695a411e79cb17054d2175f18", "2560b2cc95a411e79cb17054d2175f18" ], "data": { "Name": "Python" }, "format": "FOLDER", "uid": "2560b11495a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.oreillynet.com/python/", "Name": "OReilly Python" }, "format": "BOOKMARK", "uid": "2560b1e695a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.python.org/", "Name": "Python" }, "format": "BOOKMARK", "uid": "2560b2cc95a411e79cb17054d2175f18" }, { "children": [ "2560b48e95a411e79cb17054d2175f18", "2560b57495a411e79cb17054d2175f18" ], "data": { "Name": "Tools" }, "format": "FOLDER", "uid": "2560b3bc95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.selenic.com/mercurial/wiki/", "Name": "Mercurial" }, "format": "BOOKMARK", "uid": "2560b48e95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://hgbook.red-bean.com/hgbook.html", "Name": "Mercurial Book" }, "format": "BOOKMARK", "uid": "2560b57495a411e79cb17054d2175f18" }, { "children": [ "2560b73695a411e79cb17054d2175f18", "2560b82695a411e79cb17054d2175f18", "2560b92a95a411e79cb17054d2175f18" ], "data": { "Name": "Weather" }, "format": "FOLDER", "uid": "2560b66495a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.aviationweather.gov/adds", "Name": "ADDS - Aviation Digital Data Service" }, "format": "BOOKMARK", "uid": "2560b73695a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://forecast.weather.gov/MapClick.php?lat=39.105&lon=-77.26", "Name": "NOAA" }, "format": "BOOKMARK", "uid": "2560b82695a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "http://www.wunderground.com/cgi-bin/findweather/getForecast?query=gai", "Name": "Weather Underground" }, "format": "BOOKMARK", "uid": "2560b92a95a411e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "25608acc95a411e79cb17054d2175f18" ] } }TreeLine-3.2.1/samples/230en_sample_intern_links.trln000066400000000000000000000047001506556630100225500ustar00rootroot00000000000000{ "formats": [ { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Text", "fieldtype": "Text" } ], "formatname": "DEFAULT", "outputlines": [ "{*Name*}", "{*Text*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Link", "fieldtype": "InternalLink" } ], "formatname": "LINK_TYPE", "outputlines": [ "{*Name*}", "{*Link*}" ], "titleline": "{*Name*}" } ], "nodes": [ { "children": [ "2d70acb095a411e79cb17054d2175f18", "2d70aec295a411e79cb17054d2175f18", "2d70afd095a411e79cb17054d2175f18" ], "data": { "Name": "Main" }, "format": "DEFAULT", "uid": "2d70a88c95a411e79cb17054d2175f18" }, { "children": [], "data": { "Link": "Target Node", "Name": "Using the external link field" }, "format": "LINK_TYPE", "uid": "2d70acb095a411e79cb17054d2175f18" }, { "children": [], "data": { "Name": "Embedded links", "Text": "Links can be embedded in any text field text by using the Internal Link item from the Edit Menu. The \"Enable click on target\" button lets you simply click on the target node." }, "format": "DEFAULT", "uid": "2d70aec295a411e79cb17054d2175f18" }, { "children": [], "data": { "Name": "Target Node", "Text": "By default, the target node gets its unique ID from the content of its first field. This can be changed in the Type Config tab of the Configure Types dialog. Use the Show Advanced button to show the control for the Unique ID Reference." }, "format": "DEFAULT", "uid": "2d70afd095a411e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "2d70a88c95a411e79cb17054d2175f18" ] } }TreeLine-3.2.1/samples/240en_sample_table_booklist.trln000066400000000000000000000066011506556630100230510ustar00rootroot00000000000000{ "formats": [ { "childtype": "BOOK", "fields": [ { "fieldname": "AuthorFirstName", "fieldtype": "Text" }, { "fieldname": "AuthorLastName", "fieldtype": "Text" }, { "fieldname": "WebSite", "fieldtype": "ExternalLink", "prefix": "<", "suffix": ">" } ], "formatname": "AUTHOR", "icon": "book_1", "outputlines": [ "{*AuthorFirstName*} {*AuthorLastName*} {*WebSite*}" ], "titleline": "{*AuthorFirstName*} {*AuthorLastName*}" }, { "fields": [ { "fieldname": "Title", "fieldtype": "Text" }, { "fieldname": "Copyright", "fieldtype": "Number", "format": "0000" }, { "fieldname": "Own", "fieldtype": "Boolean", "format": "yes/no" }, { "fieldname": "ReadDate", "fieldtype": "Date", "format": "%-m/%-d/%Y" }, { "fieldname": "Rating", "fieldtype": "Choice", "format": "1/2/3/4/5" }, { "fieldname": "Plot", "fieldtype": "Text", "lines": 7 } ], "formathtml": true, "formatname": "BOOK", "icon": "book_3", "outputlines": [ "Title: \"{*Title*}\"", "Status: (c) {*Copyright*}", "Own: {*Own*}", "Last Read: {*ReadDate*}", "Rating: {*Rating*}", "Plot: {*Plot*}" ], "spacebetween": false, "tables": true, "titleline": "\"{*Title*}\"" }, { "childtype": "AUTHOR", "fields": [ { "fieldname": "NAME", "fieldtype": "Text" } ], "formatname": "ROOT", "outputlines": [ "{*NAME*}" ], "titleline": "{*NAME*}" } ], "nodes": [ { "children": [ "5cd2946cfe1011e7b8dc7054d2175f18", "5cd2bffafe1011e7b8dc7054d2175f18" ], "data": { "NAME": "SF Books" }, "format": "ROOT", "uid": "5cd28d1efe1011e7b8dc7054d2175f18" }, { "children": [ "5cd2b3d4fe1011e7b8dc7054d2175f18", "5cd2bdc0fe1011e7b8dc7054d2175f18" ], "data": { "AuthorFirstName": "Greg", "AuthorLastName": "Bear", "WebSite": "www.gregbear.com" }, "format": "AUTHOR", "uid": "5cd2946cfe1011e7b8dc7054d2175f18" }, { "children": [], "data": { "Copyright": "1999", "Own": "false", "Plot": "Evolution caused by virus begining again", "Rating": "4", "ReadDate": "2000-10-01", "Title": "Darwin's Radio" }, "format": "BOOK", "uid": "5cd2b3d4fe1011e7b8dc7054d2175f18" }, { "children": [], "data": { "Copyright": "1985", "Own": "true", "Plot": "Smart viruses take over", "Rating": "2", "ReadDate": "1998-07-01", "Title": "Blood Music" }, "format": "BOOK", "uid": "5cd2bdc0fe1011e7b8dc7054d2175f18" }, { "children": [ "5cd2c1bcfe1011e7b8dc7054d2175f18", "5cd2c392fe1011e7b8dc7054d2175f18", "5cd2c54afe1011e7b8dc7054d2175f18" ], "data": { "AuthorFirstName": "Orson Scott", "AuthorLastName": "Card", "WebSite": "www.hatrack.com" }, "format": "AUTHOR", "uid": "5cd2bffafe1011e7b8dc7054d2175f18" }, { "children": [], "data": { "Copyright": "1996", "Own": "Yes", "Plot": "Time travel to change history; discovery of America", "Rating": "4", "ReadDate": "1998-09-01", "Title": "Pastwatch, The Redemption of Christopher Columbus" }, "format": "BOOK", "uid": "5cd2c1bcfe1011e7b8dc7054d2175f18" }, { "children": [], "data": { "Copyright": "1999", "Own": "Yes", "Plot": "Boy travels back to Russian fairy tale", "Rating": "5", "ReadDate": "2000-08-01", "Title": "Enchantment" }, "format": "BOOK", "uid": "5cd2c392fe1011e7b8dc7054d2175f18" }, { "children": [], "data": { "Copyright": "1999", "Own": "Yes", "Plot": "Ender's Game from Bean's perspective", "Rating": "5", "ReadDate": "2001-05-01", "Title": "Ender's Shadow" }, "format": "BOOK", "uid": "5cd2c54afe1011e7b8dc7054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "5cd28d1efe1011e7b8dc7054d2175f18" ] } }TreeLine-3.2.1/samples/310en_sample_conditional_todo.trln000066400000000000000000000137511506556630100234060ustar00rootroot00000000000000{ "formats": [ { "childtype": "TASK_UNDONE", "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "ROOT", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "condition": "Done == \"true\"", "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Done", "fieldtype": "Boolean", "format": "yes/no", "init": "false" }, { "fieldname": "Urgent", "fieldtype": "Boolean", "format": "yes/no", "init": "false" } ], "formathtml": true, "formatname": "TASK_DONE", "icon": "smiley_4", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Done", "fieldtype": "Boolean", "format": "yes/no", "init": "false" }, { "fieldname": "Urgent", "fieldtype": "Boolean", "format": "yes/no", "init": "false" } ], "formathtml": true, "formatname": "TASK_UNDONE", "generic": "TASK_DONE", "icon": "smiley_2", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "condition": "Done == \"false\" and Urgent == \"true\"", "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Done", "fieldtype": "Boolean", "format": "yes/no", "init": "false" }, { "fieldname": "Urgent", "fieldtype": "Boolean", "format": "yes/no", "init": "true" } ], "formathtml": true, "formatname": "TASK_UNDONE_URGENT", "generic": "TASK_DONE", "icon": "smiley_5", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}!!!" } ], "nodes": [ { "children": [ "4295fc4e95a411e79cb17054d2175f18", "42960f7c95a411e79cb17054d2175f18" ], "data": { "Name": "Conditional Task List" }, "format": "ROOT", "uid": "4295faaa95a411e79cb17054d2175f18" }, { "children": [ "4295ff6e95a411e79cb17054d2175f18", "429602ac95a411e79cb17054d2175f18", "429603c495a411e79cb17054d2175f18", "429607b695a411e79cb17054d2175f18", "42960cca95a411e79cb17054d2175f18" ], "data": { "Name": "Home Tasks" }, "format": "ROOT", "uid": "4295fc4e95a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "false", "Name": "Mow lawn", "Urgent": "false" }, "format": "TASK_UNDONE", "uid": "4295ff6e95a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "false", "Name": "Patch wall", "Urgent": "false" }, "format": "TASK_UNDONE", "uid": "429602ac95a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "false", "Name": "Vacuum", "Urgent": "false" }, "format": "TASK_UNDONE", "uid": "429603c495a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "false", "Name": "Walk dog", "Urgent": "true" }, "format": "TASK_UNDONE_URGENT", "uid": "429607b695a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "true", "Name": "Watch TV", "Urgent": "false" }, "format": "TASK_DONE", "uid": "42960cca95a411e79cb17054d2175f18" }, { "children": [ "4296107695a411e79cb17054d2175f18", "429611b695a411e79cb17054d2175f18", "429612a695a411e79cb17054d2175f18", "4296139695a411e79cb17054d2175f18" ], "data": { "Name": "Work Tasks" }, "format": "ROOT", "uid": "42960f7c95a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "true", "Name": "Play solitaire", "Urgent": "false" }, "format": "TASK_DONE", "uid": "4296107695a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "false", "Name": "Write documents", "Urgent": "false" }, "format": "TASK_UNDONE", "uid": "429611b695a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "true", "Name": "Eat lunch", "Urgent": "false" }, "format": "TASK_DONE", "uid": "429612a695a411e79cb17054d2175f18" }, { "children": [], "data": { "Done": "false", "Name": "Compliment boss", "Urgent": "true" }, "format": "TASK_UNDONE_URGENT", "uid": "4296139695a411e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "4295faaa95a411e79cb17054d2175f18" ] } }TreeLine-3.2.1/samples/320en_sample_other_fields.trln000066400000000000000000000106641506556630100225260ustar00rootroot00000000000000{ "formats": [ { "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "DEFAULT", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "childtype": "DEFAULT", "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "FILE_INFO", "outputlines": [ "{*Name*}", "File: {*!File_Path*}/{*!File_Name*}", "File Size: {*!File_Size*} bytes", "File Modified: {*!File_Mod_Date*} {*!File_Mod_Time*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "File_Name", "fieldtype": "Text" }, { "fieldname": "File_Path", "fieldtype": "Text" }, { "fieldname": "File_Size", "fieldtype": "Number", "format": "#" }, { "fieldname": "File_Mod_Date", "fieldtype": "Date", "format": "%B %-d, %Y" }, { "fieldname": "File_Mod_Time", "fieldtype": "Time", "format": "%-I:%M:%S %p" }, { "fieldname": "File_Owner", "fieldtype": "Text" }, { "fieldname": "Page_Number", "fieldtype": "Text" }, { "fieldname": "Number_of_Pages", "fieldtype": "Text" } ], "formatname": "INT_TL_FILE_DATA_FORM", "outputlines": [ "" ], "titleline": "" }, { "childtype": "DEFAULT", "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "PARENT_CHILD", "outputlines": [ "{*Name*}", "Parent's Name: {**Name*}", "Children's Names: {*&Name*}" ], "titleline": "{*Name*}" }, { "childtype": "DEFAULT", "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "ROOT", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" } ], "nodes": [ { "children": [ "50cdc8dc95a411e79cb17054d2175f18", "50cdce0495a411e79cb17054d2175f18", "50cdcf7695a411e79cb17054d2175f18" ], "data": { "Name": "Other Field References" }, "format": "ROOT", "uid": "50cdc36e95a411e79cb17054d2175f18" }, { "children": [], "data": { "Name": "File Information" }, "format": "FILE_INFO", "uid": "50cdc8dc95a411e79cb17054d2175f18" }, { "children": [], "data": { "Name": "Parent Info" }, "format": "PARENT_CHILD", "uid": "50cdce0495a411e79cb17054d2175f18" }, { "children": [ "50cdd27895a411e79cb17054d2175f18", "50cdd3e095a411e79cb17054d2175f18", "50cdd4e495a411e79cb17054d2175f18" ], "data": { "Name": "Child Info" }, "format": "PARENT_CHILD", "uid": "50cdcf7695a411e79cb17054d2175f18" }, { "children": [], "data": { "Name": "First child" }, "format": "DEFAULT", "uid": "50cdd27895a411e79cb17054d2175f18" }, { "children": [], "data": { "Name": "Next child" }, "format": "DEFAULT", "uid": "50cdd3e095a411e79cb17054d2175f18" }, { "children": [], "data": { "Name": "Third child" }, "format": "DEFAULT", "uid": "50cdd4e495a411e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "50cdc36e95a411e79cb17054d2175f18" ] } }TreeLine-3.2.1/samples/330en_sample_math_fields.trln000066400000000000000000000156401506556630100223360ustar00rootroot00000000000000{ "formats": [ { "childtype": "PART", "fields": [ { "fieldname": "PartNumber", "fieldtype": "Text" }, { "fieldname": "Name", "fieldtype": "Text" }, { "eqn": "{**Level*} + 1", "fieldname": "Level", "fieldtype": "Math", "format": "#" }, { "fieldname": "LaborCost", "fieldtype": "Number", "format": "0.00", "prefix": "$" }, { "eqn": "sum({*&Cost*}) + {*LaborCost*}", "fieldname": "Cost", "fieldtype": "Math", "format": "0.00", "prefix": "$" }, { "eqn": "{**TotalCost*}", "fieldname": "TotalCost", "fieldtype": "Math", "format": "0.00", "prefix": "$" }, { "eqn": "{*Cost*} / {*TotalCost*} * 100", "fieldname": "PercentCost", "fieldtype": "Math", "format": "0", "suffix": "%" } ], "formatname": "ASSEMBLY", "outputlines": [ "Part {*PartNumber*}", "{*Name*}", "Assembly Level: {*Level*}", "Cost: {*Cost*}", "Percent Cost: {*PercentCost*}" ], "titleline": "{*PartNumber*} {*Name*}" }, { "fields": [ { "fieldname": "PartNumber", "fieldtype": "Text" }, { "fieldname": "Name", "fieldtype": "Text" }, { "eqn": "{**Level*} + 1", "fieldname": "Level", "fieldtype": "Math", "format": "#" }, { "fieldname": "Cost", "fieldtype": "Number", "format": "0.00", "prefix": "$" }, { "eqn": "{*Cost*} / {**TotalCost*} * 100", "fieldname": "PercentCost", "fieldtype": "Math", "format": "0", "suffix": "%" }, { "eqn": "('Low') if ({*PercentCost*} < 20) else ('High')", "fieldname": "CostLevel", "fieldtype": "Math", "format": "#.##", "resulttype": "text" } ], "formatname": "PART", "outputlines": [ "Part {*PartNumber*}", "{*Name*}", "Assembly Level: {*Level*}", "Cost: {*Cost*}", "Percent Cost: {*PercentCost*}", "Cost Level: {*CostLevel*}" ], "titleline": "{*PartNumber*} {*Name*}" }, { "childtype": "ASSEMBLY", "fields": [ { "fieldname": "PartNumber", "fieldtype": "Text" }, { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Level", "fieldtype": "Number", "format": "#" }, { "fieldname": "LaborCost", "fieldtype": "Number", "format": "0.00", "prefix": "$" }, { "eqn": "sum({*&Cost*}) + {*LaborCost*}", "fieldname": "TotalCost", "fieldtype": "Math", "format": "0.00", "prefix": "$" } ], "formatname": "TOP_ASSEMBLY", "outputlines": [ "Part {*PartNumber*}", "{*Name*}", "Assembly Level: {*Level*}", "Cost: {*TotalCost*}" ], "titleline": "{*PartNumber*} {*Name*}" } ], "nodes": [ { "children": [ "5f8ff84a95a411e79cb17054d2175f18", "5f901e5695a411e79cb17054d2175f18" ], "data": { "LaborCost": "3.5", "Level": "1", "Name": "Widget Top Assembly", "PartNumber": "123456", "TotalCost": "23.89" }, "format": "TOP_ASSEMBLY", "uid": "5f8fdd3895a411e79cb17054d2175f18" }, { "children": [ "5f900eb695a411e79cb17054d2175f18", "5f901d0c95a411e79cb17054d2175f18" ], "data": { "Cost": "10.040000000000001", "LaborCost": "1.75", "Level": "2", "Name": "Lever Assembly", "PartNumber": "456789", "PercentCost": "42.02595228128925", "TotalCost": "23.89" }, "format": "ASSEMBLY", "uid": "5f8ff84a95a411e79cb17054d2175f18" }, { "children": [], "data": { "Cost": "5.4", "CostLevel": "High", "Level": "3", "Name": "Lever", "PartNumber": "987654", "PercentCost": "22.60359983256593" }, "format": "PART", "uid": "5f900eb695a411e79cb17054d2175f18" }, { "children": [], "data": { "Cost": "2.89", "CostLevel": "Low", "Level": "3", "Name": "Lever Bolt", "PartNumber": "998877", "PercentCost": "12.097111762243616" }, "format": "PART", "uid": "5f901d0c95a411e79cb17054d2175f18" }, { "children": [ "5f901f6e95a411e79cb17054d2175f18", "5f90208695a411e79cb17054d2175f18" ], "data": { "Cost": "10.35", "LaborCost": "2.25", "Level": "2", "Name": "Bracket Assembly", "PartNumber": "112233", "PercentCost": "43.32356634575136", "TotalCost": "23.89" }, "format": "ASSEMBLY", "uid": "5f901e5695a411e79cb17054d2175f18" }, { "children": [], "data": { "Cost": "6.2", "CostLevel": "High", "Level": "3", "Name": "Bracket", "PartNumber": "445566", "PercentCost": "25.952281289242364" }, "format": "PART", "uid": "5f901f6e95a411e79cb17054d2175f18" }, { "children": [], "data": { "Cost": "1.9", "CostLevel": "Low", "Level": "3", "Name": "Bracket Pin", "PartNumber": "665544", "PercentCost": "7.95311845960653" }, "format": "PART", "uid": "5f90208695a411e79cb17054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "5f8fdd3895a411e79cb17054d2175f18" ] } }TreeLine-3.2.1/source/000077500000000000000000000000001506556630100145335ustar00rootroot00000000000000TreeLine-3.2.1/source/breadcrumbview.py000066400000000000000000000162771506556630100201230ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # breadcrumbview.py, provides a class for the breadcrumb view # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import operator from PyQt6.QtCore import QSize, Qt from PyQt6.QtGui import QPainter, QPalette from PyQt6.QtWidgets import (QAbstractItemView, QApplication, QStyledItemDelegate, QTableWidget, QTableWidgetItem) import globalref class CrumbItem(QTableWidgetItem): """Class to store breadcrumb item spot refs and positions. """ def __init__(self, spotRef): """Initialize the breadcrumb item. Arguments: spotRef -- ref to the associated spot item """ super().__init__(spotRef.nodeRef.title(spotRef)) self.spot = spotRef self.selectedSpot = False self.setTextAlignment(Qt.AlignmentFlag.AlignCenter) self.setForeground(QApplication.palette().brush(QPalette. ColorRole.Link)) class BorderDelegate(QStyledItemDelegate): """Class override to show borders between rows. """ def __init__(self, parent=None): """Initialize the delegate class. Arguments: parent -- the parent view """ super().__init__(parent) def paint(self, painter, styleOption, modelIndex): """Paint the cells with borders between rows. """ super().paint(painter, styleOption, modelIndex) cell = self.parent().item(modelIndex.row(), modelIndex.column()) if modelIndex.row() > 0 and cell: upperCell = None row = modelIndex.row() while not upperCell and row > 0: row -= 1 upperCell = self.parent().item(row, modelIndex.column()) if cell.text() and upperCell and upperCell.text(): painter.drawLine(styleOption.rect.topLeft(), styleOption.rect.topRight()) class BreadcrumbView(QTableWidget): """Class override for the breadcrumb view. Sets view defaults and updates the content. """ def __init__(self, treeView, parent=None): """Initialize the breadcrumb view. Arguments: treeView - the tree view, needed for the current selection model parent -- the parent main window """ super().__init__(parent) self.treeView = treeView self.borderItems = [] self.setFocusPolicy(Qt.FocusPolicy.NoFocus) self.horizontalHeader().hide() self.verticalHeader().hide() self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel) self.setHorizontalScrollMode(QAbstractItemView.ScrollMode. ScrollPerPixel) self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection) self.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.setItemDelegate(BorderDelegate(self)) self.setShowGrid(False) self.setMouseTracking(True) self.itemClicked.connect(self.changeSelection) def updateContents(self): """Reload the view's content if the view is shown. Avoids update if view is not visible or has zero height or width. """ if not self.isVisible() or self.height() == 0 or self.width() == 0: return self.clear() self.clearSpans() selModel = self.treeView.selectionModel() selSpots = selModel.selectedSpots() if len(selSpots) != 1: return selSpot = selSpots[0] spotList = sorted(list(selSpot.nodeRef.spotRefs), key=operator.methodcaller('sortKey')) chainList = [[CrumbItem(chainSpot) for chainSpot in spot.spotChain()] for spot in spotList] self.setRowCount(len(chainList)) for row in range(len(chainList)): columns = len(chainList[row]) * 2 - 1 if columns > self.columnCount(): self.setColumnCount(columns) for col in range(len(chainList[row])): item = chainList[row][col] if (row == 0 or col >= len(chainList[row - 1]) or item.spot is not chainList[row - 1][col].spot): rowSpan = 1 while (row + rowSpan < len(chainList) and col < len(chainList[row + rowSpan]) and item.spot is chainList[row + rowSpan][col].spot): rowSpan += 1 if col < len(chainList[row]) - 1: arrowItem = QTableWidgetItem('\u25ba') arrowItem.setTextAlignment(Qt.AlignmentFlag.AlignCenter) self.setItem(row, col * 2 + 1, arrowItem) if rowSpan > 1: self.setSpan(row, col * 2 + 1, rowSpan, 1) self.setItem(row, col * 2, item) if rowSpan > 1: self.setSpan(row, col * 2, rowSpan, 1) if item.spot is selSpot: item.selectedSpot = True item.setForeground(QApplication.palette(). brush(QPalette.ColorRole. WindowText)) self.resizeColumnsToContents() def changeSelection(self, item): """Change the current selection to given item bassed on a mouse click. Arguments: item -- the breadcrumb item that was clicked """ selModel = self.treeView.selectionModel() if hasattr(item, 'spot') and not item.selectedSpot: selModel.selectSpots([item.spot]) self.setCursor(Qt.CursorShape.ArrowCursor) def minimumSizeHint(self): """Set a short minimum size fint to allow the display of one row. """ return QSize(super().minimumSizeHint().width(), self.fontInfo().pixelSize() * 3) def mouseMoveEvent(self, event): """Change the mouse pointer if over a clickable item. Arguments: event -- the mouse move event """ item = self.itemAt(event.position().toPoint()) if item and hasattr(item, 'spot') and not item.selectedSpot: self.setCursor(Qt.CursorShape.PointingHandCursor) else: self.setCursor(Qt.CursorShape.ArrowCursor) super().mouseMoveEvent(event) def resizeEvent(self, event): """Update view if was collaped by splitter. """ if ((event.oldSize().height() == 0 and event.size().height()) or (event.oldSize().width() == 0 and event.size().width())): self.updateContents() return super().resizeEvent(event) TreeLine-3.2.1/source/colorset.py000066400000000000000000000276151506556630100167520ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # colorset.py, provides storage/retrieval and dialogs for GUI colors # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITTHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import enum from collections import OrderedDict from PyQt6.QtCore import pyqtSignal, Qt, QEvent, QObject from PyQt6.QtGui import QColor, QFontMetrics, QPalette, QPixmap from PyQt6.QtWidgets import (QApplication, QColorDialog, QComboBox, QDialog, QFrame, QGroupBox, QHBoxLayout, QLabel, QGridLayout, QPushButton, QVBoxLayout) import globalref roles = OrderedDict([('Window', _('Dialog background color')), ('WindowText', _('Dialog text color')), ('Base', _('Text widget background color')), ('Text', _('Text widget foreground color')), ('Highlight', _('Selected item background color')), ('HighlightedText', _('Selected item text color')), ('Link', _('Link text color')), ('ToolTipBase', _('Tool tip background color')), ('ToolTipText', _('Tool tip foreground color')), ('Button', _('Button background color')), ('ButtonText', _('Button text color')), ('Text-Disabled', _('Disabled text foreground color')), ('ButtonText-Disabled', _('Disabled button text color'))]) ThemeSetting = enum.IntEnum('ThemeSetting', 'system light dark custom') lightColors = {'Window': '#efefef', 'WindowText': '#000000', 'Base': '#ffffff', 'Text': '#000000', 'Highlight': '#308cc6', 'HighlightedText': '#ffffff', 'Link': '#0000ff', 'ToolTipBase': '#ffffdc', 'ToolTipText': '#000000', 'Button': '#efefef', 'ButtonText': '#000000', 'Text-Disabled': '#bebebe', 'ButtonText-Disabled': '#bebebe'} darkColors = {'Window': '#353535', 'WindowText': '#ffffff', 'Base': '#191919', 'Text': '#ffffff', 'Highlight': '#2a82da', 'HighlightedText': '#000000', 'Link': '#2a82da', 'ToolTipBase': '#000080', 'ToolTipText': '#c0c0c0', 'Button': '#353535', 'ButtonText': '#ffffff', 'Text-Disabled': '#808080', 'ButtonText-Disabled': '#808080'} class ColorSet: """Stores color settings and provides dialogs for user changes. """ def __init__(self): """Initialize colors settings from the system or from options. """ self.sysPalette = QApplication.palette() self.colors = [Color(roleKey) for roleKey in roles.keys()] self.theme = ThemeSetting[globalref.miscOptions['ColorTheme']] for color in self.colors: color.colorChanged.connect(self.setCustomTheme) color.setFromPalette(self.sysPalette) if self.theme == ThemeSetting.light: color.setFromTheme(lightColors) elif self.theme == ThemeSetting.dark: color.setFromTheme(darkColors) elif self.theme == ThemeSetting.custom: color.setFromOption() def setAppColors(self): """Set application to current colors. """ newPalette = QApplication.palette() for color in self.colors: color.updatePalette(newPalette) QApplication.setPalette(newPalette) def showDialog(self, parent): """Show a dialog for user color changes. Return True if changes were made. Arguments: parent -- the parent widget for the dialog """ dialog = QDialog(parent) dialog.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowSystemMenuHint) dialog.setWindowTitle(_('Color Settings')) topLayout = QVBoxLayout(dialog) dialog.setLayout(topLayout) themeBox = QGroupBox(_('Color Theme'), dialog) topLayout.addWidget(themeBox) themeLayout = QVBoxLayout(themeBox) self.themeControl = QComboBox(dialog) self.themeControl.addItem(_('Default system theme'), ThemeSetting.system) self.themeControl.addItem(_('Light theme'), ThemeSetting.light) self.themeControl.addItem(_('Dark theme'), ThemeSetting.dark) self.themeControl.addItem(_('Custom theme'), ThemeSetting.custom) self.themeControl.setCurrentIndex(self.themeControl. findData(self.theme)) self.themeControl.currentIndexChanged.connect(self.updateThemeSetting) themeLayout.addWidget(self.themeControl) self.groupBox = QGroupBox(dialog) self.setBoxTitle() topLayout.addWidget(self.groupBox) gridLayout = QGridLayout(self.groupBox) row = 0 for color in self.colors: gridLayout.addWidget(color.getLabel(), row, 0) gridLayout.addWidget(color.getSwatch(), row, 1) row += 1 ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) okButton = QPushButton(_('&OK'), dialog) ctrlLayout.addWidget(okButton) okButton.clicked.connect(dialog.accept) cancelButton = QPushButton(_('&Cancel'), dialog) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(dialog.reject) if dialog.exec() == QDialog.DialogCode.Accepted: self.theme = ThemeSetting(self.themeControl.currentData()) globalref.miscOptions.changeValue('ColorTheme', self.theme.name) if self.theme == ThemeSetting.system: QApplication.setPalette(self.sysPalette) else: # named theme or custom if self.theme == ThemeSetting.custom: for color in self.colors: color.updateOption() self.setAppColors() globalref.miscOptions.writeFile() else: for color in self.colors: color.setFromPalette(self.sysPalette) if self.theme == ThemeSetting.light: color.setFromTheme(lightColors) elif self.theme == ThemeSetting.dark: color.setFromTheme(darkColors) elif self.theme == ThemeSetting.custom: color.setFromOption() def setBoxTitle(self): """Set title of group box to standard or custom. """ if self.themeControl.currentData() == ThemeSetting.custom: title = _('Custom Colors') else: title = _('Theme Colors') self.groupBox.setTitle(title) def updateThemeSetting(self): """Update the colors based on a theme control change. """ if self.themeControl.currentData() == ThemeSetting.system: for color in self.colors: color.setFromPalette(self.sysPalette) color.changeSwatchColor() elif self.themeControl.currentData() == ThemeSetting.light: for color in self.colors: color.setFromTheme(lightColors) color.changeSwatchColor() elif self.themeControl.currentData() == ThemeSetting.dark: for color in self.colors: color.setFromTheme(darkColors) color.changeSwatchColor() else: for color in self.colors: color.setFromOption() color.changeSwatchColor() self.setBoxTitle() def setCustomTheme(self): """Set to custom theme setting after user color change. """ if self.themeControl.currentData != ThemeSetting.custom: self.themeControl.blockSignals(True) self.themeControl.setCurrentIndex(2) self.themeControl.blockSignals(False) self.setBoxTitle() class Color(QObject): """Stores a single color setting for a role. """ colorChanged = pyqtSignal() def __init__(self, roleKey, parent=None): """Initialize a Color. Arguments: roleKey -- the text name of the color role parent -- a parent object if given """ super().__init__(parent) self.roleKey = roleKey if '-' in roleKey: roleStr, groupStr = roleKey.split('-') self.group = eval('QPalette.ColorGroup.' + groupStr) else: roleStr = roleKey self.group = None self.role = eval('QPalette.ColorRole.' + roleStr) self.currentColor = None self.swatch = None def setFromPalette(self, palette): """Set the color based on the given palette. Arguments: palette -- the palette that defines the color """ if self.group: self.currentColor = palette.color(self.group, self.role) else: self.currentColor = palette.color(self.role) def setFromOption(self): """Set color based on the option setting. """ colorStr = globalref.miscOptions[self.roleKey + 'Color'] color = QColor(colorStr) if color.isValid(): self.currentColor = color def setFromTheme(self, theme): """Set color based on the given theme dictionary. Arguments: theme -- a theme dictionary that defines the color """ self.currentColor = QColor(theme[self.roleKey]) def updateOption(self): """Set the option to the current color. """ if self.currentColor: globalref.miscOptions.changeValue(self.roleKey + 'Color', self.currentColor.name()) def updatePalette(self, palette): """Set the role in the given palette to the current color. Arguments: palette -- the palette that gets set with the color """ if self.group: palette.setColor(self.group, self.role, self.currentColor) else: palette.setColor(self.role, self.currentColor) def getLabel(self): """Return a label for this role in a dialog. """ return QLabel(roles[self.roleKey]) def getSwatch(self): """Return a label color swatch with the current color. """ self.swatch = QLabel() self.changeSwatchColor() self.swatch.setFrameStyle(QFrame.Shape.Panel | QFrame.Shadow.Raised) self.swatch.setLineWidth(3) self.swatch.installEventFilter(self) return self.swatch def changeSwatchColor(self): """Set swatch to currentColor. """ height = QFontMetrics(self.swatch.font()).height() pixmap = QPixmap(3 * height, height) pixmap.fill(self.currentColor) self.swatch.setPixmap(pixmap) def eventFilter(self, obj, event): """Handle mouse clicks on swatches. Arguments: obj -- the object to handle events for event -- the specific event """ if (obj == self.swatch and event.type() == QEvent.Type.MouseButtonRelease): color = QColorDialog.getColor(self.currentColor, QApplication.activeWindow(), _('Select {0} color'). format(self.roleKey)) if color.isValid() and color != self.currentColor: self.currentColor = color self.changeSwatchColor() self.colorChanged.emit() return True return False TreeLine-3.2.1/source/conditional.py000066400000000000000000000653131506556630100174200ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # conditional.py, provides a class to store field comparison functions # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import enum from PyQt6.QtCore import QSize, Qt, pyqtSignal from PyQt6.QtWidgets import (QComboBox, QDialog, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListWidget, QPushButton, QSizePolicy, QVBoxLayout) import treeformats import configdialog import undo import globalref _operators = ['==', '<', '<=', '>', '>=', '!=', N_('starts with'), N_('ends with'), N_('contains'), N_('True'), N_('False')] _functions = {'==': '__eq__', '<': '__lt__', '<=': '__le__', '>': '__gt__', '>=': '__ge__', '!=': '__ne__', 'starts with': 'startswith', 'ends with': 'endswith', 'contains': 'contains', 'True': 'true', 'False': 'false'} _boolOper = [N_('and'), N_('or')] _allTypeEntry = _('[All Types]') _parseRe = re.compile(r'((?:and)|(?:or)) (\S+) (.+?) ' r'(?:(? "othervalue"' Arguments: conditionStr -- the condition string to set nodeFormatName -- if name is set, restricts matches to type family """ self.conditionLines = [] conditionStr = 'and ' + conditionStr for boolOper, fieldName, oper, value in _parseRe.findall(conditionStr): value = value.replace('\\"', '"').replace('\\\\', '\\') self.conditionLines.append(ConditionLine(boolOper, fieldName, oper, value)) self.origNodeFormatName = nodeFormatName self.nodeFormatNames = set() if nodeFormatName: self.nodeFormatNames.add(nodeFormatName) nodeFormats = (globalref.mainControl.activeControl.structure. treeFormats) for nodeType in nodeFormats[nodeFormatName].derivedTypes: self.nodeFormatNames.add(nodeType.name) def evaluate(self, node): """Evaluate this condition and return True or False. Arguments: node -- the node to check for a field match """ if (self.nodeFormatNames and node.formatRef.name not in self.nodeFormatNames): return False result = True for conditon in self.conditionLines: result = conditon.evaluate(node, result) return result def conditionStr(self): """Return the condition string for this condition set. """ return ' '.join([cond.conditionStr() for cond in self.conditionLines])[4:] def renameFields(self, oldName, newName): """Rename the any fields found in condition lines. Arguments: oldName -- the previous field name newName -- the updated field name """ for condition in self.conditionLines: if condition.fieldName == oldName: condition.fieldName = newName def removeField(self, fieldname): """Remove conditional lines referencing the given field. Arguments: fieldname -- the field name to be removed """ for condition in self.conditionLines[:]: if condition.fieldName == fieldname: self.conditionLines.remove(condition) def __len__(self): """Return the number of conditions for truth testing. """ return len(self.conditionLines) class ConditionLine: """Stores & evaluates a portion of a conditional comparison. """ def __init__(self, boolOper, fieldName, oper, value): """Initialize the condition line. Arguments: boolOper -- a string for combining previous lines ('and' or 'or') fieldName -- the field name to evaluate oper -- the operator string value -- the string for comparison """ self.boolOper = boolOper self.fieldName = fieldName self.oper = oper self.value = value def evaluate(self, node, prevResult=True): """Evaluate this line and return True or False. Arguments: node -- the node to check for a field match prevResult -- the result to combine with the boolOper """ try: field = node.formatRef.fieldDict[self.fieldName] except KeyError: if self.boolOper == 'and': return False return prevResult dataStr = field.compareValue(node) value = field.adjustedCompareValue(self.value) try: func = getattr(dataStr, _functions[self.oper]) except AttributeError: dataStr = StringOps(dataStr) func = getattr(dataStr, _functions[self.oper]) value = str(value) if self.boolOper == 'and': return prevResult and func(value) else: return prevResult or func(value) def conditionStr(self): """Return the text line for this condition. """ value = self.value.replace('\\', '\\\\').replace('"', '\\"') return '{0} {1} {2} "{3}"'.format(self.boolOper, self.fieldName, self.oper, value) class StringOps(str): """A string class with extra comparison functions. """ def __new__(cls, initStr=''): """Return the str object. Arguments: initStr -- the initial string value """ return str.__new__(cls, initStr) def contains(self, substr): """Return True if self contains substr. Arguments: substr -- the substring to check """ return self.find(substr) != -1 def true(self, other=''): """Always return True. Arguments: other -- unused placeholder """ return True def false(self, other=''): """Always return False. Arguments: other -- unused placeholder """ return False FindDialogType = enum.Enum('FindDialogType', 'typeDialog findDialog filterDialog') class ConditionDialog(QDialog): """Dialog for defining field condition tests. Used for defining conditional types (modal), for finding by condition (nonmodal) and for filtering by condition (nonmodal). """ dialogShown = pyqtSignal(bool) def __init__(self, dialogType, caption, nodeFormat=None, parent=None): """Create the conditional dialog. Arguments: dialogType -- either typeDialog, findDialog or filterDialog caption -- the window title for this dialog nodeFormat -- the current node format for the typeDialog parent -- the parent overall dialog """ super().__init__(parent) self.setWindowTitle(caption) self.dialogType = dialogType self.ruleList = [] self.combiningBoxes = [] self.typeCombo = None self.resultLabel = None self.endFilterButton = None self.fieldNames = [] if nodeFormat: self.fieldNames = nodeFormat.fieldNames() topLayout = QVBoxLayout(self) if dialogType == FindDialogType.typeDialog: self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) else: self.setAttribute(Qt.WidgetAttribute.WA_QuitOnClose, False) self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.WindowStaysOnTopHint) typeBox = QGroupBox(_('Node Type')) topLayout.addWidget(typeBox) typeLayout = QVBoxLayout(typeBox) self.typeCombo = QComboBox() typeLayout.addWidget(self.typeCombo) self.typeCombo.currentIndexChanged.connect(self.updateDataType) self.mainLayout = QVBoxLayout() topLayout.addLayout(self.mainLayout) upCtrlLayout = QHBoxLayout() topLayout.addLayout(upCtrlLayout) addButton = QPushButton(_('&Add New Rule')) upCtrlLayout.addWidget(addButton) addButton.clicked.connect(self.addNewRule) self.removeButton = QPushButton(_('&Remove Rule')) upCtrlLayout.addWidget(self.removeButton) self.removeButton.clicked.connect(self.removeRule) upCtrlLayout.addStretch() if dialogType == FindDialogType.typeDialog: okButton = QPushButton(_('&OK')) upCtrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) upCtrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) else: self.removeButton.setEnabled(False) saveBox = QGroupBox(_('Saved Rules')) topLayout.addWidget(saveBox) saveLayout = QVBoxLayout(saveBox) self.saveListBox = SmallListWidget() saveLayout.addWidget(self.saveListBox) self.saveListBox.itemDoubleClicked.connect(self.loadSavedRule) nameLayout = QHBoxLayout() saveLayout.addLayout(nameLayout) label = QLabel(_('Name:')) nameLayout.addWidget(label) self.saveNameEdit = QLineEdit() nameLayout.addWidget(self.saveNameEdit) self.saveNameEdit.textChanged.connect(self.updateSaveEnable) saveButtonLayout = QHBoxLayout() saveLayout.addLayout(saveButtonLayout) self.loadSavedButton = QPushButton(_('&Load')) saveButtonLayout.addWidget(self.loadSavedButton) self.loadSavedButton.clicked.connect(self.loadSavedRule) self.saveButton = QPushButton(_('&Save')) saveButtonLayout.addWidget(self.saveButton) self.saveButton.clicked.connect(self.saveRule) self.saveButton.setEnabled(False) self.delSavedButton = QPushButton(_('&Delete')) saveButtonLayout.addWidget(self.delSavedButton) self.delSavedButton.clicked.connect(self.deleteRule) saveButtonLayout.addStretch() if dialogType == FindDialogType.findDialog: self.resultLabel = QLabel() topLayout.addWidget(self.resultLabel) lowCtrlLayout = QHBoxLayout() topLayout.addLayout(lowCtrlLayout) if dialogType == FindDialogType.findDialog: previousButton = QPushButton(_('Find &Previous')) lowCtrlLayout.addWidget(previousButton) previousButton.clicked.connect(self.findPrevious) nextButton = QPushButton(_('Find &Next')) nextButton.setDefault(True) lowCtrlLayout.addWidget(nextButton) nextButton.clicked.connect(self.findNext) else: filterButton = QPushButton(_('&Filter')) lowCtrlLayout.addWidget(filterButton) filterButton.clicked.connect(self.startFilter) self.endFilterButton = QPushButton(_('&End Filter')) lowCtrlLayout.addWidget(self.endFilterButton) self.endFilterButton.setEnabled(False) self.endFilterButton.clicked.connect(self.endFilter) lowCtrlLayout.addStretch() closeButton = QPushButton(_('&Close')) lowCtrlLayout.addWidget(closeButton) closeButton.clicked.connect(self.close) origTypeName = nodeFormat.name if nodeFormat else '' self.loadTypeNames(origTypeName) self.loadSavedNames() self.ruleList.append(ConditionRule(1, self.fieldNames)) self.mainLayout.addWidget(self.ruleList[0]) def addNewRule(self, checked=False, combineBool='and'): """Add a new empty rule to the dialog. Arguments: checked -- unused placekeeper variable for signal combineBool -- the boolean op for combining with the previous rule """ if self.ruleList: boolBox = QComboBox() boolBox.setEditable(False) self.combiningBoxes.append(boolBox) boolBox.addItems([_(op) for op in _boolOper]) if combineBool != 'and': boolBox.setCurrentIndex(1) self.mainLayout.insertWidget(len(self.ruleList) * 2 - 1, boolBox, 0, Qt.AlignmentFlag.AlignHCenter) rule = ConditionRule(len(self.ruleList) + 1, self.fieldNames) self.ruleList.append(rule) self.mainLayout.insertWidget(len(self.ruleList) * 2 - 2, rule) self.removeButton.setEnabled(True) def removeRule(self): """Remove the last rule from the dialog. """ if self.ruleList: if self.combiningBoxes: self.combiningBoxes[-1].hide() del self.combiningBoxes[-1] self.ruleList[-1].hide() del self.ruleList[-1] if self.dialogType == FindDialogType.typeDialog: self.removeButton.setEnabled(len(self.ruleList) > 0) else: self.removeButton.setEnabled(len(self.ruleList) > 1) def clearRules(self): """Remove all rules from the dialog and add default rule. """ for box in self.combiningBoxes: box.hide() for rule in self.ruleList: rule.hide() self.combiningBoxes = [] self.ruleList = [ConditionRule(1, self.fieldNames)] self.mainLayout.insertWidget(0, self.ruleList[0]) self.removeButton.setEnabled(True) def setCondition(self, conditional, typeName=''): """Set rule values to match the given conditional. Arguments: conditional -- the Conditional class to match typeName -- an optional type name used with some dialog types """ if self.typeCombo: if typeName: self.typeCombo.setCurrentIndex(self.typeCombo. findText(typeName)) else: self.typeCombo.setCurrentIndex(0) while len(self.ruleList) > 1: self.removeRule() if conditional: self.ruleList[0].setCondition(conditional.conditionLines[0]) for conditionLine in conditional.conditionLines[1:]: self.addNewRule(combineBool=conditionLine.boolOper) self.ruleList[-1].setCondition(conditionLine) def conditional(self): """Return a Conditional instance for the current settings. """ combineBools = [0] + [boolBox.currentIndex() for boolBox in self.combiningBoxes] typeName = self.typeCombo.currentText() if self.typeCombo else '' if typeName == _allTypeEntry: typeName = '' conditional = Conditional('', typeName) for boolIndex, rule in zip(combineBools, self.ruleList): condition = rule.conditionLine() if boolIndex != 0: condition.boolOper = 'or' conditional.conditionLines.append(condition) return conditional def loadTypeNames(self, origTypeName=''): """Load format type names into combo box. Arguments: origTypeName -- a starting type name if given """ if not origTypeName: origTypeName = self.typeCombo.currentText() nodeFormats = globalref.mainControl.activeControl.structure.treeFormats self.typeCombo.blockSignals(True) self.typeCombo.clear() self.typeCombo.addItem(_allTypeEntry) typeNames = nodeFormats.typeNames() self.typeCombo.addItems(typeNames) if origTypeName and origTypeName != _allTypeEntry: try: self.typeCombo.setCurrentIndex(typeNames.index(origTypeName) + 1) except ValueError: if self.endFilterButton and self.endFilterButton.isEnabled(): self.endFilter() self.clearRules() self.typeCombo.blockSignals(False) self.updateDataType() def updateDataType(self): """Update the node format based on a data type change. """ typeName = self.typeCombo.currentText() if not typeName: return nodeFormats = globalref.mainControl.activeControl.structure.treeFormats if typeName == _allTypeEntry: fieldNameSet = set() for typeFormat in nodeFormats.values(): fieldNameSet.update(typeFormat.fieldNames()) self.fieldNames = sorted(list(fieldNameSet)) else: self.fieldNames = nodeFormats[typeName].fieldNames() for rule in self.ruleList: currentField = rule.conditionLine().fieldName if currentField not in self.fieldNames: if self.endFilterButton and self.endFilterButton.isEnabled(): self.endFilter() self.clearRules() break rule.reloadFieldBox(self.fieldNames, currentField) def loadSavedNames(self, updateOtherDialog=False): """Refresh the list of saved rule names. """ selNum = 0 if self.saveListBox.count(): selNum = self.saveListBox.currentRow() self.saveListBox.clear() nodeFormats = globalref.mainControl.activeControl.structure.treeFormats savedRules = nodeFormats.savedConditions() ruleNames = sorted(list(savedRules.keys())) if ruleNames: self.saveListBox.addItems(ruleNames) if selNum >= len(ruleNames): selNum = len(ruleNames) - 1 self.saveListBox.setCurrentRow(selNum) self.loadSavedButton.setEnabled(len(ruleNames) > 0) self.delSavedButton.setEnabled(len(ruleNames) > 0) if updateOtherDialog: if (self != globalref.mainControl.findConditionDialog and globalref.mainControl.findConditionDialog and globalref.mainControl.findConditionDialog.isVisible()): globalref.mainControl.findConditionDialog.loadSavedNames() elif (self != globalref.mainControl.filterConditionDialog and globalref.mainControl.filterConditionDialog and globalref.mainControl.filterConditionDialog .isVisible()): globalref.mainControl.filterConditionDialog.loadSavedNames() def updateSaveEnable(self): """Set the save rule button enabled based on save name entry. """ self.saveButton.setEnabled(len(self.saveNameEdit.text())) def updateFilterControls(self): """Set filter button status based on active window changes. """ window = globalref.mainControl.activeControl.activeWindow if window.treeFilterView: filterView = window.treeFilterView conditional = filterView.conditionalFilter self.setCondition(conditional, conditional.origNodeFormatName) self.endFilterButton.setEnabled(True) else: self.endFilterButton.setEnabled(False) def loadSavedRule(self): """Load the current saved rule into the dialog. """ nodeFormats = globalref.mainControl.activeControl.structure.treeFormats savedRules = nodeFormats.savedConditions() ruleName = self.saveListBox.currentItem().text() conditional = savedRules[ruleName] self.setCondition(conditional, conditional.origNodeFormatName) def saveRule(self): """Save the current rule settings. """ name = self.saveNameEdit.text() self.saveNameEdit.setText('') treeStructure = globalref.mainControl.activeControl.structure undo.FormatUndo(treeStructure.undoList, treeStructure.treeFormats, treeformats.TreeFormats()) typeName = self.typeCombo.currentText() if typeName == _allTypeEntry: nodeFormat = treeStructure.treeFormats else: nodeFormat = treeStructure.treeFormats[typeName] nodeFormat.savedConditionText[name] = (self.conditional(). conditionStr()) self.loadSavedNames(True) self.saveListBox.setCurrentItem(self.saveListBox. findItems(name, Qt.MatchFlag.MatchExactly)[0]) globalref.mainControl.activeControl.setModified() def deleteRule(self): """Remove the current saved rule. """ treeStructure = globalref.mainControl.activeControl.structure nodeFormats = treeStructure.treeFormats undo.FormatUndo(treeStructure.undoList, nodeFormats, treeformats.TreeFormats()) savedRules = nodeFormats.savedConditions() ruleName = self.saveListBox.currentItem().text() conditional = savedRules[ruleName] if conditional.origNodeFormatName: typeFormat = nodeFormats[conditional. origNodeFormatName] del typeFormat.savedConditionText[ruleName] else: del nodeFormats.savedConditionText[ruleName] self.loadSavedNames(True) globalref.mainControl.activeControl.setModified() def find(self, forward=True): """Find another match in the indicated direction. Arguments: forward -- next if True, previous if False """ self.resultLabel.setText('') conditional = self.conditional() control = globalref.mainControl.activeControl if not control.findNodesByCondition(conditional, forward): self.resultLabel.setText(_('No conditional matches were found')) def findPrevious(self): """Find the previous match. """ self.find(False) def findNext(self): """Find the next match. """ self.find(True) def startFilter(self): """Start filtering nodes. """ window = globalref.mainControl.activeControl.activeWindow filterView = window.filterView() filterView.conditionalFilter = self.conditional() filterView.updateContents() self.endFilterButton.setEnabled(True) def endFilter(self): """Stop filtering nodes. """ window = globalref.mainControl.activeControl.activeWindow window.removeFilterView() self.endFilterButton.setEnabled(False) def closeEvent(self, event): """Signal that the dialog is closing. Arguments: event -- the close event """ self.dialogShown.emit(False) def reject(self): """Handle use of escape key to close this dialog. """ self.close() class ConditionRule(QGroupBox): """Group boxes for conditional rules in the ConditionDialog. """ def __init__(self, num, fieldNames, parent=None): """Create the conditional rule group box. Arguments: num -- the sequence number for the title fieldNames -- a list of available field names parent -- the parent dialog """ super().__init__(parent) self.fieldNames = fieldNames self.setTitle(_('Rule {0}').format(num)) layout = QHBoxLayout(self) self.fieldBox = QComboBox() self.fieldBox.setEditable(False) self.fieldBox.addItems(fieldNames) layout.addWidget(self.fieldBox) self.operBox = QComboBox() self.operBox.setEditable(False) self.operBox.addItems([_(op) for op in _operators]) layout.addWidget(self.operBox) self.operBox.currentIndexChanged.connect(self.changeOper) self.editor = QLineEdit() layout.addWidget(self.editor) self.fieldBox.setFocus() def reloadFieldBox(self, fieldNames, currentField=''): """Load the field combo box with a new field list. Arguments: fieldNames -- list of field names to add currentField -- a field name to make current if given """ self.fieldNames = fieldNames self.fieldBox.clear() self.fieldBox.addItems(fieldNames) if currentField: fieldNum = fieldNames.index(currentField) self.fieldBox.setCurrentIndex(fieldNum) self.changeOper() def setCondition(self, conditionLine): """Set values to match the given condition. Arguments: conditionLine -- the ConditionLine to match """ fieldNum = self.fieldNames.index(conditionLine.fieldName) self.fieldBox.setCurrentIndex(fieldNum) operNum = _operators.index(conditionLine.oper) self.operBox.setCurrentIndex(operNum) self.editor.setText(conditionLine.value) def conditionLine(self): """Return a conditionLine for the current settings. """ operTransDict = dict([(_(name), name) for name in _operators]) oper = operTransDict[self.operBox.currentText()] return ConditionLine('and', self.fieldBox.currentText(), oper, self.editor.text()) def changeOper(self): """Set the field available based on an operator change. """ realOp = self.operBox.currentText() not in (_(op) for op in ('True', 'False')) self.editor.setEnabled(realOp) if (not realOp and self.parent().typeCombo.currentText() == _allTypeEntry): realOp = True self.fieldBox.setEnabled(realOp) class SmallListWidget(QListWidget): """ListWidget with a smaller size hint. """ def __init__(self, parent=None): """Initialize the widget. Arguments: parent -- the parent, if given """ super().__init__(parent) def sizeHint(self): """Return smaller height. """ if self.count(): rowHeight = self.sizeHintForRow(0) else: self.addItem('tmp') rowHeight = self.sizeHintForRow(0) self.takeItem(0) newHeight = rowHeight * 3 + self.frameWidth() * 2 return QSize(super().sizeHint().width(), newHeight) TreeLine-3.2.1/source/configdialog.py000066400000000000000000003175611506556630100175470ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # configdialog.py, provides classes for the type configuration dialog # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import copy import operator from PyQt6.QtCore import QPoint, QSize, Qt, pyqtSignal from PyQt6.QtGui import QTextCursor from PyQt6.QtWidgets import (QAbstractItemView, QApplication, QButtonGroup, QCheckBox, QComboBox, QDialog, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListView, QListWidget, QListWidgetItem, QMenu, QMessageBox, QPushButton, QScrollArea, QSizePolicy, QSpinBox, QTabWidget, QTextEdit, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget) import nodeformat import fieldformat import icondict import conditional import matheval import globalref class ConfigDialog(QDialog): """Class override for the main config dialog Contains the tabbed pages that handle the actual settings. """ dialogShown = pyqtSignal(bool) treeStruct = None formatsRef = None currentTypeName = '' currentFieldName = '' def __init__(self, parent=None): """Initialize the config dialog. Arguments: parent -- the parent window """ super().__init__(parent) self.setAttribute(Qt.WidgetAttribute.WA_QuitOnClose, False) self.setWindowFlags(Qt.WindowType.Window) self.setWindowTitle(_('Configure Data Types')) self.prevPage = None self.localControl = None self.selectionModel = None topLayout = QVBoxLayout(self) self.setLayout(topLayout) self.tabs = QTabWidget() topLayout.addWidget(self.tabs) typeListPage = TypeListPage(self) self.tabs.addTab(typeListPage, _('T&ype List')) typeConfigPage = TypeConfigPage(self) self.tabs.addTab(typeConfigPage, _('Typ&e Config')) fieldListPage = FieldListPage(self) self.tabs.addTab(fieldListPage, _('Field &List')) fieldConfigPage = FieldConfigPage(self) self.tabs.addTab(fieldConfigPage, _('&Field Config')) outputPage = OutputPage(self) self.tabs.addTab(outputPage, _('O&utput')) self.tabs.currentChanged.connect(self.updatePage) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) self.advancedButton = QPushButton(_('&Show Advanced')) ctrlLayout.addWidget(self.advancedButton) self.advancedButton.setCheckable(True) self.advancedButton.clicked.connect(self.toggleAdavanced) ctrlLayout.addStretch() okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.applyAndClose) self.applyButton = QPushButton(_('&Apply')) ctrlLayout.addWidget(self.applyButton) self.applyButton.clicked.connect(self.applyChanges) self.resetButton = QPushButton(_('&Reset')) ctrlLayout.addWidget(self.resetButton) self.resetButton.clicked.connect(self.reset) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.resetAndClose) def setRefs(self, localControl, resetSelect=False, forceCopy=False): """Set refs to model and formats, then update dialog data. Sets current type to current node's type if resetSelect or if invalid. Sets current field to first field if resetSelect or if invalid. Arguments: localControl -- a reference to the local control resetSelect -- if True, forces reset of current selections forceCopy -- if True, force making a new copy of formats """ self.localControl = localControl ConfigDialog.treeStruct = localControl.structure ConfigDialog.formatsRef = (ConfigDialog.treeStruct. getConfigDialogFormats(forceCopy)) self.selectionModel = localControl.currentSelectionModel() self.updateSelections(resetSelect) self.prevPage = None self.updatePage() self.applyButton.setEnabled(ConfigDialog.formatsRef.configModified) self.resetButton.setEnabled(ConfigDialog.formatsRef.configModified) def updateSelections(self, forceUpdate=False): """Sets current type & current field if invalid or forceUpdate is True. Arguments: forceUpdate -- if True, forces reset of current selections """ if forceUpdate or (ConfigDialog.currentTypeName not in ConfigDialog.formatsRef): try: ConfigDialog.currentTypeName = (self.selectionModel. currentNode().formatRef.name) except AttributeError: # no current node ConfigDialog.currentTypeName = (ConfigDialog.treeStruct. childList[0].formatRef.name) if forceUpdate or (ConfigDialog.currentFieldName not in ConfigDialog.formatsRef[ConfigDialog. currentTypeName].fieldNames()): ConfigDialog.currentFieldName = (ConfigDialog. formatsRef[ConfigDialog. currentTypeName]. fieldNames()[0]) def updatePage(self): """Update new page and advanced button state when changing tabs. """ if self.prevPage: self.prevPage.readChanges() page = self.tabs.currentWidget() self.advancedButton.setEnabled(len(page.advancedWidgets)) page.toggleAdvanced(self.advancedButton.isChecked()) page.updateContent() self.prevPage = page def setModified(self, dummyArg=None, modified=True): """Set the format to a modified status and update the controls. Arguments: dummyArg -- placeholder for unused signal arguments modified -- set to modified if True """ ConfigDialog.formatsRef.configModified = modified self.applyButton.setEnabled(modified) self.resetButton.setEnabled(modified) def toggleAdavanced(self, show): """Toggle the display of advanced widgets in the sub-dialogs. Arguments: show -- show if true, hide if false """ if show: self.advancedButton.setText(_('&Hide Advanced')) else: self.advancedButton.setText(_('&Show Advanced')) page = self.tabs.currentWidget() page.toggleAdvanced(show) def reset(self): """Set the formats back to original settings. """ ConfigDialog.formatsRef = (ConfigDialog.treeStruct. getConfigDialogFormats(True)) self.updateSelections() self.setModified(modified=False) self.prevPage = None self.updatePage() def applyChanges(self): """Apply copied format changes to the main format. Return False if there is a circular math reference. """ self.tabs.currentWidget().readChanges() if ConfigDialog.formatsRef.configModified: try: ConfigDialog.treeStruct.applyConfigDialogFormats() except matheval.CircularMathError: QMessageBox.warning(self, 'TreeLine', _('Error - circular reference in math field equations')) return False self.setModified(modified=False) self.localControl.updateAll() return True def applyAndClose(self): """Apply copied format changes to the main format and close the dialog. """ if self.applyChanges(): self.close() def resetAndClose(self): """Set the formats back to original settings and close the dialog. """ self.reset() self.close() def closeEvent(self, event): """Signal that the dialog is closing. Arguments: event -- the close event """ self.dialogShown.emit(False) def reject(self): """Handle use of escape key to close this dialog. """ self.close() class ConfigPage(QWidget): """Abstract base class for config dialog tabbed pages. """ def __init__(self, parent=None): """Initialize the config dialog page. Arguments: parent -- the parent overall dialog """ super().__init__(parent) self.mainDialogRef = parent self.advancedWidgets = [] def updateContent(self): """Update page contents from current format settings. Base class does nothing. """ pass def readChanges(self): """Make changes to the format for each widget. Base class does nothing. """ pass def changeCurrentType(self, typeName): """Change the current format type based on a signal from lists. Arguments: typeName -- the name of the new current type """ self.readChanges() ConfigDialog.currentTypeName = typeName ConfigDialog.currentFieldName = (ConfigDialog.formatsRef[typeName]. fieldNames()[0]) if type(self) != TypeListPage: # "if" statement added to work around list view selection bug self.updateContent() def changeCurrentField(self, fieldName): """Change the current format field based on a signal from lists. Arguments: fieldName -- the name of the new current field """ self.readChanges() ConfigDialog.currentFieldName = fieldName self.updateContent() def toggleAdvanced(self, show=True): """Toggle the display state of advanced widgets. Arguments: show -- show if true, hide if false """ for widget in self.advancedWidgets: widget.setVisible(show) class TypeListPage(ConfigPage): """Config dialog page with an editable list of node types. """ def __init__(self, parent=None): """Initialize the config dialog page. Arguments: parent -- the parent overall dialog """ super().__init__(parent) topLayout = QVBoxLayout(self) box = QGroupBox(_('Add or Remove Data Types')) topLayout.addWidget(box) horizLayout = QHBoxLayout(box) self.listBox = QListWidget() self.listBox.setSelectionMode(QAbstractItemView.SelectionMode. SingleSelection) horizLayout.addWidget(self.listBox) self.listBox.currentTextChanged.connect(self.changeCurrentType) buttonLayout = QVBoxLayout() horizLayout.addLayout(buttonLayout) newButton = QPushButton(_('&New Type...')) buttonLayout.addWidget(newButton) newButton.clicked.connect(self.newType) copyButton = QPushButton(_('Co&py Type...')) buttonLayout.addWidget(copyButton) copyButton.clicked.connect(self.copyType) renameButton = QPushButton(_('Rena&me Type...')) buttonLayout.addWidget(renameButton) renameButton.clicked.connect(self.renameType) deleteButton = QPushButton(_('&Delete Type')) buttonLayout.addWidget(deleteButton) deleteButton.clicked.connect(self.deleteType) def updateContent(self): """Update page contents from current format settings. """ names = ConfigDialog.formatsRef.typeNames() self.listBox.blockSignals(True) self.listBox.clear() self.listBox.addItems(names) self.listBox.setCurrentRow(names.index(ConfigDialog.currentTypeName)) self.listBox.blockSignals(False) def newType(self): """Create a new type based on button signal. """ dlg = NameEntryDialog(_('Add Type'), _('Enter new type name:'), '', '', ConfigDialog.formatsRef.typeNames(), self) if dlg.exec() == QDialog.DialogCode.Accepted: newFormat = nodeformat.NodeFormat(dlg.text, ConfigDialog.formatsRef, None, True) ConfigDialog.formatsRef[dlg.text] = newFormat ConfigDialog.currentTypeName = dlg.text ConfigDialog.currentFieldName = newFormat.fieldNames()[0] self.updateContent() self.mainDialogRef.setModified() def copyType(self): """Copy selected type based on button signal. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] dlg = NameEntryDialog(_('Copy Type'), _('Enter new type name:'), ConfigDialog.currentTypeName, _('&Derive from original'), ConfigDialog.formatsRef.typeNames(), self) if currentFormat.genericType: dlg.extraCheckBox.setEnabled(False) if dlg.exec() == QDialog.DialogCode.Accepted: newFormat = copy.deepcopy(currentFormat) newFormat.name = dlg.text # avoid using copied reference for parentFormats newFormat.parentFormats = currentFormat.parentFormats ConfigDialog.formatsRef[dlg.text] = newFormat ConfigDialog.currentTypeName = dlg.text if dlg.extraChecked: newFormat.genericType = currentFormat.name ConfigDialog.formatsRef.updateDerivedRefs() self.updateContent() self.mainDialogRef.setModified() def renameType(self): """Rename the selected type based on button signal. """ oldName = ConfigDialog.currentTypeName dlg = NameEntryDialog(_('Rename Type'), _('Rename from {} to:').format(oldName), oldName, '', ConfigDialog.formatsRef.typeNames(), self) if dlg.exec() == QDialog.DialogCode.Accepted: currentType = ConfigDialog.formatsRef[oldName] currentType.name = dlg.text del ConfigDialog.formatsRef[oldName] ConfigDialog.formatsRef[dlg.text] = currentType # reverse the rename dict - find original name (multiple renames) reverseDict = {} for old, new in ConfigDialog.formatsRef.typeRenameDict.items(): reverseDict[new] = old origName = reverseDict.get(oldName, oldName) ConfigDialog.formatsRef.typeRenameDict[origName] = dlg.text if oldName in ConfigDialog.formatsRef.fieldRenameDict: ConfigDialog.formatsRef.fieldRenameDict[dlg.text] = \ ConfigDialog.formatsRef.fieldRenameDict[oldName] del ConfigDialog.formatsRef.fieldRenameDict[oldName] for nodeType in ConfigDialog.formatsRef.values(): if nodeType.childType == oldName: nodeType.childType = dlg.text if nodeType.genericType == oldName: nodeType.genericType = dlg.text if oldName in nodeType.childTypeLimit: nodeType.childTypeLimit.remove(oldName) nodeType.childTypeLimit.add(dlg.text) ConfigDialog.currentTypeName = dlg.text self.updateContent() self.mainDialogRef.setModified() def deleteType(self): """Delete the selected type based on button signal. """ # reverse the rename dict - find original name (before any rename) reverseDict = {} for old, new in ConfigDialog.formatsRef.typeRenameDict.items(): reverseDict[new] = old origName = reverseDict.get(ConfigDialog.currentTypeName, ConfigDialog.currentTypeName) if ConfigDialog.treeStruct.usesType(origName): QMessageBox.warning(self, 'TreeLine', _('Cannot delete data type being used by nodes')) return del ConfigDialog.formatsRef[ConfigDialog.currentTypeName] if origName != ConfigDialog.currentTypeName: del ConfigDialog.formatsRef.typeRenameDict[origName] for nodeType in ConfigDialog.formatsRef.values(): if nodeType.childType == ConfigDialog.currentTypeName: nodeType.childType = '' if nodeType.genericType == ConfigDialog.currentTypeName: nodeType.genericType = '' nodeType.conditional = None nodeType.childTypeLimit.discard(ConfigDialog.currentTypeName) ConfigDialog.formatsRef.updateDerivedRefs() ConfigDialog.currentTypeName = ConfigDialog.formatsRef.typeNames()[0] ConfigDialog.currentFieldName = ConfigDialog.formatsRef[ConfigDialog. currentTypeName].fieldNames()[0] self.updateContent() self.mainDialogRef.setModified() _noTypeSetName = _('[None]', 'no type set') class TypeConfigPage(ConfigPage): """Config dialog page to change parmaters of a node type. """ def __init__(self, parent=None): """Initialize the config dialog page. Arguments: parent -- the parent overall dialog """ super().__init__(parent) topLayout = QGridLayout(self) typeBox = QGroupBox(_('&Data Type')) topLayout.addWidget(typeBox, 0, 0) typeLayout = QVBoxLayout(typeBox) self.typeCombo = QComboBox() typeLayout.addWidget(self.typeCombo) self.typeCombo.currentTextChanged.connect(self.changeCurrentType) childBox = QGroupBox(_('Default Child &Type')) topLayout.addWidget(childBox, 0, 1) childLayout = QVBoxLayout(childBox) self.childCombo = QComboBox() childLayout.addWidget(self.childCombo) self.childCombo.currentIndexChanged.connect(self.mainDialogRef. setModified) iconBox = QGroupBox(_('Icon')) topLayout.addWidget(iconBox, 1, 1) iconLayout = QHBoxLayout(iconBox) self.iconImage = QLabel() iconLayout.addWidget(self.iconImage) self.iconImage.setAlignment(Qt.AlignmentFlag.AlignCenter) iconButton = QPushButton(_('Change &Icon')) iconLayout.addWidget(iconButton) iconButton.clicked.connect(self.changeIcon) optionsBox = QGroupBox(_('Output Options')) topLayout.addWidget(optionsBox, 1, 0, 2, 1) optionsLayout = QVBoxLayout(optionsBox) self.blanksButton = QCheckBox(_('Add &blank lines between ' 'nodes')) optionsLayout.addWidget(self.blanksButton) self.blanksButton.toggled.connect(self.mainDialogRef.setModified) self.htmlButton = QCheckBox(_('Allow &HTML rich text in format')) optionsLayout.addWidget(self.htmlButton) self.htmlButton.toggled.connect(self.mainDialogRef.setModified) self.bulletButton = QCheckBox(_('Add text bullet&s')) optionsLayout.addWidget(self.bulletButton) self.bulletButton.toggled.connect(self.changeUseBullets) self.tableButton = QCheckBox(_('Use a table for field &data')) optionsLayout.addWidget(self.tableButton) self.tableButton.toggled.connect(self.changeUseTable) # advanced widgets outputSepBox = QGroupBox(_('Combination && Child List Output ' '&Separator')) topLayout.addWidget(outputSepBox, 2, 1) self.advancedWidgets.append(outputSepBox) outputSepLayout = QVBoxLayout(outputSepBox) self.outputSepEdit = QLineEdit() outputSepLayout.addWidget(self.outputSepEdit) sizePolicy = self.outputSepEdit.sizePolicy() sizePolicy.setHorizontalPolicy(QSizePolicy.Policy.Preferred) self.outputSepEdit.setSizePolicy(sizePolicy) self.outputSepEdit.textEdited.connect(self.mainDialogRef.setModified) genericBox = QGroupBox(_('Derived from &Generic Type')) topLayout.addWidget(genericBox, 3, 0) self.advancedWidgets.append(genericBox) genericLayout = QVBoxLayout(genericBox) self.genericCombo = QComboBox() genericLayout.addWidget(self.genericCombo) self.genericCombo.currentIndexChanged.connect(self.setConditionAvail) self.genericCombo.currentIndexChanged.connect(self.mainDialogRef. setModified) conditionBox = QGroupBox(_('Automatic Types')) topLayout.addWidget(conditionBox, 3, 1) self.advancedWidgets.append(conditionBox) conditionLayout = QVBoxLayout(conditionBox) self.conditionButton = QPushButton() conditionLayout.addWidget(self.conditionButton) self.conditionButton.clicked.connect(self.showConditionDialog) typeLimitBox = QGroupBox(_('Child Type Limits')) topLayout.addWidget(typeLimitBox, 4, 0) self.advancedWidgets.append(typeLimitBox) typeLimitLayout = QVBoxLayout(typeLimitBox) self.typeLimitCombo = TypeLimitCombo() typeLimitLayout.addWidget(self.typeLimitCombo) self.typeLimitCombo.limitChanged.connect(self.mainDialogRef. setModified) topLayout.setRowStretch(5, 1) def updateContent(self): """Update page contents from current format settings. """ typeNames = ConfigDialog.formatsRef.typeNames() self.typeCombo.blockSignals(True) self.typeCombo.clear() self.typeCombo.addItems(typeNames) self.typeCombo.setCurrentIndex(typeNames.index(ConfigDialog. currentTypeName)) self.typeCombo.blockSignals(False) currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] self.childCombo.blockSignals(True) self.childCombo.clear() self.childCombo.addItem(_noTypeSetName) self.childCombo.addItems(typeNames) try: childItem = typeNames.index(currentFormat.childType) + 1 except ValueError: childItem = 0 self.childCombo.setCurrentIndex(childItem) self.childCombo.blockSignals(False) icon = globalref.treeIcons.getIcon(currentFormat.iconName, True) if icon: self.iconImage.setPixmap(icon.pixmap(16, 16)) else: self.iconImage.setText(_('None')) self.blanksButton.blockSignals(True) self.blanksButton.setChecked(currentFormat.spaceBetween) self.blanksButton.blockSignals(False) self.htmlButton.blockSignals(True) self.htmlButton.setChecked(currentFormat.formatHtml) self.htmlButton.blockSignals(False) self.bulletButton.blockSignals(True) self.bulletButton.setChecked(currentFormat.useBullets) self.bulletButton.blockSignals(False) self.tableButton.blockSignals(True) self.tableButton.setChecked(currentFormat.useTables) self.tableButton.blockSignals(False) self.htmlButton.setEnabled(not currentFormat.useBullets and not currentFormat.useTables) self.outputSepEdit.setText(currentFormat.outputSeparator) self.genericCombo.blockSignals(True) self.genericCombo.clear() self.genericCombo.addItem(_noTypeSetName) genTypeNames = [name for name in typeNames if name != ConfigDialog.currentTypeName and not ConfigDialog.formatsRef[name].genericType] self.genericCombo.addItems(genTypeNames) try: generic = genTypeNames.index(currentFormat.genericType) + 1 except ValueError: generic = 0 self.genericCombo.setCurrentIndex(generic) self.genericCombo.blockSignals(False) self.setConditionAvail() self.typeLimitCombo.updateLists(typeNames, currentFormat.childTypeLimit) def changeIcon(self): """Show the change icon dialog based on a button press. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] dlg = IconSelectDialog(currentFormat, self) if (dlg.exec() == QDialog.DialogCode.Accepted and dlg.currentIconName != currentFormat.iconName): currentFormat.iconName = dlg.currentIconName self.mainDialogRef.setModified() self.updateContent() def changeUseBullets(self, checked=True): """Change setting to use bullets for output. Does not allow bullets and table to both be checked, and automatically checks use HTML. Arguments: checked -- True if bullets are selected """ if checked: self.tableButton.setChecked(False) self.htmlButton.setChecked(True) self.htmlButton.setEnabled(not checked) self.mainDialogRef.setModified() def changeUseTable(self, checked=True): """Change setting to use tables for output. Does not allow bullets and table to both be checked, and automatically checks use HTML. Arguments: checked -- True if tables are selected """ if checked: self.bulletButton.setChecked(False) self.htmlButton.setChecked(True) self.htmlButton.setEnabled(not checked) self.mainDialogRef.setModified() def setConditionAvail(self): """Enable conditional button if generic or dervived type. Set button text based on presence of conditions. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] if self.genericCombo.currentIndex() > 0 or currentFormat.derivedTypes: self.conditionButton.setEnabled(True) if currentFormat.conditional: self.conditionButton.setText(_('Modify Co&nditional Types')) return else: self.conditionButton.setEnabled(False) self.conditionButton.setText(_('Create Co&nditional Types')) def showConditionDialog(self): """Show the dialog to create or modify conditional types. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] dialog = conditional.ConditionDialog(conditional.FindDialogType. typeDialog, _('Set Types Conditionally'), currentFormat) if currentFormat.conditional: dialog.setCondition(currentFormat.conditional) if dialog.exec() == QDialog.DialogCode.Accepted: currentFormat.conditional = dialog.conditional() if not currentFormat.conditional: currentFormat.conditional = None ConfigDialog.formatsRef.updateDerivedRefs() self.mainDialogRef.setModified() self.updateContent() def readChanges(self): """Make changes to the format for each widget. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] currentFormat.childType = self.childCombo.currentText() if currentFormat.childType == _noTypeSetName: currentFormat.childType = '' currentFormat.outputSeparator = self.outputSepEdit.text() prevGenericType = currentFormat.genericType currentFormat.genericType = self.genericCombo.currentText() if currentFormat.genericType == _noTypeSetName: currentFormat.genericType = '' if currentFormat.genericType != prevGenericType: ConfigDialog.formatsRef.updateDerivedRefs() currentFormat.updateFromGeneric(formatsRef=ConfigDialog.formatsRef) if ConfigDialog.currentFieldName not in currentFormat.fieldNames(): ConfigDialog.currentFieldName = currentFormat.fieldNames()[0] currentFormat.spaceBetween = self.blanksButton.isChecked() currentFormat.formatHtml = self.htmlButton.isChecked() currentFormat.childTypeLimit = self.typeLimitCombo.selectSet useBullets = self.bulletButton.isChecked() useTables = self.tableButton.isChecked() if (useBullets != currentFormat.useBullets or useTables != currentFormat.useTables): currentFormat.useBullets = useBullets currentFormat.useTables = useTables if useBullets: currentFormat.addBullets() elif useTables: currentFormat.addTables() else: currentFormat.clearBulletsAndTables() class FieldListPage(ConfigPage): """Config dialog page with an editable list of fields. """ def __init__(self, parent=None): """Initialize the config dialog page. Arguments: parent -- the parent overall dialog """ super().__init__(parent) topLayout = QVBoxLayout(self) typeBox = QGroupBox(_('&Data Type')) topLayout.addWidget(typeBox) typeLayout = QVBoxLayout(typeBox) self.typeCombo = QComboBox() typeLayout.addWidget(self.typeCombo) self.typeCombo.currentTextChanged.connect(self.changeCurrentType) fieldBox = QGroupBox(_('Modify &Field List')) topLayout.addWidget(fieldBox) horizLayout = QHBoxLayout(fieldBox) self.fieldListBox = QTreeWidget() horizLayout.addWidget(self.fieldListBox) self.fieldListBox.setRootIsDecorated(False) self.fieldListBox.setColumnCount(3) self.fieldListBox.setHeaderLabels([_('Name'), _('Type'), _('Sort Key')]) self.fieldListBox.currentItemChanged.connect(self.changeField) buttonLayout = QVBoxLayout() horizLayout.addLayout(buttonLayout) self.upButton = QPushButton(_('Move U&p')) buttonLayout.addWidget(self.upButton) self.upButton.clicked.connect(self.moveUp) self.downButton = QPushButton(_('Move Do&wn')) buttonLayout.addWidget(self.downButton) self.downButton.clicked.connect(self.moveDown) self.newButton = QPushButton(_('&New Field...')) buttonLayout.addWidget(self.newButton) self.newButton.clicked.connect(self.newField) self.renameButton = QPushButton(_('Rena&me Field...')) buttonLayout.addWidget(self.renameButton) self.renameButton.clicked.connect(self.renameField) self.deleteButton = QPushButton(_('Dele&te Field')) buttonLayout.addWidget(self.deleteButton) self.deleteButton.clicked.connect(self.deleteField) sortKeyButton = QPushButton(_('Sort &Keys...')) buttonLayout.addWidget(sortKeyButton) sortKeyButton.clicked.connect(self.defineSortKeys) def updateContent(self): """Update page contents from current format settings. """ typeNames = ConfigDialog.formatsRef.typeNames() self.typeCombo.blockSignals(True) self.typeCombo.clear() self.typeCombo.addItems(typeNames) self.typeCombo.setCurrentIndex(typeNames.index(ConfigDialog. currentTypeName)) self.typeCombo.blockSignals(False) currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] sortFields = [field for field in currentFormat.fields() if field.sortKeyNum > 0] sortFields.sort(key = operator.attrgetter('sortKeyNum')) if not sortFields: sortFields = [list(currentFormat.fields())[0]] self.fieldListBox.blockSignals(True) self.fieldListBox.clear() for field in currentFormat.fields(): try: sortKey = repr(sortFields.index(field) + 1) sortDir = _('fwd') if field.sortKeyForward else _('rev') sortKey = '{0} ({1})'.format(sortKey, sortDir) except ValueError: sortKey = '' typeName = fieldformat.translatedTypeName(field.typeName) QTreeWidgetItem(self.fieldListBox, [field.name, typeName, sortKey]) selectNum = currentFormat.fieldNames().index(ConfigDialog. currentFieldName) selectItem = self.fieldListBox.topLevelItem(selectNum) self.fieldListBox.setCurrentItem(selectItem) selectItem.setSelected(True) width = self.fieldListBox.viewport().width() self.fieldListBox.setColumnWidth(0, int(width // 2.5)) self.fieldListBox.setColumnWidth(1, int(width // 2.5)) self.fieldListBox.setColumnWidth(2, width // 5) self.fieldListBox.blockSignals(False) num = currentFormat.fieldNames().index(ConfigDialog.currentFieldName) self.upButton.setEnabled(num > 0 and not currentFormat.genericType) self.downButton.setEnabled(num < len(currentFormat.fieldDict) - 1 and not currentFormat.genericType) self.newButton.setEnabled(not currentFormat.genericType) self.renameButton.setEnabled(not currentFormat.genericType) self.deleteButton.setEnabled(len(currentFormat.fieldDict) > 1 and not currentFormat.genericType) def changeField(self, currentItem, prevItem): """Change the current format field based on a tree widget signal. Arguments: currentItem -- the new current tree widget item prevItem -- the old current tree widget item """ self.changeCurrentField(currentItem.text(0)) def moveUp(self): """Move field upward in the list based on button signal. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] fieldList = currentFormat.fieldNames() num = fieldList.index(ConfigDialog.currentFieldName) if num > 0: fieldList[num-1], fieldList[num] = fieldList[num], fieldList[num-1] currentFormat.reorderFields(fieldList) currentFormat.updateDerivedTypes() self.updateContent() self.mainDialogRef.setModified() def moveDown(self): """Move field downward in the list based on button signal. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] fieldList = currentFormat.fieldNames() num = fieldList.index(ConfigDialog.currentFieldName) if num < len(fieldList) - 1: fieldList[num], fieldList[num+1] = fieldList[num+1], fieldList[num] currentFormat.reorderFields(fieldList) currentFormat.updateDerivedTypes() self.updateContent() self.mainDialogRef.setModified() def newField(self): """Create and add a new field based on button signal. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] dlg = NameEntryDialog(_('Add Field'), _('Enter new field name:'), '', '', currentFormat.fieldNames(), self) if dlg.exec() == QDialog.DialogCode.Accepted: currentFormat.addField(dlg.text) ConfigDialog.currentFieldName = dlg.text currentFormat.updateDerivedTypes() self.updateContent() self.mainDialogRef.setModified() def renameField(self): """Prompt for new name and rename field based on button signal. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] fieldList = currentFormat.fieldNames() oldName = ConfigDialog.currentFieldName dlg = NameEntryDialog(_('Rename Field'), _('Rename from {} to:').format(oldName), oldName, '', fieldList, self) if dlg.exec() == QDialog.DialogCode.Accepted: num = fieldList.index(oldName) fieldList[num] = dlg.text for nodeFormat in [currentFormat] + currentFormat.derivedTypes: field = nodeFormat.fieldDict[oldName] field.name = dlg.text nodeFormat.fieldDict[field.name] = field nodeFormat.reorderFields(fieldList) if nodeFormat.conditional: nodeFormat.conditional.renameFields(oldName, field.name) # savedConditions = {} # for name, text in nodeFormat.savedConditionText.items(): # condition = conditional.Conditional(text, nodeFormat.name) # condition.renameFields(oldName, field.name) # savedConditions[name] = condition.conditionStr() # nodeFormat.savedConditionText = savedConditions renameDict = (ConfigDialog.formatsRef.fieldRenameDict. setdefault(nodeFormat.name, {})) # reverse rename dict - find original name (multiple renames) reverseDict = {} for old, new in renameDict.items(): reverseDict[new] = old origName = reverseDict.get(oldName, oldName) renameDict[origName] = dlg.text ConfigDialog.currentFieldName = dlg.text self.updateContent() self.mainDialogRef.setModified() def deleteField(self): """Delete field based on button signal. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] num = currentFormat.fieldNames().index(ConfigDialog.currentFieldName) for nodeFormat in [currentFormat] + currentFormat.derivedTypes: field = nodeFormat.fieldDict[ConfigDialog.currentFieldName] nodeFormat.removeField(field) del nodeFormat.fieldDict[ConfigDialog.currentFieldName] if num > 0: num -= 1 ConfigDialog.currentFieldName = currentFormat.fieldNames()[num] ConfigDialog.formatsRef.updateDerivedRefs() self.updateContent() self.mainDialogRef.setModified() def defineSortKeys(self): """Show a dialog to change sort key fields and directions. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] dlg = SortKeyDialog(currentFormat.fieldDict, self) if dlg.exec() == QDialog.DialogCode.Accepted: self.updateContent() self.mainDialogRef.setModified() _fileInfoFormatName = _('File Info Reference') class FieldConfigPage(ConfigPage): """Config dialog page to change parmaters of a field. """ def __init__(self, parent=None): """Initialize the config dialog page. Arguments: parent -- the parent overall dialog """ super().__init__(parent) self.currentFileInfoField = '' topLayout = QGridLayout(self) typeBox = QGroupBox(_('&Data Type')) topLayout.addWidget(typeBox, 0, 0) typeLayout = QVBoxLayout(typeBox) self.typeCombo = QComboBox() typeLayout.addWidget(self.typeCombo) self.typeCombo.currentTextChanged.connect(self.changeCurrentType) fieldBox = QGroupBox(_('F&ield')) topLayout.addWidget(fieldBox, 0, 1) fieldLayout = QVBoxLayout(fieldBox) self.fieldCombo = QComboBox() fieldLayout.addWidget(self.fieldCombo) self.fieldCombo.currentTextChanged.connect(self. changeCurrentField) fieldTypeBox = QGroupBox(_('&Field Type')) topLayout.addWidget(fieldTypeBox, 1, 0) fieldTypeLayout = QVBoxLayout(fieldTypeBox) self.fieldTypeCombo = QComboBox() fieldTypeLayout.addWidget(self.fieldTypeCombo) self.fieldTypeCombo.addItems(fieldformat.translatedFieldTypes) self.fieldTypeCombo.currentIndexChanged.connect(self.changeFieldType) self.formatBox = QGroupBox(_('Outpu&t Format')) topLayout.addWidget(self.formatBox, 1, 1) formatLayout = QHBoxLayout(self.formatBox) self.formatEdit = QLineEdit() formatLayout.addWidget(self.formatEdit) self.formatEdit.textEdited.connect(self.mainDialogRef.setModified) self.helpButton = QPushButton(_('Format &Help')) formatLayout.addWidget(self.helpButton) self.helpButton.clicked.connect(self.formatHelp) extraBox = QGroupBox(_('Extra Text')) topLayout.addWidget(extraBox, 2, 0, 2, 1) extraLayout = QVBoxLayout(extraBox) extraLayout.setSpacing(0) prefixLabel = QLabel(_('&Prefix')) extraLayout.addWidget(prefixLabel) self.prefixEdit = QLineEdit() extraLayout.addWidget(self.prefixEdit) prefixLabel.setBuddy(self.prefixEdit) self.prefixEdit.textEdited.connect(self.mainDialogRef.setModified) extraLayout.addSpacing(8) suffixLabel = QLabel(_('Suffi&x')) extraLayout.addWidget(suffixLabel) self.suffixEdit = QLineEdit() extraLayout.addWidget(self.suffixEdit) suffixLabel.setBuddy(self.suffixEdit) self.suffixEdit.textEdited.connect(self.mainDialogRef.setModified) defaultBox = QGroupBox(_('Default &Value for New Nodes')) topLayout.addWidget(defaultBox, 2, 1) defaultLayout = QVBoxLayout(defaultBox) self.defaultCombo = QComboBox() defaultLayout.addWidget(self.defaultCombo) self.defaultCombo.setEditable(True) self.defaultCombo.editTextChanged.connect(self.mainDialogRef. setModified) self.heightBox = QGroupBox(_('Editor Height')) topLayout.addWidget(self.heightBox, 3, 1) heightLayout = QHBoxLayout(self.heightBox) heightLabel = QLabel(_('Num&ber of text lines')) heightLayout.addWidget(heightLabel) self.heightCtrl = QSpinBox() heightLayout.addWidget(self.heightCtrl) self.heightCtrl.setMinimum(1) self.heightCtrl.setMaximum(999) heightLabel.setBuddy(self.heightCtrl) self.heightCtrl.valueChanged.connect(self.mainDialogRef.setModified) self.equationBox = QGroupBox(_('Math Equation')) topLayout.addWidget(self.equationBox, 4, 0, 1, 2) equationLayout = QHBoxLayout(self.equationBox) self.equationViewer = QLineEdit() equationLayout.addWidget(self.equationViewer) self.equationViewer.setReadOnly(True) equationButton = QPushButton(_('Define Equation')) equationLayout.addWidget(equationButton) equationButton.clicked.connect(self.defineMathEquation) htmlBox = QGroupBox(_('Output HTML')) topLayout.addWidget(htmlBox, 5, 0) htmlLayout = QVBoxLayout(htmlBox) self.htmlButton = QCheckBox(_('Evaluate &HTML tags')) htmlLayout.addWidget(self.htmlButton) self.htmlButton.toggled.connect(self.mainDialogRef.setModified) topLayout.setRowStretch(6, 1) def updateContent(self): """Update page contents from current format settings. """ typeNames = ConfigDialog.formatsRef.typeNames() self.typeCombo.blockSignals(True) self.typeCombo.clear() self.typeCombo.addItems(typeNames) self.typeCombo.addItem(_fileInfoFormatName) if self.currentFileInfoField: self.typeCombo.setCurrentIndex(len(typeNames)) else: self.typeCombo.setCurrentIndex(typeNames.index(ConfigDialog. currentTypeName)) self.typeCombo.blockSignals(False) currentFormat, currentField = self.currentFormatAndField() self.fieldCombo.blockSignals(True) self.fieldCombo.clear() self.fieldCombo.addItems(currentFormat.fieldNames()) selectNum = currentFormat.fieldNames().index(currentField.name) self.fieldCombo.setCurrentIndex(selectNum) self.fieldCombo.blockSignals(False) self.fieldTypeCombo.blockSignals(True) selectNum = fieldformat.fieldTypes.index(currentField.typeName) self.fieldTypeCombo.setCurrentIndex(selectNum) self.fieldTypeCombo.blockSignals(False) # also disable for generic types self.fieldTypeCombo.setEnabled(not self.currentFileInfoField) self.formatBox.setEnabled(currentField.defaultFormat != '') if (hasattr(currentField, 'resultType') and currentField.resultType == fieldformat.MathResult.text): self.formatBox.setEnabled(False) self.formatEdit.setText(currentField.format) self.prefixEdit.setText(currentField.prefix) self.suffixEdit.setText(currentField.suffix) self.defaultCombo.blockSignals(True) self.defaultCombo.clear() initDefault = currentField.getEditorInitDefault() self.defaultCombo.addItem(initDefault) initDefaultList = currentField.initDefaultChoices() if initDefaultList: if initDefaultList[0] == initDefault: initDefaultList[0] = '' # don't duplicate first entry self.defaultCombo.addItems(initDefaultList) self.defaultCombo.setCurrentIndex(0) self.defaultCombo.blockSignals(False) self.defaultCombo.setEnabled(currentField.supportsInitDefault and not self.currentFileInfoField) self.heightCtrl.blockSignals(True) self.heightCtrl.setValue(currentField.numLines) self.heightCtrl.blockSignals(False) self.heightBox.setEnabled(not self.currentFileInfoField and currentField.editorClassName in ('RichTextEditor', 'HtmlTextEditor', 'PlainTextEditor')) self.htmlButton.blockSignals(True) self.htmlButton.setChecked(currentField.evalHtml) self.htmlButton.blockSignals(False) self.htmlButton.setEnabled(not currentField.fixEvalHtmlSetting) if currentField.typeName == 'Math': self.equationBox.show() eqnText = currentField.equationText() self.equationViewer.setText(eqnText) else: self.equationBox.hide() def currentFormatAndField(self): """Return a tuple of the current format and field. Adjusts for a current file info field. """ if self.currentFileInfoField: currentFormat = ConfigDialog.formatsRef.fileInfoFormat fieldName = self.currentFileInfoField else: currentFormat = ConfigDialog.formatsRef[ConfigDialog. currentTypeName] fieldName = ConfigDialog.currentFieldName currentField = currentFormat.fieldDict[fieldName] return (currentFormat, currentField) def changeCurrentType(self, typeName): """Change the current format type based on a signal from lists. Arguments: typeName -- the name of the new current type """ self.readChanges() if typeName == _fileInfoFormatName: self.currentFileInfoField = (ConfigDialog.formatsRef. fileInfoFormat.fieldNames()[0]) else: ConfigDialog.currentTypeName = typeName ConfigDialog.currentFieldName = (ConfigDialog.formatsRef[typeName]. fieldNames()[0]) self.currentFileInfoField = '' self.updateContent() def changeCurrentField(self, fieldName): """Change the current format field based on a signal from lists. Arguments: fieldName -- the name of the new current field """ self.readChanges() if self.currentFileInfoField: self.currentFileInfoField = fieldName else: ConfigDialog.currentFieldName = fieldName self.updateContent() def changeFieldType(self): """Change the field type based on a combo box signal. """ self.readChanges() # preserve previous changes currentFormat, currentField = self.currentFormatAndField() selectNum = self.fieldTypeCombo.currentIndex() fieldTypeName = fieldformat.fieldTypes[selectNum] currentField.changeType(fieldTypeName) currentFormat.updateDerivedTypes() self.updateContent() self.mainDialogRef.setModified() def defineMathEquation(self): """Show the dialog to define an equation for a Math field. """ currentFormat, currentField = self.currentFormatAndField() prevEqnText = currentField.equationText() prevResultType = currentField.resultType dlg = MathEquationDialog(currentFormat, currentField, self) if (dlg.exec() == QDialog.DialogCode.Accepted and (currentField.equationText() != prevEqnText or currentField.resultType != prevResultType)): self.mainDialogRef.setModified() self.updateContent() def formatHelp(self): """Provide a format help menu based on a button signal. """ currentFormat, currentField = self.currentFormatAndField() menu = QMenu(self) self.formatHelpDict = {} for descript, key in currentField.getFormatHelpMenuList(): if descript: self.formatHelpDict[descript] = key menu.addAction(descript) else: menu.addSeparator() menu.popup(self.helpButton. mapToGlobal(QPoint(0, self.helpButton.height()))) menu.triggered.connect(self.insertFormat) def insertFormat(self, action): """Insert format text from help menu into edit box. Arguments: action -- the action from the help menu """ self.formatEdit.insert(self.formatHelpDict[action.text()]) def readChanges(self): """Make changes to the format for each widget. """ currentFormat, currentField = self.currentFormatAndField() if not currentField.fixEvalHtmlSetting: currentField.evalHtml = self.htmlButton.isChecked() prevFormat = currentField.format try: currentField.setFormat(self.formatEdit.text()) if (self.currentFileInfoField and self.formatEdit.text() != prevFormat): currentFormat.fieldFormatModified = True except ValueError: self.formatEdit.setText(currentField.format) currentField.prefix = self.prefixEdit.text() currentField.suffix = self.suffixEdit.text() if self.currentFileInfoField and (currentField.prefix or currentField.suffix): currentFormat.fieldFormatModified = True try: currentField.setInitDefault(self.defaultCombo.currentText()) except ValueError: self.defaultCombo.blockSignals(True) self.defaultCombo.setEditText(currentField.getEditorInitDefault()) self.defaultCombo.blockSignals(False) currentField.numLines = self.heightCtrl.value() _refLevelList = ['No Other Reference', 'File Info Reference', 'Any Ancestor Reference', 'Parent Reference', 'Grandparent Reference', 'Great Grandparent Reference', 'Child Reference', 'Child Count'] # _refLevelFlags correspond to _refLevelList _refLevelFlags = ['', '!', '?', '*', '**', '***', '&', '#'] fieldPattern = re.compile(r'{\*.*?\*}') class OutputPage(ConfigPage): """Config dialog page to define the node output strings. """ def __init__(self, parent=None): """Initialize the config dialog page. Arguments: parent -- the parent overall dialog """ super().__init__(parent) self.refLevelFlag = '' self.refLevelType = None topLayout = QGridLayout(self) typeBox = QGroupBox(_('&Data Type')) topLayout.addWidget(typeBox, 0, 0) typeLayout = QVBoxLayout(typeBox) self.typeCombo = QComboBox() typeLayout.addWidget(self.typeCombo) self.typeCombo.currentTextChanged.connect(self.changeCurrentType) fieldBox = QGroupBox(_('F&ield List')) topLayout.addWidget(fieldBox, 1, 0, 2, 1) boxLayout = QVBoxLayout(fieldBox) self.fieldListBox = QTreeWidget() boxLayout.addWidget(self.fieldListBox) self.fieldListBox.setRootIsDecorated(False) self.fieldListBox.setSelectionMode(QAbstractItemView.SelectionMode. ExtendedSelection) self.fieldListBox.setColumnCount(2) self.fieldListBox.setHeaderLabels([_('Name'), _('Type')]) self.fieldListBox.itemSelectionChanged.connect(self.changeField) titleButtonLayout = QVBoxLayout() topLayout.addLayout(titleButtonLayout, 1, 1) self.toTitleButton = QPushButton('>>') titleButtonLayout.addWidget(self.toTitleButton) self.toTitleButton.setMaximumWidth(self.toTitleButton. sizeHint().height()) self.toTitleButton.clicked.connect(self.fieldToTitle) self.delTitleButton = QPushButton('<<') titleButtonLayout.addWidget(self.delTitleButton) self.delTitleButton.setMaximumWidth(self.delTitleButton. sizeHint().height()) self.delTitleButton.clicked.connect(self.delTitleField) titleBox = QGroupBox(_('&Title Format')) topLayout.addWidget(titleBox, 1, 2) titleLayout = QVBoxLayout(titleBox) self.titleEdit = TitleEdit() titleLayout.addWidget(self.titleEdit) self.titleEdit.cursorPositionChanged.connect(self. setControlAvailability) self.titleEdit.textEdited.connect(self.mainDialogRef.setModified) outputButtonLayout = QVBoxLayout() topLayout.addLayout(outputButtonLayout, 2, 1) self.toOutputButton = QPushButton('>>') outputButtonLayout.addWidget(self.toOutputButton) self.toOutputButton.setMaximumWidth(self.toOutputButton. sizeHint().height()) self.toOutputButton.clicked.connect(self.fieldToOutput) self.delOutputButton = QPushButton('<<') outputButtonLayout.addWidget(self.delOutputButton) self.delOutputButton.setMaximumWidth(self.delOutputButton. sizeHint().height()) self.delOutputButton.clicked.connect(self.delOutputField) outputBox = QGroupBox(_('Out&put Format')) topLayout.addWidget(outputBox, 2, 2) outputLayout = QVBoxLayout(outputBox) self.outputEdit = QTextEdit() self.outputEdit.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap) outputLayout.addWidget(self.outputEdit) self.outputEdit.setTabChangesFocus(True) self.outputEdit.cursorPositionChanged.connect(self. setControlAvailability) self.outputEdit.textChanged.connect(self.mainDialogRef.setModified) # advanced widgets otherBox = QGroupBox(_('Other Field References')) topLayout.addWidget(otherBox, 0, 2) self.advancedWidgets.append(otherBox) otherLayout = QHBoxLayout(otherBox) levelLayout = QVBoxLayout() otherLayout.addLayout(levelLayout) levelLayout.setSpacing(0) levelLabel = QLabel(_('Reference Le&vel')) levelLayout.addWidget(levelLabel) levelCombo = QComboBox() levelLayout.addWidget(levelCombo) levelLabel.setBuddy(levelCombo) levelCombo.addItems(_refLevelList) levelCombo.currentIndexChanged.connect(self.changeRefLevel) refTypeLayout = QVBoxLayout() otherLayout.addLayout(refTypeLayout) refTypeLayout.setSpacing(0) refTypeLabel = QLabel(_('Refere&nce Type')) refTypeLayout.addWidget(refTypeLabel) self.refTypeCombo = QComboBox() refTypeLayout.addWidget(self.refTypeCombo) refTypeLabel.setBuddy(self.refTypeCombo) self.refTypeCombo.currentIndexChanged.connect(self.changeRefType) topLayout.setRowStretch(1, 1) topLayout.setRowStretch(2, 1) def updateContent(self): """Update page contents from current format settings. """ typeNames = ConfigDialog.formatsRef.typeNames() self.typeCombo.blockSignals(True) self.typeCombo.clear() self.typeCombo.addItems(typeNames) self.typeCombo.setCurrentIndex(typeNames.index(ConfigDialog. currentTypeName)) self.typeCombo.blockSignals(False) currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] self.updateFieldList() self.titleEdit.blockSignals(True) self.titleEdit.setText(currentFormat.getTitleLine()) self.titleEdit.end(False) self.titleEdit.blockSignals(False) self.outputEdit.blockSignals(True) self.outputEdit.setPlainText('\n'.join(currentFormat.getOutputLines())) cursor = self.outputEdit.textCursor() cursor.movePosition(QTextCursor.MoveOperation.End) self.outputEdit.setTextCursor(cursor) self.outputEdit.blockSignals(False) self.refTypeCombo.blockSignals(True) self.refTypeCombo.clear() self.refTypeCombo.addItems(typeNames) refLevelType = (self.refLevelType if self.refLevelType else ConfigDialog.currentTypeName) try: self.refTypeCombo.setCurrentIndex(typeNames.index(refLevelType)) except ValueError: # type no longer exists self.refLevelType = ConfigDialog.currentTypeName self.refTypeCombo.setCurrentIndex(typeNames.index(self. refLevelType)) self.refTypeCombo.blockSignals(False) self.setControlAvailability() def updateFieldList(self): """Reload the field list box. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] if not self.refLevelFlag: activeFormat = currentFormat elif self.refLevelFlag == '!': activeFormat = ConfigDialog.formatsRef.fileInfoFormat elif self.refLevelFlag == '#': activeFormat = nodeformat.DescendantCountFormat() else: try: activeFormat = ConfigDialog.formatsRef[self.refLevelType] except (KeyError, ValueError): self.refLevelType = ConfigDialog.currentTypeName activeFormat = currentFormat self.fieldListBox.blockSignals(True) self.fieldListBox.clear() for field in activeFormat.fields(): if field.showInDialog: typeName = fieldformat.translatedTypeName(field.typeName) QTreeWidgetItem(self.fieldListBox, [field.name, typeName]) selectList = self.fieldListBox.findItems(ConfigDialog.currentFieldName, Qt.MatchFlag.MatchFixedString | Qt.MatchFlag.MatchCaseSensitive) selectItem = (selectList[0] if selectList else self.fieldListBox.topLevelItem(0)) self.fieldListBox.setCurrentItem(selectItem) selectItem.setSelected(True) self.fieldListBox.setColumnWidth(0, self.fieldListBox.width() // 2) self.fieldListBox.blockSignals(False) def changeField(self): """Change the current format field based on a tree widget signal. Not set if a special field ref level is active. """ selectList = self.fieldListBox.selectedItems() if (not self.refLevelFlag and len(selectList) == 1): ConfigDialog.currentFieldName = selectList[0].text(0) self.setControlAvailability() def setControlAvailability(self): """Set controls available based on text cursor movements. """ fieldsSelected = len(self.fieldListBox.selectedItems()) > 0 cursorInTitleField = self.isCursorInTitleField() self.toTitleButton.setEnabled(cursorInTitleField == None and fieldsSelected) self.delTitleButton.setEnabled(cursorInTitleField == True) cursorInOutputField = self.isCursorInOutputField() self.toOutputButton.setEnabled(cursorInOutputField == None and fieldsSelected) self.delOutputButton.setEnabled(cursorInOutputField == True) self.refTypeCombo.setEnabled(self.refLevelFlag not in ('', '!', '#')) def fieldToTitle(self): """Add selected field to cursor pos in title editor. """ self.titleEdit.insert(self.selectedFieldSepNames(' ')) self.titleEdit.setFocus() def delTitleField(self): """Remove field from cursor pos in title editor. """ if self.isCursorInTitleField(True): self.titleEdit.insert('') def fieldToOutput(self): """Add selected field to cursor pos in output editor. """ self.outputEdit.insertPlainText(self.selectedFieldSepNames()) self.outputEdit.setFocus() def delOutputField(self): """Remove field from cursor pos in output editor. """ if self.isCursorInOutputField(True): self.outputEdit.insertPlainText('') def selectedFieldSepNames(self, sep='\n'): """Return selected field name(s) with proper separators. Adjusts for special field ref levels. Multiple selections result in fields joined with the separator. Arguments: sep -- the separator to join multiple fields. """ fields = ['{{*{0}{1}*}}'.format(self.refLevelFlag, item.text(0)) for item in self.fieldListBox.selectedItems()] return '\n'.join(fields) def isCursorInTitleField(self, selectField=False): """Return True if a field pattern encloses the cursor/selection. Return False if the selection overlaps a field. Return None if there is no field at the cursor. Arguments: selectField -- select the entire field pattern if True. """ cursorPos = self.titleEdit.cursorPosition() selectStart = self.titleEdit.selectionStart() if selectStart < 0: selectStart = cursorPos elif selectStart == cursorPos: # backward selection cursorPos += len(self.titleEdit.selectedText()) fieldPos = self.fieldPosAtCursor(selectStart, cursorPos, self.titleEdit.text()) if not fieldPos: return None start, end = fieldPos if start == None or end == None: return False if selectField: self.titleEdit.setSelection(start, end - start) return True def isCursorInOutputField(self, selectField=False): """Return True if a field pattern encloses the cursor/selection. Return False if the selection overlaps a field. Return None if there is no field at the cursor. Arguments: selectField -- select the entire field pattern if True. """ outputCursor = self.outputEdit.textCursor() selectStart = outputCursor.anchor() cursorPos = outputCursor.position() block = outputCursor.block() blockStart = block.position() if selectStart < blockStart or (selectStart > blockStart + block.length()): return False # multi-line selection fieldPos = self.fieldPosAtCursor(selectStart - blockStart, cursorPos - blockStart, block.text()) if not fieldPos: return None start, end = fieldPos if start == None or end == None: return False if selectField: outputCursor.setPosition(start + blockStart) outputCursor.setPosition(end + blockStart, QTextCursor.MoveMode.KeepAnchor) self.outputEdit.setTextCursor(outputCursor) return True def fieldPosAtCursor(self, anchorPos, cursorPos, textLine): """Find the position of the field pattern that encloses the selection. Return a tuple of (start, end) positions of the field if found. Return (start, None) or (None, end) if the selection overlaps. Return None if no field is found. Arguments: anchorPos -- the selection start cursorPos -- the selection end textLine -- the text to search """ for match in fieldPattern.finditer(textLine): start = (match.start() if match.start() < anchorPos < match.end() else None) end = (match.end() if match.start() < cursorPos < match.end() else None) if start != None or end != None: return (start, end) return None def changeRefLevel(self, num): """Change other field ref level based on a combobox signal. Arguments: num -- the combobox index selected """ self.refLevelFlag = _refLevelFlags[num] if self.refLevelFlag in ('', '!', '#'): self.refLevelType = None elif not self.refLevelType: self.refLevelType = ConfigDialog.currentTypeName self.updateFieldList() self.setControlAvailability() def changeRefType(self, num): """Change the other field ref level type based on a combobox signal. Arguments: num -- the combobox index selected """ self.refLevelType = ConfigDialog.formatsRef.typeNames()[num] self.updateFieldList() self.setControlAvailability() def readChanges(self): """Make changes to the format for each widget. """ currentFormat = ConfigDialog.formatsRef[ConfigDialog.currentTypeName] currentFormat.changeTitleLine(self.titleEdit.text()) currentFormat.changeOutputLines(self.outputEdit.toPlainText().strip(). split('\n'), not currentFormat.formatHtml) class TitleEdit(QLineEdit): """LineEdit that avoids changing the selection on focus changes. """ focusIn = pyqtSignal(QWidget) def __init__(self, parent=None): """Initialize the config dialog page. Arguments: parent -- the parent dialog """ super().__init__(parent) def focusInEvent(self, event): """Override to keep selection & cursor position. Arguments: event -- the focus event """ cursorPos = self.cursorPosition() selectStart = self.selectionStart() if selectStart == cursorPos: selectStart = cursorPos + len(self.selectedText()) super().focusInEvent(event) self.setCursorPosition(cursorPos) if selectStart >= 0: self.setSelection(selectStart, cursorPos - selectStart) self.focusIn.emit(self) def focusOutEvent(self, event): """Override to keep selection & cursor position. Arguments: event -- the focus event """ cursorPos = self.cursorPosition() selectStart = self.selectionStart() if selectStart == cursorPos: selectStart = cursorPos + len(self.selectedText()) super().focusOutEvent(event) self.setCursorPosition(cursorPos) if selectStart >= 0: self.setSelection(selectStart, cursorPos - selectStart) class TypeLimitCombo(QComboBox): """A combo box for selecting limited child types. """ limitChanged = pyqtSignal() def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.checkBoxDialog = None self.typeNames = [] self.selectSet = set() def updateLists(self, typeNames, selectSet): """Update control text and store data for popup. Arguments: typeNames -- a list of available type names selectSet -- a set of seleected type names """ self.typeNames = typeNames self.updateSelects(selectSet) def updateSelects(self, selectSet): """Update control text and store selected items. Arguments: selectSet -- a set of seleected type names """ self.selectSet = selectSet if not selectSet or selectSet == set(self.typeNames): text = _('[All Types Available]') self.selectSet = set() else: text = ', '.join(sorted(selectSet)) self.addItem(text) self.setCurrentText(text) def showPopup(self): """Override to show a popup entry widget in place of a list view. """ self.checkBoxDialog = TypeLimitCheckBox(self.typeNames, self.selectSet, self) self.checkBoxDialog.setMinimumWidth(self.width()) self.checkBoxDialog.buttonChanged.connect(self.updateFromButton) self.checkBoxDialog.show() pos = self.mapToGlobal(self.rect().bottomRight()) pos.setX(pos.x() - self.checkBoxDialog.width() + 1) screenBottom = (QApplication.primaryScreen().availableGeometry(). bottom()) if pos.y() + self.checkBoxDialog.height() > screenBottom: pos.setY(pos.y() - self.rect().height() - self.checkBoxDialog.height()) self.checkBoxDialog.move(pos) def hidePopup(self): """Override to hide the popup entry widget. """ if self.checkBoxDialog: self.checkBoxDialog.hide() super().hidePopup() def updateFromButton(self): """Update selected items based on a button change. """ self.updateSelects(self.checkBoxDialog.selectSet()) self.limitChanged.emit() class TypeLimitCheckBox(QDialog): """A popup dialog box for selecting limited child types. """ buttonChanged = pyqtSignal() def __init__(self, textList, selectSet, parent=None): """Initialize the combination dialog. Arguments: textList -- a list of text choices selectSet -- a set of choices to preselect parent -- the parent, if given """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Popup) topLayout = QVBoxLayout(self) topLayout.setContentsMargins(0, 0, 0, 0) scrollArea = QScrollArea() scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) topLayout.addWidget(scrollArea) innerWidget = QWidget() innerLayout = QVBoxLayout(innerWidget) self.buttonGroup = QButtonGroup(self) self.buttonGroup.setExclusive(False) self.buttonGroup.buttonClicked.connect(self.buttonChanged) for text in textList: button = QCheckBox(text, innerWidget) if text in selectSet: button.setChecked(True) self.buttonGroup.addButton(button) innerLayout.addWidget(button) scrollArea.setWidget(innerWidget) buttons = self.buttonGroup.buttons() if buttons: buttons[0].setFocus() def selectSet(self): """Return a set of currently checked text. """ result = set() for button in self.buttonGroup.buttons(): if button.isChecked(): result.add(button.text()) return result def selectAll(self): """Select all of the entries. """ for button in self.buttonGroup.buttons(): button.setChecked(True) def selectNone(self): """Clear all of the selections. """ for button in self.buttonGroup.buttons(): button.setChecked(False) def contextMenuEvent(self, event): """Create a popup context menu. Arguments: event -- the menu even to process """ menu = QMenu(self) menu.addAction(_('&Select All'), self.selectAll) menu.addAction(_('Select &None'), self.selectNone) menu.exec(event.globalPos()) _illegalRe = re.compile(r'[^\w_\-.]') class NameEntryDialog(QDialog): """Dialog to handle user entry of a type or field name. Restricts entry to alpha-numerics, underscores, dashes and periods. """ def __init__(self, caption, labelText, defaultText='', addCheckBox = '', badText=None, parent=None): """Initialize the name entry class. Arguments: caption -- the window title labelText -- text for a descriptive lable defaultText -- initial text addCheckBox -- the label for an extra check box if needed badText -- a set or list of other illegal strings parent -- the parent overall dialog """ super().__init__(parent) self.badText = set() if badText: self.badText = badText self.text = '' self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(caption) topLayout = QVBoxLayout(self) label = QLabel(labelText) topLayout.addWidget(label) self.entry = QLineEdit(defaultText) topLayout.addWidget(self.entry) self.entry.setFocus() self.entry.returnPressed.connect(self.accept) self.extraChecked = False if addCheckBox: self.extraCheckBox = QCheckBox(addCheckBox) topLayout.addWidget(self.extraCheckBox) else: self.extraCheckBox = None ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) def accept(self): """Check for acceptable string before closing. """ self.text = self.entry.text().strip() if not self.text: error = _('The name cannot be empty') elif not self.text[0].isalpha(): error = _('The name must start with a letter') elif self.text[:3].lower() == 'xml': error = _('The name cannot start with "xml"') elif ' ' in self.text: error = _('The name cannot contain spaces') elif _illegalRe.search(self.text): badChars = set(_illegalRe.findall(self.text)) error = (_('The following characters are not allowed: {}'). format(''.join(badChars))) elif self.text in self.badText: error = _('The name was already used') else: if self.extraCheckBox: self.extraChecked = self.extraCheckBox.isChecked() return super().accept() QMessageBox.warning(self, 'TreeLine', error) class IconSelectDialog(QDialog): """Dialog for selecting icons for a format type. """ dialogSize = () dialogPos = () def __init__(self, nodeFormat, parent=None): """Create the icon select dialog. Arguments: nodeFormat -- the current node format to be set parent -- the parent overall dialog """ super().__init__(parent) self.currentIconName = nodeFormat.iconName if (not self.currentIconName or self.currentIconName not in globalref.treeIcons): self.currentIconName = icondict.defaultName self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Set Data Type Icon')) topLayout = QVBoxLayout(self) self.iconView = QListWidget() self.iconView.setViewMode(QListView.ViewMode.ListMode) self.iconView.setMovement(QListView.Movement.Static) self.iconView.setWrapping(True) self.iconView.setGridSize(QSize(112, 32)) topLayout.addWidget(self.iconView) self.iconView.itemDoubleClicked.connect(self.accept) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() clearButton = QPushButton(_('Clear &Select')) ctrlLayout.addWidget(clearButton) clearButton.clicked.connect(self.iconView.clearSelection) okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) if IconSelectDialog.dialogSize: self.resize(IconSelectDialog.dialogSize[0], IconSelectDialog.dialogSize[1]) self.move(IconSelectDialog.dialogPos[0], IconSelectDialog.dialogPos[1]) self.loadIcons() def loadIcons(self): """Load icons from the icon dict source. """ if not globalref.treeIcons.allLoaded: globalref.treeIcons.loadAllIcons() for name, icon in globalref.treeIcons.items(): if icon: item = QListWidgetItem(icon, name, self.iconView) if name == self.currentIconName: self.iconView.setCurrentItem(item) self.iconView.sortItems() selectedItem = self.iconView.currentItem() if selectedItem: self.iconView.scrollToItem(selectedItem, QAbstractItemView.ScrollHint. PositionAtCenter) def saveSize(self): """Record dialog size at close. """ IconSelectDialog.dialogSize = (self.width(), self.height()) IconSelectDialog.dialogPos = (self.x(), self.y()) def accept(self): """Save changes before closing. """ selectedItems = self.iconView.selectedItems() if selectedItems: self.currentIconName = selectedItems[0].text() if self.currentIconName == icondict.defaultName: self.currentIconName = '' else: self.currentIconName = icondict.noneName self.saveSize() super().accept() def reject(self): """Save dialog size before closing. """ self.saveSize() super().reject() class SortKeyDialog(QDialog): """Dialog for defining sort key fields and directions. """ directionNameDict = {True: _('forward'), False: _('reverse')} directionVarDict = dict([(name, boolVal) for boolVal, name in directionNameDict.items()]) def __init__(self, fieldDict, parent=None): """Create the sort key dialog. Arguments: fieldDict -- a dict of field names and values parent -- the parent overall dialog """ super().__init__(parent) self.fieldDict = fieldDict self.numChanges = 0 self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Sort Key Fields')) topLayout = QVBoxLayout(self) horizLayout = QHBoxLayout() topLayout.addLayout(horizLayout) fieldBox = QGroupBox(_('Available &Fields')) horizLayout.addWidget(fieldBox) boxLayout = QVBoxLayout(fieldBox) self.fieldListBox = QTreeWidget() boxLayout.addWidget(self.fieldListBox) self.fieldListBox.setRootIsDecorated(False) self.fieldListBox.setColumnCount(2) self.fieldListBox.setHeaderLabels([_('Name'), _('Type')]) midButtonLayout = QVBoxLayout() horizLayout.addLayout(midButtonLayout) self.addFieldButton = QPushButton('>>') midButtonLayout.addWidget(self.addFieldButton) self.addFieldButton.setMaximumWidth(self.addFieldButton. sizeHint().height()) self.addFieldButton.clicked.connect(self.addField) self.removeFieldButton = QPushButton('<<') midButtonLayout.addWidget(self.removeFieldButton) self.removeFieldButton.setMaximumWidth(self.removeFieldButton. sizeHint().height()) self.removeFieldButton.clicked.connect(self.removeField) sortBox = QGroupBox(_('&Sort Criteria')) horizLayout.addWidget(sortBox) boxLayout = QVBoxLayout(sortBox) self.sortListBox = QTreeWidget() boxLayout.addWidget(self.sortListBox) self.sortListBox.setRootIsDecorated(False) self.sortListBox.setColumnCount(3) self.sortListBox.setHeaderLabels(['#', _('Field'), _('Direction')]) self.sortListBox.currentItemChanged.connect(self.setControlsAvail) rightButtonLayout = QVBoxLayout() horizLayout.addLayout(rightButtonLayout) self.upButton = QPushButton(_('Move &Up')) rightButtonLayout.addWidget(self.upButton) self.upButton.clicked.connect(self.moveUp) self.downButton = QPushButton(_('&Move Down')) rightButtonLayout.addWidget(self.downButton) self.downButton.clicked.connect(self.moveDown) self.flipButton = QPushButton(_('Flip &Direction')) rightButtonLayout.addWidget(self.flipButton) self.flipButton.clicked.connect(self.flipDirection) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() self.okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(self.okButton) self.okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.updateContent() def updateContent(self): """Update dialog contents from current format settings. """ sortFields = [field for field in self.fieldDict.values() if field.sortKeyNum > 0] sortFields.sort(key = operator.attrgetter('sortKeyNum')) if not sortFields: sortFields = [list(self.fieldDict.values())[0]] self.fieldListBox.clear() for field in self.fieldDict.values(): if field not in sortFields: QTreeWidgetItem(self.fieldListBox, [field.name, field.typeName]) if self.fieldListBox.topLevelItemCount() > 0: self.fieldListBox.setCurrentItem(self.fieldListBox.topLevelItem(0)) self.fieldListBox.setColumnWidth(0, self.fieldListBox.sizeHint(). width() // 2) self.sortListBox.blockSignals(True) self.sortListBox.clear() for num, field in enumerate(sortFields, 1): sortDir = SortKeyDialog.directionNameDict[field.sortKeyForward] QTreeWidgetItem(self.sortListBox, [repr(num), field.name, sortDir]) self.sortListBox.setCurrentItem(self.sortListBox.topLevelItem(0)) self.sortListBox.blockSignals(False) self.sortListBox.setColumnWidth(0, self.sortListBox.sizeHint(). width() // 8) self.setControlsAvail() def setControlsAvail(self): """Set controls available based on selections. """ self.addFieldButton.setEnabled(self.fieldListBox.topLevelItemCount() > 0) hasSortItems = self.sortListBox.topLevelItemCount() > 0 self.removeFieldButton.setEnabled(hasSortItems) if hasSortItems: sortPosNum = self.sortListBox.indexOfTopLevelItem(self.sortListBox. currentItem()) self.upButton.setEnabled(hasSortItems and sortPosNum > 0) self.downButton.setEnabled(hasSortItems and sortPosNum < self.sortListBox.topLevelItemCount() - 1) self.flipButton.setEnabled(hasSortItems) self.okButton.setEnabled(hasSortItems) def addField(self): """Add a field to the sort criteria list. """ itemNum = self.fieldListBox.indexOfTopLevelItem(self.fieldListBox. currentItem()) fieldName = self.fieldListBox.takeTopLevelItem(itemNum).text(0) field = self.fieldDict[fieldName] sortNum = self.sortListBox.topLevelItemCount() + 1 sortDir = SortKeyDialog.directionNameDict[field.sortKeyForward] self.sortListBox.blockSignals(True) sortItem = QTreeWidgetItem(self.sortListBox, [repr(sortNum), fieldName, sortDir]) self.sortListBox.setCurrentItem(sortItem) self.sortListBox.blockSignals(False) self.setControlsAvail() self.numChanges += 1 def removeField(self): """Remove a field from the sort criteria list. """ itemNum = self.sortListBox.indexOfTopLevelItem(self.sortListBox. currentItem()) self.sortListBox.blockSignals(True) fieldName = self.sortListBox.takeTopLevelItem(itemNum).text(1) self.renumberSortFields() self.sortListBox.blockSignals(False) field = self.fieldDict[fieldName] sortFieldNames = set() for num in range(self.sortListBox.topLevelItemCount()): sortFieldNames.add(self.sortListBox.topLevelItem(num).text(1)) fieldList = [field for field in self.fieldDict.values() if field.name not in sortFieldNames] pos = fieldList.index(field) fieldItem = QTreeWidgetItem([fieldName, field.typeName]) self.fieldListBox.insertTopLevelItem(pos, fieldItem) self.setControlsAvail() self.numChanges += 1 def moveUp(self): """Move a field upward in the sort criteria. """ itemNum = self.sortListBox.indexOfTopLevelItem(self.sortListBox. currentItem()) self.sortListBox.blockSignals(True) sortItem = self.sortListBox.takeTopLevelItem(itemNum) self.sortListBox.insertTopLevelItem(itemNum - 1, sortItem) self.sortListBox.setCurrentItem(sortItem) self.renumberSortFields() self.sortListBox.blockSignals(False) self.setControlsAvail() self.numChanges += 1 def moveDown(self): """Move a field downward in the sort criteria. """ itemNum = self.sortListBox.indexOfTopLevelItem(self.sortListBox. currentItem()) self.sortListBox.blockSignals(True) sortItem = self.sortListBox.takeTopLevelItem(itemNum) self.sortListBox.insertTopLevelItem(itemNum + 1, sortItem) self.sortListBox.setCurrentItem(sortItem) self.renumberSortFields() self.sortListBox.blockSignals(False) self.setControlsAvail() self.numChanges += 1 def flipDirection(self): """Toggle the direction of the current sort field. """ sortItem = self.sortListBox.currentItem() oldDirection = SortKeyDialog.directionVarDict[sortItem.text(2)] newDirection = SortKeyDialog.directionNameDict[not oldDirection] sortItem.setText(2, newDirection) self.numChanges += 1 def renumberSortFields(self): """Update field numbers in the sort list. """ for num in range(self.sortListBox.topLevelItemCount()): self.sortListBox.topLevelItem(num).setText(0, repr(num + 1)) def accept(self): """Save changes before closing. """ if not self.numChanges: return self.reject() for field in self.fieldDict.values(): field.sortKeyNum = 0 field.sortKeyForward = True for num in range(self.sortListBox.topLevelItemCount()): fieldItem = self.sortListBox.topLevelItem(num) field = self.fieldDict[fieldItem.text(1)] field.sortKeyNum = num + 1 field.sortKeyForward = SortKeyDialog.directionVarDict[fieldItem. text(2)] return super().accept() _mathRefLevels = [_('Self Reference'), _('Parent Reference'), _('Root Reference'), _('Child Reference'), _('Child Count')] # _mathRefLevelFlags correspond to _mathRefLevels _mathRefLevelFlags = ['', '*', '$', '&', '#'] _mathResultTypes = [N_('Number Result'), N_('Date Result'), N_('Time Result'), N_('Boolean Result'), N_('Text Result')] _operatorTypes = [_('Arithmetic Operators'), _('Comparison Operators'), _('Text Operators')] _arithmeticOperators = [('+', _('add')), ('-', _('subtract')), ('*', _('multiply')), ('/', _('divide')), ('//', _('floor divide')), ('%', _('modulus')), ('**', _('power')), ('sum()', _('sum of items')), ('max()', _('maximum')), ('min()', _('minimum')), ('mean()', _('average')), ('abs()', _('absolute value')), ('sqrt()', _('square root')), ('log()', _('natural logarithm')), ('log10()', _('base-10 logarithm')), ('factorial()', _('factorial')), ('round()', _('round to num digits')), ('floor()', _('lower integer')), ('ceil()', _('higher integer')), ('int()', _('truncated integer')), ('float()', _('floating point')), ('sin()', _('sine of radians')), ('cos()', _('cosine of radians')), ('tan()', _('tangent of radians')), ('asin()', _('arc sine')), ('acos()', _('arc cosine')), ('atan()', _('arc tangent')), ('degrees()', _('radians to degrees')), ('radians()', _('degrees to radians')), ('pi', _('pi constant')), ('e', _('natural log constant')), ('count()', _('number of words in arg'))] _comparisonOperators = [('==', _('equal to')), ('<', _('less than')), ('>', _('greater than')), ('<=', _('less than or equal to')), ('>=', _('greater than or equal to')), ('!=', _('not equal to')), ('() if () else ()', _('true value, condition, false value')), ('and', _('logical and')), ('or', _('logical or')), ('startswith()', _('true if 1st text arg starts with 2nd arg')), ('endswith()', _('true if 1st text arg ends with 2nd arg')), ('contains()', _('true if 1st text arg contains 2nd arg'))] _textOperators = [('+', _('concatenate text')), ("join(' ', )", _('join text using 1st arg as separator')), ('upper()', _('convert text to upper case')), ('lower()', _('convert text to lower case')), ('replace()', _('in 1st arg, replace 2nd arg with 3rd arg'))] # _operatorLists correspond to _operatorTypes _operatorLists = [_arithmeticOperators, _comparisonOperators, _textOperators] class MathEquationDialog(QDialog): """Dialog for defining equations for Math fields. """ def __init__(self, nodeFormat, field, parent=None): """Create the math equation dialog. Arguments: nodeFormat -- the current node format field -- the Math field """ super().__init__(parent) self.nodeFormat = nodeFormat self.typeFormats = self.nodeFormat.parentFormats self.field = field self.refLevelFlag = '' self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Define Math Field Equation')) topLayout = QGridLayout(self) fieldBox = QGroupBox(_('Field References')) topLayout.addWidget(fieldBox, 0, 0, 2, 1) fieldLayout = QVBoxLayout(fieldBox) innerLayout = QVBoxLayout() innerLayout.setSpacing(0) fieldLayout.addLayout(innerLayout) levelLabel = QLabel(_('Reference &Level')) innerLayout.addWidget(levelLabel) levelCombo = QComboBox() innerLayout.addWidget(levelCombo) levelLabel.setBuddy(levelCombo) levelCombo.addItems(_mathRefLevels) levelCombo.currentIndexChanged.connect(self.changeRefLevel) innerLayout = QVBoxLayout() innerLayout.setSpacing(0) fieldLayout.addLayout(innerLayout) typeLabel = QLabel(_('Reference &Type')) innerLayout.addWidget(typeLabel) self.typeCombo = QComboBox() innerLayout.addWidget(self.typeCombo) typeLabel.setBuddy(self.typeCombo) self.typeCombo.addItems(self.typeFormats.typeNames()) self.typeCombo.currentIndexChanged.connect(self.updateFieldList) innerLayout = QVBoxLayout() innerLayout.setSpacing(0) fieldLayout.addLayout(innerLayout) fieldLabel = QLabel(_('Available &Field List')) innerLayout.addWidget(fieldLabel) self.fieldListBox = QTreeWidget() innerLayout.addWidget(self.fieldListBox) fieldLabel.setBuddy(self.fieldListBox) self.fieldListBox.setRootIsDecorated(False) self.fieldListBox.setColumnCount(2) self.fieldListBox.setHeaderLabels([_('Name'), _('Type')]) resultTypeBox = QGroupBox(_('&Result Type')) topLayout.addWidget(resultTypeBox, 0, 1) resultTypeLayout = QVBoxLayout(resultTypeBox) self.resultTypeCombo = QComboBox() resultTypeLayout.addWidget(self.resultTypeCombo) self.resultTypeCombo.addItems([_(str) for str in _mathResultTypes]) results = [s.split(' ', 1)[0].lower() for s in _mathResultTypes] resultStr = self.field.resultType.name self.resultTypeCombo.setCurrentIndex(results.index(resultStr)) operBox = QGroupBox(_('Operations')) topLayout.addWidget(operBox, 1, 1) operLayout = QVBoxLayout(operBox) innerLayout = QVBoxLayout() innerLayout.setSpacing(0) operLayout.addLayout(innerLayout) operTypeLabel = QLabel(_('O&perator Type')) innerLayout.addWidget(operTypeLabel) operTypeCombo = QComboBox() innerLayout.addWidget(operTypeCombo) operTypeLabel.setBuddy(operTypeCombo) operTypeCombo.addItems(_operatorTypes) operTypeCombo.currentIndexChanged.connect(self.replaceOperatorList) innerLayout = QVBoxLayout() innerLayout.setSpacing(0) operLayout.addLayout(innerLayout) operListLabel = QLabel(_('Oper&ator List')) innerLayout.addWidget(operListLabel) self.operListBox = QTreeWidget() innerLayout.addWidget(self.operListBox) operListLabel.setBuddy(self.operListBox) self.operListBox.setRootIsDecorated(False) self.operListBox.setColumnCount(2) self.operListBox.setHeaderLabels([_('Name'), _('Description')]) self.replaceOperatorList(0) buttonLayout = QHBoxLayout() topLayout.addLayout(buttonLayout, 2, 0) buttonLayout.addStretch() self.addFieldButton = QPushButton('\u25bc') buttonLayout.addWidget(self.addFieldButton) self.addFieldButton.setMaximumWidth(self.addFieldButton. sizeHint().height()) self.addFieldButton.clicked.connect(self.addField) self.delFieldButton = QPushButton('\u25b2') buttonLayout.addWidget(self.delFieldButton) self.delFieldButton.setMaximumWidth(self.delFieldButton. sizeHint().height()) self.delFieldButton.clicked.connect(self.deleteField) buttonLayout.addStretch() buttonLayout = QHBoxLayout() topLayout.addLayout(buttonLayout, 2, 1) self.addOperButton = QPushButton('\u25bc') buttonLayout.addWidget(self.addOperButton) self.addOperButton.setMaximumWidth(self.addOperButton. sizeHint().height()) self.addOperButton.clicked.connect(self.addOperator) equationBox = QGroupBox(_('&Equation')) topLayout.addWidget(equationBox, 3, 0, 1, 2) equationLayout = QVBoxLayout(equationBox) self.equationEdit = TitleEdit() equationLayout.addWidget(self.equationEdit) self.equationEdit.setText(self.field.equationText()) self.equationEdit.cursorPositionChanged.connect(self. setControlAvailability) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout, 4, 0, 1, 2) ctrlLayout.addStretch() okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.setDefault(True) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.changeRefLevel(0) self.equationEdit.setFocus() def updateFieldList(self): """Update field list based on reference type setting. """ currentFormat = self.typeFormats[self.typeCombo.currentText()] self.fieldListBox.clear() if self.refLevelFlag != '#': for field in currentFormat.fields(): if (hasattr(field, 'mathValue') and field.showInDialog and (self.refLevelFlag or field != self.field)): QTreeWidgetItem(self.fieldListBox, [field.name, _(field.typeName)]) else: QTreeWidgetItem(self.fieldListBox, [_('Count'), _('Number of Children')]) if self.fieldListBox.topLevelItemCount(): selectItem = self.fieldListBox.topLevelItem(0) self.fieldListBox.setCurrentItem(selectItem) selectItem.setSelected(True) self.fieldListBox.resizeColumnToContents(0) self.fieldListBox.setColumnWidth(0, self.fieldListBox.columnWidth(0) * 2) self.setControlAvailability() def setControlAvailability(self): """Set controls available based on text cursor movements. """ cursorInField = self.isCursorInField() fieldCount = self.fieldListBox.topLevelItemCount() self.addFieldButton.setEnabled(cursorInField == None and fieldCount) self.delFieldButton.setEnabled(cursorInField == True) self.addOperButton.setEnabled(cursorInField == None) def addField(self): """Add selected field to cursor pos in the equation editor. """ fieldSepName = '{{*{0}{1}*}}'.format(self.refLevelFlag, self.fieldListBox.currentItem(). text(0)) self.equationEdit.insert(fieldSepName) self.equationEdit.setFocus() def deleteField(self): """Remove field from cursor pos in the equation editor. """ if self.isCursorInField(True): self.equationEdit.insert('') self.equationEdit.setFocus() def addOperator(self): """Add selected operator to cursor pos in the equation editor. """ oper = self.operListBox.currentItem().text(0) origText = self.equationEdit.text() cursorPos = self.equationEdit.cursorPosition() if cursorPos != 0 and origText[cursorPos - 1] != ' ': oper = ' ' + oper self.equationEdit.insert(oper + ' ') parenPos = oper.find(')') if parenPos >= 0: cursorPos = self.equationEdit.cursorPosition() self.equationEdit.setCursorPosition(cursorPos - len(oper) + parenPos - 1) self.equationEdit.setFocus() def isCursorInField(self, selectField=False): """Return True if a field pattern encloses the cursor/selection. Return False if the selection overlaps a field. Return None if there is no field at the cursor. Arguments: selectField -- select the entire field pattern if True. """ cursorPos = self.equationEdit.cursorPosition() selectStart = self.equationEdit.selectionStart() if selectStart < 0: selectStart = cursorPos elif selectStart == cursorPos: # backward selection cursorPos += len(self.equationEdit.selectedText()) start = end = None for match in fieldPattern.finditer(self.equationEdit.text()): start = (match.start() if match.start() < selectStart < match.end() else None) end = (match.end() if match.start() < cursorPos < match.end() else None) if start != None or end != None: break if start == None and end == None: return None if start == None or end == None: return False if selectField: self.equationEdit.setSelection(start, end - start) return True def changeRefLevel(self, num): """Change the reference level based on a combobox signal. Arguments: num -- the combobox index selected """ self.refLevelFlag = _mathRefLevelFlags[num] if self.refLevelFlag in ('', '#'): self.typeCombo.setEnabled(False) self.typeCombo.setCurrentIndex(self.typeFormats.typeNames(). index(self.nodeFormat.name)) else: self.typeCombo.setEnabled(True) self.updateFieldList() def replaceOperatorList(self, num): """Change the operator list based on a signal from the oper type combo. Arguments: num -- the combobox index selected """ self.operListBox.clear() for oper, descr in _operatorLists[num]: QTreeWidgetItem(self.operListBox, [oper, descr]) self.operListBox.resizeColumnToContents(0) self.operListBox.setColumnWidth(0, int(self.operListBox.columnWidth(0) * 1.2)) self.operListBox.resizeColumnToContents(1) selectItem = self.operListBox.topLevelItem(0) self.operListBox.setCurrentItem(selectItem) selectItem.setSelected(True) def accept(self): """Verify the equation and close the dialog if acceptable. """ eqnText = self.equationEdit.text().strip() if eqnText: eqn = matheval.MathEquation(eqnText) try: eqn.validate() except ValueError as err: QMessageBox.warning(self, 'TreeLine', _('Equation error: {}').format(err)) return self.typeFormats.emptiedMathDict.setdefault(self.nodeFormat.name, set()).discard(self.field.name) self.field.equation = eqn else: if self.field.equationText(): self.typeFormats.emptiedMathDict.setdefault(self.nodeFormat. name, set()).add(self.field.name) self.field.equation = None resultStr = (_mathResultTypes[self.resultTypeCombo.currentIndex()]. split(' ', 1)[0].lower()) self.field.changeResultType(fieldformat.MathResult[resultStr]) super().accept() TreeLine-3.2.1/source/dataeditors.py000066400000000000000000003270741506556630100174250ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # dataeditors.py, provides classes for data editors in the data edit view # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import xml.sax.saxutils import os.path import sys import re import math import enum import datetime import subprocess from PyQt6.QtCore import (QDate, QDateTime, QPoint, QPointF, QRect, QSize, QTime, Qt, pyqtSignal) from PyQt6.QtGui import (QAction, QBrush, QFont, QFontMetrics, QPainter, QPainterPath, QPixmap, QPen, QTextCursor, QTextDocument, QValidator) from PyQt6.QtWidgets import (QAbstractItemView, QAbstractSpinBox, QApplication, QButtonGroup, QCalendarWidget, QCheckBox, QColorDialog, QComboBox, QDialog, QFileDialog, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu, QPushButton, QRadioButton, QScrollArea, QSizePolicy, QSpinBox, QTextEdit, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget) import dataeditview import fieldformat import urltools import globalref import optiondefaults multipleSpaceRegEx = re.compile(r' {2,}') class PlainTextEditor(QTextEdit): """An editor widget for multi-line plain text fields. """ dragLinkEnabled = False contentsChanged = pyqtSignal(QWidget) editEnding = pyqtSignal(QWidget) keyPressed = pyqtSignal(QWidget) def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.setAcceptRichText(False) self.setPalette(QApplication.palette()) self.setStyleSheet('QTextEdit {border: 2px solid palette(highlight)}') self.setTabChangesFocus(True) self.cursorPositionChanged.connect(self.updateActions) self.selectionChanged.connect(self.updateActions) self.allActions = parent.parent().allActions self.modified = False self.textChanged.connect(self.signalUpdate) self.allActions['FormatInsertDate'].triggered.connect(self.insDate) def setContents(self, text): """Set the contents of the editor to text. Arguments: text - the new text contents for the editor """ self.blockSignals(True) self.setPlainText(text) self.blockSignals(False) def contents(self): """Return the editor text contents. """ return self.toPlainText() def hasSelectedText(self): """Return True if text is selected. """ return self.textCursor().hasSelection() def cursorPosTuple(self): """Return a tuple of the current cursor position and anchor (integers). """ cursor = self.textCursor() return (cursor.anchor(), cursor.position()) def setCursorPos(self, anchor, position): """Set the cursor to the given anchor and position. Arguments: anchor -- the cursor selection start integer position -- the cursor position or select end integer """ cursor = self.textCursor() cursor.setPosition(anchor) cursor.setPosition(position, QTextCursor.MoveMode.KeepAnchor) self.setTextCursor(cursor) # self.ensureCursorVisible() def setCursorPoint(self, point): """Set the cursor to the given point. Arguments: point -- the QPoint for the new cursor position """ self.setTextCursor(self.cursorForPosition(self.mapFromGlobal(point))) def resetCursor(self): """Set the cursor to end for tab-focus use. """ self.moveCursor(QTextCursor.MoveOperation.End) def scrollPosition(self): """Return the current scrollbar position. """ return self.verticalScrollBar().value() def setScrollPosition(self, value): """Set the scrollbar position to value. Arguments: value -- the new scrollbar position """ self.verticalScrollBar().setValue(value) def signalUpdate(self): """Signal the delegate to update the model based on an editor change. """ self.modified = True self.contentsChanged.emit(self) def disableActions(self): """Reset action availability after focus is lost. """ try: self.allActions['EditCut'].setEnabled(True) self.allActions['EditCopy'].setEnabled(True) mime = QApplication.clipboard().mimeData() self.allActions['EditPaste'].setEnabled(len(mime.data('text/xml') or mime.data('text/plain')) > 0) self.allActions['FormatInsertDate'].setEnabled(False) except RuntimeError: pass # avoid calling a deleted C++ editor object def updateActions(self): """Set availability of context menu actions. """ hasSelection = self.textCursor().hasSelection() self.allActions['EditCut'].setEnabled(hasSelection) self.allActions['EditCopy'].setEnabled(hasSelection) mime = QApplication.clipboard().mimeData() self.allActions['EditPaste'].setEnabled(len(mime.data('text/plain')) > 0) self.allActions['FormatInsertDate'].setEnabled(True) def insDate(self): """Insert the current date using the editor format. """ date = datetime.date.today() editorFormat = fieldformat.adjOutDateFormat(globalref. genOptions['EditDateFormat']) dateText = date.strftime(editorFormat) self.insertPlainText(dateText) def contextMenuEvent(self, event): """Override popup menu to add global actions. Arguments: event -- the menu event """ menu = QMenu(self) menu.addAction(self.allActions['FormatSelectAll']) menu.addSeparator() menu.addAction(self.allActions['EditCut']) menu.addAction(self.allActions['EditCopy']) menu.addAction(self.allActions['EditPaste']) menu.addSeparator() menu.addAction(self.allActions['FormatInsertDate']) menu.exec(event.globalPos()) def focusInEvent(self, event): """Set availability and update format actions. Arguments: event -- the focus event """ super().focusInEvent(event) self.updateActions() def focusOutEvent(self, event): """Reset format actions on focus loss if not focusing a menu. Arguments: event -- the focus event """ super().focusOutEvent(event) if event.reason() != Qt.FocusReason.PopupFocusReason: self.disableActions() self.editEnding.emit(self) def hideEvent(self, event): """Reset format actions when the editor is hidden. Arguments: event -- the hide event """ self.disableActions() self.editEnding.emit(self) super().hideEvent(event) def keyPressEvent(self, event): """Emit a signal after every key press and handle page up/down. Needed to adjust scroll position in unlimited height editors. Arguments: event -- the key press event """ if (event.key() in (Qt.Key.Key_PageUp, Qt.Key.Key_PageDown) and not globalref.genOptions['EditorLimitHeight']): pos = self.cursorRect().center() if event.key() == Qt.Key.Key_PageUp: pos.setY(pos.y() - self.parent().height()) if pos.y() < 0: pos.setY(0) else: pos.setY(pos.y() + self.parent().height()) if pos.y() > self.height(): pos.setY(self.height()) newCursor = self.cursorForPosition(pos) if event.modifiers() == Qt.KeyboardModifier.ShiftModifier: cursor = self.textCursor() cursor.setPosition(newCursor.position(), QTextCursor.MoveMode.KeepAnchor) self.setTextCursor(cursor) else: self.setTextCursor(newCursor) event.accept() self.keyPressed.emit(self) return super().keyPressEvent(event) self.keyPressed.emit(self) class HtmlTextEditor(PlainTextEditor): """An editor for HTML fields, plain text with HTML insert commands. """ htmlFontSizes = ('small', '', 'large', 'x-large', 'xx-large') dragLinkEnabled = True inLinkSelectMode = pyqtSignal(bool) def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.intLinkDialog = None self.nodeRef = None self.allActions['FormatBoldFont'].triggered.connect(self.setBoldFont) self.allActions['FormatItalicFont'].triggered.connect(self. setItalicFont) self.allActions['FormatUnderlineFont'].triggered.connect(self. setUnderlineFont) self.allActions['FormatStrikethroughFont'].triggered.connect(self. setStrikethroughFont) self.allActions['FormatFontSize'].parent().triggered.connect(self. setFontSize) self.allActions['FormatFontSize'].triggered.connect(self. showFontSizeMenu) self.allActions['FormatFontColor'].triggered.connect(self.setFontColor) self.allActions['FormatExtLink'].triggered.connect(self.setExtLink) self.allActions['FormatIntLink'].triggered.connect(self.setIntLink) def insertTagText(self, prefix, suffix): """Insert given tag text and maintain the original selection. Arguments: prefix -- the opening tag suffix -- the closing tag """ cursor = self.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() text = '{0}{1}{2}'.format(prefix, cursor.selectedText(), suffix) self.insertPlainText(text) cursor.setPosition(start + len(prefix)) cursor.setPosition(end + len(prefix), QTextCursor.MoveMode.KeepAnchor) self.setTextCursor(cursor) def setBoldFont(self, checked): """Insert tags for a bold font. Arguments: checked -- current toggle state of the control """ try: if self.hasFocus() and checked: self.insertTagText('', '') except RuntimeError: pass # avoid calling a deleted C++ editor object def setItalicFont(self, checked): """Insert tags for an italic font. Arguments: checked -- current toggle state of the control """ try: if self.hasFocus() and checked: self.insertTagText('', '') except RuntimeError: pass # avoid calling a deleted C++ editor object def setUnderlineFont(self, checked): """Insert tags for an underline font. Arguments: checked -- current toggle state of the control """ try: if self.hasFocus() and checked: self.insertTagText('', '') except RuntimeError: pass # avoid calling a deleted C++ editor object def setStrikethroughFont(self, checked): """Insert tags for a strikethrough font. Arguments: checked -- current toggle state of the control """ try: if self.hasFocus() and checked: self.insertTagText('', '') except RuntimeError: pass # avoid calling a deleted C++ editor object def setFontSize(self, action): """Set the font size of the selection or the current setting. Arguments: action -- the sub-menu action that was picked """ try: if self.hasFocus(): actions = self.allActions['FormatFontSize'].parent().actions() sizeNum = actions.index(action) size = HtmlTextEditor.htmlFontSizes[sizeNum] self.insertTagText(''.format(size), '') except RuntimeError: pass # avoid calling a deleted C++ editor object def setFontColor(self): """Set the font color of the selection or the current setting. Prompt the user for a color using a dialog. """ try: if self.hasFocus(): charFormat = self.currentCharFormat() oldColor = charFormat.foreground().color() newColor = QColorDialog.getColor(oldColor, self) if newColor.isValid(): self.insertTagText(''. format(newColor.name()), '') except RuntimeError: pass # avoid calling a deleted C++ editor object def setExtLink(self): """Add or modify an extrnal web link at the cursor. """ try: if self.hasFocus(): dialog = ExtLinkDialog(False, self) address, name = self.selectLink() if address.startswith('#'): address = name = '' dialog.setFromComponents(address, name) if dialog.exec() == QDialog.DialogCode.Accepted: self.insertPlainText(dialog.htmlText()) except RuntimeError: pass # avoid calling a deleted C++ editor object def setIntLink(self): """Show dialog to add or modify an internal node link at the cursor. """ try: if self.hasFocus(): self.intLinkDialog = EmbedIntLinkDialog(self.nodeRef. treeStructureRef(), self) address, name = self.selectLink() if address.startswith('#'): address = address.lstrip('#') else: address = '' self.intLinkDialog.setFromComponents(address, name) self.intLinkDialog.finished.connect(self.insertInternalLink) self.intLinkDialog.show() self.inLinkSelectMode.emit(True) except RuntimeError: pass # avoid calling a deleted C++ editor object def insertInternalLink(self, resultCode): """Add or modify an internal node link based on dialog approval. Arguments: resultCode -- the result from the dialog (OK or cancel) """ if resultCode == QDialog.DialogCode.Accepted: self.insertPlainText(self.intLinkDialog.htmlText()) self.intLinkDialog = None self.inLinkSelectMode.emit(False) def setLinkFromNode(self, node): """Set the current internal link from a clicked node. Arguments: node -- the node to set the unique ID from """ if self.intLinkDialog: self.intLinkDialog.setFromNode(node) def selectLink(self): """Select the full link at the cursor, return link data. Any links at the cursor or partially selected are fully selected. Returns a tuple of the link address and name, or a tuple with empty strings if none are found. """ cursor = self.textCursor() anchor = cursor.anchor() position = cursor.position() for match in fieldformat.linkRegExp.finditer(self.toPlainText()): start = match.start() end = match.end() if start < anchor < end or start < position < end: address, name = match.groups() cursor.setPosition(start) cursor.setPosition(end, QTextCursor.MoveMode.KeepAnchor) self.setTextCursor(cursor) return (address, name) return ('', cursor.selectedText()) def addDroppedUrl(self, urlText): """Add the URL link that was dropped on this editor from the view. Arguments: urlText -- the text of the link """ name = urltools.shortName(urlText) text = '{1}'.format(urlText, name) self.insertPlainText(text) def disableActions(self): """Set format actions to unavailable. """ super().disableActions() try: self.allActions['FormatBoldFont'].setEnabled(False) self.allActions['FormatItalicFont'].setEnabled(False) self.allActions['FormatUnderlineFont'].setEnabled(False) self.allActions['FormatStrikethroughFont'].setEnabled(False) self.allActions['FormatFontSize'].parent().setEnabled(False) self.allActions['FormatFontColor'].setEnabled(False) self.allActions['FormatExtLink'].setEnabled(False) self.allActions['FormatIntLink'].setEnabled(False) except RuntimeError: pass # avoid calling a deleted C++ editor object def updateActions(self): """Set editor format actions to available and update toggle states. """ super().updateActions() boldFontAct = self.allActions['FormatBoldFont'] boldFontAct.setEnabled(True) boldFontAct.setChecked(False) italicAct = self.allActions['FormatItalicFont'] italicAct.setEnabled(True) italicAct.setChecked(False) underlineAct = self.allActions['FormatUnderlineFont'] underlineAct.setEnabled(True) underlineAct.setChecked(False) strikethroughAct = self.allActions['FormatStrikethroughFont'] strikethroughAct.setEnabled(True) strikethroughAct.setChecked(False) fontSizeSubMenu = self.allActions['FormatFontSize'].parent() fontSizeSubMenu.setEnabled(True) for action in fontSizeSubMenu.actions(): action.setChecked(False) self.allActions['FormatFontColor'].setEnabled(True) self.allActions['FormatExtLink'].setEnabled(True) self.allActions['FormatIntLink'].setEnabled(True) def showFontSizeMenu(self): """Show a context menu for font size at this edit box. """ if self.hasFocus(): rect = self.rect() pt = self.mapToGlobal(QPoint(rect.center().x(), rect.bottom())) self.allActions['FormatFontSize'].parent().popup(pt) def contextMenuEvent(self, event): """Override popup menu to add formatting and global actions. Arguments: event -- the menu event """ menu = QMenu(self) menu.addAction(self.allActions['FormatBoldFont']) menu.addAction(self.allActions['FormatItalicFont']) menu.addAction(self.allActions['FormatUnderlineFont']) menu.addAction(self.allActions['FormatStrikethroughFont']) menu.addSeparator() menu.addMenu(self.allActions['FormatFontSize'].parent()) menu.addAction(self.allActions['FormatFontColor']) menu.addSeparator() menu.addAction(self.allActions['FormatExtLink']) menu.addAction(self.allActions['FormatIntLink']) menu.addAction(self.allActions['FormatInsertDate']) menu.addSeparator() menu.addAction(self.allActions['FormatSelectAll']) menu.addSeparator() menu.addAction(self.allActions['EditCut']) menu.addAction(self.allActions['EditCopy']) menu.addAction(self.allActions['EditPaste']) menu.exec(event.globalPos()) def hideEvent(self, event): """Close the internal link dialog when the editor is hidden. Arguments: event -- the hide event """ if self.intLinkDialog: self.intLinkDialog.close() self.intLinkDialog = None super().hideEvent(event) class RichTextEditor(HtmlTextEditor): """An editor widget for multi-line wysiwyg rich text fields. """ fontPointSizes = [] def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.setAcceptRichText(True) if not RichTextEditor.fontPointSizes: doc = QTextDocument() doc.setDefaultFont(self.font()) for sizeName in HtmlTextEditor.htmlFontSizes: if sizeName: doc.setHtml('text'. format(sizeName)) pointSize = (QTextCursor(doc).charFormat().font(). pointSize()) else: pointSize = self.font().pointSize() RichTextEditor.fontPointSizes.append(pointSize) self.allActions['FormatClearFormat'].triggered.connect(self. setClearFormat) self.allActions['EditPastePlain'].triggered.connect(self.pastePlain) def setContents(self, text): """Set the contents of the editor to text. Arguments: text - the new text contents for the editor """ self.blockSignals(True) self.setHtml(text) self.blockSignals(False) def contents(self): """Return simplified HTML code for the editor contents. Replace Unicode line feeds with HTML breaks, escape <, >, &, and replace some rich formatting with HTML tags. """ doc = self.document() block = doc.begin() result = '' while block.isValid(): if result: result += '
    ' fragIter = block.begin() while not fragIter.atEnd(): text = xml.sax.saxutils.escape(fragIter.fragment().text()) text = text.replace('\u2028', '
    ') charFormat = fragIter.fragment().charFormat() if charFormat.fontWeight() >= QFont.Weight.Bold: text = '{0}'.format(text) if charFormat.fontItalic(): text = '{0}'.format(text) if charFormat.fontStrikeOut(): text = '{0}'.format(text) size = charFormat.font().pointSize() if size != self.font().pointSize(): closeSize = min((abs(size - i), i) for i in RichTextEditor.fontPointSizes)[1] sizeNum = RichTextEditor.fontPointSizes.index(closeSize) htmlSize = HtmlTextEditor.htmlFontSizes[sizeNum] if htmlSize: text = ('{1}'. format(htmlSize, text)) if charFormat.anchorHref(): text = '{1}'.format(charFormat. anchorHref(), text) else: # ignore underline and font color for links if charFormat.fontUnderline(): text = '{0}'.format(text) if (charFormat.foreground().color().name() != block.charFormat().foreground().color().name()): text = ('{1}'. format(charFormat.foreground().color().name(), text)) result += text fragIter += 1 block = block.next() return result def setBoldFont(self, checked): """Set the selection or the current setting to a bold font. Arguments: checked -- current toggle state of the control """ try: if self.hasFocus(): if checked: self.setFontWeight(QFont.Weight.Bold) else: self.setFontWeight(QFont.Weight.Normal) except RuntimeError: pass # avoid calling a deleted C++ editor object def setItalicFont(self, checked): """Set the selection or the current setting to an italic font. Arguments: checked -- current toggle state of the control """ try: if self.hasFocus(): self.setFontItalic(checked) except RuntimeError: pass # avoid calling a deleted C++ editor object def setUnderlineFont(self, checked): """Set the selection or the current setting to an underlined font. Arguments: checked -- current toggle state of the control """ try: if self.hasFocus(): self.setFontUnderline(checked) except RuntimeError: pass # avoid calling a deleted C++ editor object def setStrikethroughFont(self, checked): """Set the selection or the current setting to a strikethrough font. Arguments: checked -- current toggle state of the control """ try: if self.hasFocus(): charFormat = self.currentCharFormat() charFormat.setFontStrikeOut(checked) self.setCurrentCharFormat(charFormat) except RuntimeError: pass # avoid calling a deleted C++ editor object def setFontSize(self, action): """Set the font size of the selection or the current setting. Arguments: action -- the sub-menu action that was picked """ try: if self.hasFocus(): actions = self.allActions['FormatFontSize'].parent().actions() sizeNum = actions.index(action) pointSize = RichTextEditor.fontPointSizes[sizeNum] charFormat = self.currentCharFormat() charFormat.setFontPointSize(pointSize) self.setCurrentCharFormat(charFormat) except RuntimeError: pass # avoid calling a deleted C++ editor object def setFontColor(self): """Set the font color of the selection or the current setting. Prompt the user for a color using a dialog. """ try: if self.hasFocus(): charFormat = self.currentCharFormat() oldColor = charFormat.foreground().color() newColor = QColorDialog.getColor(oldColor, self) if newColor.isValid(): charFormat.setForeground(QBrush(newColor)) self.setCurrentCharFormat(charFormat) except RuntimeError: pass # avoid calling a deleted C++ editor object def setClearFormat(self): """Clear the current or selected text formatting. """ try: if self.hasFocus(): self.setCurrentFont(self.font()) charFormat = self.currentCharFormat() charFormat.clearForeground() charFormat.setAnchor(False) charFormat.setAnchorHref('') self.setCurrentCharFormat(charFormat) except RuntimeError: pass # avoid calling a deleted C++ editor object def setExtLink(self): """Add or modify an extrnal web link at the cursor. """ try: if self.hasFocus(): dialog = ExtLinkDialog(False, self) address, name = self.selectLink() if address.startswith('#'): address = name = '' dialog.setFromComponents(address, name) if dialog.exec() == QDialog.DialogCode.Accepted: if self.textCursor().hasSelection(): self.insertHtml(dialog.htmlText()) else: self.insertHtml(dialog.htmlText() + ' ') except RuntimeError: pass # avoid calling a deleted C++ editor object def insertInternalLink(self, resultCode): """Add or modify an internal node link based on dialog approval. Arguments: resultCode -- the result from the dialog (OK or cancel) """ if resultCode == QDialog.DialogCode.Accepted: if self.textCursor().hasSelection(): self.insertHtml(self.intLinkDialog.htmlText()) else: self.insertHtml(self.intLinkDialog.htmlText() + ' ') self.intLinkDialog = None self.inLinkSelectMode.emit(False) def selectLink(self): """Select the full link at the cursor, return link data. Any links at the cursor or partially selected are fully selected. Returns a tuple of the link address and name, or a tuple with empty strings if none are found. """ cursor = self.textCursor() if not cursor.hasSelection() and not cursor.charFormat().anchorHref(): return ('', '') selectText = cursor.selection().toPlainText() anchorCursor = QTextCursor(self.document()) anchorCursor.setPosition(cursor.anchor()) cursor.clearSelection() if cursor < anchorCursor: anchorCursor, cursor = cursor, anchorCursor position = cursor.position() address = name = '' if anchorCursor.charFormat().anchorHref(): fragIter = anchorCursor.block().begin() while not (fragIter.fragment().contains(anchorCursor.position()) or fragIter.fragment().contains(anchorCursor.position() - 1)): fragIter += 1 fragment = fragIter.fragment() anchorCursor.setPosition(fragment.position()) address = fragment.charFormat().anchorHref() name = fragment.text() if cursor.charFormat().anchorHref(): fragIter = cursor.block().begin() while not (fragIter.fragment().contains(cursor.position()) or fragIter.fragment().contains(cursor.position() - 1)): fragIter += 1 fragment = fragIter.fragment() position = fragment.position() + fragment.length() address = fragment.charFormat().anchorHref() name = fragment.text() if not name: name = selectText.split('\n')[0] cursor.setPosition(anchorCursor.position()) cursor.setPosition(position, QTextCursor.MoveMode.KeepAnchor) self.setTextCursor(cursor) return (address, name) def addDroppedUrl(self, urlText): """Add the URL link that was dropped on this editor from the view. Arguments: urlText -- the text of the link """ name = urltools.shortName(urlText) text = '{1}'.format(urlText, name) if not self.textCursor().hasSelection(): text += ' ' self.insertHtml(text) def pastePlain(self): """Paste non-formatted text from the clipboard. """ text = QApplication.clipboard().mimeData().text() if text and self.hasFocus(): self.insertPlainText(text) def disableActions(self): """Set format actions to unavailable. """ super().disableActions() try: self.allActions['FormatClearFormat'].setEnabled(False) self.allActions['EditPastePlain'].setEnabled(False) except RuntimeError: pass # avoid calling a deleted C++ editor object def updateActions(self): """Set editor format actions to available and update toggle states. """ super().updateActions() self.allActions['FormatBoldFont'].setChecked(self.fontWeight() == QFont.Weight.Bold) self.allActions['FormatItalicFont'].setChecked(self.fontItalic()) self.allActions['FormatUnderlineFont'].setChecked(self.fontUnderline()) self.allActions['FormatStrikethroughFont'].setChecked(self. currentCharFormat().fontStrikeOut()) fontSizeSubMenu = self.allActions['FormatFontSize'].parent() pointSize = int(self.fontPointSize()) try: sizeNum = RichTextEditor.fontPointSizes.index(pointSize) except ValueError: sizeNum = 1 # default size fontSizeSubMenu.actions()[sizeNum].setChecked(True) self.allActions['FormatClearFormat'].setEnabled(True) mime = QApplication.clipboard().mimeData() self.allActions['EditPastePlain'].setEnabled(len(mime. data('text/plain')) > 0) def contextMenuEvent(self, event): """Override popup menu to add formatting and global actions. Arguments: event -- the menu event """ menu = QMenu(self) menu.addAction(self.allActions['FormatBoldFont']) menu.addAction(self.allActions['FormatItalicFont']) menu.addAction(self.allActions['FormatUnderlineFont']) menu.addAction(self.allActions['FormatStrikethroughFont']) menu.addSeparator() menu.addMenu(self.allActions['FormatFontSize'].parent()) menu.addAction(self.allActions['FormatFontColor']) menu.addSeparator() menu.addAction(self.allActions['FormatExtLink']) menu.addAction(self.allActions['FormatIntLink']) menu.addAction(self.allActions['FormatInsertDate']) menu.addSeparator() menu.addAction(self.allActions['FormatSelectAll']) menu.addAction(self.allActions['FormatClearFormat']) menu.addSeparator() menu.addAction(self.allActions['EditCut']) menu.addAction(self.allActions['EditCopy']) menu.addAction(self.allActions['EditPaste']) menu.addAction(self.allActions['EditPastePlain']) menu.exec(event.globalPos()) def mousePressEvent(self, event): """Handle ctrl + click to follow links. Arguments: event -- the mouse event """ if (event.button() == Qt.MouseButton.LeftButton and event.modifiers() == Qt.KeyboardModifier.ControlModifier): cursor = self.cursorForPosition(event.position().toPoint()) address = cursor.charFormat().anchorHref() if address: if address.startswith('#'): editView = self.parent().parent() selectModel = editView.treeView.selectionModel() selectModel.selectNodeById(address[1:]) else: # check for relative path if urltools.isRelative(address): defaultPath = str(globalref.mainControl. defaultPathObj(True)) address = urltools.toAbsolute(address, defaultPath) openExtUrl(address) event.accept() else: super().mousePressEvent(event) class OneLineTextEditor(RichTextEditor): """An editor widget for single-line wysiwyg rich text fields. """ def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) def insertFromMimeData(self, mimeSource): """Override to verify that only a single line is pasted or dropped. Arguments: mimeSource -- the mime source to be inserted """ super().insertFromMimeData(mimeSource) text = self.contents() if '
    ' in text: text = text.split('
    ', 1)[0] self.blockSignals(True) self.setHtml(text) self.blockSignals(False) self.moveCursor(QTextCursor.MoveOperation.End) def keyPressEvent(self, event): """Customize handling of return and control keys. Arguments: event -- the key press event """ if event.key() not in (Qt.Key.Key_Enter, Qt.Key.Key_Return): super().keyPressEvent(event) class LineEditor(QLineEdit): """An editor widget for unformatted single-line fields. Used both stand-alone and as part of the combo box editor. """ dragLinkEnabled = False contentsChanged = pyqtSignal(QWidget) editEnding = pyqtSignal(QWidget) contextMenuPrep = pyqtSignal() def __init__(self, parent=None, subControl=False): """Initialize the editor class. Includes a colored triangle error flag for non-matching formats. Arguments: parent -- the parent, if given subcontrol -- true if used inside a combo box (no border or signal) """ super().__init__(parent) self.setPalette(QApplication.palette()) self.cursorPositionChanged.connect(self.updateActions) self.selectionChanged.connect(self.updateActions) try: self.allActions = parent.parent().allActions except AttributeError: # view is a level up if embedded in a combo self.allActions = parent.parent().parent().allActions self.modified = False self.errorFlag = False self.savedCursorPos = None self.extraMenuActions = [] if not subControl: self.setStyleSheet('QLineEdit {border: 2px solid ' 'palette(highlight)}') self.textEdited.connect(self.signalUpdate) def setContents(self, text): """Set the contents of the editor to text. Arguments: text - the new text contents for the editor """ self.setText(text) def contents(self): """Return the editor text contents. """ return self.text() def signalUpdate(self): """Signal the delegate to update the model based on an editor change. """ self.modified = True self.errorFlag = False self.contentsChanged.emit(self) def setErrorFlag(self): """Set the error flag to True and repaint the widget. """ self.errorFlag = True self.update() def cursorPosTuple(self): """Return a tuple of the current cursor position and anchor (integers). """ pos = start = self.cursorPosition() if self.hasSelectedText(): start = self.selectionStart() return (start, pos) def setCursorPos(self, anchor, position): """Set the cursor to the given anchor and position. Arguments: anchor -- the cursor selection start integer position -- the cursor position or select end integer """ if anchor == position: self.deselect() self.setCursorPosition(position) else: self.setSelection(anchor, position - anchor) def setCursorPoint(self, point): """Set the cursor to the given point. Arguments: point -- the QPoint for the new cursor position """ self.savedCursorPos = self.cursorPositionAt(self.mapFromGlobal(point)) self.setCursorPosition(self.savedCursorPos) def resetCursor(self): """Set the cursor to select all for tab-focus use. """ self.selectAll() def scrollPosition(self): """Return the current scrollbar position. """ return 0 def setScrollPosition(self, value): """Set the scrollbar position to value. No operation with single line editor. Arguments: value -- the new scrollbar position """ pass def paintEvent(self, event): """Add painting of the error flag to the paint event. Arguments: event -- the paint event """ super().paintEvent(event) if self.errorFlag: painter = QPainter(self) path = QPainterPath(QPointF(0, 0)) path.lineTo(0, 10) path.lineTo(10, 0) path.closeSubpath() painter.fillPath(path, QApplication.palette().highlight()) def disableActions(self): """Reset action availability after focus is lost. """ try: self.allActions['EditCut'].setEnabled(True) self.allActions['EditCopy'].setEnabled(True) mime = QApplication.clipboard().mimeData() self.allActions['EditPaste'].setEnabled(len(mime.data('text/xml') or mime.data('text/plain')) > 0) except RuntimeError: pass # avoid calling a deleted C++ editor object def updateActions(self): """Set availability of context menu actions. """ hasSelection = self.hasSelectedText() self.allActions['EditCut'].setEnabled(hasSelection) self.allActions['EditCopy'].setEnabled(hasSelection) mime = QApplication.clipboard().mimeData() self.allActions['EditPaste'].setEnabled(len(mime.data('text/plain')) > 0) def contextMenuEvent(self, event): """Override popup menu to add formatting actions. Arguments: event -- the menu event """ self.contextMenuPrep.emit() menu = QMenu(self) if self.extraMenuActions: for action in self.extraMenuActions: menu.addAction(action) menu.addSeparator() menu.addAction(self.allActions['FormatSelectAll']) menu.addSeparator() menu.addAction(self.allActions['EditCut']) menu.addAction(self.allActions['EditCopy']) menu.addAction(self.allActions['EditPaste']) menu.exec(event.globalPos()) def focusInEvent(self, event): """Restore a saved cursor position for new editors. Arguments: event -- the focus event """ super().focusInEvent(event) if (event.reason() == Qt.FocusReason.OtherFocusReason and self.savedCursorPos != None): self.setCursorPosition(self.savedCursorPos) self.savedCursorPos = None self.updateActions() def focusOutEvent(self, event): """Reset format actions on focus loss if not focusing a menu. Arguments: event -- the focus event """ super().focusOutEvent(event) if event.reason() != Qt.FocusReason.PopupFocusReason: self.disableActions() self.editEnding.emit(self) def hideEvent(self, event): """Reset format actions when the editor is hidden. Arguments: event -- the hide event """ self.disableActions() self.editEnding.emit(self) super().hideEvent(event) class ReadOnlyEditor(LineEditor): """An editor widget that doesn't allow any edits. """ def __init__(self, parent=None): """Initialize the editor class. Includes a colored triangle error flag for non-matching formats. Arguments: parent -- the parent, if given """ super().__init__(parent, True) self.setReadOnly(True) self.setStyleSheet('QLineEdit {border: 2px solid palette(highlight); ' 'background-color: palette(button)}') class ComboEditor(QComboBox): """A general combo box editor widget. Uses the LineEditor class to paint the error flag. """ dragLinkEnabled = False contentsChanged = pyqtSignal(QWidget) editEnding = pyqtSignal(QWidget) def __init__(self, parent=None): """Initialize the editor class. The self.fieldRef and self.nodeRef must be set after creation. Arguments: parent -- the parent, if given """ super().__init__(parent) self.setPalette(QApplication.palette()) self.setStyleSheet('QComboBox {border: 2px solid palette(highlight)}') self.setEditable(True) self.setLineEdit(LineEditor(self, True)) self.listView = QTreeWidget() self.listView.setColumnCount(2) self.listView.header().hide() self.listView.setRootIsDecorated(False) self.listView.setSelectionBehavior(QAbstractItemView. SelectionBehavior.SelectRows) self.listView.header().setSectionResizeMode(QHeaderView.ResizeMode. ResizeToContents) self.setModel(self.listView.model()) self.setView(self.listView) self.setModelColumn(0) self.modified = False self.fieldRef = None self.nodeRef = None self.editTextChanged.connect(self.signalUpdate) self.lineEdit().editEnding.connect(self.signalEditEnd) def setContents(self, text): """Set the contents of the editor to text. Arguments: text - the new text contents for the editor """ self.blockSignals(True) self.setEditText(text) self.blockSignals(False) def contents(self): """Return the editor text contents. """ return self.currentText() def showPopup(self): """Load combo box with choices before showing it. """ self.listView.setColumnCount(self.fieldRef.numChoiceColumns) text = self.currentText() if self.fieldRef.autoAddChoices: self.fieldRef.clearChoices() for node in self.nodeRef.treeStructureRef().nodeDict.values(): if node.formatRef == self.nodeRef.formatRef: self.fieldRef.addChoice(node.data.get(self.fieldRef.name, '')) self.blockSignals(True) self.clear() if self.fieldRef.numChoiceColumns == 1: choices = self.fieldRef.comboChoices() self.addItems(choices) else: annotatedChoices = self.fieldRef.annotatedComboChoices(text) for choice, annot in annotatedChoices: QTreeWidgetItem(self.listView, [choice, annot]) choices = [choice for (choice, annot) in annotatedChoices] try: self.setCurrentIndex(choices.index(text)) except ValueError: self.setEditText(text) self.blockSignals(False) super().showPopup() def signalUpdate(self): """Signal the delegate to update the model based on an editor change. """ self.modified = True self.lineEdit().errorFlag = False self.contentsChanged.emit(self) def setErrorFlag(self): """Set the error flag to True and repaint the widget. """ self.lineEdit().errorFlag = True self.update() def hasSelectedText(self): """Return True if text is selected. """ return self.lineEdit().hasSelectedText() def selectAll(self): """Select all text in the line editor. """ self.lineEdit().selectAll() def cursorPosTuple(self): """Return a tuple of the current cursor position and anchor (integers). """ return self.lineEdit().cursorPosTuple() def setCursorPos(self, anchor, position): """Set the cursor to the given anchor and position. Arguments: anchor -- the cursor selection start integer position -- the cursor position or select end integer """ self.lineEdit().setCursorPos(anchor, position) def setCursorPoint(self, point): """Set the cursor to the given point. Arguments: point -- the QPoint for the new cursor position """ self.lineEdit().setCursorPoint(point) def resetCursor(self): """Set the cursor to select all for tab-focus use. """ self.lineEdit().selectAll() def scrollPosition(self): """Return the current scrollbar position. """ return 0 def setScrollPosition(self, value): """Set the scrollbar position to value. No operation with single line editor. Arguments: value -- the new scrollbar position """ pass def copy(self): """Copy text selected in the line editor. """ self.lineEdit().copy() def cut(self): """Cut text selected in the line editor. """ self.lineEdit().cut() def paste(self): """Paste from the clipboard into the line editor. """ self.lineEdit().paste() def signalEditEnd(self): """Emit editEnding signal based on line edit signal. """ self.editEnding.emit(self) class CombinationEditor(ComboEditor): """An editor widget for combination and auto-combination fields. Uses a combo box with a list of checkboxes in place of the list popup. """ def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.checkBoxDialog = None def showPopup(self): """Override to show a popup entry widget in place of a list view. """ if self.fieldRef.autoAddChoices: self.fieldRef.clearChoices() for node in self.nodeRef.treeStructureRef().nodeDict.values(): if node.formatRef == self.nodeRef.formatRef: self.fieldRef.addChoice(node.data.get(self.fieldRef.name, '')) selectList = self.fieldRef.comboActiveChoices(self.currentText()) self.checkBoxDialog = CombinationDialog(self.fieldRef.comboChoices(), selectList, self) self.checkBoxDialog.setMinimumWidth(self.width()) self.checkBoxDialog.buttonChanged.connect(self.updateText) self.checkBoxDialog.show() pos = self.mapToGlobal(self.rect().bottomRight()) pos.setX(pos.x() - self.checkBoxDialog.width() + 1) screenBottom = (QApplication.primaryScreen().availableGeometry(). bottom()) if pos.y() + self.checkBoxDialog.height() > screenBottom: pos.setY(pos.y() - self.rect().height() - self.checkBoxDialog.height()) self.checkBoxDialog.move(pos) def hidePopup(self): """Override to hide the popup entry widget. """ if self.checkBoxDialog: self.checkBoxDialog.hide() super().hidePopup() def updateText(self): """Update the text based on a changed signal. """ if self.checkBoxDialog: self.setEditText(self.fieldRef.joinText(self.checkBoxDialog. selectList())) class CombinationDialog(QDialog): """A popup dialog box for combination and auto-combination fields. """ buttonChanged = pyqtSignal() def __init__(self, choiceList, selectList, parent=None): """Initialize the combination dialog. Arguments: choiceList -- a list of text choices selectList -- a lit of choices to preselect parent -- the parent, if given """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Popup) topLayout = QVBoxLayout(self) topLayout.setContentsMargins(0, 0, 0, 0) scrollArea = QScrollArea() scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) topLayout.addWidget(scrollArea) innerWidget = QWidget() innerLayout = QVBoxLayout(innerWidget) selected = set(selectList) self.buttonGroup = QButtonGroup(self) self.buttonGroup.setExclusive(False) self.buttonGroup.buttonClicked.connect(self.buttonChanged) for text in choiceList: button = QCheckBox(text, innerWidget) if text in selected: button.setChecked(True) self.buttonGroup.addButton(button) innerLayout.addWidget(button) scrollArea.setWidget(innerWidget) buttons = self.buttonGroup.buttons() if buttons: buttons[0].setFocus() def selectList(self): """Return a list of currently checked text. """ result = [] for button in self.buttonGroup.buttons(): if button.isChecked(): result.append(button.text()) return result class DateEditor(ComboEditor): """An editor widget for date fields. Uses a combo box with a calendar widget in place of the list popup. """ def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.calendar = None nowAction = QAction(_('Today\'s &Date'), self) nowAction.triggered.connect(self.setNow) self.lineEdit().extraMenuActions = [nowAction] def editorDate(self): """Return the date (as a QDate) set in the line editor. If none or invalid, return an invalid date. """ try: dateStr = self.fieldRef.storedText(self.currentText()) except ValueError: return QDate() return QDate.fromString(dateStr, Qt.DateFormat.ISODate) def showPopup(self): """Override to show a calendar widget in place of a list view. """ if not self.calendar: self.calendar = QCalendarWidget(self) self.calendar.setWindowFlags(Qt.WindowType.Popup) weekStart = optiondefaults.daysOfWeek.index(globalref. genOptions['WeekStart']) self.calendar.setFirstDayOfWeek(Qt.DayOfWeek(weekStart + 1)) self.calendar.setVerticalHeaderFormat(QCalendarWidget. VerticalHeaderFormat. NoVerticalHeader) self.calendar.clicked.connect(self.setDate) date = self.editorDate() if date.isValid(): self.calendar.setSelectedDate(date) self.calendar.show() pos = self.mapToGlobal(self.rect().bottomRight()) pos.setX(pos.x() - self.calendar.width()) screenBottom = (QApplication.primaryScreen().availableGeometry(). bottom()) if pos.y() + self.calendar.height() > screenBottom: pos.setY(pos.y() - self.rect().height() - self.calendar.height()) self.calendar.move(pos) def hidePopup(self): """Override to hide the calendar widget. """ if self.calendar: self.calendar.hide() super().hidePopup() def setDate(self, date): """Set the date based on a signal from the calendar popup. Arguments: date -- the QDate to be set """ dateStr = date.toString(Qt.DateFormat.ISODate) self.setEditText(self.fieldRef.formatEditorText(dateStr)) self.calendar.hide() def setNow(self): """Set to today's date. """ dateStr = QDate.currentDate().toString(Qt.DateFormat.ISODate) self.setEditText(self.fieldRef.formatEditorText(dateStr)) class TimeEditor(ComboEditor): """An editor widget for time fields. Adds a clock popup dialog and a "now" right-click menu action. """ def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.dialog = None nowAction = QAction(_('Set to &Now'), self) nowAction.triggered.connect(self.setNow) self.lineEdit().extraMenuActions = [nowAction] def showPopup(self): """Override to show a popup entry widget in place of a list view. """ if not self.dialog: self.dialog = TimeDialog(self) self.dialog.contentsChanged.connect(self.setTime) self.dialog.show() pos = self.mapToGlobal(self.rect().bottomRight()) pos.setX(pos.x() - self.dialog.width() + 1) screenBottom = QApplication.primaryScreen().availableGeometry().bottom() if pos.y() + self.dialog.height() > screenBottom: pos.setY(pos.y() - self.rect().height() - self.dialog.height()) self.dialog.move(pos) try: storedText = self.fieldRef.storedText(self.currentText()) except ValueError: storedText = '' if storedText: self.dialog.setTimeFromText(storedText) def hidePopup(self): """Override to hide the popup entry widget. """ if self.dialog: self.dialog.hide() super().hidePopup() def setTime(self): """Set the time fom the dialog. """ if self.dialog: timeStr = self.dialog.timeObject().isoformat() + '.000' self.setEditText(self.fieldRef.formatEditorText(timeStr)) def setNow(self): """Set to the current time. """ timeStr = QTime.currentTime().toString('hh:mm:ss.zzz') self.setEditText(self.fieldRef.formatEditorText(timeStr)) TimeElem = enum.Enum('TimeElem', 'hour minute second') class TimeDialog(QDialog): """A popup clock dialog for time editing. """ contentsChanged = pyqtSignal() def __init__(self, addCalendar=False, parent=None): """Initialize the dialog widgets. Arguments: parent -- the dialog's parent widget """ super().__init__(parent) self.focusElem = None self.setWindowFlags(Qt.WindowType.Popup) horizLayout = QHBoxLayout(self) if addCalendar: self.calendar = QCalendarWidget() horizLayout.addWidget(self.calendar) weekStart = optiondefaults.daysOfWeek.index(globalref. genOptions['WeekStart']) self.calendar.setFirstDayOfWeek(Qt.DayOfWeek(weekStart + 1)) self.calendar.setVerticalHeaderFormat(QCalendarWidget. VerticalHeaderFormat. NoVerticalHeader) self.calendar.clicked.connect(self.contentsChanged) vertLayout = QVBoxLayout() horizLayout.addLayout(vertLayout) upperLayout = QHBoxLayout() vertLayout.addLayout(upperLayout) upperLayout.addStretch(0) self.hourBox = TimeSpinBox(TimeElem.hour, 1, 12, False) upperLayout.addWidget(self.hourBox) self.hourBox.valueChanged.connect(self.signalUpdate) self.hourBox.focusChanged.connect(self.handleFocusChange) colon = QLabel(':') upperLayout.addWidget(colon) self.minuteBox = TimeSpinBox(TimeElem.minute, 0, 59, True) upperLayout.addWidget(self.minuteBox) self.minuteBox.valueChanged.connect(self.signalUpdate) self.minuteBox.focusChanged.connect(self.handleFocusChange) colon = QLabel(':') upperLayout.addWidget(colon) self.secondBox = TimeSpinBox(TimeElem.second, 0, 59, True) upperLayout.addWidget(self.secondBox) self.secondBox.valueChanged.connect(self.signalUpdate) self.secondBox.focusChanged.connect(self.handleFocusChange) self.amPmBox = AmPmSpinBox() upperLayout.addSpacing(4) upperLayout.addWidget(self.amPmBox) self.amPmBox.valueChanged.connect(self.signalUpdate) upperLayout.addStretch(0) lowerLayout = QHBoxLayout() vertLayout.addLayout(lowerLayout) self.clock = ClockWidget() lowerLayout.addWidget(self.clock, Qt.AlignmentFlag.AlignCenter) self.clock.numClicked.connect(self.setFromClock) if addCalendar: self.calendar.setFocus() self.updateClock() else: self.hourBox.setFocus() self.hourBox.selectAll() def setTimeFromText(self, text): """Set the time dialog from a string. Arguments: text -- the time in ISO format """ time = (datetime.datetime. strptime(text, fieldformat.TimeField.isoFormat).time()) hour = time.hour if time.hour <= 12 else time.hour - 12 self.blockSignals(True) self.hourBox.setValue(hour) self.minuteBox.setValue(time.minute) self.secondBox.setValue(time.second) amPm = 'AM' if time.hour < 12 else 'PM' self.amPmBox.setValue(amPm) self.blockSignals(False) self.updateClock() def setDateFromText(self, text): """Set the date dialog from a string. Arguments: text -- the date in ISO format """ date = QDate.fromString(text, Qt.DateFormat.ISODate) if date.isValid(): self.calendar.setSelectedDate(date) def timeObject(self): """Return a datetime time object for the current dialog setting. """ hour = self.hourBox.value() if self.amPmBox.value == 'PM': if hour < 12: hour += 12 elif hour == 12: hour = 0 return datetime.time(hour, self.minuteBox.value(), self.secondBox.value()) def updateClock(self): """Update the clock based on the current time and focused widget. """ hands = [self.focusElem] if self.focusElem else [TimeElem.hour, TimeElem.minute, TimeElem.second] self.clock.setDisplay(self.timeObject(), hands) def handleFocusChange(self, elemType, isFocused): """Update clock based on focus changes. Arguments: elemType -- the TimeElem of the focus change isFocused -- True if focus is gained """ if isFocused: if elemType != self.focusElem: self.focusElem = elemType self.updateClock() elif elemType == self.focusElem: self.focusElem = None self.updateClock() def setFromClock(self, num): """Set the active spin box value from a clock click. Arguments: num -- the number clicked """ spinBox = getattr(self, self.focusElem.name + 'Box') spinBox.setValue(num) spinBox.selectAll() def signalUpdate(self): """Signal a time change and update the clock. """ self.updateClock() self.contentsChanged.emit() class TimeSpinBox(QSpinBox): """A spin box for time values with optional leading zero. """ focusChanged = pyqtSignal(TimeElem, bool) def __init__(self, elemType, minValue, maxValue, leadZero=True, parent=None): """Initialize the spin box. Arguments: elemType -- the TimeElem of this box minValue -- the minimum allowed value maxValue -- the maximum allowed value leadZero -- true if a leading zero used with single digit values parent -- the box's parent widget """ self.elemType = elemType self.leadZero = leadZero super().__init__(parent) self.setMinimum(minValue) self.setMaximum(maxValue) self.setWrapping(True) self.setAlignment(Qt.AlignmentFlag.AlignRight) def textFromValue(self, value): """Override to optionally add leading zero. Arguments: value -- the int value to convert """ if self.leadZero and value < 10: return '0' + repr(value) return repr(value) def focusInEvent(self, event): """Emit a signal when focused. Arguments: event -- the focus event """ super().focusInEvent(event) self.focusChanged.emit(self.elemType, True) def focusOutEvent(self, event): """Emit a signal if focus is lost. Arguments: event -- the focus event """ super().focusOutEvent(event) self.focusChanged.emit(self.elemType, False) class AmPmSpinBox(QAbstractSpinBox): """A spin box for AM/PM values. """ valueChanged = pyqtSignal() def __init__(self, parent=None): """Initialize the spin box. Arguments: parent -- the box's parent widget """ super().__init__(parent) self.value = 'AM' self.setDisplay() def stepBy(self, steps): """Step the spin box to the alternate value. Arguments: steps -- number of steps (ignored) """ self.value = 'PM' if self.value == 'AM' else 'AM' self.setDisplay() def stepEnabled(self): """Return enabled to show that stepping is always enabled. """ return (QAbstractSpinBox.StepEnabledFlag.StepUpEnabled | QAbstractSpinBox.StepEnabledFlag.StepDownEnabled) def setValue(self, value): """Set to text value if valid. Arguments: value -- the text value to set """ if value in ('AM', 'PM'): self.value = value self.setDisplay() def setDisplay(self): """Update display to match value. """ self.lineEdit().setText(self.value) self.valueChanged.emit() if self.hasFocus(): self.selectAll() def validate(self, inputStr, pos): """Check if the input string is acceptable. Arguments: inputStr -- the string to check pos -- the pos in the string (ignored) """ inputStr = inputStr.upper() if inputStr in ('AM', 'A'): self.value = 'AM' self.setDisplay() return (QValidator.State.Acceptable, 'AM', 2) if inputStr in ('PM', 'P'): self.value = 'PM' self.setDisplay() return (QValidator.State.Acceptable, 'PM', 2) return (QValidator.State.Invalid, 'xx', 2) def sizeHint(self): """Set prefered size. """ return super().sizeHint() + (QFontMetrics(self.font()). size(Qt.TextFlag.TextSingleLine, 'AM')) def focusInEvent(self, event): """Set select all when focused. Arguments: event -- the focus event """ super().focusInEvent(event) self.selectAll() def focusOutEvent(self, event): """Remove selection if focus is lost. Arguments: event -- the focus event """ super().focusOutEvent(event) self.lineEdit().deselect() class ClockWidget(QWidget): """A widget showing a clickable clock face. """ radius = 80 margin = 10 handLengths = {TimeElem.hour: int(radius * 0.5), TimeElem.minute: int(radius * 0.9), TimeElem.second: int(radius * 0.95)} handWidths = {TimeElem.hour: 7, TimeElem.minute: 5, TimeElem.second: 2} divisor = {TimeElem.hour: 120, TimeElem.minute: 10, TimeElem.second: 1 / 6} numClicked = pyqtSignal(int) def __init__(self, parent=None): """Initialize the clock. Arguments: parent -- the dialog's parent widget """ super().__init__(parent) self.time = datetime.time() self.hands = [] self.highlightAngle = None self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) self.setMouseTracking(True) def setDisplay(self, time, hands): """Set the clock display. Arguments: time -- a datetime time value hands -- a list of TimeElem clock hands to show """ self.time = time self.hands = hands self.highlightAngle = None self.update() def paintEvent(self, event): """Paint the clock face. Arguments: event -- the paint event """ painter = QPainter(self) painter.save() painter.setBrush(QApplication.palette().base()) painter.setPen(Qt.PenStyle.NoPen) painter.drawEllipse(self.rect()) painter.translate(ClockWidget.radius + ClockWidget.margin, ClockWidget.radius + ClockWidget.margin) for timeElem in self.hands: painter.save() painter.setBrush(QApplication.palette().windowText()) painter.setPen(Qt.PenStyle.NoPen) seconds = (self.time.hour * 3600 + self.time.minute * 60 + self.time.second) angle = seconds / ClockWidget.divisor[timeElem] % 360 if len(self.hands) == 1: painter.setBrush(QApplication.palette().highlight()) if self.hands[0] == TimeElem.hour: angle = int(angle // 30 * 30) # truncate to whole hour else: angle = int(angle // 6 * 6) # truncate to whole min/sec painter.rotate(angle) points = (QPoint(0, -ClockWidget.handLengths[timeElem]), QPoint(ClockWidget.handWidths[timeElem], 8), QPoint(-ClockWidget.handWidths[timeElem], 8)) painter.drawConvexPolygon(*points) painter.restore() rect = QRect(0, 0, 20, 20) if len(self.hands) != 1 or self.hands[0] == TimeElem.hour: labels = [repr(num) for num in range(1, 13)] else: labels = ['{0:0>2}'.format(num) for num in range(5, 56, 5)] labels.append('00') for ang in range(30, 361, 30): rect.moveCenter(self.pointOnRadius(ang)) painter.setPen(QPen(QApplication.palette().text(), 1)) if len(self.hands) == 1 and (ang == angle or ang == self.highlightAngle): painter.setPen(QPen(QApplication.palette().highlight(), 1)) painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, labels.pop(0)) painter.restore() super().paintEvent(event) def sizeHint(self): """Set prefered size. """ width = (ClockWidget.radius + ClockWidget.margin) * 2 return QSize(width, width) def pointOnRadius(self, angle): """Return a QPoint on the radius at the given angle. Arguments: angle -- the angle in dgrees from vertical (clockwise) """ angle = math.radians(angle) x = round(ClockWidget.radius * math.sin(angle)) y = 0 - round(ClockWidget.radius * math.cos(angle)) return QPoint(x, y) def pointToPosition(self, point): """Return a position (1 to 12) based on a screen point. Return None if not on a position. Arguments: point -- a QPoint screen position """ x = point.x() - ClockWidget.radius - ClockWidget.margin y = point.y() - ClockWidget.radius - ClockWidget.margin radius = math.sqrt(x**2 + y**2) if (ClockWidget.radius - 2 * ClockWidget.margin <= radius <= ClockWidget.radius + 2 * ClockWidget.margin): angle = math.degrees(math.atan2(-x, y)) + 180 if angle % 30 <= 10 or angle % 30 >= 20: pos = round(angle / 30) if pos == 0: pos = 12 return pos return None def mousePressEvent(self, event): """Signal user clicks on clock numbers if in single hand mode. Arguments: event -- the mouse press event """ if len(self.hands) == 1 and event.button() == Qt.MouseButton.LeftButton: pos = self.pointToPosition(event.position().toPoint()) if pos: if self.hands[0] != TimeElem.hour: if pos == 12: pos = 0 pos *= 5 self.numClicked.emit(pos) super().mousePressEvent(event) def mouseMoveEvent(self, event): """Highlight clickable numbers if in single hand mode. Arguments: event -- the mouse move event """ if len(self.hands) == 1: pos = self.pointToPosition(event.position().toPoint()) if pos: self.highlightAngle = pos * 30 self.update() elif self.highlightAngle != None: self.highlightAngle = None self.update() super().mouseMoveEvent(event) class DateTimeEditor(ComboEditor): """An editor widget for DateTimeFields. Uses a combo box with a clandar widget in place of the list popup. """ def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.dialog = None nowAction = QAction(_('Set to &Now'), self) nowAction.triggered.connect(self.setNow) self.lineEdit().extraMenuActions = [nowAction] def showPopup(self): """Override to show a popup entry widget in place of a list view. """ if not self.dialog: self.dialog = TimeDialog(True, self) self.dialog.contentsChanged.connect(self.setDateTime) self.dialog.show() pos = self.mapToGlobal(self.rect().bottomRight()) pos.setX(pos.x() - self.dialog.width() + 1) screenBottom = QApplication.primaryScreen().availableGeometry().bottom() if pos.y() + self.dialog.height() > screenBottom: pos.setY(pos.y() - self.rect().height() - self.dialog.height()) self.dialog.move(pos) try: storedText = self.fieldRef.storedText(self.currentText()) except ValueError: storedText = '' if storedText: dateText, timeText = storedText.split(' ', 1) self.dialog.setDateFromText(dateText) self.dialog.setTimeFromText(timeText) def hidePopup(self): """Override to hide the popup entry widget. """ if self.dialog: self.dialog.hide() super().hidePopup() def setDateTime(self): """Set the date and time based on a signal from the dialog calendar. """ if self.dialog: dateStr = self.dialog.calendar.selectedDate().toString(Qt.DateFormat.ISODate) timeStr = self.dialog.timeObject().isoformat() + '.000' self.setEditText(self.fieldRef.formatEditorText(dateStr + ' ' + timeStr)) def setNow(self): """Set to the current date and time. """ dateTime = QDateTime.currentDateTime() dateTimeStr = dateTime.toString('yyyy-MM-dd HH:mm:ss.zzz') self.setEditText(self.fieldRef.formatEditorText(dateTimeStr)) class ExtLinkEditor(ComboEditor): """An editor widget for external link fields. Uses a combo box with a link entry box in place of the list popup. """ dragLinkEnabled = True def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.setAcceptDrops(True) self.dialog = None openAction = QAction(_('&Open Link'), self) openAction.triggered.connect(self.openLink) folderAction = QAction(_('Open &Folder'), self) folderAction.triggered.connect(self.openFolder) self.lineEdit().extraMenuActions = [openAction, folderAction] self.lineEdit().contextMenuPrep.connect(self.updateActions) def showPopup(self): """Override to show a popup entry widget in place of a list view. """ if not self.dialog: self.dialog = ExtLinkDialog(True, self) self.dialog.contentsChanged.connect(self.setLink) self.dialog.show() pos = self.mapToGlobal(self.rect().bottomRight()) pos.setX(pos.x() - self.dialog.width() + 1) screenBottom = QApplication.primaryScreen().availableGeometry().bottom() if pos.y() + self.dialog.height() > screenBottom: pos.setY(pos.y() - self.rect().height() - self.dialog.height()) self.dialog.move(pos) self.dialog.setFromEditor(self.currentText()) def hidePopup(self): """Override to hide the popup entry widget. """ if self.dialog: self.dialog.hide() super().hidePopup() def setLink(self): """Set the current link from the popup dialog. """ self.setEditText(self.dialog.editorText()) def openLink(self): """Open the link in a web browser. """ text = self.currentText() if text: nameMatch = fieldformat.linkSeparateNameRegExp.match(text) if nameMatch: address = nameMatch.group(1).strip() else: address = text.strip() if address: if urltools.isRelative(address): defaultPath = globalref.mainControl.defaultPathObj(True) address = urltools.toAbsolute(address, str(defaultPath)) openExtUrl(address) def openFolder(self): """Open the link in a file manager/explorer. """ text = self.currentText() if text: nameMatch = fieldformat.linkSeparateNameRegExp.match(text) if nameMatch: address = nameMatch.group(1).strip() else: address = text.strip() if address and urltools.extractScheme(address) in ('', 'file'): if urltools.isRelative(address): defaultPath = globalref.mainControl.defaultPathObj(True) address = urltools.toAbsolute(address, str(defaultPath)) address = os.path.dirname(address) openExtUrl(address) def updateActions(self): """Set availability of custom context menu actions. """ address = self.currentText() if address: nameMatch = fieldformat.linkSeparateNameRegExp.match(address) if nameMatch: address = nameMatch.group(1).strip() else: address = address.strip() openAction, folderAction = self.lineEdit().extraMenuActions openAction.setEnabled(len(address) > 0) folderAction.setEnabled(len(address) > 0 and urltools.extractScheme(address) in ('', 'file')) def addDroppedUrl(self, urlText): """Add the URL link that was dropped on this editor from the view. Arguments: urlText -- the text of the link """ self.setEditText(urlText) def dragEnterEvent(self, event): """Accept drags of files to this widget. Arguments: event -- the drag event object """ if event.mimeData().hasUrls(): event.accept() def dropEvent(self, event): """Open a file dropped onto this widget. Arguments: event -- the drop event object """ fileList = event.mimeData().urls() if fileList: self.setEditText(fileList[0].toLocalFile()) _extLinkSchemes = ('http://', 'https://', 'mailto:', 'file://') _extLinkSchemeDict = {proto.split(':', 1)[0]: proto for proto in _extLinkSchemes} class ExtLinkDialog(QDialog): """A popup or normal dialog box for external link editing. """ contentsChanged = pyqtSignal() def __init__(self, popupDialog=False, parent=None): """Initialize the dialog widgets. Arguments: popupDialog -- add OK and cancel buttons if False parent -- the dialog's parent widget """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('External Link')) vertLayout = QVBoxLayout(self) vertLayout.setSpacing(1) schemeLabel = QLabel(_('Scheme')) vertLayout.addWidget(schemeLabel) schemeLayout = QHBoxLayout() vertLayout.addLayout(schemeLayout) schemeLayout.setSpacing(8) self.schemeButtons = QButtonGroup(self) self.schemeButtonDict = {} for scheme in _extLinkSchemes: scheme = scheme.split(':', 1)[0] button = QRadioButton(scheme) self.schemeButtons.addButton(button) self.schemeButtonDict[scheme] = button schemeLayout.addWidget(button) self.schemeButtonDict['http'].setChecked(True) self.schemeButtons.buttonClicked.connect(self.updateScheme) vertLayout.addSpacing(8) self.browseButton = QPushButton(_('&Browse for File')) self.browseButton.setAutoDefault(False) self.browseButton.clicked.connect(self.fileBrowse) vertLayout.addWidget(self.browseButton) vertLayout.addSpacing(8) self.pathTypeLabel = QLabel(_('File Path Type')) vertLayout.addWidget(self.pathTypeLabel) pathTypeLayout = QHBoxLayout() vertLayout.addLayout(pathTypeLayout) pathTypeLayout.setSpacing(8) pathTypeButtons = QButtonGroup(self) self.absoluteButton = QRadioButton(_('Absolute')) pathTypeButtons.addButton(self.absoluteButton) pathTypeLayout.addWidget(self.absoluteButton) self.relativeButton = QRadioButton(_('Relative')) pathTypeButtons.addButton(self.relativeButton) pathTypeLayout.addWidget(self.relativeButton) self.absoluteButton.setChecked(True) pathTypeButtons.buttonClicked.connect(self.updatePathType) vertLayout.addSpacing(8) addressLabel = QLabel(_('Address')) vertLayout.addWidget(addressLabel) self.addressEdit = QLineEdit() self.addressEdit.textEdited.connect(self.checkAddress) vertLayout.addWidget(self.addressEdit) vertLayout.addSpacing(8) nameLabel = QLabel(_('Display Name')) vertLayout.addWidget(nameLabel) self.nameEdit = QLineEdit() self.nameEdit.textEdited.connect(self.contentsChanged) vertLayout.addWidget(self.nameEdit) if popupDialog: self.setWindowFlags(Qt.WindowType.Popup) else: vertLayout.addSpacing(8) ctrlLayout = QHBoxLayout() vertLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.addressEdit.setFocus() def setFromEditor(self, editorText): """Set the dialog contents from a string in editor format. Arguments: editorText -- string in "link [name]" format """ name = address = '' editorText = editorText.strip() if editorText: nameMatch = fieldformat.linkSeparateNameRegExp.match(editorText) if nameMatch: address, name = nameMatch.groups() address = address.strip() else: address = editorText name = urltools.shortName(address) self.setFromComponents(address, name) def setFromComponents(self, address, name): """Set the dialog contents from separate address and name. Arguments: address -- the link address, including the scheme prefix name -- the displayed name for the link """ scheme = urltools.extractScheme(address) if scheme not in _extLinkSchemeDict: if not scheme: address = urltools.replaceScheme('file', address) scheme = 'file' self.schemeButtonDict[scheme].setChecked(True) if address and urltools.isRelative(address): self.relativeButton.setChecked(True) else: self.absoluteButton.setChecked(True) self.addressEdit.setText(address) self.nameEdit.setText(name) self.updateFileControls() def editorText(self): """Return the dialog contents in data editor format ("link [name]"). """ address = self.currentAddress() if not address: return '' name = self.nameEdit.text().strip() if not name: name = urltools.shortName(address) return '{0} [{1}]'.format(address, name) def htmlText(self): """Return the dialog contents in HTML link format. """ address = self.currentAddress() if not address: return '' name = self.nameEdit.text().strip() if not name: name = urltools.shortName(address) return '{1}'.format(address, name) def currentAddress(self): """Return current address with the selected scheme prefix. """ scheme = self.schemeButtons.checkedButton().text() address = self.addressEdit.text().strip() return urltools.replaceScheme(scheme, address) def checkAddress(self): """Update controls based on a change to the address field. Makes minimum changes to scheme and absolute controls, since the address may be incomplete. """ address = self.addressEdit.text().strip() scheme = urltools.extractScheme(address) if scheme in _extLinkSchemeDict: self.schemeButtonDict[scheme].setChecked(True) if scheme != 'file': self.absoluteButton.setChecked(True) self.updateFileControls() self.contentsChanged.emit() def updateScheme(self): """Update scheme in the address due to scheme button change. """ scheme = self.schemeButtons.checkedButton().text() address = self.addressEdit.text().strip() address = urltools.replaceScheme(scheme, address) self.addressEdit.setText(address) if urltools.isRelative(address): self.relativeButton.setChecked(True) else: self.absoluteButton.setChecked(True) self.updateFileControls() self.contentsChanged.emit() def updatePathType(self): """Update file path based on a change in the absolute/relative control. """ absolute = self.absoluteButton.isChecked() defaultPath = globalref.mainControl.defaultPathObj(True) address = self.addressEdit.text().strip() if absolute: address = urltools.toAbsolute(address, str(defaultPath)) else: address = urltools.toRelative(address, str(defaultPath)) self.addressEdit.setText(address) self.contentsChanged.emit() def updateFileControls(self): """Set file browse & type controls available based on current scheme. """ enable = self.schemeButtons.checkedButton().text() == 'file' self.browseButton.setEnabled(enable) self.pathTypeLabel.setEnabled(enable) self.absoluteButton.setEnabled(enable) self.relativeButton.setEnabled(enable) def fileBrowse(self): """Show dialog to browse for a file to be linked. Adjust based on absolute or relative path settings. """ refPath = str(globalref.mainControl.defaultPathObj(True)) defaultPath = refPath oldAddress = self.addressEdit.text().strip() oldScheme = urltools.extractScheme(oldAddress) if oldAddress and not oldScheme or oldScheme == 'file': if urltools.isRelative(oldAddress): oldAddress = urltools.toAbsolute(oldAddress, refPath) oldAddress = urltools.extractAddress(oldAddress) if os.access(oldAddress, os.F_OK): defaultPath = oldAddress address, selFltr = QFileDialog.getOpenFileName(QApplication. activeWindow(), _('TreeLine - External Link File'), defaultPath, globalref.fileFilters['all']) if address: if self.relativeButton.isChecked(): address = urltools.toRelative(address, refPath) self.setFromComponents(address, urltools.shortName(address)) self.show() self.contentsChanged.emit() class IntLinkEditor(ComboEditor): """An editor widget for internal link fields. Uses a combo box with a link select dialog in place of the list popup. """ inLinkSelectMode = pyqtSignal(bool) def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.address = '' self.intLinkDialog = None self.setLineEdit(PartialLineEditor(self)) openAction = QAction(_('&Go to Target'), self) openAction.triggered.connect(self.openLink) clearAction = QAction(_('Clear &Link'), self) clearAction.triggered.connect(self.clearLink) self.lineEdit().extraMenuActions = [openAction, clearAction] def setContents(self, text): """Set the contents of the editor to text. Arguments: text - the new text contents for the editor """ super().setContents(text) if not text: self.lineEdit().staticLength = 0 self.address = '' return try: self.address, name = self.fieldRef.addressAndName(self.nodeRef. data.get(self.fieldRef.name, '')) except ValueError: self.address = '' self.address = self.address.lstrip('#') nameMatch = fieldformat.linkSeparateNameRegExp.match(text) if nameMatch: link = nameMatch.group(1) self.lineEdit().staticLength = len(link) + 1 else: self.lineEdit().staticLength = 0 def contents(self): """Return the editor contents in "address [name]" format. """ if not self.address: return self.currentText() nameMatch = fieldformat.linkSeparateNameRegExp.match(self. currentText()) if nameMatch: name = nameMatch.group(2) else: name = '' return '{0} [{1}]'.format(self.address, name.strip()) def clearLink(self): """Clear the contents of the editor. """ self.setContents('') self.signalUpdate() def showPopup(self): """Override to show a popup entry widget in place of a list view. """ if not self.intLinkDialog: self.intLinkDialog = IntLinkDialog(True, self) self.intLinkDialog.show() pos = self.mapToGlobal(self.rect().bottomRight()) pos.setX(pos.x() - self.intLinkDialog.width() + 1) screenBottom = (QApplication.primaryScreen().availableGeometry(). bottom()) if pos.y() + self.intLinkDialog.height() > screenBottom: pos.setY(pos.y() - self.rect().height() - self.intLinkDialog.height()) self.intLinkDialog.move(pos) self.inLinkSelectMode.emit(True) def hidePopup(self): """Override to hide the popup entry widget. """ if self.intLinkDialog: self.intLinkDialog.hide() self.inLinkSelectMode.emit(False) super().hidePopup() def setLinkFromNode(self, node): """Set the current link from a clicked node. Arguments: node -- the node to set the unique ID from """ self.hidePopup() self.address = node.uId linkTitle = node.title() nameMatch = fieldformat.linkSeparateNameRegExp.match(self. currentText()) if nameMatch: name = nameMatch.group(2) else: name = linkTitle self.setEditText('LinkTo: {0} [{1}]'.format(linkTitle, name)) self.lineEdit().staticLength = len(linkTitle) + 9 def openLink(self): """Open the link in a web browser. """ if self.address: editView = self.parent().parent() editView.treeView.selectionModel().selectNodeById(self.address) def setCursorPoint(self, point): """Set the cursor to the given point. Arguments: point -- the QPoint for the new cursor position """ self.lineEdit().setCursorPoint(point) self.lineEdit().fixSelection() class PartialLineEditor(LineEditor): """A line used in internal link combo editors. Only allows the name portion to be selected or editd. """ def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent, True) self.staticLength = 0 def fixSelection(self): """Fix the selection and cursor to not include static portion of text. """ cursorPos = self.cursorPosition() if -1 < self.selectionStart() < self.staticLength: endPos = self.selectionStart() + len(self.selectedText()) if endPos > self.staticLength: if cursorPos >= self.staticLength: self.setSelection(self.staticLength, endPos - self.staticLength) else: # reverse select to get cursor at selection start self.setSelection(endPos, self.staticLength - endPos) return self.deselect() if cursorPos < self.staticLength: self.setCursorPosition(self.staticLength) def selectAll(self): """Select all editable text. """ self.setSelection(self.staticLength, len(self.text())) def mouseReleaseEvent(self, event): """Fix selection if required after mouse release. Arguments: event -- the mouse release event """ super().mouseReleaseEvent(event) self.fixSelection() def keyPressEvent(self, event): """Avoid edits or cursor movements to the static portion of the text. Arguments: event -- the mouse release event """ if (event.key() == Qt.Key.Key_Backspace and (self.cursorPosition() <= self.staticLength and not self.hasSelectedText())): return if event.key() in (Qt.Key.Key_Left, Qt.Key.Key_Home): super().keyPressEvent(event) self.fixSelection() return super().keyPressEvent(event) class IntLinkDialog(QDialog): """A popup dialog box for internal link editing. """ contentsChanged = pyqtSignal() def __init__(self, popupDialog=False, parent=None): """Initialize the dialog widgets. Arguments: popupDialog -- add OK and cancel buttons if False parent -- the dialog's parent widget """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.FramelessWindowHint) layout = QVBoxLayout(self) label = QLabel(_('(Click link target in tree)')) layout.addWidget(label) class EmbedIntLinkDialog(QDialog): """A popup or normal dialog box for internal link editing. """ contentsChanged = pyqtSignal() targetClickDialogRef = None def __init__(self, structRef, parent=None): """Initialize the dialog widgets. Arguments: structRef -- a ref to the tree structure parent -- the dialog's parent widget """ super().__init__(parent) self.structRef = structRef self.address = '' self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Internal Link')) vertLayout = QVBoxLayout(self) vertLayout.setSpacing(1) self.linkLabel = QLabel() vertLayout.addWidget(self.linkLabel) infoLabel = QLabel(_('(Click link target in tree)')) vertLayout.addWidget(infoLabel) vertLayout.addSpacing(8) nameLabel = QLabel(_('Display Name')) vertLayout.addWidget(nameLabel) self.nameEdit = QLineEdit() self.nameEdit.textEdited.connect(self.contentsChanged) vertLayout.addWidget(self.nameEdit) vertLayout.addSpacing(8) ctrlLayout = QHBoxLayout() vertLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) self.okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(self.okButton) self.okButton.setDefault(True) self.okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) def updateLinkText(self): """Update the link label using the current address. """ title = '' name = self.nameEdit.text().strip() if self.address: targetNode = self.structRef.nodeDict.get(self.address, None) if targetNode: title = targetNode.title() if not name: self.nameEdit.setText(title) self.linkLabel.setText('LinkTo: {0}'.format(title)) self.okButton.setEnabled(len(self.address) > 0) def setFromNode(self, node): """Set the dialog contents from a clicked node. Arguments: node -- the node to set the unique ID from """ self.address = node.uId self.updateLinkText() def setFromComponents(self, address, name): """Set the dialog contents from separate address and name. Arguments: address -- the link address, including the protocol prefix name -- the displayed name for the link """ self.address = address self.nameEdit.setText(name) self.updateLinkText() def htmlText(self): """Return the dialog contents in HTML link format. """ name = self.nameEdit.text().strip() if not name: name = _('link') return '{1}'.format(self.address, name) class PictureLinkEditor(ComboEditor): """An editor widget for picture link fields. Uses a combo box with a link entry box in place of the list popup. """ dragLinkEnabled = True def __init__(self, parent=None): """Initialize the editor class. Arguments: parent -- the parent, if given """ super().__init__(parent) self.dialog = None openAction = QAction(_('&Open Picture'), self) openAction.triggered.connect(self.openPicture) self.lineEdit().extraMenuActions = [openAction] def showPopup(self): """Override to show a popup entry widget in place of a list view. """ if not self.dialog: self.dialog = PictureLinkDialog(True, self) self.dialog.contentsChanged.connect(self.setLink) self.dialog.show() pos = self.mapToGlobal(self.rect().bottomRight()) pos.setX(pos.x() - self.dialog.width() + 1) screenBottom = (QApplication.primaryScreen().availableGeometry(). bottom()) if pos.y() + self.dialog.height() > screenBottom: pos.setY(pos.y() - self.rect().height() - self.dialog.height()) self.dialog.move(pos) self.dialog.setAddress(self.currentText()) def hidePopup(self): """Override to hide the popup entry widget. """ if self.dialog: self.dialog.hide() super().hidePopup() def setLink(self): """Set the current link from the popup dialog. """ self.setEditText(self.dialog.currentAddress()) def openPicture(self): """Open the link in a web browser. """ address = self.currentText() if address: if urltools.isRelative(address): defaultPath = globalref.mainControl.defaultPathObj(True) address = urltools.toAbsolute(address, str(defaultPath)) openExtUrl(address) def addDroppedUrl(self, urlText): """Add the URL link that was dropped on this editor from the view. Arguments: urlText -- the text of the link """ self.setEditText(urlText) class PictureLinkDialog(QDialog): """A popup or normal dialog box for picture link editing. """ thumbnailSize = QSize(250, 100) contentsChanged = pyqtSignal() def __init__(self, popupDialog=False, parent=None): """Initialize the dialog widgets. Arguments: popupDialog -- add OK and cancel buttons if False parent -- the dialog's parent widget """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Picture Link')) self.setMinimumWidth(self.thumbnailSize.width()) vertLayout = QVBoxLayout(self) vertLayout.setSpacing(1) self.thumbnail = QLabel() pixmap = QPixmap(self.thumbnailSize) pixmap.fill() self.thumbnail.setPixmap(pixmap) vertLayout.addWidget(self.thumbnail, 0, Qt.AlignmentFlag.AlignHCenter) vertLayout.addSpacing(8) self.browseButton = QPushButton(_('&Browse for File')) self.browseButton.setAutoDefault(False) self.browseButton.clicked.connect(self.fileBrowse) vertLayout.addWidget(self.browseButton) vertLayout.addSpacing(8) self.pathTypeLabel = QLabel(_('File Path Type')) vertLayout.addWidget(self.pathTypeLabel) pathTypeLayout = QHBoxLayout() vertLayout.addLayout(pathTypeLayout) pathTypeLayout.setSpacing(8) pathTypeButtons = QButtonGroup(self) self.absoluteButton = QRadioButton(_('Absolute')) pathTypeButtons.addButton(self.absoluteButton) pathTypeLayout.addWidget(self.absoluteButton) self.relativeButton = QRadioButton(_('Relative')) pathTypeButtons.addButton(self.relativeButton) pathTypeLayout.addWidget(self.relativeButton) self.absoluteButton.setChecked(True) pathTypeButtons.buttonClicked.connect(self.updatePathType) vertLayout.addSpacing(8) addressLabel = QLabel(_('Address')) vertLayout.addWidget(addressLabel) self.addressEdit = QLineEdit() self.addressEdit.textEdited.connect(self.checkAddress) vertLayout.addWidget(self.addressEdit) vertLayout.addSpacing(8) if popupDialog: self.setWindowFlags(Qt.WindowType.Popup) else: vertLayout.addSpacing(8) ctrlLayout = QHBoxLayout() vertLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.addressEdit.setFocus() def setAddress(self, address): """Set the dialog contents from a string in editor format. Arguments: address -- URL string for the address """ if address and urltools.isRelative(address): self.relativeButton.setChecked(True) else: self.absoluteButton.setChecked(True) self.addressEdit.setText(address) self.updateThumbnail() def setFromHtml(self, htmlStr): """Set the dialog contents from an HTML link. Arguments: htmlStr -- string in HTML link format """ linkMatch = imageRegExp.search(htmlStr) if linkMatch: address = linkMatch.group(1) self.setAddress(address.strip()) def htmlText(self): """Return the dialog contents in HTML link format. """ address = self.currentAddress() if not address: return '' return ''.format(address) def currentAddress(self): """Return current address with the selected scheme prefix. """ return self.addressEdit.text().strip() def checkAddress(self): """Update absolute controls based on a change to the address field. """ address = self.addressEdit.text().strip() if address: if urltools.isRelative(address): self.relativeButton.setChecked(True) else: self.absoluteButton.setChecked(True) self.updateThumbnail() self.contentsChanged.emit() def updatePathType(self): """Update path based on a change in the absolute/relative control. """ absolute = self.absoluteButton.isChecked() defaultPath = globalref.mainControl.defaultPathObj(True) address = self.addressEdit.text().strip() if absolute: address = urltools.toAbsolute(address, str(defaultPath), False) else: address = urltools.toRelative(address, str(defaultPath)) self.addressEdit.setText(address) self.updateThumbnail() self.contentsChanged.emit() def updateThumbnail(self): """Update the thumbnail with an image from the current address. """ address = self.addressEdit.text().strip() if urltools.isRelative(address): refPath = str(globalref.mainControl.defaultPathObj(True)) address = urltools.toAbsolute(address, refPath, False) pixmap = QPixmap(address) if pixmap.isNull(): pixmap = QPixmap(self.thumbnailSize) pixmap.fill() else: pixmap = pixmap.scaled(self.thumbnailSize, Qt.AspectRatioMode.KeepAspectRatio) self.thumbnail.setPixmap(pixmap) def fileBrowse(self): """Show dialog to browse for a file to be linked. Adjust based on absolute or relative path settings. """ refPath = str(globalref.mainControl.defaultPathObj(True)) defaultPath = refPath oldAddress = self.addressEdit.text().strip() if oldAddress: if urltools.isRelative(oldAddress): oldAddress = urltools.toAbsolute(oldAddress, refPath) oldAddress = urltools.extractAddress(oldAddress) if os.access(oldAddress, os.F_OK): defaultPath = oldAddress address, selFltr = QFileDialog.getOpenFileName(QApplication. activeWindow(), _('TreeLine - Picture File'), defaultPath, globalref.fileFilters['all']) if address: if self.relativeButton.isChecked(): address = urltools.toRelative(address, refPath) self.setAddress(address) self.updateThumbnail() self.show() self.contentsChanged.emit() #### Utility Functions #### def openExtUrl(path): """Open a web browser or a application for a directory or file. Arguments: path -- the path to open """ if sys.platform.startswith('win'): os.startfile(path) elif sys.platform.startswith('darwin'): subprocess.call(['open', path]) else: subprocess.call(['xdg-open', path]) TreeLine-3.2.1/source/dataeditview.py000066400000000000000000001070051506556630100175620ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # dataeditview.py, provides a class for the data edit right-hand view # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** from PyQt6.QtCore import QEvent, QPointF, QRectF, QSize, Qt, pyqtSignal from PyQt6.QtGui import (QKeySequence, QPainterPath, QPalette, QPen, QSyntaxHighlighter, QTextCharFormat, QTextCursor, QTextDocument) from PyQt6.QtWidgets import (QAbstractItemView, QApplication, QStyledItemDelegate, QTableWidget, QTableWidgetItem) import treenode import undo import urltools import dataeditors import globalref _minColumnWidth = 80 defaultFont = None class DataEditCell(QTableWidgetItem): """Class override for data edit view cells. Used for the cells with editable content. """ def __init__(self, spot, field, titleCellRef, typeCellRef): """Initialize the editable cells in the data edit view. Arguments: spot -- the spot referenced by this cell field -- the field object referenced by this cell titleCellRef -- the title cell to update based on data changes typeCellRef -- the format type cell to update based on type changes """ super().__init__() self.spot = spot self.node = spot.nodeRef self.field = field self.titleCellRef = titleCellRef self.typeCellRef = typeCellRef self.errorFlag = False self.cursorPos = (-1, -1) self.scrollPos = -1 # store doc to speed up delegate sizeHint and paint calls self.doc = QTextDocument() self.doc.setDefaultFont(defaultFont) self.doc.setDocumentMargin(6) self.updateText() def updateText(self): """Update the text based on the current node data. """ self.errorFlag = False try: self.setText(self.field.editorText(self.node)) except ValueError as err: if len(err.args) >= 2: self.setText(err.args[1]) else: self.setText(self.node.data.get(self.field.name, '')) self.errorFlag = True if self.field.showRichTextInCell: self.doc.setHtml(self.text()) else: self.doc.setPlainText(self.text()) def storeEditorState(self, editor): """Store the cursor & scroll positions baseed on an editor signal. Arguments: editor -- the editor that will get its state saved """ self.cursorPos = editor.cursorPosTuple() self.scrollPos = editor.scrollPosition() class DataEditDelegate(QStyledItemDelegate): """Class override for display and editing of DataEditCells. """ def __init__(self, parent=None): """Initialize the delegate class. Arguments: parent -- the parent view """ super().__init__(parent) self.editorClickPos = None self.tallEditScrollPos = -1 self.lastEditor = None self.prevNumLines = -1 def paint(self, painter, styleOption, modelIndex): """Paint the Data Edit Cells with support for rich text. Other cells are painted with the base class default. Also paints an error rectangle if the format error flag is set. Arguments: painter -- the painter instance styleOption -- the data for styles and geometry modelIndex -- the index of the cell to be painted """ cell = self.parent().item(modelIndex.row(), modelIndex.column()) if isinstance(cell, DataEditCell): painter.save() doc = cell.doc doc.setTextWidth(styleOption.rect.width()) painter.translate(styleOption.rect.topLeft()) paintRect = QRectF(0, 0, styleOption.rect.width(), styleOption.rect.height()) painter.setClipRect(paintRect) painter.fillRect(paintRect, QApplication.palette().base()) painter.setPen(QPen(QApplication.palette().text(), 1)) painter.drawRect(paintRect.adjusted(0, 0, -1, -1)) doc.drawContents(painter) if cell.errorFlag: path = QPainterPath(QPointF(0, 0)) path.lineTo(0, 10) path.lineTo(10, 0) path.closeSubpath() painter.fillPath(path, QApplication.palette().highlight()) painter.restore() else: super().paint(painter, styleOption, modelIndex) def sizeHint(self, styleOption, modelIndex): """Return the size of Data Edit Cells with rich text. Other cells return the base class size. Arguments: styleOption -- the data for styles and geometry modelIndex -- the index of the cell to be painted """ cell = self.parent().item(modelIndex.row(), modelIndex.column()) if isinstance(cell, DataEditCell): doc = cell.doc doc.setTextWidth(styleOption.rect.width()) size = doc.documentLayout().documentSize().toSize() maxHeight = self.parent().height() * 9 // 10 # 90% of view height if (size.height() > maxHeight and globalref.genOptions['EditorLimitHeight']): size.setHeight(maxHeight) if cell.field.numLines > 1: minDoc = QTextDocument('\n' * (cell.field.numLines - 1)) minDoc.setDefaultFont(cell.doc.defaultFont()) minHeight = (minDoc.documentLayout().documentSize().toSize(). height()) if minHeight > size.height(): size.setHeight(minHeight) return size + QSize(0, 4) return super().sizeHint(styleOption, modelIndex) def createEditor(self, parent, styleOption, modelIndex): """Return a new text editor for a cell. Arguments: parent -- the parent widget for the editor styleOption -- the data for styles and geometry modelIndex -- the index of the cell to be edited """ cell = self.parent().item(modelIndex.row(), modelIndex.column()) if isinstance(cell, DataEditCell): editor = getattr(dataeditors, cell.field.editorClassName)(parent) editor.setFont(cell.doc.defaultFont()) if hasattr(editor, 'fieldRef'): editor.fieldRef = cell.field if hasattr(editor, 'nodeRef'): editor.nodeRef = cell.node if cell.errorFlag: editor.setErrorFlag() # self.parent().setFocusProxy(editor) editor.contentsChanged.connect(self.commitData) editor.editEnding.connect(cell.storeEditorState) if (not globalref.genOptions['EditorLimitHeight'] and hasattr(editor, 'keyPressed')): editor.keyPressed.connect(self.scrollOnKeyPress) if hasattr(editor, 'inLinkSelectMode'): editor.inLinkSelectMode.connect(self.parent(). changeInLinkSelectMode) if hasattr(editor, 'setLinkFromNode'): self.parent().internalLinkSelected.connect(editor. setLinkFromNode) # viewport filter required to catch editor events try: editor.viewport().installEventFilter(self) except AttributeError: try: editor.lineEdit().installEventFilter(self) except AttributeError: pass self.lastEditor = editor editor.setFocus() return editor return super().createEditor(parent, styleOption, modelIndex) def setEditorData(self, editor, modelIndex): """Sets the text to be edited by the editor item. Arguments: editor -- the editor widget modelIndex -- the index of the cell to being edited """ cell = self.parent().item(modelIndex.row(), modelIndex.column()) if isinstance(cell, DataEditCell): try: # set from data to pick up any background changes editor.setContents(cell.field.editorText(cell.node)) except ValueError: # if data bad, just set it like the cell editor.setContents(modelIndex.data()) if cell.errorFlag: editor.setErrorFlag() editor.show() if self.editorClickPos: editor.setCursorPoint(self.editorClickPos) self.editorClickPos = None elif globalref.genOptions['EditorLimitHeight']: if cell.cursorPos[1] >= 0: editor.setCursorPos(*cell.cursorPos) cell.cursorPos = (-1, -1) if cell.scrollPos >= 0: editor.setScrollPosition(cell.scrollPos) cell.scrollPos = -1 else: editor.resetCursor() if (not globalref.genOptions['EditorLimitHeight'] and globalref.genOptions['EditorOnHover'] and self.tallEditScrollPos >= 0): # maintain scroll position for unlimited height editors # when hovering (use adjustScroll() for non-hovering self.parent().verticalScrollBar().setValue(self. tallEditScrollPos) else: super().setEditorData(editor, modelIndex) def setModelData(self, editor, styleOption, modelIndex): """Update the model with the results from an editor. Sets the cell error flag if the format doesn't match. Arguments: editor -- the editor widget styleOption -- the data for styles and geometry modelIndex -- the index of the cell to be painted """ cell = self.parent().item(modelIndex.row(), modelIndex.column()) if isinstance(cell, DataEditCell): if editor.modified: newText = editor.contents() numLines = newText.count('\n') skipUndoAvail = numLines == self.prevNumLines self.prevNumLines = numLines treeStructure = globalref.mainControl.activeControl.structure undo.DataUndo(treeStructure.undoList, cell.node, False, False, skipUndoAvail, cell.field.name) try: cell.node.setData(cell.field, newText) except ValueError: editor.setErrorFlag() self.parent().nodeModified.emit(cell.node) cell.titleCellRef.setText(cell.node.title(cell.spot)) cell.typeCellRef.setText(cell.node.formatRef.name) editor.modified = False else: super().setModelData(editor, styleOption, modelIndex) def updateEditorGeometry(self, editor, styleOption, modelIndex): """Update the editor geometry to match the cell. Arguments: editor -- the editor widget styleOption -- the data for styles and geometry modelIndex -- the index of the cell to be painted """ editor.setMaximumSize(self.sizeHint(styleOption, modelIndex)) super().updateEditorGeometry(editor, styleOption, modelIndex) def adjustScroll(self): """Reset the scroll back to the original for unlimited height editors. Called from signal after any scroll change. Needed for non-hovering to fix late scroll reset after editor created. """ if (not globalref.genOptions['EditorLimitHeight'] and not globalref.genOptions['EditorOnHover'] and self.tallEditScrollPos >= 0): self.parent().verticalScrollBar().setValue(self.tallEditScrollPos) self.tallEditScrollPos = -1 def scrollOnKeyPress(self, editor): """Adjust the scroll position to make cursor visible. Needed after key presses on unlimited height editors. Arguments: editor -- the editor with the key press """ if not globalref.genOptions['EditorLimitHeight']: view = self.parent() cursorRect = editor.cursorRect() upperPos = editor.mapToGlobal(cursorRect.topLeft()).y() lowerPos = editor.mapToGlobal(cursorRect.bottomLeft()).y() viewRect = view.viewport().rect() viewTop = view.mapToGlobal(viewRect.topLeft()).y() viewBottom = view.mapToGlobal(viewRect.bottomLeft()).y() bar = view.verticalScrollBar() if upperPos < viewTop: bar.setValue(bar.value() - (viewTop - upperPos)) elif lowerPos > viewBottom: bar.setValue(bar.value() + (lowerPos - viewBottom)) def editorEvent(self, event, model, styleOption, modelIndex): """Save the mouse click position in order to set the editor's cursor. Arguments: event -- the mouse click event model -- the model (not used) styleOption -- the data for styles and geometry (not used) modelIndex -- the index of the cell (not used) """ if event.type() == QEvent.Type.MouseButtonPress: self.editorClickPos = event.globalPosition().toPoint() # save scroll position for clicks on unlimited height editors self.tallEditScrollPos = self.parent().verticalScrollBar().value() return super().editorEvent(event, model, styleOption, modelIndex) def eventFilter(self, editor, event): """Override to handle various focus changes and control keys. Navigate away from this view if tab hit on end items. Catches tab before QDelegate's event filter on the editor. Also closes the editor if focus is lost for certain reasons. Arguments: editor -- the editor that Qt installed a filter on event -- the key press event """ if event.type() == QEvent.Type.KeyPress: view = self.parent() if (event.key() == Qt.Key.Key_Tab and view.currentRow() == view.rowCount() - 1): view.focusOtherView.emit(True) return True if (event.key() == Qt.Key.Key_Backtab and view.currentRow() == 1): view.focusOtherView.emit(False) return True if (event.modifiers() == Qt.KeyboardModifier.ControlModifier and Qt.Key.Key_A <= event.key() <= Qt.Key.Key_Z): key = QKeySequence(event.keyCombination()) view.shortcutEntered.emit(key) return True if event.type() == QEvent.Type.MouseButtonPress: self.prevNumLines = -1 # reset undo avail for mouse cursor changes if event.type() == QEvent.Type.FocusOut: self.prevNumLines = -1 # reset undo avail for any focus loss if (event.reason() in (Qt.FocusReason.MouseFocusReason, Qt.FocusReason.TabFocusReason, Qt.FocusReason.BacktabFocusReason) and (not hasattr(editor, 'calendar') or not editor.calendar or not editor.calendar.isVisible()) and (not hasattr(editor, 'intLinkDialog') or not editor.intLinkDialog or not editor.intLinkDialog.isVisible())): self.parent().endEditor() return True return super().eventFilter(editor, event) class DataEditView(QTableWidget): """Class override for the table-based data edit view. Sets view defaults and updates the content. """ nodeModified = pyqtSignal(treenode.TreeNode) inLinkSelectMode = pyqtSignal(bool) internalLinkSelected = pyqtSignal(treenode.TreeNode) focusOtherView = pyqtSignal(bool) hoverFocusActive = pyqtSignal() shortcutEntered = pyqtSignal(QKeySequence) def __init__(self, treeView, allActions, isChildView=True, parent=None): """Initialize the data edit view default view settings. Arguments: treeView - the tree view, needed for the current selection model allActions -- a dict containing actions for the editor context menu isChildView -- shows selected nodes if false, child nodes if true parent -- the parent main window """ super().__init__(0, 2, parent) self.treeView = treeView self.allActions = allActions self.isChildView = isChildView self.hideChildView = not globalref.genOptions['InitShowChildPane'] self.prevHoverCell = None self.inLinkSelectActive = False self.setAcceptDrops(True) self.setMouseTracking(globalref.genOptions['EditorOnHover']) self.horizontalHeader().hide() self.verticalHeader().hide() self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel) self.setHorizontalScrollMode(QAbstractItemView.ScrollMode. ScrollPerPixel) self.verticalScrollBar().setSingleStep(self.fontMetrics(). lineSpacing()) self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.setItemDelegate(DataEditDelegate(self)) self.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.setShowGrid(False) pal = self.palette() pal.setBrush(QPalette.ColorRole.Base, QApplication.palette().window()) pal.setBrush(QPalette.ColorRole.Text, QApplication.palette().windowText()) self.setPalette(pal) self.currentItemChanged.connect(self.moveEditor) self.verticalScrollBar().valueChanged.connect(self.itemDelegate(). adjustScroll) def updateContents(self): """Reload the view's content if the view is shown. Avoids update if view is not visible or has zero height or width. """ selSpots = self.treeView.selectionModel().selectedSpots() if self.isChildView: if (len(selSpots) > 1 or self.hideChildView or (selSpots and not selSpots[0].nodeRef.childList)): self.hide() return if not selSpots: # use top node childList from tree structure selSpots = [globalref.mainControl.activeControl.structure. structSpot()] elif not selSpots: self.hide() return self.show() if not self.isVisible() or self.height() == 0 or self.width() == 0: return if self.isChildView: selSpots = selSpots[0].childSpots() self.clear() if selSpots: self.hide() # 2nd update very slow if shown during update self.setRowCount(100000) rowNum = -2 for spot in selSpots: rowNum = self.addNodeData(spot, rowNum + 2) self.setRowCount(rowNum + 1) self.adjustSizes() self.scrollToTop() self.show() def addNodeData(self, spot, startRow): """Populate the view with the data from the given node. Returns the last row number used. Arguments: spot -- the spot to add startRow -- the row offset """ node = spot.nodeRef formatName = node.formatRef.name typeCell = self.createInactiveCell(formatName) self.setItem(startRow, 0, typeCell) titleCell = self.createInactiveCell(node.title(spot)) self.setItem(startRow, 1, titleCell) fields = node.formatRef.fields() if not globalref.genOptions['EditNumbering']: fields = [field for field in fields if field.typeName != 'Numbering'] if not globalref.genOptions['ShowMath']: fields = [field for field in fields if field.typeName != 'Math'] row = 0 # initialize for cases with only Numbering or Math fields for row, field in enumerate(fields, startRow + 1): self.setItem(row, 0, self.createInactiveCell(field.name, Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)) self.setItem(row, 1, DataEditCell(spot, field, titleCell, typeCell)) self.setItem(row + 1, 0, self.createInactiveCell('')) self.setItem(row + 1, 1, self.createInactiveCell('')) return row def updateUnselectedCells(self): """Refresh the data in active cells, keeping the cell structure. """ if not self.isVisible() or self.height() == 0 or self.width() == 0: return selSpots = self.treeView.selectionModel().selectedSpots() if self.isChildView: if not selSpots: # use top node childList from tree structure selSpots = [globalref.mainControl.activeControl.structure. structSpot()] selSpots = selSpots[0].childSpots() elif not selSpots: return rowNum = -2 for spot in selSpots: rowNum = self.refreshNodeData(spot, rowNum + 2) def refreshNodeData(self, spot, startRow): """Refresh the data in active cells for this node. Returns the last row number used. Arguments: node -- the node to add startRow -- the row offset """ node = spot.nodeRef self.item(startRow, 1).setText(node.title(spot)) fields = node.formatRef.fields() if not globalref.genOptions['EditNumbering']: fields = [field for field in fields if field.typeName != 'Numbering'] if not globalref.genOptions['ShowMath']: fields = [field for field in fields if field.typeName != 'Math'] for row, field in enumerate(fields, startRow + 1): cell = self.item(row, 1) if not cell.isSelected(): cell.updateText() return row @staticmethod def createInactiveCell(text, alignment=None): """Return a new inactive data edit view cell. Arguments: text -- the initial text string for the cell alignment -- the text alignment QT constant (None for default) """ cell = QTableWidgetItem(text) cell.setFlags(Qt.ItemFlag.NoItemFlags) if alignment: cell.setTextAlignment(alignment) return cell def moveEditor(self, newCell, prevCell): """Close old editor and open new one based on new current cell. Arguments: newCell -- the new current edit cell item prevCell - the old current cell item """ try: if prevCell and hasattr(prevCell, 'updateText'): self.closePersistentEditor(prevCell) prevCell.updateText() self.resizeRowToContents(prevCell.row()) except RuntimeError: pass # avoid non-repeatable error involving deleted c++ object if newCell: self.openPersistentEditor(newCell) def endEditor(self): """End persistent editors by changing active cells. """ self.setCurrentCell(-1, -1) def setFont(self, font): """Override to avoid setting fonts of inactive cells. Arguments: font -- the font to set """ global defaultFont defaultFont = font def changeInLinkSelectMode(self, active=True): """Change the internal link select mode. Changes the internal variable (controlling hover) and signals the tree. Arguments: active -- if True, starts the mode, o/w ends """ self.inLinkSelectActive = active self.inLinkSelectMode.emit(active) def updateInLinkSelectMode(self, active=True): """Update the internal link select mode. Updates the internal variable (controlling hover). Arguments: active -- if True, starts the mode, o/w ends """ self.inLinkSelectActive = active def highlightSearch(self, wordList=None, regExpList=None): """Highlight any found search terms. Arguments: wordList -- list of words to highlight regExpList -- a list of regular expression objects to highlight """ backColor = self.palette().brush(QPalette.ColorGroup.Active, QPalette.ColorRole.Highlight) foreColor = self.palette().brush(QPalette.ColorGroup.Active, QPalette.ColorRole.HighlightedText) charFormat = QTextCharFormat() charFormat.setBackground(backColor) charFormat.setForeground(foreColor) spot = self.treeView.selectionModel().selectedSpots()[0] if wordList is None: wordList = [] if regExpList is None: regExpList = [] for regExp in regExpList: for match in regExp.finditer('\n'.join(spot.nodeRef. output(spotRef=spot))): matchText = match.group().lower() if matchText not in wordList: wordList.append(matchText) cells = [] completedCells = [] for word in wordList: cells.extend(self.findItems(word, Qt.MatchFlag.MatchFixedString | Qt.MatchFlag.MatchContains)) for cell in cells: if hasattr(cell, 'doc') and cell not in completedCells: highlighter = SearchHighlighter(wordList, charFormat, cell.doc) completedCells.append(cell) def highlightMatch(self, searchText='', regExpObj=None, cellNum=0, skipMatches=0): """Highlight a specific search result. Arguments: searchText -- the text to find in a non-regexp search regExpObj -- the regular expression to find if searchText is blank cellNum -- the vertical position (field number) of the cell skipMatches -- number of previous matches to skip in this field """ backColor = self.palette().brush(QPalette.ColorGroup.Active, QPalette.ColorRole.Highlight) foreColor = self.palette().brush(QPalette.ColorGroup.Active, QPalette.ColorRole.HighlightedText) charFormat = QTextCharFormat() charFormat.setBackground(backColor) charFormat.setForeground(foreColor) cellNum += 1 # skip title line cell = self.item(cellNum, 1) highlighter = MatchHighlighter(cell.doc, charFormat, searchText, regExpObj, skipMatches) def adjustSizes(self): """Update the column widths and row heights. """ self.resizeColumnToContents(0) if self.columnWidth(0) < _minColumnWidth: self.setColumnWidth(0, _minColumnWidth) self.setColumnWidth(1, max(self.width() - self.columnWidth(0) - self.verticalScrollBar().width() - 5, _minColumnWidth)) self.resizeRowsToContents() def focusInEvent(self, event): """Handle focus-in to start an editor when tab is used. Arguments: event -- the focus in event """ if event.reason() == Qt.FocusReason.TabFocusReason: for row in range(self.rowCount()): cell = self.item(row, 1) if hasattr(cell, 'doc'): self.setCurrentItem(cell) break elif event.reason() == Qt.FocusReason.BacktabFocusReason: for row in range(self.rowCount() - 1, -1, -1): cell = self.item(row, 1) if hasattr(cell, 'doc'): self.setCurrentItem(cell) break super().focusInEvent(event) def resizeEvent(self, event): """Update view if was collaped by splitter. """ if ((event.oldSize().height() == 0 and event.size().height()) or (event.oldSize().width() == 0 and event.size().width())): self.updateContents() self.adjustSizes() return super().resizeEvent(event) def dragEnterEvent(self, event): """Accept drags of files to this window. Arguments: event -- the drag event object """ if event.mimeData().hasUrls(): event.accept() def dragMoveEvent(self, event): """Accept drags of files to this window. Arguments: event -- the drag event object """ cell = self.itemAt(event.position().toPoint()) if (isinstance(cell, DataEditCell) and getattr(dataeditors, cell.field.editorClassName).dragLinkEnabled): event.accept() else: event.ignore() def dropEvent(self, event): """Open a file dropped onto this window. Arguments: event -- the drop event object """ cell = self.itemAt(event.position().toPoint()) fileList = event.mimeData().urls() if fileList and isinstance(cell, DataEditCell): self.setCurrentItem(cell) self.setFocus() self.itemDelegate().lastEditor.addDroppedUrl(fileList[0]. toLocalFile()) def mousePressEvent(self, event): """Handle ctrl + click to follow links. Arguments: event -- the mouse event """ if (event.button() == Qt.MouseButton.LeftButton and event.modifiers() == Qt.KeyboardModifier.ControlModifier): cell = self.itemAt(event.position().toPoint()) if cell and isinstance(cell, DataEditCell): xOffest = (event.position().toPoint().x() - self.columnViewportPosition(cell.column())) yOffset = (event.position().toPoint().y() - self.rowViewportPosition(cell.row())) pt = QPointF(xOffest, yOffset) pos = cell.doc.documentLayout().hitTest(pt, Qt.HitTestAccuracy.ExactHit) if pos >= 0: cursor = QTextCursor(cell.doc) cursor.setPosition(pos) address = cursor.charFormat().anchorHref() if address: if address.startswith('#'): (self.treeView.selectionModel(). selectNodeById(address[1:])) else: # check for relative path if urltools.isRelative(address): defaultPath = (globalref.mainControl. defaultPathObj(True)) address = urltools.toAbsolute(address, str(defaultPath)) dataeditors.openExtUrl(address) event.accept() else: super().mousePressEvent(event) def mouseMoveEvent(self, event): """Handle mouse move event to create editors on hover. Arguments: event -- the mouse event """ cell = self.itemAt(event.position().toPoint()) if cell and hasattr(cell, 'doc'): oldCell = self.currentItem() if (cell != oldCell and cell != self.prevHoverCell and not self.inLinkSelectActive): # save scroll position for unlimited height editors self.itemDelegate().tallEditScrollPos = (self. verticalScrollBar(). value()) self.prevHoverCell = cell self.hoverFocusActive.emit() self.setFocus() if oldCell and hasattr(oldCell, 'doc'): # these lines result in two calls to moveEditor, but seems # to be necessary to avoid race that leaves stray editors self.moveEditor(None, oldCell) self.setCurrentItem(None) try: self.setCurrentItem(cell) except RuntimeError: # catch error if view updates due to node rename ending pass else: self.prevHoverCell = None class SearchHighlighter(QSyntaxHighlighter): """Class override to highlight search terms in cell text. Used to highlight search words from a list. """ def __init__(self, wordList, charFormat, doc): """Initialize the highlighter with the text document. Arguments: wordList -- list of search terms charFormat -- the formatting to apply doc -- the text document """ super().__init__(doc) self.wordList = wordList self.charFormat = charFormat def highlightBlock(self, text): """Override method to highlight search terms in block of text. Arguments: text -- the text to highlight """ for word in self.wordList: pos = text.lower().find(word, 0) while pos >= 0: self.setFormat(pos, len(word), self.charFormat) pos = text.lower().find(word, pos + len(word)) class MatchHighlighter(QSyntaxHighlighter): """Class override to highlight a specific search result in cell text. Used to highlight a text or reg exp match. """ def __init__(self, doc, charFormat, searchText='', regExpObj=None, skipMatches=0): """Initialize the highlighter with the text document. Arguments: doc -- the text document charFormat -- the formatting to apply searchText -- the text to find if no regexp is given regExpObj -- the regular expression to find if given skipMatches -- number of previous matches to skip """ super().__init__(doc) self.charFormat = charFormat self.searchText = searchText self.regExpObj = regExpObj self.skipMatches = skipMatches def highlightBlock(self, text): """Override method to highlight a match in block of text. Arguments: text -- the text to highlight """ pos = matchLen = 0 for matchNum in range(self.skipMatches + 1): pos += matchLen if self.regExpObj: match = self.regExpObj.search(text, pos) pos = match.start() if match else -1 matchLen = len(match.group()) if match else 0 else: pos = text.lower().find(self.searchText, pos) matchLen = len(self.searchText) if pos >= 0: self.setFormat(pos, matchLen, self.charFormat) TreeLine-3.2.1/source/exports.py000066400000000000000000002621241506556630100166200ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # exports.py, provides classes for a file export dialog and export functions # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import os.path import pathlib import re import json import copy import io import zipfile import csv import shutil from xml.etree import ElementTree from PyQt6.QtCore import Qt from PyQt6.QtGui import QFontInfo from PyQt6.QtWidgets import (QApplication, QButtonGroup, QCheckBox, QDialog, QFileDialog, QGroupBox, QHBoxLayout, QLabel, QMessageBox, QRadioButton, QSpinBox, QVBoxLayout, QWizard, QWizardPage) import treestructure import treenode import treeformats import nodeformat import fieldformat import treeoutput import treemaincontrol import imports import urltools import globalref try: from __main__ import __version__ except ImportError: __version__ = '' try: from __main__ import templatePath except ImportError: templatePath = None _bookmarkTitle = _('Bookmarks') _odfNamespace = {'fo': 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0', 'office': 'urn:oasis:names:tc:opendocument:xmlns:office:1.0', 'style': 'urn:oasis:names:tc:opendocument:xmlns:style:1.0', 'svg': 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0', 'text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0', 'manifest': 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0'} _intLinkRe = re.compile(r']*href="#(.*?)"[^>]*>.*?', re.I | re.S) _genLinkRe = re.compile(r']*href="(.*?)"[^>]*>.*?', re.I | re.S) _imgLinkRe = re.compile(r']*src="(.*?)"[^>]*>.*?', re.I | re.S) _idReplaceCharsRe = re.compile(r'[^a-zA-Z0-9_-]+') class ExportControl: """Control to do file exports for tree branches and nodes. """ def __init__(self, structure, selectionModel, defaultPathObj, printData): """Initialize export control object. Arguments: structure -- the tree structure ref for exporting the entire tree selectionModel -- the selection model for partial exports defaultPathObj -- path object to use as file dialog default printData -- a ref to print data for old treeline exports """ self.structure = structure self.selectedSpots = selectionModel.selectedSpots() self.selectedNodes = selectionModel.selectedNodes() self.defaultPathObj = defaultPathObj self.printData = printData def interactiveExport(self): """Prompt the user for types, options, filename & proceed with export. Return True if export is successful. """ exportMethods = {'htmlSingle': self.exportHtmlSingle, 'htmlNavSingle': self.exportHtmlNavSingle, 'htmlPages': self.exportHtmlPages, 'htmlTables': self.exportHtmlTables, 'htmlLiveLink': self.exportHtmlLiveLink, 'htmlLiveSingle': self.exportHtmlLiveSingle, 'textTitles': self.exportTextTitles, 'textPlain': self.exportTextPlain, 'textTableMultiCsv': self.exportTextTableMultiCsv, 'textTableCsv': self.exportTextTableCsv, 'textTableTab': self.exportTextTableTab, 'oldTreeLine': self.exportOldTreeLine, 'treeLineSubtree': self.exportSubtree, 'xmlGeneric': self.exportXmlGeneric, 'odfText': self.exportOdfText, 'bookmarksHtml': self.exportBookmarksHtml, 'bookmarksXbel': self.exportBookmarksXbel} exportDialog = ExportDialog(len(self.selectedNodes), QApplication.activeWindow()) if exportDialog.exec() == QDialog.DialogCode.Accepted: result = exportMethods[ExportDialog.currentSubtype]() QApplication.restoreOverrideCursor() return result return False def getFileName(self, dialogTitle, defaultExt='txt'): """Prompt the user for a filename and return a path object. Arguments: dialogTitle -- the title for use on the dialog window defaultExt -- the default file extension from globalref """ filters = ';;'.join((globalref.fileFilters[defaultExt], globalref.fileFilters['all'])) defaultExt = defaultExt[:4] if self.defaultPathObj.is_file(): self.defaultPathObj = self.defaultPathObj.with_suffix('.' + defaultExt) filePath, selectFilter = QFileDialog.getSaveFileName(QApplication. activeWindow(), dialogTitle, str(self.defaultPathObj), filters) if filePath: pathObj = pathlib.Path(filePath) if not pathObj.suffix: pathObj = pathObj.with_suffix('.' + defaultExt) return pathObj return None def exportHtmlSingle(self, pathObj=None): """Export to a single web page, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export HTML'), 'html') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedSpots = self.structure.rootSpots() outputGroup = treeoutput.OutputGroup(self.selectedSpots, ExportDialog.includeRoot, ExportDialog.exportWhat != ExportDialog.selectNode, ExportDialog.openOnly) outputGroup.addAnchors() if outputGroup.hasPrefixes(): outputGroup.combineAllSiblings() outputGroup.addBlanksBetween() outputGroup.addIndents() outGroups = outputGroup.splitColumns(ExportDialog.numColumns) htmlTitle = pathObj.stem indent = globalref.genOptions['IndentOffset'] lines = ['', '', '', '', '{0}'.format(htmlTitle), '', '', ''] if ExportDialog.addHeader: headerText = (globalref.mainControl.activeControl.printData. formatHeaderFooter(True)) if headerText: lines.append(headerText) lines.extend(['', '', '
    ']) lines.extend(outGroups[0].getLines()) for group in outGroups[1:]: lines.append('') lines.extend(group.getLines()) lines.extend(['
    ']) if ExportDialog.addHeader: footerText = (globalref.mainControl.activeControl.printData. formatHeaderFooter(False)) if footerText: lines.append(footerText) lines.extend(['', '']) with pathObj.open('w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in lines]) return True def exportHtmlNavSingle(self, pathObj=None): """Export single web page with a navigation pane, ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export HTML'), 'html') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedSpots = self.structure.rootSpots() outputGroup = treeoutput.OutputGroup(self.selectedSpots, ExportDialog.includeRoot, True, ExportDialog.openOnly) outputGroup.addAnchors(ExportDialog.navPaneLevels) if outputGroup.hasPrefixes(): outputGroup.combineAllSiblings() outputGroup.addBlanksBetween() outputGroup.addIndents() htmlTitle = pathObj.stem indent = globalref.genOptions['IndentOffset'] lines = ['', '', '', '', '{0}'.format(htmlTitle), '', '', '', '') level -= 1 lines.extend(['', '
    ']) if ExportDialog.addHeader: headerText = (globalref.mainControl.activeControl.printData. formatHeaderFooter(True)) if headerText: lines.append(headerText) lines.extend(outputGroup.getLines()) if ExportDialog.addHeader: footerText = (globalref.mainControl.activeControl.printData. formatHeaderFooter(False)) if footerText: lines.append(footerText) lines.extend(['
    ', '', '']) with pathObj.open('w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in lines]) return True def exportHtmlPages(self, pathObj=None): """Export multiple web pages with navigation, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: path = QFileDialog.getExistingDirectory(QApplication. activeWindow(), _('TreeLine - Export HTML'), str(self.defaultPathObj)) if not path: return False pathObj = pathlib.Path(path) QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) oldDir = os.getcwd() os.chdir(str(pathObj)) indent = globalref.genOptions['IndentOffset'] cssLines = ['#sidebar {', ' width: 16em;', ' float: left;', ' border-right: 1px solid black;', '}', '#sidebar div {{margin-left: {0}em;}}'.format(indent), '#content {', ' margin-left: 16em;', ' border-left: 1px solid black;', ' padding-left: 6px;', '}'] with open('default.css', 'w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in cssLines]) if ExportDialog.exportWhat != ExportDialog.entireTree: self.structure = treestructure.TreeStructure(topNodes=self. selectedNodes, addSpots=False) if len(self.structure.childList) > 1: self.structure = treestructure.TreeStructure(topNodes=self. structure.childList, addSpots=False) rootType = nodeformat.NodeFormat(treeformats.defaultTypeName, self.structure.treeFormats, addDefaultField=True) self.structure.treeFormats.addTypeIfMissing(rootType) root = treenode.TreeNode(self.structure. treeFormats[treeformats.defaultTypeName]) root.setTitle(treestructure.defaultRootTitle) self.structure.addNodeDictRef(root) root.childList = self.structure.childList self.structure.childList = [root] pathDict = {} _setHtmlDirectories(self.structure.childList[0], pathDict, pathObj, set()) _writeHtmlPage(self.structure.childList[0], None, None, pathDict) os.chdir(oldDir) return True def exportHtmlTables(self, pathObj=None): """Export to multiple web page tables, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: path = QFileDialog.getExistingDirectory(QApplication. activeWindow(), _('TreeLine - Export HTML'), str(self.defaultPathObj)) if not path: return False pathObj = pathlib.Path(path) QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) oldDir = os.getcwd() os.chdir(str(pathObj)) if ExportDialog.exportWhat != ExportDialog.entireTree: self.structure = treestructure.TreeStructure(topNodes=self. selectedNodes, addSpots=False) if len(self.structure.childList) > 1: self.structure = treestructure.TreeStructure(topNodes=self. structure.childList, addSpots=False) rootType = nodeformat.NodeFormat(treeformats.defaultTypeName, self.structure.treeFormats, addDefaultField=True) self.structure.treeFormats.addTypeIfMissing(rootType) root = treenode.TreeNode(self.structure. treeFormats[treeformats.defaultTypeName]) name = self.defaultPathObj.stem if not name: name = treestructure.defaultRootTitle root.setTitle(name) self.structure.addNodeDictRef(root) root.childList = self.structure.childList self.structure.childList = [root] pathDict = {} _setHtmlDirectories(self.structure.childList[0], pathDict, pathObj, set(), False) _writeHtmlTable(self.structure.childList[0], None, pathDict) os.chdir(oldDir) return True def exportHtmlLiveLink(self, pathObj=None): """Export a live tree view, linked back to the source file. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: path = QFileDialog.getExistingDirectory(QApplication. activeWindow(), _('TreeLine - Export HTML'), str(self.defaultPathObj)) if not path: return False pathObj = pathlib.Path(path) QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) control = globalref.mainControl prefPath = templatePath + '/exports' if templatePath else '' htmlPath = control.findResourceFile('live_tree_export.html', 'templates/exports', prefPath) jsPath = control.findResourceFile('live_tree_export.js', 'templates/exports', prefPath) cssPath = control.findResourceFile('live_tree_export.css', 'templates/exports', prefPath) if not htmlPath or not jsPath or not cssPath: QApplication.restoreOverrideCursor() QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - export template files not found.\n' 'Check your TreeLine installation.')) return False refPath = globalref.mainControl.activeControl.filePathObj if not refPath: QApplication.restoreOverrideCursor() QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - cannot link to unsaved TreeLine ' 'file.\nSave the file and retry.')) return False try: refPath = pathlib.Path(os.path.relpath(str(refPath), str(pathObj))) except ValueError: QApplication.restoreOverrideCursor() msg = _('Warning - no relative path from "{0}" to "{1}".\n' 'Continue with absolute path?').format(pathObj.as_posix(), refPath.as_posix()) ans = QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', msg, QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.Yes) if ans == QMessageBox.StandardButton.No: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) fileStem = refPath.stem outPath = pathObj / (fileStem + '.html') with htmlPath.open(encoding='utf-8') as fileIn: with outPath.open('w', encoding='utf-8') as fileOut: for line in fileIn: if '' in line: line = re.sub(r'<title>.*', '{0}'.format(fileStem), line) elif 'dataFilePath' in line: line = line.replace('""', '"{0}"'. format(refPath.parent.as_posix())) elif 'dataFileName' in line: line = line.replace('""', '"{0}"'.format(refPath.name)) fileOut.write(line) shutil.copy(str(jsPath), str(pathObj)) shutil.copy(str(cssPath), str(pathObj)) return True def exportHtmlLiveSingle(self, pathObj=None): """Export a live tree view to a single file (embedded data). Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export HTML'), 'html') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) control = globalref.mainControl prefPath = templatePath + '/exports' if templatePath else '' htmlPath = control.findResourceFile('live_tree_export.html', 'templates/exports', prefPath) jsPath = control.findResourceFile('live_tree_export.js', 'templates/exports', prefPath) cssPath = control.findResourceFile('live_tree_export.css', 'templates/exports', prefPath) if not htmlPath or not jsPath or not cssPath: QApplication.restoreOverrideCursor() QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - export template files not found.\n' 'Check your TreeLine installation.')) return False if ExportDialog.exportWhat == ExportDialog.entireTree: fileData = self.structure.fileData() else: self.structure = treestructure.TreeStructure(topNodes=self. selectedNodes, addSpots=False) fileData = self.structure.fileData() if ExportDialog.exportWhat == ExportDialog.selectNode: topNodeIds = set([node.uId for node in self.structure.childList]) nodeData = [data for data in fileData['nodes'] if data['uid'] in topNodeIds] for data in nodeData: data['children'] = [] fileData['nodes'] = nodeData with htmlPath.open(encoding='utf-8') as htmlIn: with pathObj.open('w', encoding='utf-8') as htmlOut: for line in htmlIn: if 'stylesheet' in line: htmlOut.write('') elif '' in line: line = re.sub(r'<title>.*', '{0}'. format(pathObj.stem), line) htmlOut.write(line) elif 'application/json' in line: htmlOut.write(line) json.dump(fileData, htmlOut, indent=2, sort_keys=True) elif 'dataFileName' in line: htmlOut.write(line) with jsPath.open(encoding='utf-8') as jsIn: htmlOut.write(jsIn.read()) elif 'script src=' not in line: htmlOut.write(line) return True def exportTextTitles(self, pathObj=None): """Export tabbed title text, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export Text Titles'), 'txt') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedSpots = self.structure.rootSpots() if ExportDialog.exportWhat == ExportDialog.selectNode: lines = [spot.nodeRef.title(spot) for spot in self.selectedSpots] else: treeView = (globalref.mainControl.activeControl.activeWindow. treeView) lines = [] for rootSpot in self.selectedSpots: for spot, level in rootSpot.levelSpotDescendantGen(treeView, ExportDialog.includeRoot, None, ExportDialog.openOnly): lines.append('\t' * level + spot.nodeRef.title(spot)) try: with pathObj.open('w', encoding=globalref.localTextEncoding) as f: f.writelines([(line + '\n') for line in lines]) except UnicodeEncodeError: with pathObj.open('w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in lines]) return True def exportTextPlain(self, pathObj=None): """Export unformatted text for all output, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export Plain Text'), 'txt') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedSpots = self.structure.rootSpots() lines = [] if ExportDialog.exportWhat == ExportDialog.selectNode: for rootSpot in self.selectedSpots: lines.extend(rootSpot.nodeRef.output(True, False, rootSpot)) if rootSpot.nodeRef.formatRef.spaceBetween: lines.append('') else: treeView = (globalref.mainControl.activeControl.activeWindow. treeView) for rootSpot in self.selectedSpots: for spot, level in rootSpot.levelSpotDescendantGen(treeView, ExportDialog.includeRoot, None, ExportDialog.openOnly): lines.extend(spot.nodeRef.output(True, False, spot)) if spot.nodeRef.formatRef.spaceBetween: lines.append('') try: with pathObj.open('w', encoding=globalref.localTextEncoding) as f: f.writelines([(line + '\n') for line in lines]) except UnicodeEncodeError: with pathObj.open('w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in lines]) return True def exportTextTableMultiCsv(self, pathObj=None): """Export descendant CSV delimited text table with level numbers. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export Text Tables'), 'csv') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedSpots = self.structure.rootSpots() treeView = (globalref.mainControl.activeControl.activeWindow.treeView) types = set() headings = [] for rootSpot in self.selectedSpots: for spot, level in rootSpot.levelSpotDescendantGen(treeView, ExportDialog.includeRoot, None, ExportDialog.openOnly): nodeFormat = spot.nodeRef.formatRef if nodeFormat not in types: for fieldName in nodeFormat.fieldNames(): if fieldName not in headings: headings.append(fieldName) types.add(nodeFormat) lines = [['Level'] + headings] for rootSpot in self.selectedSpots: for spot, level in rootSpot.levelSpotDescendantGen(treeView, ExportDialog.includeRoot, None, ExportDialog.openOnly): newLine = [spot.nodeRef.data.get(head, '') for head in headings] lines.append([repr(level)] + newLine) try: with pathObj.open('w', newline='', encoding=globalref.localTextEncoding) as f: writer = csv.writer(f) writer.writerows(lines) except UnicodeEncodeError: with pathObj.open('w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerows(lines) return True def exportTextTableCsv(self, pathObj=None): """Export child CSV delimited text table, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export Text Tables'), 'csv') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.selectNode: nodeList = self.selectedNodes else: nodeList = [] for node in self.selectedNodes: nodeList.extend(node.childList) types = set() headings = [] for node in nodeList: nodeFormat = node.formatRef if nodeFormat not in types: for fieldName in nodeFormat.fieldNames(): if fieldName not in headings: headings.append(fieldName) types.add(nodeFormat) lines = [headings] for node in nodeList: lines.append([node.data.get(head, '') for head in headings]) try: with pathObj.open('w', newline='', encoding=globalref.localTextEncoding) as f: writer = csv.writer(f) writer.writerows(lines) except UnicodeEncodeError: with pathObj.open('w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerows(lines) return True def exportTextTableTab(self, pathObj=None): """Export child tab delimited text table, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export Text Tables'), 'txt') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.selectNode: nodeList = self.selectedNodes else: nodeList = [] for node in self.selectedNodes: nodeList.extend(node.childList) types = set() headings = [] for node in nodeList: nodeFormat = node.formatRef if nodeFormat not in types: for fieldName in nodeFormat.fieldNames(): if fieldName not in headings: headings.append(fieldName) types.add(nodeFormat) lines = ['\t'.join(headings)] for node in nodeList: lines.append('\t'.join([node.data.get(head, '') for head in headings])) try: with pathObj.open('w', encoding=globalref.localTextEncoding) as f: f.writelines([(line + '\n') for line in lines]) except UnicodeEncodeError: with pathObj.open('w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in lines]) return True def exportOldTreeLine(self, pathObj=None): """Export old TreeLine version (2.0.x), use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export TreeLine Subtree'), 'trl') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat != ExportDialog.entireTree: self.structure = treestructure.TreeStructure(topNodes=self. selectedNodes, addSpots=False) addDescend = ExportDialog.exportWhat != ExportDialog.selectNode addChildren = addDescend if len(self.structure.childList) > 1: if not addDescend: addChildren = True self.structure = treestructure.TreeStructure(topNodes=self. structure.childList, addSpots=False) rootType = nodeformat.NodeFormat(treeformats.defaultTypeName, self.structure.treeFormats, addDefaultField=True) self.structure.treeFormats.addTypeIfMissing(rootType) root = treenode.TreeNode(self.structure. treeFormats[treeformats.defaultTypeName]) root.setTitle(treestructure.defaultRootTitle) self.structure.addNodeDictRef(root) root.childList = self.structure.childList self.structure.childList = [root] idDict = {} for node in self.structure.childList[0].descendantGen(): _setOldUniqueId(idDict, node) idDict = {i[1]: i[0] for i in idDict.items()} # reverse (new id keys) rootElement = _oldElementXml(self.structure.childList[0], self.structure, idDict, addChildren=addChildren, addDescend=addDescend) if __version__: rootElement.set('tlversion', __version__) rootElement.attrib.update(_convertOldPrintData(self.printData. fileData())) elementTree = ElementTree.ElementTree(rootElement) elementTree.write(str(pathObj), 'utf-8', True) return True def exportSubtree(self, pathObj=None): """Export TreeLine subtree, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export TreeLine Subtree'), 'trlnsave') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) self.structure = treestructure.TreeStructure(topNodes=self. selectedNodes, addSpots=False) fileData = self.structure.fileData() fileData['properties'].update(self.printData.fileData()) if ExportDialog.exportWhat == ExportDialog.selectNode: topNodeIds = set([node.uId for node in self.structure.childList]) nodeData = [data for data in fileData['nodes'] if data['uid'] in topNodeIds] for data in nodeData: data['children'] = [] fileData['nodes'] = nodeData indent = 3 if globalref.genOptions['PrettyPrint'] else 0 with pathObj.open('w', encoding='utf-8', newline='\n') as f: json.dump(fileData, f, indent=indent, sort_keys=True) return True def exportXmlGeneric(self, pathObj=None): """Export generic XML, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export Generic XML'), 'xml') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedNodes = self.structure.childList addBranches = ExportDialog.exportWhat != ExportDialog.selectNode if len(self.selectedNodes) > 1: rootElement = ElementTree.Element(treeformats.defaultTypeName) for node in self.selectedNodes: rootElement.append(_createGenericXml(node, addBranches)) else: rootElement = _createGenericXml(self.selectedNodes[0], addBranches) elementTree = ElementTree.ElementTree(rootElement) elementTree.write(str(pathObj), 'utf-8', True) return True def exportOdfText(self, pathObj=None): """Export an ODF text file, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export ODF Text'), 'odt') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedSpots = self.structure.rootSpots() addBranches = ExportDialog.exportWhat != ExportDialog.selectNode for prefix, uri in _odfNamespace.items(): ElementTree.register_namespace(prefix, uri) versionAttr = {'office:version': '1.0'} fontInfo = QFontInfo(globalref.mainControl.activeControl. activeWindow.editorSplitter.widget(0). font()) fontAttr = {'style:font-pitch': 'fixed' if fontInfo.fixedPitch() else 'variable', 'style:name': fontInfo.family(), 'svg:font-family': fontInfo.family()} fontElem = _addOdfElement('office:font-face-decls') _addOdfElement('style:font-face', fontElem, fontAttr) fontSizeDelta = 2 contentRoot = _addOdfElement('office:document-content', attr=versionAttr) contentRoot.append(fontElem) contentBodyElem = _addOdfElement('office:body', contentRoot) contentTextElem = _addOdfElement('office:text', contentBodyElem) maxLevel = 0 for spot in self.selectedSpots: level = _addOdfText(spot, contentTextElem, addBranches) maxLevel = max(level, maxLevel) manifestRoot = _addOdfElement('manifest:manifest') _addOdfElement('manifest:file-entry', manifestRoot, {'manifest:media-type': 'application/vnd.oasis.opendocument.text', 'manifest:full-path': '/'}) _addOdfElement('manifest:file-entry', manifestRoot, {'manifest:media-type': 'text/xml', 'manifest:full-path': 'content.xml'}) _addOdfElement('manifest:file-entry', manifestRoot, {'manifest:media-type': 'text/xml', 'manifest:full-path': 'styles.xml'}) styleRoot = _addOdfElement('office:document-styles', attr=versionAttr) styleRoot.append(fontElem) stylesElem = _addOdfElement('office:styles', styleRoot) defaultStyleElem = _addOdfElement('style:default-style', stylesElem, {'style:family': 'paragraph'}) _addOdfElement('style:paragraph-properties', defaultStyleElem, {'style:writing-mode': 'page'}) _addOdfElement('style:text-properties', defaultStyleElem, {'fo:font-size': '{0}pt'.format(fontInfo.pointSize()), 'fo:hyphenate': 'false', 'style:font-name': fontInfo.family()}) _addOdfElement('style:style', stylesElem, {'style:name': 'Standard', 'style:class': 'text', 'style:family': 'paragraph'}) bodyStyleElem = _addOdfElement('style:style', stylesElem, {'style:name': 'Text_20_body', 'style:display-name': 'Text body', 'style:class': 'text', 'style:family': 'paragraph', 'style:parent-style-name': 'Standard'}) _addOdfElement('style:paragraph-properties', bodyStyleElem, {'fo:margin-bottom': '6.0pt'}) headStyleElem = _addOdfElement('style:style', stylesElem, {'style:name': 'Heading', 'style:class': 'text', 'style:family': 'paragraph', 'style:next-style-name': 'Text_20_body', 'style:parent-style-name': 'Standard'}) _addOdfElement('style:paragraph-properties', headStyleElem, {'fo:keep-with-next': 'always', 'fo:margin-bottom': '6.0pt', 'fo:margin-top': '12.0pt'}) _addOdfElement('style:text-properties', headStyleElem, {'fo:font-size': '{0}pt'.format(fontInfo.pointSize() + fontSizeDelta), 'style:font-name': fontInfo.family()}) outlineStyleElem = _addOdfElement('text:outline-style') for level in range(1, maxLevel + 1): size = fontInfo.pointSize() if level <= 2: size += 2 * fontSizeDelta elif level <= 4: size += fontSizeDelta levelStyleElem = _addOdfElement('style:style', stylesElem, {'style:name': 'Heading_20_{0}'.format(level), 'style:display-name': 'Heading {0}'.format(level), 'style:class': 'text', 'style:family': 'paragraph', 'style:parent-style-name': 'Heading', 'style:default-outline-level': '{0}'.format(level)}) levelTextElem = _addOdfElement('style:text-properties', levelStyleElem, {'fo:font-size': '{0}pt'.format(size), 'fo:font-weight': 'bold'}) if level % 2 == 0: levelTextElem.set('fo:font-style', 'italic') _addOdfElement('text:outline-level-style', outlineStyleElem, {'text:level': '{0}'.format(level), 'style:num-format': ''}) stylesElem.append(outlineStyleElem) autoStyleElem = _addOdfElement('office:automatic-styles', styleRoot) pageLayElem = _addOdfElement('style:page-layout', autoStyleElem, {'style:name': 'pm1'}) _addOdfElement('style:page-layout-properties', pageLayElem, {'fo:margin-bottom': '0.75in', 'fo:margin-left': '0.75in', 'fo:margin-right': '0.75in', 'fo:margin-top': '0.75in', 'fo:page-height': '11in', 'fo:page-width': '8.5in', 'style:print-orientation': 'portrait'}) masterStyleElem = _addOdfElement('office:master-styles', styleRoot) _addOdfElement('style:master-page', masterStyleElem, {'style:name': 'Standard', 'style:page-layout-name': 'pm1'}) with zipfile.ZipFile(str(pathObj), 'w', zipfile.ZIP_DEFLATED) as odfZip: _addElemToZip(odfZip, contentRoot, 'content.xml') _addElemToZip(odfZip, manifestRoot, 'META-INF/manifest.xml') _addElemToZip(odfZip, styleRoot, 'styles.xml') return True def exportBookmarksHtml(self, pathObj=None): """Export HTML format bookmarks, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export HTML Bookmarks'), 'html') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedNodes = self.structure.childList addBranches = ExportDialog.exportWhat != ExportDialog.selectNode title = _bookmarkTitle if len(self.selectedNodes) == 1 and addBranches: title = self.selectedNodes[0].title() self.selectedNodes = self.selectedNodes[0].childList lines = ['', '', '{0}'.format(title), '

    {0}

    '.format(title)] for node in self.selectedNodes: lines.extend(_exportHtmlBookmarks(node, addBranches)) with pathObj.open('w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in lines]) return True def exportBookmarksXbel(self, pathObj=None): """Export XBEL format bookmarks, use ExportDialog options. Prompt user for path if not given in argument. Return True on successful export. Arguments: pathObj -- use if given, otherwise prompt user """ if not pathObj: pathObj = self.getFileName(_('TreeLine - Export XBEL Bookmarks'), 'xml') if not pathObj: return False QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if ExportDialog.exportWhat == ExportDialog.entireTree: self.selectedNodes = self.structure.childList addBranches = ExportDialog.exportWhat != ExportDialog.selectNode title = _bookmarkTitle if len(self.selectedNodes) == 1 and addBranches: title = self.selectedNodes[0].title() self.selectedNodes = self.selectedNodes[0].childList rootElem = ElementTree.Element('xbel') titleElem = ElementTree.Element('title') titleElem.text = title rootElem.append(titleElem) for node in self.selectedNodes: rootElem.append(_exportXbel(node, addBranches)) elementTree = ElementTree.ElementTree(rootElem) with pathObj.open('wb') as f: f.write(b'\n') elementTree.write(f, 'utf-8', False) return True def _setHtmlDirectories(node, pathDict, parentPath, siblingNames, addSuffix=True): """Recursively create path obj for node and add to the path dict by uId. Arguments: node -- the node to create a path object for pathDict -- the dict of paths by uId for adding an entry parentPath -- the path of the parent node siblingNames -- set of already used sibling names addSuffix -- add '.html' suffix to file names if True """ name = node.title() maxLength = 32 if len(name) > maxLength: pos = name.rfind(' ', maxLength // 2, maxLength + 1) if pos < 0: pos = maxLength name = name[:pos] name = name.replace(' ', '_') name = _idReplaceCharsRe.sub('', name) if not name: name = 'id' elif not 'a' <= name.lower() <= 'z': name = 'id_' + name origName = name i = 1 while name in siblingNames: name = origName + '_' + repr(i) i += 1 siblingNames.add(name) pathObj = parentPath / name filePathObj = pathObj.with_suffix('.html') if addSuffix else pathObj pathDict[node.uId] = filePathObj siblings = set() for child in node.childList: _setHtmlDirectories(child, pathDict, pathObj, siblings, addSuffix) def _writeHtmlPage(node, parent, grandparent, pathDict, level=0): """Write web pages with navigation for this node and descendents. Arguments: node -- the node to write the page for parent -- the parent node (or None) grandparent -- the grandparent node (or None) pathDict -- the dict of paths by uId level -- indicates the depth and how far up the css file is """ lines = ['', '', '', '', ''.format('../' * level), '{0}'.format(node.title()), '', '', '', '
    ']) outputLines = [line + '
    ' for line in node.output()] if node.formatRef.siblingPrefix: outputLines[0] = node.formatRef.siblingPrefix + outputLines[0] if node.formatRef.siblingSuffix: outputLines[-1] += node.formatRef.siblingSuffix for i in range(len(outputLines)): startPos = 0 while True: match = _genLinkRe.search(outputLines[i], startPos) if not match: break addr = match.group(1) if addr.startswith('#'): pathObj = pathDict.get(addr[1:], None) if pathObj: relPath = os.path.relpath(str(pathObj), nodeDir) outputLines[i] = (outputLines[i][:match.start(1)] + relPath + outputLines[i][match.end(1):]) elif urltools.isRelative(addr): outputLines[i] = (outputLines[i][:match.start(1)] + '../' * level + addr + outputLines[i][match.end(1):]) startPos = match.start(1) startPos = 0 while True: match = _imgLinkRe.search(outputLines[i], startPos) if not match: break addr = match.group(1) if not addr.startswith('#') and urltools.isRelative(addr): outputLines[i] = (outputLines[i][:match.start(1)] + '../' * level + addr + outputLines[i][match.end(1):]) startPos = match.start(1) lines.extend(outputLines) lines.extend(['
    ', '', '']) with pathDict[node.uId].open('w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in lines]) if node.childList: dirObj = pathDict[node.uId].with_suffix('') if not dirObj.is_dir(): dirObj.mkdir(0o755) os.chdir(str(dirObj)) for child in node.childList: _writeHtmlPage(child, node, parent, pathDict, level + 1) os.chdir('..') def _writeHtmlTable(node, parent, pathDict, level=1): """Write web pages with tables for child data to nested directories. Arguments: node -- the node to write the page for parent -- the parent node (or None) pathDict -- the dict of paths by uId level -- the depth and how far up local links should point """ if not node.childList: return dirObj = pathDict[node.uId] if not dirObj.is_dir(): dirObj.mkdir(0o755) os.chdir(str(dirObj)) title = node.title() lines = ['', '', '', '', '{0}'.format(title), '', ''] if ExportDialog.addHeader: headerText = (globalref.mainControl.activeControl.printData. formatHeaderFooter(True)) if headerText: lines.append(headerText) lines.append('

    {0}

    '.format(title)) if parent: lines.append('

    {0}: {1}' '

    '.format(_('Parent'), parent.title())) lines.extend(['', '']) lines.extend([''.format(name) for name in node.childList[0].formatRef.fieldNames()]) lines.append('') for child in node.childList: cellList = [field.outputText(child, False, False, True) for field in child.formatRef.fields()] for i in range(len(cellList)): startPos = 0 while True: match = _genLinkRe.search(cellList[i], startPos) if not match: break addr = match.group(1) if addr.startswith('#'): pathObj = pathDict.get(addr[1:], None) if pathObj: name = pathObj.stem pathObj = pathObj / '..' / 'index.html' relPath = os.path.relpath(str(pathObj), str(dirObj)) relPath += '#' + name cellList[i] = (cellList[i][:match.start(1)] + relPath + cellList[i][match.end(1):]) elif urltools.isRelative(addr): cellList[i] = (cellList[i][:match.start(1)] + '../' * level + addr + cellList[i][match.end(1):]) startPos = match.start(1) startPos = 0 while True: match = _imgLinkRe.search(cellList[i], startPos) if not match: break addr = match.group(1) if not addr.startswith('#') and urltools.isRelative(addr): cellList[i] = (cellList[i][:match.start(1)] + '../' * level + addr + cellList[i][match.end(1):]) startPos = match.start(1) if child.childList: cellList[0] = ('{1}'. format(pathDict[child.uId].stem, cellList[0])) cellList[0] = '{1}'.format(pathDict[child.uId].stem, cellList[0]) lines.extend([''.format(cell) for cell in cellList]) lines.append('') lines.extend(['', '
    {0}
    {0}
    ']) if ExportDialog.addHeader: footerText = (globalref.mainControl.activeControl.printData. formatHeaderFooter(False)) if footerText: lines.append(footerText) lines.extend(['', '']) with open('index.html', 'w', encoding='utf-8') as f: f.writelines([(line + '\n') for line in lines]) for child in node.childList: _writeHtmlTable(child, node, pathDict, level + 1) os.chdir('..') def _oldElementXml(node, structRef, idDict, skipTypeFormats=None, extraFormats=True, addChildren=True, addDescend=True): """Return an Element object with the XML for this node's branch. Arguments: node -- the root node to save structRef -- a ref to the tree structure idDict -- a dict of new IDs to old IDs skipTypeFormats -- a set of node format types not included in XML extraFormats -- if True, includes unused format info addChildren -- if True, include data for the first level of children addDescend -- if True, add lower descendant nodes """ if skipTypeFormats == None: skipTypeFormats = set() nodeFormat = node.formatRef addFormat = nodeFormat.name not in skipTypeFormats element = ElementTree.Element(nodeFormat.name, {'item':'y'}) # add line feeds to make output somewhat readable element.tail = '\n' element.text = '\n' element.set('uniqueid', idDict[node.uId]) if addFormat: element.attrib.update(_convertOldNodeFormat(nodeFormat.storeFormat())) skipTypeFormats.add(nodeFormat.name) firstField = True for field in nodeFormat.fields(): text = node.data.get(field.name, '') if text or addFormat: fieldElement = ElementTree.SubElement(element, field.name) fieldElement.tail = '\n' if field.typeName in ('Date', 'DateTime'): text = text.replace('-', '/') if (field.typeName in ('Time', 'DateTime') and text.endswith('.000000')): text = text[:-7] linkCount = 0 startPos = 0 while True: match = _intLinkRe.search(text, startPos) if not match: break uId = idDict.get(match.group(1), '') if uId: text = text[:match.start(1)] + uId + text[match.end(1):] linkCount += 1 startPos = match.start(1) if linkCount: fieldElement.attrib['linkcount'] = repr(linkCount) fieldElement.text = text if addFormat: fieldElement.attrib.update(_convertOldFieldFormat(field. formatData())) if firstField: fieldElement.attrib['idref'] = 'y' firstField = False if addChildren: for child in node.childList: element.append(_oldElementXml(child, structRef, idDict, skipTypeFormats, False, addChildren=addDescend)) nodeFormats = [] if extraFormats: # write format info for unused formats nodeFormats = list(structRef.treeFormats.values()) if structRef.treeFormats.fileInfoFormat.fieldFormatModified: nodeFormats.append(structRef.treeFormats.fileInfoFormat) for nodeFormat in nodeFormats: if nodeFormat.name not in skipTypeFormats: formatElement = ElementTree.SubElement(element, nodeFormat.name, {'item':'n'}) formatElement.tail = '\n' formatElement.attrib.update(_convertOldNodeFormat(nodeFormat. storeFormat())) firstField = True for field in nodeFormat.fields(): fieldElement = ElementTree.SubElement(formatElement, field.name) fieldElement.tail = '\n' fieldElement.attrib.update(_convertOldFieldFormat(field. formatData())) if firstField: fieldElement.attrib['idref'] = 'y' firstField = False return element def _setOldUniqueId(idDict, node): """Set an old TreeLine unique ID for this node amd add to dict. Arguments: idDict -- a dict of old IDs to new IDs. node -- the node to give an old ID """ nodeFormat = node.formatRef idField = next(iter(nodeFormat.fieldDict.values())) uId = idField.outputText(node, True, True, nodeFormat.formatHtml) uId = uId.strip().split('\n', 1)[0] maxLength = 50 if len(uId) > maxLength: pos = uId.rfind(' ', maxLength // 2, maxLength + 1) if pos < 0: pos = maxLength uId = uId[:pos] uId = uId.replace(' ', '_').lower() uId = _idReplaceCharsRe.sub('', uId) if not uId: uId = 'id_1' elif not 'a' <= uId <= 'z': uId = 'id_' + uId if uId in idDict: if uId == 'id_1': uId = 'id' i = 1 while uId + '_' + repr(i) in idDict: i += 1 uId = uId + '_' + repr(i) idDict[uId] = node.uId def _convertOldNodeFormat(attrib): """Return old XML node format attributes from current data. Arguments: attrib -- current node format data attributes """ if 'spacebetween' in attrib and not attrib['spacebetween']: attrib['spacebetween'] = 'n' for key in ('formathtml', 'bullets', 'tables'): if key in attrib and attrib[key]: attrib[key] = 'y' attrib['line0'] = attrib.get('titleline', '') del attrib['titleline'] for i, line in enumerate(attrib['outputlines'], 1): attrib['line' + repr(i)] = line del attrib['outputlines'] del attrib['formatname'] del attrib['fields'] return attrib def _convertOldFieldFormat(attrib): """Return old XML field format attributes from current data. Arguments: attrib -- current field format data attributes """ if 'fieldtype' in attrib: attrib['type'] = attrib['fieldtype'] del attrib['fieldtype'] for key in ('lines', 'sortkeynum'): if key in attrib: attrib[key] = repr(attrib[key]) if 'sortkeyfwd' in attrib and not attrib['sortkeyfwd']: attrib['sortkeydir'] = 'r' if 'evalhtml' in attrib: attrib['evalhtml'] = 'y' if attrib['evalhtml'] else 'n' if attrib['type'] in ('Date', 'Time', 'DateTime'): fieldFormat = attrib.get('format', '') if fieldFormat: fieldFormat = fieldFormat.replace('%A', 'dddd') fieldFormat = fieldFormat.replace('%a', 'ddd') fieldFormat = fieldFormat.replace('%d', 'dd') fieldFormat = fieldFormat.replace('%-d', 'd') fieldFormat = fieldFormat.replace('%B', 'MMMM') fieldFormat = fieldFormat.replace('%b', 'MMM') fieldFormat = fieldFormat.replace('%m', 'MM') fieldFormat = fieldFormat.replace('%-m', 'M') fieldFormat = fieldFormat.replace('%Y', 'yyyy') fieldFormat = fieldFormat.replace('%y', 'yy') fieldFormat = fieldFormat.replace('%H', 'HH') fieldFormat = fieldFormat.replace('%-H', 'H') fieldFormat = fieldFormat.replace('%I', 'hh') fieldFormat = fieldFormat.replace('%-I', 'h') fieldFormat = fieldFormat.replace('%M', 'mm') fieldFormat = fieldFormat.replace('%-M', 'm') fieldFormat = fieldFormat.replace('%S', 'ss') fieldFormat = fieldFormat.replace('%-S', 's') fieldFormat = fieldFormat.replace('%f', 'zzz') fieldFormat = fieldFormat.replace('%p', 'AP') attrib['format'] = fieldFormat del attrib['fieldname'] return attrib def _convertOldPrintData(attrib): """Return old XML print data attributes from current print data. Arguments: attrib -- current print data attributes """ for key in ('printlines', 'printwidowcontrol', 'printportrait'): if key in attrib and not attrib[key]: attrib[key] = 'n' for key in ('printindentfactor', 'printpaperwidth', 'printpaperheight', 'printheadermargin', 'printfootermargin', 'printcolumnspace', 'printnumcolumns'): if key in attrib: attrib[key] = repr(attrib[key]) if 'printmargins' in attrib: attrib['printmargins'] = ' '.join([repr(margin) for margin in attrib['printmargins']]) return attrib def _createGenericXml(node, addChildren=True): """Return an ElementTree element with generic XML from this branch. Called recursively for children if addChildren is True. Arguments: node -- the node to export addChildren -- add branch if True """ nodeFormat = node.formatRef element = ElementTree.Element(nodeFormat.name) element.tail = '\n' for fieldName in nodeFormat.fieldNames(): text = node.data.get(fieldName, '') if text and fieldName != imports.genericXmlTextFieldName: element.set(fieldName, text) if imports.genericXmlTextFieldName in nodeFormat.fieldDict: text = node.data.get(imports.genericXmlTextFieldName, '') if text: element.text = text if addChildren and node.childList: if not text: element.text = '\n' for child in node.childList: element.append(_createGenericXml(child)) return element def _addElemToZip(destZip, rootElem, fileName): """Adds ElementTree root elements to the given zip file. Arguments: destZip -- the destination zip file rootElem -- the root element tree item to add fileName -- the file name or path in the zip file """ elemTree = ElementTree.ElementTree(rootElem) with io.BytesIO() as output: elemTree.write(output, 'utf-8', True) destZip.writestr(fileName, output.getvalue()) def _addOdfElement(name, parent=None, attr=None): """Shortcut function to add elements to the ElementTree. Converts names and attr keys from short version (with ':') to the full URI. Returns the new element. Arguments: name -- the element tag parent -- new element is added here if given attr -- a dict of the element's attrbutes """ if ':' in name: prefix, name = name.split(':', 1) name = '{{{0}}}{1}'.format(_odfNamespace[prefix], name) newAttr = {} if attr: for key, value in attr.items(): if ':' in key: prefix, key = key.split(':', 1) key = '{{{0}}}{1}'.format(_odfNamespace[prefix], key) newAttr[key] = value elem = ElementTree.Element(name, newAttr) elem.tail = '\n' if parent is not None: parent.append(elem) return elem def _addOdfText(spot, parentElem, addChildren=True, level=1, maxLevel=1): """Add heading and text elements to the parent element tree element. Called recursively for children if addChildren is True. Returns the maximum indent level used for this branch. Arguments: spot -- the spot to export parentElem -- the parent element tree element to add to addChildren -- add branch if True level -- the current tree indent level maxLevel -- the previous max indent level """ headElem = _addOdfElement('text:h', parentElem, {'text:outline-level': '{0}'.format(level), 'text:style-name': 'Heading_20_{0}'.format(level)}) headElem.text = spot.nodeRef.title(spot) output = spot.nodeRef.output(True, False, spot) if output and output[0] == spot.nodeRef.title(spot): del output[0] # remove first line if same as title for line in output: textElem = _addOdfElement('text:p', parentElem, {'text:outline-level': '{0}'.format(level), 'text:style-name': 'Text_20_body'}) textElem.text = line if addChildren and spot.nodeRef.childList: for child in spot.childSpots(): childlevel = _addOdfText(child, parentElem, True, level + 1, maxLevel) maxLevel = max(childlevel, maxLevel) else: maxLevel = max(level, maxLevel) return maxLevel def _exportHtmlBookmarks(node, addChildren=True): """Return a text list ith descendant bookmarks in Mozilla format. Called recursively for children if addChildren is True. Arguments: node -- the node to export addChildren -- add branch if True """ title = node.title() if not node.childList: nodeFormat = node.formatRef field = _findLinkField(nodeFormat) if field: linkMatch = fieldformat.linkRegExp.search(node.data. get(field.name, '')) if linkMatch: link = linkMatch.group(1) return ['
    {1}'.format(link, title)] elif (len(nodeFormat.fieldDict) == 1 and not node.data.get(nodeFormat.fieldNames()[0], '')): return ['
    '] result = ['

    {0}

    '.format(title)] if addChildren: result.append('

    ') for child in node.childList: result.extend(_exportHtmlBookmarks(child)) result.append('

    ') return result def _exportXbel(node, addChildren=True): """Return an ElementTree element with XBEL bookmarks from this branch. Called recursively for children if addChildren is True. Arguments: node -- the node to export addChildren -- add branch if True """ titleElem = ElementTree.Element('title') titleElem.text = node.title() if not node.childList: nodeFormat = node.formatRef field = _findLinkField(nodeFormat) if field: linkMatch = fieldformat.linkRegExp.search(node.data. get(field.name, '')) if linkMatch: link = linkMatch.group(1) element = ElementTree.Element('bookmark', {'href': link}) element.append(titleElem) element.tail = '\n' return element elif (len(nodeFormat.fieldDict) == 1 and not node.data.get(nodeFormat.fieldNames()[0], '')): element = ElementTree.Element('separator') element.tail = '\n' return element element = ElementTree.Element('folder') element.append(titleElem) element.tail = '\n' if addChildren: for child in node.childList: element.append(_exportXbel(child)) return element def _findLinkField(nodeFormat): """Return the field most likely to contain a bookmark URL. Return None if there are no matches. Arguments: nodeFormat -- the format to find a field in """ availFields = [field for field in nodeFormat.fieldDict.values() if field.typeName == 'ExternalLink'] if not availFields: return None bestFields = [field for field in availFields if field.name.lower() == imports.bookmarkLinkFieldName.lower()] if bestFields: return bestFields[0] return availFields[0] class ExportDialog(QWizard): """Dialog/wizard for setting file export type and options. """ typePage, subtypePage, optionPage = range(3) entireTree, selectBranch, selectNode = range(3) exportWhat = entireTree includeRoot = False openOnly = False addHeader = False numColumns = 1 navPaneLevels = 2 exportTypes = ['html', 'text', 'treeline', 'xml', 'odf', 'bookmarks'] currentType = 'html' exportTypeDescript = {'html': _('&HTML'), 'text': _('&Text'), 'treeline': _('Tree&Line'), 'xml': _('&XML (generic)'), 'odf': _('&ODF Outline'), 'bookmarks': _('Book&marks')} exportSubtypes = {'html': ['htmlSingle', 'htmlNavSingle','htmlPages', 'htmlTables', 'htmlLiveLink', 'htmlLiveSingle'], 'text': ['textTitles', 'textPlain', 'textTableMultiCsv', 'textTableCsv', 'textTableTab'], 'treeline': ['oldTreeLine', 'treeLineSubtree'], 'xml': ['xmlGeneric'], 'odf': ['odfText'], 'bookmarks': ['bookmarksHtml', 'bookmarksXbel']} currentSubtype = 'htmlSingle' subtypeDescript = {'htmlSingle': _('&Single HTML page'), 'htmlNavSingle': _('Single &HTML page with ' 'navigation pane'), 'htmlPages': _('Multiple HTML &pages with ' 'navigation pane'), 'htmlTables': _('Multiple HTML &data tables'), 'htmlLiveLink': _('Live tree view, linked to ' 'TreeLine file (for web server)'), 'htmlLiveSingle': _('Live tree view, single file ' '(embedded data)'), 'textTitles': _('&Tabbed title text'), 'textPlain': _('&Unformatted output of all text'), 'textTableMultiCsv': _('&Comma delimited (CSV) table ' 'of descendants (level numbers)'), 'textTableCsv': _('Comma &delimited (CSV) table ' 'of children (single level)'), 'textTableTab': _('Tab &delimited table of children ' '(&single level)'), 'oldTreeLine': _('&Old TreeLine (2.0.x)'), 'treeLineSubtree': _('&TreeLine Subtree'), 'bookmarksHtml': _('&HTML format bookmarks'), 'bookmarksXbel': _('&XBEL format bookmarks')} disableEntireTree = {'textTableCsv', 'textTableTab', 'treeLineSubtree'} disableSelBranches = {'htmlLiveLink'} disableSelNodes = {'htmlNavSingle', 'htmlPages', 'htmlTables', 'htmlLiveLink', 'textTableMultiCsv'} enableRootNode = {'htmlSingle', 'htmlNavSingle', 'textTitles', 'textPlain', 'textTableMultiCsv', 'ODF'} forceRootNodeOff = {'textTableCsv', 'textTableTab'} enableOpenOnly = {'htmlSingle', 'htmlNavSingle', 'textTitles', 'textPlain', 'textTableMultiCsv', 'ODF'} enableHeader = {'htmlSingle', 'htmlNavSingle', 'htmlTables'} enableColumns = {'htmlSingle'} enableNavLevels = {'htmlNavSingle'} def __init__(self, selectionAvail=True, parent=None): """Initialize the export wizard. Arguments: selectionAvail -- false if no nodes or branches are selected parent -- the parent window """ super().__init__(parent, Qt.WindowType.Dialog) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('File Export')) self.setWizardStyle(QWizard.WizardStyle.ClassicStyle) self.setPage(ExportDialog.typePage, ExportDialogTypePage()) self.setPage(ExportDialog.subtypePage, ExportDialogSubtypePage()) self.setPage(ExportDialog.optionPage, ExportDialogOptionPage(selectionAvail)) class ExportDialogTypePage(QWizardPage): """A wizard page for selecting the main export type. """ def __init__(self, parent=None): """Initialize the export wizard page. Arguments: parent -- parent widget, set automatically by addPage or setPage """ super().__init__(parent) topLayout = QVBoxLayout(self) self.setLayout(topLayout) self.setTitle(_('Choose export format type')) typeButtons = QButtonGroup(self) for id, exportType in enumerate(ExportDialog.exportTypes): button = QRadioButton(ExportDialog. exportTypeDescript[exportType]) typeButtons.addButton(button, id) topLayout.addWidget(button) if exportType == ExportDialog.currentType: button.setChecked(True) typeButtons.idClicked.connect(self.setCurrentType) def setCurrentType(self, buttonID): """Set the saved current type value based on a button click. Also sets the subtype to a default value. Arguments: buttonId -- the ID number of the button that was clicked """ ExportDialog.currentType = ExportDialog.exportTypes[buttonID] ExportDialog.currentSubtype = (ExportDialog. exportSubtypes[ExportDialog.currentType][0]) def nextId(self): """Return the ID for the next page in the wizard sequence. """ if len(ExportDialog.exportSubtypes[ExportDialog.currentType]) > 1: return ExportDialog.subtypePage return ExportDialog.optionPage class ExportDialogSubtypePage(QWizardPage): """A wizard page for selecting the export subtype. """ def __init__(self, parent=None): """Initialize the export wizard page. Arguments: parent -- parent widget, set automatically by addPage or setPage """ super().__init__(parent) topLayout = QVBoxLayout(self) self.setLayout(topLayout) self.setTitle(_('Choose export format subtype')) self.subtypeButtons = QButtonGroup(self) self.subtypeButtons.idClicked.connect(self.setCurrentSubtype) def initializePage(self): """Add buttons to this page based on current settings. """ topLayout = self.layout() # remove old buttons from a previously set subtype for button in self.subtypeButtons.buttons(): self.subtypeButtons.removeButton(button) topLayout.removeWidget(button) button.deleteLater() for id, subtype in enumerate(ExportDialog. exportSubtypes[ExportDialog.currentType]): button = QRadioButton(ExportDialog.subtypeDescript[subtype]) self.subtypeButtons.addButton(button, id) topLayout.addWidget(button) if subtype == ExportDialog.currentSubtype: button.setChecked(True) def setCurrentSubtype(self, buttonId): """Set the saved current subtype value based on a button click. Arguments: buttonId -- the ID number of the button that was clicked """ availSubtypes = ExportDialog.exportSubtypes[ExportDialog.currentType] ExportDialog.currentSubtype = availSubtypes[buttonId] class ExportDialogOptionPage(QWizardPage): """A wizard page for selecting other export options. """ def __init__(self, selectionAvail=True, parent=None): """Initialize the export wizard page. Arguments: selectionAvail -- false if no nodes or branches are selected parent -- parent widget, set automatically by addPage or setPage """ super().__init__(parent) self.selectionAvail = selectionAvail topLayout = QVBoxLayout(self) self.setLayout(topLayout) self.setTitle(_('Choose export options')) whatGroupBox = QGroupBox(_('What to Export')) topLayout.addWidget(whatGroupBox) whatLayout = QVBoxLayout(whatGroupBox) self.whatButtons = QButtonGroup(self) treeButton = QRadioButton(_('&Entire tree')) self.whatButtons.addButton(treeButton, ExportDialog.entireTree) whatLayout.addWidget(treeButton) branchButton = QRadioButton(_('Selected &branches')) self.whatButtons.addButton(branchButton, ExportDialog.selectBranch) whatLayout.addWidget(branchButton) nodeButton = QRadioButton(_('Selected &nodes')) self.whatButtons.addButton(nodeButton, ExportDialog.selectNode) whatLayout.addWidget(nodeButton) self.whatButtons.button(ExportDialog.exportWhat).setChecked(True) self.whatButtons.idClicked.connect(self.setExportWhat) optionBox = QGroupBox(_('Other Options')) topLayout.addWidget(optionBox) optionLayout = QVBoxLayout(optionBox) self.rootButton = QCheckBox(_('&Include root nodes')) optionLayout.addWidget(self.rootButton) self.rootButton.setChecked(ExportDialog.includeRoot) self.rootButton.toggled.connect(self.setIncludeRoot) self.openOnlyButton = QCheckBox(_('&Only open node children')) optionLayout.addWidget(self.openOnlyButton) self.openOnlyButton.setChecked(ExportDialog.openOnly) self.openOnlyButton.toggled.connect(self.setOpenOnly) self.headerButton = QCheckBox(_('Include &print header && ' 'footer')) optionLayout.addWidget(self.headerButton) self.headerButton.setChecked(ExportDialog.addHeader) self.headerButton.toggled.connect(self.setAddHeader) columnLayout = QHBoxLayout() optionLayout.addLayout(columnLayout) self.numColSpin = QSpinBox() columnLayout.addWidget(self.numColSpin) self.numColSpin.setRange(1, 9) self.numColSpin.setMaximumWidth(40) self.numColSpin.setValue(ExportDialog.numColumns) self.colLabel = QLabel(_('&Columns')) columnLayout.addWidget(self.colLabel) self.colLabel.setBuddy(self.numColSpin) self.numColSpin.valueChanged.connect(self.setNumColumns) navLevelsLayout = QHBoxLayout() optionLayout.addLayout(navLevelsLayout) self.navLevelsSpin = QSpinBox() navLevelsLayout.addWidget(self.navLevelsSpin) self.navLevelsSpin.setRange(1, 9) self.navLevelsSpin.setMaximumWidth(40) self.navLevelsSpin.setValue(ExportDialog.navPaneLevels) self.navLevelsLabel = QLabel(_('Navigation pane &levels')) navLevelsLayout.addWidget(self.navLevelsLabel) self.navLevelsLabel.setBuddy(self.navLevelsSpin) self.navLevelsSpin.valueChanged.connect(self.setNavLevels) def initializePage(self): """Enable or disable controls based on current settings. """ subtype = ExportDialog.currentSubtype treeButton, branchButton, nodeButton = self.whatButtons.buttons() treeButton.setEnabled(subtype not in ExportDialog.disableEntireTree) branchButton.setEnabled(subtype not in ExportDialog.disableSelBranches and self.selectionAvail) nodeButton.setEnabled(subtype not in ExportDialog.disableSelNodes and self.selectionAvail) num = 0 while not self.whatButtons.checkedButton().isEnabled(): try: self.whatButtons.button(num).setChecked(True) except AttributeError: QMessageBox.warning(self, 'TreeLine', _('Must select nodes prior to export')) parent = self.parent() while parent: try: parent.reject() return except AttributeError: parent = parent.parent() num += 1 if (subtype in ExportDialog.enableRootNode and ExportDialog.exportWhat != ExportDialog.selectNode): self.rootButton.setEnabled(True) self.rootButton.setChecked(ExportDialog.includeRoot) else: self.rootButton.setEnabled(False) self.rootButton.setChecked(subtype not in ExportDialog.forceRootNodeOff) if (subtype in ExportDialog.enableOpenOnly and ExportDialog.exportWhat != ExportDialog.selectNode): self.openOnlyButton.setEnabled(True) else: self.openOnlyButton.setEnabled(False) self.openOnlyButton.setChecked(False) self.headerButton.setEnabled(subtype in ExportDialog.enableHeader) if subtype not in ExportDialog.enableHeader: self.headerButton.setChecked(False) columnsEnabled = subtype in ExportDialog.enableColumns self.numColSpin.setVisible(columnsEnabled) self.colLabel.setVisible(columnsEnabled) if not columnsEnabled: self.numColSpin.setValue(1) navLevelsEnabled = subtype in ExportDialog.enableNavLevels self.navLevelsSpin.setVisible(navLevelsEnabled) self.navLevelsLabel.setVisible(navLevelsEnabled) def setExportWhat(self, buttonNum): """Set what to export (all, branch, node) based on button group click. Arguments: buttonNum -- the ID number of the clicked button """ ExportDialog.exportWhat = buttonNum self.initializePage() def setIncludeRoot(self, checked): """Set whether root node is included based on a button click. Arguments: checked -- True if the check box is checked """ ExportDialog.includeRoot = checked def setOpenOnly(self, checked): """Set whether only open nodes are included based on a button click. Arguments: checked -- True if the check box is checked """ ExportDialog.openOnly = checked def setAddHeader(self, checked): """Set whether headers and footers are added based on a button click. Arguments: checked -- True if the check box is checked """ ExportDialog.addHeader = checked def setNumColumns(self, num): """Set number of columns based on a spin box change. Arguments: num -- the new spin box setting """ ExportDialog.numColumns = num def setNavLevels(self, num): """Set number of navigation pane levels based on a spin box change. Arguments: num -- the new spin box setting """ ExportDialog.navPaneLevels = num TreeLine-3.2.1/source/fieldformat.py000066400000000000000000002752721506556630100174200ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # fieldformat.py, provides a class to handle field format types # # TreeLine, an information storage program # Copyright (C) 2023, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import sys import enum import datetime import xml.sax.saxutils as saxutils import gennumber import genboolean import numbering import matheval import urltools import globalref fieldTypes = [N_('Text'), N_('HtmlText'), N_('OneLineText'), N_('SpacedText'), N_('Number'), N_('Math'), N_('Numbering'), N_('Date'), N_('Time'), N_('DateTime'), N_('Boolean'), N_('Choice'), N_('AutoChoice'), N_('Combination'), N_('AutoCombination'), N_('ExternalLink'), N_('InternalLink'), N_('Picture'), N_('RegularExpression')] translatedFieldTypes = [_(name) for name in fieldTypes] _errorStr = '#####' _dateStampString = _('Now') _timeStampString = _('Now') MathResult = enum.Enum('MathResult', 'number date time boolean text') _mathResultBlank = {MathResult.number: 0, MathResult.date: 0, MathResult.time: 0, MathResult.boolean: False, MathResult.text: ''} _multipleSpaceRegEx = re.compile(r' {2,}') _lineBreakRegEx = re.compile(r'', re.I) _stripTagRe = re.compile(r'<.*?>') linkRegExp = re.compile(r']*href="([^"]+)"[^>]*>(.*?)', re.I | re.S) linkSeparateNameRegExp = re.compile(r'(.*) \[(.*)\]\s*$') _imageRegExp = re.compile(r']*src="([^"]+)"[^>]*>', re.I | re.S) class TextField: """Class to handle a rich-text field format type. Stores options and format strings for a text field type. Provides methods to return formatted data. """ typeName = 'Text' defaultFormat = '' showRichTextInCell = True evalHtmlDefault = False fixEvalHtmlSetting = True defaultNumLines = 1 editorClassName = 'RichTextEditor' sortTypeStr = '80_text' supportsInitDefault = True formatHelpMenuList = [] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ self.name = name if not formatData: formatData = {} self.prefix = formatData.get('prefix', '') self.suffix = formatData.get('suffix', '') self.initDefault = formatData.get('init', '') self.numLines = formatData.get('lines', type(self).defaultNumLines) self.sortKeyNum = formatData.get('sortkeynum', 0) self.sortKeyForward = formatData.get('sortkeyfwd', True) self.evalHtml = self.evalHtmlDefault if not self.fixEvalHtmlSetting: self.evalHtml = formatData.get('evalhtml', self.evalHtmlDefault) self.useFileInfo = False self.showInDialog = True self.setFormat(formatData.get('format', type(self).defaultFormat)) def formatData(self): """Return a dictionary of this field's format settings. """ formatData = {'fieldname': self.name, 'fieldtype': self.typeName} if self.format: formatData['format'] = self.format if self.prefix: formatData['prefix'] = self.prefix if self.suffix: formatData['suffix'] = self.suffix if self.initDefault: formatData['init'] = self.initDefault if self.numLines != self.defaultNumLines: formatData['lines'] = self.numLines if self.sortKeyNum > 0: formatData['sortkeynum'] = self.sortKeyNum if not self.sortKeyForward: formatData['sortkeyfwd'] = False if (not self.fixEvalHtmlSetting and self.evalHtml != self.evalHtmlDefault): formatData['evalhtml'] = self.evalHtml return formatData def setFormat(self, format): """Set the format string and initialize as required. Derived classes may raise a ValueError if the format is illegal. Arguments: format -- the new format string """ self.format = format def outputText(self, node, oneLine, noHtml, formatHtml, spotRef=None): """Return formatted output text for this field in this node. Arguments: node -- the tree item storing the data oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix spotRef -- optional, used for ancestor field refs """ if self.useFileInfo and node.spotRefs: # get file info node if not already the file info node node = node.treeStructureRef().fileInfoNode storedText = node.data.get(self.name, '') if storedText: return self.formatOutput(storedText, oneLine, noHtml, formatHtml) return '' def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ prefix = self.prefix suffix = self.suffix if oneLine: storedText = _lineBreakRegEx.split(storedText, 1)[0] if noHtml: storedText = removeMarkup(storedText) if formatHtml: prefix = removeMarkup(prefix) suffix = removeMarkup(suffix) if not formatHtml: prefix = saxutils.escape(prefix) suffix = saxutils.escape(suffix) return '{0}{1}{2}'.format(prefix, storedText, suffix) def editorText(self, node): """Return text formatted for use in the data editor. The function for default text just returns the stored text. Overloads may raise a ValueError if the data does not match the format. Arguments: node -- the tree item storing the data """ storedText = node.data.get(self.name, '') return self.formatEditorText(storedText) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. The function for default text just returns the stored text. Overloads may raise a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ return storedText def storedText(self, editorText): """Return new text to be stored based on text from the data editor. The function for default text field just returns the editor text. Overloads may raise a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ return editorText def storedTextFromTitle(self, titleText): """Return new text to be stored based on title text edits. Overloads may raise a ValueError if the data does not match the format. Arguments: titleText -- the new title text """ return self.storedText(saxutils.escape(titleText)) def getInitDefault(self): """Return the initial stored value for newly created nodes. """ return self.initDefault def setInitDefault(self, editorText): """Set the default initial value from editor text. The function for default text field just returns the stored text. Arguments: editorText -- the new text entered into the editor """ self.initDefault = self.storedText(editorText) def getEditorInitDefault(self): """Return initial value in editor format. """ value = '' if self.supportsInitDefault: try: value = self.formatEditorText(self.initDefault) except ValueError: pass return value def initDefaultChoices(self): """Return a list of choices for setting the init default. """ return [] def mathValue(self, node, zeroBlanks=True, noMarkup=True): """Return a value to be used in math field equations. Return None if blank and not zeroBlanks. Arguments: node -- the tree item storing the data zeroBlanks -- accept blank field values if True noMarkup -- if true, remove html markup """ storedText = node.data.get(self.name, '') if storedText and noMarkup: storedText = removeMarkup(storedText) return storedText if storedText or zeroBlanks else None def compareValue(self, node): """Return a value for comparison to other nodes and for sorting. Returns lowercase text for text fields or numbers for non-text fields. Arguments: node -- the tree item storing the data """ storedText = node.data.get(self.name, '') return self.adjustedCompareValue(storedText) def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Text version removes any markup and goes to lower case. Arguments: value -- the comparison value to adjust """ value = removeMarkup(value) return value.lower() def sortKey(self, node): """Return a tuple with field type and comparison value for sorting. Allows different types to be sorted. Arguments: node -- the tree item storing the data """ return (self.sortTypeStr, self.compareValue(node)) def changeType(self, newType): """Change this field's type to newType with a default format. Arguments: newType -- the new type name, excluding "Field" """ oldType = self.typeName self.__class__ = globals()[newType + 'Field'] # Don't lose format between Choice & Combination types if (oldType not in ('Choice', 'Combination') or newType not in ('Choice', 'Combination') or not self.format): self.setFormat(self.defaultFormat) if self.fixEvalHtmlSetting: self.evalHtml = self.evalHtmlDefault def sepName(self): """Return the name enclosed with {* *} separators """ if self.useFileInfo: return '{{*!{0}*}}'.format(self.name) return '{{*{0}*}}'.format(self.name) def getFormatHelpMenuList(self): """Return the list of descriptions and keys for the format help menu. """ return self.formatHelpMenuList class HtmlTextField(TextField): """Class to handle an HTML text field format type Stores options and format strings for an HTML text field type. Does not use the rich text editor. Provides methods to return formatted data. """ typeName = 'HtmlText' showRichTextInCell = False evalHtmlDefault = True editorClassName = 'HtmlTextEditor' def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def storedTextFromTitle(self, titleText): """Return new text to be stored based on title text edits. Overloads may raise a ValueError if the data does not match the format. Arguments: titleText -- the new title text """ return self.storedText(titleText) class OneLineTextField(TextField): """Class to handle a single-line rich-text field format type. Stores options and format strings for a text field type. Provides methods to return formatted data. """ typeName = 'OneLineText' editorClassName = 'OneLineTextEditor' def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ text = _lineBreakRegEx.split(storedText, 1)[0] return super().formatOutput(text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ return _lineBreakRegEx.split(storedText, 1)[0] class SpacedTextField(TextField): """Class to handle a preformatted text field format type. Stores options and format strings for a spaced text field type. Uses

     tags to preserve spacing.
        Does not use the rich text editor.
        Provides methods to return formatted data.
        """
        typeName = 'SpacedText'
        showRichTextInCell = False
        editorClassName = 'PlainTextEditor'
        def __init__(self, name, formatData=None):
            """Initialize a field format type.
    
            Arguments:
                name -- the field name string
                formatData -- the dict that defines this field's format
            """
            super().__init__(name, formatData)
    
        def formatOutput(self, storedText, oneLine, noHtml, formatHtml):
            """Return formatted output text from stored text for this field.
    
            Arguments:
                storedText -- the source text to format
                oneLine -- if True, returns only first line of output (for titles)
                noHtml -- if True, removes all HTML markup (for titles, etc.)
                formatHtml -- if False, escapes HTML from prefix & suffix
            """
            if storedText:
                storedText = '
    {0}
    '.format(storedText) return super().formatOutput(storedText, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Arguments: storedText -- the source text to format """ return saxutils.unescape(storedText) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Arguments: editorText -- the new text entered into the editor """ return saxutils.escape(editorText) def storedTextFromTitle(self, titleText): """Return new text to be stored based on title text edits. Arguments: titleText -- the new title text """ return self.storedText(titleText) class NumberField(HtmlTextField): """Class to handle a general number field format type. Stores options and format strings for a number field type. Provides methods to return formatted data. """ typeName = 'Number' defaultFormat = '#.##' evalHtmlDefault = False editorClassName = 'LineEditor' sortTypeStr = '20_num' formatHelpMenuList = [(_('Optional Digit\t#'), '#'), (_('Required Digit\t0'), '0'), (_('Digit or Space (external)\t'), ' '), ('', ''), (_('Decimal Point\t.'), '.'), (_('Decimal Comma\t,'), ','), ('', ''), (_('Comma Separator\t\\,'), '\\,'), (_('Dot Separator\t\\.'), '\\.'), (_('Space Separator (internal)\t'), ' '), ('', ''), (_('Optional Sign\t-'), '-'), (_('Required Sign\t+'), '+'), ('', ''), (_('Exponent (capital)\tE'), 'E'), (_('Exponent (small)\te'), 'e')] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ try: text = gennumber.GenNumber(storedText).numStr(self.format) except ValueError: text = _errorStr return super().formatOutput(text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not storedText: return '' return gennumber.GenNumber(storedText).numStr(self.format) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ if not editorText: return '' return repr(gennumber.GenNumber().setFromStr(editorText, self.format)) def mathValue(self, node, zeroBlanks=True, noMarkup=True): """Return a numeric value to be used in math field equations. Return None if blank and not zeroBlanks, raise a ValueError if it isn't a number. Arguments: node -- the tree item storing the data zeroBlanks -- replace blank field values with zeros if True noMarkup -- not applicable to numbers """ storedText = node.data.get(self.name, '') if storedText: return gennumber.GenNumber(storedText).num return 0 if zeroBlanks else None def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Number version converts to a numeric value. Arguments: value -- the comparison value to adjust """ try: return gennumber.GenNumber(value).num except ValueError: return 0 class MathField(HtmlTextField): """Class to handle a math calculation field type. Stores options and format strings for a math field type. Provides methods to return formatted data. """ typeName = 'Math' defaultFormat = '#.##' evalHtmlDefault = False fixEvalHtmlSetting = False editorClassName = 'ReadOnlyEditor' def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the attributes that define this field's format """ super().__init__(name, formatData) self.equation = None self.resultType = MathResult[formatData.get('resulttype', 'number')] equationText = formatData.get('eqn', '').strip() if equationText: self.equation = matheval.MathEquation(equationText) try: self.equation.validate() except ValueError: self.equation = None def formatData(self): """Return a dictionary of this field's attributes. Add the math equation to the standard XML output. """ formatData = super().formatData() if self.equation: formatData['eqn'] = self.equation.equationText() if self.resultType != MathResult.number: formatData['resulttype'] = self.resultType.name return formatData def setFormat(self, format): """Set the format string and initialize as required. Arguments: format -- the new format string """ if not hasattr(self, 'equation'): self.equation = None self.resultType = MathResult.number super().setFormat(format) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ text = storedText try: if self.resultType == MathResult.number: text = gennumber.GenNumber(text).numStr(self.format) elif self.resultType == MathResult.date: date = datetime.datetime.strptime(text, DateField.isoFormat).date() text = date.strftime(adjOutDateFormat(self.format)) elif self.resultType == MathResult.time: time = datetime.datetime.strptime(text, TimeField.isoFormat).time() text = time.strftime(adjOutDateFormat(self.format)) elif self.resultType == MathResult.boolean: text = genboolean.GenBoolean(text).boolStr(self.format) except ValueError: text = _errorStr return super().formatOutput(text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not storedText: return '' if self.resultType == MathResult.number: return gennumber.GenNumber(storedText).numStr(self.format) if self.resultType == MathResult.date: date = datetime.datetime.strptime(storedText, DateField.isoFormat).date() editorFormat = adjOutDateFormat(globalref. genOptions['EditDateFormat']) return date.strftime(editorFormat) if self.resultType == MathResult.time: time = datetime.datetime.strptime(storedText, TimeField.isoFormat).time() editorFormat = adjOutDateFormat(globalref. genOptions['EditTimeFormat']) return time.strftime(editorFormat) if self.resultType == MathResult.boolean: return genboolean.GenBoolean(storedText).boolStr(self.format) if storedText == _errorStr: raise ValueError return storedText def equationText(self): """Return the current equation text. """ if self.equation: return self.equation.equationText() return '' def equationValue(self, node): """Return a text value from the result of the equation. Returns the '#####' error string for illegal math operations. Arguments: node -- the tree item with this equation """ if self.equation: zeroValue = _mathResultBlank[self.resultType] try: num = self.equation.equationValue(node, self.resultType, zeroValue, not self.evalHtml) except ValueError: return _errorStr if num == None: return '' if self.resultType == MathResult.date: date = DateField.refDate + datetime.timedelta(days=num) return date.strftime(DateField.isoFormat) if self.resultType == MathResult.time: dateTime = datetime.datetime.combine(DateField.refDate, TimeField.refTime) dateTime = dateTime + datetime.timedelta(seconds=num) time = dateTime.time() return time.strftime(TimeField.isoFormat) text = str(num) if not self.evalHtml: text = saxutils.escape(text) return text return '' def resultClass(self): """Return the result type's field class. """ return globals()[self.resultType.name.capitalize() + 'Field'] def changeResultType(self, resultType): """Change the result type and reset the output format. Arguments: resultType -- the new result type """ if resultType != self.resultType: self.resultType = resultType self.setFormat(self.resultClass().defaultFormat) def mathValue(self, node, zeroBlanks=True, noMarkup=True): """Return a numeric value to be used in math field equations. Return None if blank and not zeroBlanks, raise a ValueError if it isn't valid. Arguments: node -- the tree item storing the data zeroBlanks -- replace blank field values with zeros if True noMarkup -- if true, remove html markup """ storedText = node.data.get(self.name, '') if storedText: if self.resultType == MathResult.number: return gennumber.GenNumber(storedText).num if self.resultType == MathResult.date: date = datetime.datetime.strptime(storedText, DateField.isoFormat).date() return (date - DateField.refDate).days if self.resultType == MathResult.time: time = datetime.datetime.strptime(storedText, TimeField.isoFormat).time() return (time - TimeField.refTime).seconds if self.resultType == MathResult.boolean: return genboolean.GenBoolean(storedText).value if noMarkup: storedText = removeMarkup(storedText) return storedText return _mathResultBlank[self.resultType] if zeroBlanks else None def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Number version converts to a numeric value. Arguments: value -- the comparison value to adjust """ try: if self.resultType == MathResult.number: return gennumber.GenNumber(value).num if self.resultType == MathResult.date: date = datetime.datetime.strptime(value, DateField.isoFormat).date() return date.strftime(DateField.isoFormat) if self.resultType == MathResult.time: time = datetime.datetime.strptime(value, TimeField.isoFormat).time() return time.strftime(TimeField.isoFormat) if self.resultType == MathResult.boolean: return genboolean.GenBoolean(value).value return value.lower() except ValueError: return 0 def sortKey(self, node): """Return a tuple with field type and comparison value for sorting. Allows different types to be sorted. Arguments: node -- the tree item storing the data """ return (self.resultClass().sortTypeStr, self.compareValue(node)) def getFormatHelpMenuList(self): """Return the list of descriptions and keys for the format help menu. """ return self.resultClass().formatHelpMenuList class NumberingField(HtmlTextField): """Class to handle formats for hierarchical node numbering. Stores options and format strings for a node numbering field type. Provides methods to return formatted node numbers. """ typeName = 'Numbering' defaultFormat = '1..' evalHtmlDefault = False editorClassName = 'LineEditor' sortTypeStr = '10_numbering' formatHelpMenuList = [(_('Number\t1'), '1'), (_('Capital Letter\tA'), 'A'), (_('Small Letter\ta'), 'a'), (_('Capital Roman Numeral\tI'), 'I'), (_('Small Roman Numeral\ti'), 'i'), ('', ''), (_('Level Separator\t/'), '/'), (_('Section Separator\t.'), '.'), ('', ''), (_('"/" Character\t//'), '//'), (_('"." Character\t..'), '..'), ('', ''), (_('Outline Example\tI../A../1../a)/i)'), 'I../A../1../a)/i)'), (_('Section Example\t1.1.1.1'), '1.1.1.1')] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the attributes that define this field's format """ self.numFormat = None super().__init__(name, formatData) def setFormat(self, format): """Set the format string and initialize as required. Arguments: format -- the new format string """ self.numFormat = numbering.NumberingGroup(format) super().setFormat(format) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ try: text = self.numFormat.numString(storedText) except ValueError: text = _errorStr return super().formatOutput(text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if storedText: checkData = [int(num) for num in storedText.split('.')] return storedText def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ if editorText: checkData = [int(num) for num in editorText.split('.')] return editorText def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Number version converts to a numeric value. Arguments: value -- the comparison value to adjust """ if value: try: return [int(num) for num in value.split('.')] except ValueError: pass return [0] class DateField(HtmlTextField): """Class to handle a general date field format type. Stores options and format strings for a date field type. Provides methods to return formatted data. """ typeName = 'Date' defaultFormat = '%B %-d, %Y' isoFormat = '%Y-%m-%d' evalHtmlDefault = False fixEvalHtmlSetting = False editorClassName = 'DateEditor' refDate = datetime.date(1970, 1, 1) sortTypeStr = '40_date' formatHelpMenuList = [(_('Day (1 or 2 digits)\t%-d'), '%-d'), (_('Day (2 digits)\t%d'), '%d'), ('', ''), (_('Weekday Abbreviation\t%a'), '%a'), (_('Weekday Name\t%A'), '%A'), ('', ''), (_('Month (1 or 2 digits)\t%-m'), '%-m'), (_('Month (2 digits)\t%m'), '%m'), (_('Month Abbreviation\t%b'), '%b'), (_('Month Name\t%B'), '%B'), ('', ''), (_('Year (2 digits)\t%y'), '%y'), (_('Year (4 digits)\t%Y'), '%Y'), ('', ''), (_('Week Number (0 to 53)\t%-U'), '%-U'), (_('Day of year (1 to 366)\t%-j'), '%-j')] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ try: date = datetime.datetime.strptime(storedText, DateField.isoFormat).date() text = date.strftime(adjOutDateFormat(self.format)) except ValueError: text = _errorStr if not self.evalHtml: text = saxutils.escape(text) return super().formatOutput(text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not storedText: return '' date = datetime.datetime.strptime(storedText, DateField.isoFormat).date() editorFormat = adjOutDateFormat(globalref.genOptions['EditDateFormat']) return date.strftime(editorFormat) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Two digit years are interpretted as 1950-2049. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ editorText = _multipleSpaceRegEx.sub(' ', editorText.strip()) if not editorText: return '' editorFormat = adjInDateFormat(globalref.genOptions['EditDateFormat']) try: date = datetime.datetime.strptime(editorText, editorFormat).date() except ValueError: # allow use of a 4-digit year to fix invalid dates fullYearFormat = editorFormat.replace('%y', '%Y') if fullYearFormat != editorFormat: date = datetime.datetime.strptime(editorText, fullYearFormat).date() else: raise return date.strftime(DateField.isoFormat) def getInitDefault(self): """Return the initial stored value for newly created nodes. """ if self.initDefault == _dateStampString: date = datetime.date.today() return date.strftime(DateField.isoFormat) return super().getInitDefault() def setInitDefault(self, editorText): """Set the default initial value from editor text. The function for default text field just returns the stored text. Arguments: editorText -- the new text entered into the editor """ if editorText == _dateStampString: self.initDefault = _dateStampString else: super().setInitDefault(editorText) def getEditorInitDefault(self): """Return initial value in editor format. """ if self.initDefault == _dateStampString: return _dateStampString return super().getEditorInitDefault() def initDefaultChoices(self): """Return a list of choices for setting the init default. """ return [_dateStampString] def mathValue(self, node, zeroBlanks=True, noMarkup=True): """Return a numeric value to be used in math field equations. Return None if blank and not zeroBlanks, raise a ValueError if it isn't a valid date. Arguments: node -- the tree item storing the data zeroBlanks -- replace blank field values with zeros if True """ storedText = node.data.get(self.name, '') if storedText: date = datetime.datetime.strptime(storedText, DateField.isoFormat).date() return (date - DateField.refDate).days return 0 if zeroBlanks else None def compareValue(self, node): """Return a value for comparison to other nodes and for sorting. Returns lowercase text for text fields or numbers for non-text fields. Date field uses ISO date format (YYY-MM-DD). Arguments: node -- the tree item storing the data """ return node.data.get(self.name, '') def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Date version converts to an ISO date format (YYYY-MM-DD). Arguments: value -- the comparison value to adjust """ value = _multipleSpaceRegEx.sub(' ', value.strip()) if not value: return '' if value == _dateStampString: date = datetime.date.today() return date.strftime(DateField.isoFormat) try: return self.storedText(value) except ValueError: return value class TimeField(HtmlTextField): """Class to handle a general time field format type Stores options and format strings for a time field type. Provides methods to return formatted data. """ typeName = 'Time' defaultFormat = '%-I:%M:%S %p' isoFormat = '%H:%M:%S.%f' evalHtmlDefault = False fixEvalHtmlSetting = False editorClassName = 'TimeEditor' numChoiceColumns = 2 autoAddChoices = False refTime = datetime.time() sortTypeStr = '50_time' formatHelpMenuList = [(_('Hour (0-23, 1 or 2 digits)\t%-H'), '%-H'), (_('Hour (00-23, 2 digits)\t%H'), '%H'), (_('Hour (1-12, 1 or 2 digits)\t%-I'), '%-I'), (_('Hour (01-12, 2 digits)\t%I'), '%I'), ('', ''), (_('Minute (1 or 2 digits)\t%-M'), '%-M'), (_('Minute (2 digits)\t%M'), '%M'), ('', ''), (_('Second (1 or 2 digits)\t%-S'), '%-S'), (_('Second (2 digits)\t%S'), '%S'), ('', ''), (_('Microseconds (6 digits)\t%f'), '%f'), ('', ''), (_('AM/PM\t%p'), '%p')] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the attributes that define this field's format """ super().__init__(name, formatData) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ try: time = datetime.datetime.strptime(storedText, TimeField.isoFormat).time() outFormat = adjOutDateFormat(self.format) outFormat = adjTimeAmPm(outFormat, time) text = time.strftime(outFormat) except ValueError: text = _errorStr if not self.evalHtml: text = saxutils.escape(text) return super().formatOutput(text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not storedText: return '' time = datetime.datetime.strptime(storedText, TimeField.isoFormat).time() editorFormat = adjOutDateFormat(globalref.genOptions['EditTimeFormat']) editorFormat = adjTimeAmPm(editorFormat, time) return time.strftime(editorFormat) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ editorText = _multipleSpaceRegEx.sub(' ', editorText.strip()) if not editorText: return '' editorFormat = adjInDateFormat(globalref.genOptions['EditTimeFormat']) time = None try: time = datetime.datetime.strptime(editorText, editorFormat).time() except ValueError: noSecFormat = editorFormat.replace(':%S', '') noSecFormat = _multipleSpaceRegEx.sub(' ', noSecFormat.strip()) try: time = datetime.datetime.strptime(editorText, noSecFormat).time() except ValueError: for altFormat in (editorFormat, noSecFormat): noAmFormat = altFormat.replace('%p', '') noAmFormat = _multipleSpaceRegEx.sub(' ', noAmFormat.strip()) try: time = datetime.datetime.strptime(editorText, noAmFormat).time() break except ValueError: pass if not time: raise ValueError return time.strftime(TimeField.isoFormat) def annotatedComboChoices(self, editorText): """Return a list of (choice, annotation) tuples for the combo box. Arguments: editorText -- the text entered into the editor """ editorFormat = adjOutDateFormat(globalref.genOptions['EditTimeFormat']) choices = [(datetime.datetime.now().time().strftime(editorFormat), '({0})'.format(_timeStampString))] for hour in (6, 9, 12, 15, 18, 21, 0): choices.append((datetime.time(hour).strftime(editorFormat), '')) return choices def getInitDefault(self): """Return the initial stored value for newly created nodes. """ if self.initDefault == _timeStampString: time = datetime.datetime.now().time() return time.strftime(TimeField.isoFormat) return super().getInitDefault() def setInitDefault(self, editorText): """Set the default initial value from editor text. The function for default text field just returns the stored text. Arguments: editorText -- the new text entered into the editor """ if editorText == _timeStampString: self.initDefault = _timeStampString else: super().setInitDefault(editorText) def getEditorInitDefault(self): """Return initial value in editor format. """ if self.initDefault == _timeStampString: return _timeStampString return super().getEditorInitDefault() def initDefaultChoices(self): """Return a list of choices for setting the init default. """ return [_timeStampString] def mathValue(self, node, zeroBlanks=True, noMarkup=True): """Return a numeric value to be used in math field equations. Return None if blank and not zeroBlanks, raise a ValueError if it isn't a valid time. Arguments: node -- the tree item storing the data zeroBlanks -- replace blank field values with zeros if True """ storedText = node.data.get(self.name, '') if storedText: time = datetime.datetime.strptime(storedText, TimeField.isoFormat).time() dateTime = datetime.datetime.combine(DateField.refDate, time) refDateTime = datetime.datetime.combine(DateField.refDate, TimeField.refTime) return (dateTime - refDateTime).seconds return 0 if zeroBlanks else None def compareValue(self, node): """Return a value for comparison to other nodes and for sorting. Returns lowercase text for text fields or numbers for non-text fields. Time field uses HH:MM:SS format. Arguments: node -- the tree item storing the data """ return node.data.get(self.name, '') def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Time version converts to HH:MM:SS format. Arguments: value -- the comparison value to adjust """ value = _multipleSpaceRegEx.sub(' ', value.strip()) if not value: return '' if value == _timeStampString: time = datetime.datetime.now().time() return time.strftime(TimeField.isoFormat) try: return self.storedText(value) except ValueError: return value class DateTimeField(HtmlTextField): """Class to handle a general date and time field format type. Stores options and format strings for a date and time field type. Provides methods to return formatted data. """ typeName = 'DateTime' defaultFormat = '%B %-d, %Y %-I:%M:%S %p' isoFormat = '%Y-%m-%d %H:%M:%S.%f' evalHtmlDefault = False fixEvalHtmlSetting = False editorClassName = 'DateTimeEditor' refDateTime = datetime.datetime(1970, 1, 1) sortTypeStr ='45_datetime' formatHelpMenuList = [(_('Day (1 or 2 digits)\t%-d'), '%-d'), (_('Day (2 digits)\t%d'), '%d'), ('', ''), (_('Weekday Abbreviation\t%a'), '%a'), (_('Weekday Name\t%A'), '%A'), ('', ''), (_('Month (1 or 2 digits)\t%-m'), '%-m'), (_('Month (2 digits)\t%m'), '%m'), (_('Month Abbreviation\t%b'), '%b'), (_('Month Name\t%B'), '%B'), ('', ''), (_('Year (2 digits)\t%y'), '%y'), (_('Year (4 digits)\t%Y'), '%Y'), ('', ''), (_('Week Number (0 to 53)\t%-U'), '%-U'), (_('Day of year (1 to 366)\t%-j'), '%-j'), (_('Hour (0-23, 1 or 2 digits)\t%-H'), '%-H'), (_('Hour (00-23, 2 digits)\t%H'), '%H'), (_('Hour (1-12, 1 or 2 digits)\t%-I'), '%-I'), (_('Hour (01-12, 2 digits)\t%I'), '%I'), ('', ''), (_('Minute (1 or 2 digits)\t%-M'), '%-M'), (_('Minute (2 digits)\t%M'), '%M'), ('', ''), (_('Second (1 or 2 digits)\t%-S'), '%-S'), (_('Second (2 digits)\t%S'), '%S'), ('', ''), (_('Microseconds (6 digits)\t%f'), '%f'), ('', ''), (_('AM/PM\t%p'), '%p')] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ try: dateTime = datetime.datetime.strptime(storedText, DateTimeField.isoFormat) outFormat = adjOutDateFormat(self.format) outFormat = adjTimeAmPm(outFormat, dateTime) text = dateTime.strftime(outFormat) except ValueError: text = _errorStr if not self.evalHtml: text = saxutils.escape(text) return super().formatOutput(text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not storedText: return '' dateTime = datetime.datetime.strptime(storedText, DateTimeField.isoFormat) editorFormat = '{0} {1}'.format(globalref.genOptions['EditDateFormat'], globalref.genOptions['EditTimeFormat']) editorFormat = adjOutDateFormat(editorFormat) editorFormat = adjTimeAmPm(editorFormat, dateTime) return dateTime.strftime(editorFormat) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Two digit years are interpretted as 1950-2049. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ editorText = _multipleSpaceRegEx.sub(' ', editorText.strip()) if not editorText: return '' editorFormat = '{0} {1}'.format(globalref.genOptions['EditDateFormat'], globalref.genOptions['EditTimeFormat']) editorFormat = adjInDateFormat(editorFormat) dateTime = None try: dateTime = datetime.datetime.strptime(editorText, editorFormat) except ValueError: noSecFormat = editorFormat.replace(':%S', '') noSecFormat = _multipleSpaceRegEx.sub(' ', noSecFormat.strip()) altFormats = [editorFormat, noSecFormat] for altFormat in altFormats[:]: noAmFormat = altFormat.replace('%p', '') noAmFormat = _multipleSpaceRegEx.sub(' ', noAmFormat.strip()) altFormats.append(noAmFormat) for altFormat in altFormats[:]: fullYearFormat = altFormat.replace('%y', '%Y') altFormats.append(fullYearFormat) for editorFormat in altFormats[1:]: try: dateTime = datetime.datetime.strptime(editorText, editorFormat) break except ValueError: pass if not dateTime: raise ValueError return dateTime.strftime(DateTimeField.isoFormat) def getInitDefault(self): """Return the initial stored value for newly created nodes. """ if self.initDefault == _timeStampString: dateTime = datetime.datetime.now() return dateTime.strftime(DateTimeField.isoFormat) return super().getInitDefault() def setInitDefault(self, editorText): """Set the default initial value from editor text. The function for default text field just returns the stored text. Arguments: editorText -- the new text entered into the editor """ if editorText == _timeStampString: self.initDefault = _timeStampString else: super().setInitDefault(editorText) def getEditorInitDefault(self): """Return initial value in editor format. """ if self.initDefault == _timeStampString: return _timeStampString return super().getEditorInitDefault() def initDefaultChoices(self): """Return a list of choices for setting the init default. """ return [_timeStampString] def mathValue(self, node, zeroBlanks=True, noMarkup=True): """Return a numeric value to be used in math field equations. Return None if blank and not zeroBlanks, raise a ValueError if it isn't a valid time. Arguments: node -- the tree item storing the data zeroBlanks -- replace blank field values with zeros if True """ storedText = node.data.get(self.name, '') if storedText: dateTime = datetime.datetime.strptime(storedText, DateTimeField.isoFormat) return (dateTime - DateTimeField.refDateTime).total_seconds() return 0 if zeroBlanks else None def compareValue(self, node): """Return a value for comparison to other nodes and for sorting. Returns lowercase text for text fields or numbers for non-text fields. DateTime field uses YYYY-MM-DD HH:MM:SS format. Arguments: node -- the tree item storing the data """ return node.data.get(self.name, '') def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Time version converts to HH:MM:SS format. Arguments: value -- the comparison value to adjust """ value = _multipleSpaceRegEx.sub(' ', value.strip()) if not value: return '' if value == _timeStampString: dateTime = datetime.datetime.now() return dateTime.strftime(DateTimeField.isoFormat) try: return self.storedText(value) except ValueError: return value class ChoiceField(HtmlTextField): """Class to handle a field with pre-defined, individual text choices. Stores options and format strings for a choice field type. Provides methods to return formatted data. """ typeName = 'Choice' editSep = '/' defaultFormat = '1/2/3/4' evalHtmlDefault = False fixEvalHtmlSetting = False editorClassName = 'ComboEditor' numChoiceColumns = 1 autoAddChoices = False formatHelpMenuList = [(_('Separator\t/'), '/'), ('', ''), (_('"/" Character\t//'), '//'), ('', ''), (_('Example\t1/2/3/4'), '1/2/3/4')] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def setFormat(self, format): """Set the format string and initialize as required. Arguments: format -- the new format string """ super().setFormat(format) self.choiceList = self.splitText(self.format) if self.evalHtml: self.choices = set(self.choiceList) else: self.choices = set([saxutils.escape(choice) for choice in self.choiceList]) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ if storedText not in self.choices: storedText = _errorStr return super().formatOutput(storedText, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if storedText and storedText not in self.choices: raise ValueError if self.evalHtml: return storedText return saxutils.unescape(storedText) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ if not self.evalHtml: editorText = saxutils.escape(editorText) if not editorText or editorText in self.choices: return editorText raise ValueError def comboChoices(self): """Return a list of choices for the combo box. """ return self.choiceList def initDefaultChoices(self): """Return a list of choices for setting the init default. """ return self.choiceList def splitText(self, textStr): """Split textStr using editSep, return a list of strings. Double editSep's are not split (become single). Removes duplicates and empty strings. Arguments: textStr -- the text to split """ result = [] textStr = textStr.replace(self.editSep * 2, '\0') for text in textStr.split(self.editSep): text = text.strip().replace('\0', self.editSep) if text and text not in result: result.append(text) return result class AutoChoiceField(HtmlTextField): """Class to handle a field with automatically populated text choices. Stores options and possible entries for an auto-choice field type. Provides methods to return formatted data. """ typeName = 'AutoChoice' evalHtmlDefault = False fixEvalHtmlSetting = False editorClassName = 'ComboEditor' numChoiceColumns = 1 autoAddChoices = True def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the attributes that define this field's format """ super().__init__(name, formatData) self.choices = set() def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Arguments: storedText -- the source text to format """ if self.evalHtml: return storedText return saxutils.unescape(storedText) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Arguments: editorText -- the new text entered into the editor """ if self.evalHtml: return editorText return saxutils.escape(editorText) def comboChoices(self): """Return a list of choices for the combo box. """ if self.evalHtml: choices = self.choices else: choices = [saxutils.unescape(text) for text in self.choices] return sorted(choices, key=str.lower) def addChoice(self, text): """Add a new choice. Arguments: text -- the choice to be added """ if text: self.choices.add(text) def clearChoices(self): """Remove all current choices. """ self.choices = set() class CombinationField(ChoiceField): """Class to handle a field with multiple pre-defined text choices. Stores options and format strings for a combination field type. Provides methods to return formatted data. """ typeName = 'Combination' editorClassName = 'CombinationEditor' numChoiceColumns = 2 def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def setFormat(self, format): """Set the format string and initialize as required. Arguments: format -- the new format string """ TextField.setFormat(self, format) if not self.evalHtml: format = saxutils.escape(format) self.choiceList = self.splitText(format) self.choices = set(self.choiceList) self.outputSep = '' def outputText(self, node, oneLine, noHtml, formatHtml, spotRef=None): """Return formatted output text for this field in this node. Sets output separator prior to calling base class methods. Arguments: node -- the tree item storing the data oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix spotRef -- optional, used for ancestor field refs """ self.outputSep = node.formatRef.outputSeparator return super().outputText(node, oneLine, noHtml, formatHtml, spotRef) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ selections, valid = self.sortedSelections(storedText) if valid: result = self.outputSep.join(selections) else: result = _errorStr return TextField.formatOutput(self, result, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ selections = set(self.splitText(storedText)) if selections.issubset(self.choices): if self.evalHtml: return storedText return saxutils.unescape(storedText) raise ValueError def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ if not self.evalHtml: editorText = saxutils.escape(editorText) selections, valid = self.sortedSelections(editorText) if not valid: raise ValueError return self.joinText(selections) def comboChoices(self): """Return a list of choices for the combo box. """ if self.evalHtml: return self.choiceList return [saxutils.unescape(text) for text in self.choiceList] def comboActiveChoices(self, editorText): """Return a sorted list of choices currently in editorText. Arguments: editorText -- the text entered into the editor """ selections, valid = self.sortedSelections(saxutils.escape(editorText)) if self.evalHtml: return selections return [saxutils.unescape(text) for text in selections] def initDefaultChoices(self): """Return a list of choices for setting the init default. """ return [] def sortedSelections(self, inText): """Split inText using editSep and sort like format string. Return a tuple of resulting selection list and bool validity. Valid if all choices are in the format string. Arguments: inText -- the text to split and sequence """ selections = set(self.splitText(inText)) result = [text for text in self.choiceList if text in selections] return (result, len(selections) == len(result)) def joinText(self, textList): """Join the text list using editSep, return the string. Any editSep in text items become double. Arguments: textList -- the list of text items to join """ return self.editSep.join([text.replace(self.editSep, self.editSep * 2) for text in textList]) class AutoCombinationField(CombinationField): """Class for a field with multiple automatically populated text choices. Stores options and possible entries for an auto-choice field type. Provides methods to return formatted data. """ typeName = 'AutoCombination' autoAddChoices = True defaultFormat = '' formatHelpMenuList = [] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the attributes that define this field's format """ super().__init__(name, formatData) self.choices = set() self.outputSep = '' def outputText(self, node, oneLine, noHtml, formatHtml, spotRef=None): """Return formatted output text for this field in this node. Sets output separator prior to calling base class methods. Arguments: node -- the tree item storing the data oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix spotRef -- optional, used for ancestor field refs """ self.outputSep = node.formatRef.outputSeparator return super().outputText(node, oneLine, noHtml, formatHtml, spotRef) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ result = self.outputSep.join(self.splitText(storedText)) return TextField.formatOutput(self, result, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Arguments: storedText -- the source text to format """ if self.evalHtml: return storedText return saxutils.unescape(storedText) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Also resets outputSep, to be defined at the next output. Arguments: editorText -- the new text entered into the editor """ self.outputSep = '' if not self.evalHtml: editorText = saxutils.escape(editorText) selections = sorted(self.splitText(editorText), key=str.lower) return self.joinText(selections) def comboChoices(self): """Return a list of choices for the combo box. """ if self.evalHtml: choices = self.choices else: choices = [saxutils.unescape(text) for text in self.choices] return sorted(choices, key=str.lower) def comboActiveChoices(self, editorText): """Return a sorted list of choices currently in editorText. Arguments: editorText -- the text entered into the editor """ selections, valid = self.sortedSelections(saxutils.escape(editorText)) if self.evalHtml: return selections return [saxutils.unescape(text) for text in selections] def sortedSelections(self, inText): """Split inText using editSep and sort like format string. Return a tuple of resulting selection list and bool validity. This version always returns valid. Arguments: inText -- the text to split and sequence """ selections = sorted(self.splitText(inText), key=str.lower) return (selections, True) def addChoice(self, text): """Add a new choice. Arguments: text -- the stored text combinations to be added """ for choice in self.splitText(text): self.choices.add(choice) def clearChoices(self): """Remove all current choices. """ self.choices = set() class BooleanField(ChoiceField): """Class to handle a general boolean field format type. Stores options and format strings for a boolean field type. Provides methods to return formatted data. """ typeName = 'Boolean' defaultFormat = _('yes/no') evalHtmlDefault = False fixEvalHtmlSetting = False sortTypeStr ='30_bool' formatHelpMenuList = [(_('true/false'), 'true/false'), (_('T/F'), 'T/F'), ('', ''), (_('yes/no'), 'yes/no'), (_('Y/N'), 'Y/N'), ('', ''), ('1/0', '1/0')] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def setFormat(self, format): """Set the format string and initialize as required. Arguments: format -- the new format string """ HtmlTextField.setFormat(self, format) self.strippedFormat = removeMarkup(self.format) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ try: text = genboolean.GenBoolean(storedText).boolStr(self.format) except ValueError: text = _errorStr if not self.evalHtml: text = saxutils.escape(text) return HtmlTextField.formatOutput(self, text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not storedText: return '' boolFormat = self.strippedFormat if self.evalHtml else self.format return genboolean.GenBoolean(storedText).boolStr(boolFormat) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ if not editorText: return '' boolFormat = self.strippedFormat if self.evalHtml else self.format try: return repr(genboolean.GenBoolean().setFromStr(editorText, boolFormat)) except ValueError: return repr(genboolean.GenBoolean(editorText)) def comboChoices(self): """Return a list of choices for the combo box. """ if self.evalHtml: return self.splitText(self.strippedFormat) return self.splitText(self.format) def initDefaultChoices(self): """Return a list of choices for setting the init default. """ return self.comboChoices() def mathValue(self, node, zeroBlanks=True, noMarkup=True): """Return a value to be used in math field equations. Return None if blank and not zeroBlanks, raise a ValueError if it isn't a valid boolean. Arguments: node -- the tree item storing the data zeroBlanks -- replace blank field values with zeros if True """ storedText = node.data.get(self.name, '') if storedText: return genboolean.GenBoolean(storedText).value return False if zeroBlanks else None def compareValue(self, node): """Return a value for comparison to other nodes and for sorting. Returns lowercase text for text fields or numbers for non-text fields. Bool fields return True or False values. Arguments: node -- the tree item storing the data """ storedText = node.data.get(self.name, '') try: return genboolean.GenBoolean(storedText).value except ValueError: return False def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Bool version converts to a bool value. Arguments: value -- the comparison value to adjust """ try: return genboolean.GenBoolean().setFromStr(value, self.format).value except ValueError: try: return genboolean.GenBoolean(value).value except ValueError: return False class ExternalLinkField(HtmlTextField): """Class to handle a field containing various types of external HTML links. Protocol choices include http, https, file, mailto. Stores data as HTML tags, shows in editors as "protocol:address [name]". """ typeName = 'ExternalLink' evalHtmlDefault = False editorClassName = 'ExtLinkEditor' sortTypeStr ='60_link' def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the attributes that define this field's format """ super().__init__(name, formatData) def addressAndName(self, storedText): """Return the link title and the name from the given stored link. Raise ValueError if the stored text is not formatted as a link. Arguments: storedText -- the source text to format """ if not storedText: return ('', '') linkMatch = linkRegExp.search(storedText) if not linkMatch: raise ValueError address, name = linkMatch.groups() return (address, name) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ if noHtml: linkMatch = linkRegExp.search(storedText) if linkMatch: address, name = linkMatch.groups() storedText = name.strip() if not storedText: storedText = address.lstrip('#') return super().formatOutput(storedText, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not storedText: return '' address, name = self.addressAndName(storedText) name = name.strip() if not name: name = urltools.shortName(address) return '{0} [{1}]'.format(address, name) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ if not editorText: return '' nameMatch = linkSeparateNameRegExp.match(editorText) if nameMatch: address, name = nameMatch.groups() else: raise ValueError return '{1}'.format(address.strip(), name.strip()) def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Link fields use link address. Arguments: value -- the comparison value to adjust """ if not value: return '' try: address, name = self.addressAndName(value) except ValueError: return value.lower() return address.lstrip('#').lower() class InternalLinkField(ExternalLinkField): """Class to handle a field containing internal links to nodes. Stores data as HTML local link tag, shows in editors as "id [name]". """ typeName = 'InternalLink' editorClassName = 'IntLinkEditor' supportsInitDefault = False def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the attributes that define this field's format """ super().__init__(name, formatData) def editorText(self, node): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Also raises a ValueError if the link is not a valid destination, with the editor text as the second argument to the exception. Arguments: node -- the tree item storing the data """ storedText = node.data.get(self.name, '') return self.formatEditorText(storedText, node.treeStructureRef()) def formatEditorText(self, storedText, treeStructRef): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Also raises a ValueError if the link is not a valid destination, with the editor text as the second argument to the exception. Arguments: storedText -- the source text to format treeStructRef -- ref to the tree structure to get the linked title """ if not storedText: return '' address, name = self.addressAndName(storedText) address = address.lstrip('#') targetNode = treeStructRef.nodeDict.get(address, None) linkTitle = targetNode.title() if targetNode else _errorStr name = name.strip() if not name and targetNode: name = linkTitle result = 'LinkTo: {0} [{1}]'.format(linkTitle, name) if linkTitle == _errorStr: raise ValueError('invalid address', result) return result def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Uses the "address [name]" format as input, not the final editor form. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new editor text in "address [name]" format """ if not editorText: return '' nameMatch = linkSeparateNameRegExp.match(editorText) if not nameMatch: raise ValueError address, name = nameMatch.groups() if not address: raise ValueError('invalid address', '') if not name: name = _errorStr result = '{1}'.format(address.strip(), name.strip()) if name == _errorStr: raise ValueError('invalid name', result) return result class PictureField(HtmlTextField): """Class to handle a field containing various types of external HTML links. Protocol choices include http, https, file, mailto. Stores data as HTML tags, shows in editors as "protocol:address [name]". """ typeName = 'Picture' evalHtmlDefault = False editorClassName = 'PictureLinkEditor' sortTypeStr ='60_link' def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the attributes that define this field's format """ super().__init__(name, formatData) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ if noHtml: linkMatch = _imageRegExp.search(storedText) if linkMatch: address = linkMatch.group(1) storedText = address.strip() return super().formatOutput(storedText, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not storedText: return '' linkMatch = _imageRegExp.search(storedText) if not linkMatch: raise ValueError return linkMatch.group(1) def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ editorText = editorText.strip() if not editorText: return '' nameMatch = linkSeparateNameRegExp.match(editorText) if nameMatch: address, name = nameMatch.groups() else: address = editorText name = urltools.shortName(address) return ''.format(editorText) def adjustedCompareValue(self, value): """Return value adjusted like the compareValue for use in conditionals. Link fields use link address. Arguments: value -- the comparison value to adjust """ if not value: return '' linkMatch = _imageRegExp.search(value) if not linkMatch: return value.lower() return linkMatch.group(1).lower() class RegularExpressionField(HtmlTextField): """Class to handle a field format type controlled by a regular expression. Stores options and format strings for a number field type. Provides methods to return formatted data. """ typeName = 'RegularExpression' defaultFormat = '.*' evalHtmlDefault = False fixEvalHtmlSetting = False editorClassName = 'LineEditor' formatHelpMenuList = [(_('Any Character\t.'), '.'), (_('End of Text\t$'), '$'), ('', ''), (_('0 Or More Repetitions\t*'), '*'), (_('1 Or More Repetitions\t+'), '+'), (_('0 Or 1 Repetitions\t?'), '?'), ('', ''), (_('Set of Numbers\t[0-9]'), '[0-9]'), (_('Lower Case Letters\t[a-z]'), '[a-z]'), (_('Upper Case Letters\t[A-Z]'), '[A-Z]'), (_('Not a Number\t[^0-9]'), '[^0-9]'), ('', ''), (_('Or\t|'), '|'), (_('Escape a Special Character\t\\'), '\\')] def __init__(self, name, formatData=None): """Initialize a field format type. Arguments: name -- the field name string formatData -- the dict that defines this field's format """ super().__init__(name, formatData) def setFormat(self, format): """Set the format string and initialize as required. Raise a ValueError if the format is illegal. Arguments: format -- the new format string """ try: re.compile(format) except re.error: raise ValueError super().setFormat(format) def formatOutput(self, storedText, oneLine, noHtml, formatHtml): """Return formatted output text from stored text for this field. Arguments: storedText -- the source text to format oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix """ match = re.fullmatch(self.format, saxutils.unescape(storedText)) if not storedText or match: text = storedText else: text = _errorStr return super().formatOutput(text, oneLine, noHtml, formatHtml) def formatEditorText(self, storedText): """Return text formatted for use in the data editor. Raises a ValueError if the data does not match the format. Arguments: storedText -- the source text to format """ if not self.evalHtml: storedText = saxutils.unescape(storedText) match = re.fullmatch(self.format, storedText) if not storedText or match: return storedText raise ValueError def storedText(self, editorText): """Return new text to be stored based on text from the data editor. Raises a ValueError if the data does not match the format. Arguments: editorText -- the new text entered into the editor """ match = re.fullmatch(self.format, editorText) if not editorText or match: if self.evalHtml: return editorText return saxutils.escape(editorText) raise ValueError class AncestorLevelField(TextField): """Placeholder format for ref. to ancestor fields at specific levels. """ typeName = 'AncestorLevel' def __init__(self, name, ancestorLevel=1): """Initialize a field format placeholder type. Arguments: name -- the field name string ancestorLevel -- the number of generations to go back """ super().__init__(name, {}) self.ancestorLevel = ancestorLevel def outputText(self, node, oneLine, noHtml, formatHtml, spotRef=None): """Return formatted output text for this field in this node. Finds the appropriate ancestor node to get the field text. Arguments: node -- the tree node to start from oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix spotRef -- optional, used for ancestor field refs """ if not spotRef: spotRef = node.spotByNumber(0) for num in range(self.ancestorLevel): spotRef = spotRef.parentSpot if not spotRef: return '' try: field = spotRef.nodeRef.formatRef.fieldDict[self.name] except (AttributeError, KeyError): return '' return field.outputText(spotRef.nodeRef, oneLine, noHtml, formatHtml, spotRef) def sepName(self): """Return the name enclosed with {* *} separators """ return '{{*{0}{1}*}}'.format(self.ancestorLevel * '*', self.name) class AnyAncestorField(TextField): """Placeholder format for ref. to matching ancestor fields at any level. """ typeName = 'AnyAncestor' def __init__(self, name): """Initialize a field format placeholder type. Arguments: name -- the field name string """ super().__init__(name, {}) def outputText(self, node, oneLine, noHtml, formatHtml, spotRef=None): """Return formatted output text for this field in this node. Finds the appropriate ancestor node to get the field text. Arguments: node -- the tree node to start from oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix spotRef -- optional, used for ancestor field refs """ if not spotRef: spotRef = node.spotByNumber(0) while spotRef.parentSpot: spotRef = spotRef.parentSpot try: field = spotRef.nodeRef.formatRef.fieldDict[self.name] except (AttributeError, KeyError): pass else: return field.outputText(spotRef.nodeRef, oneLine, noHtml, formatHtml, spotRef) return '' def sepName(self): """Return the name enclosed with {* *} separators """ return '{{*?{0}*}}'.format(self.name) class ChildListField(TextField): """Placeholder format for ref. to matching ancestor fields at any level. """ typeName = 'ChildList' def __init__(self, name): """Initialize a field format placeholder type. Arguments: name -- the field name string """ super().__init__(name, {}) def outputText(self, node, oneLine, noHtml, formatHtml, spotRef=None): """Return formatted output text for this field in this node. Returns a joined list of matching child field data. Arguments: node -- the tree node to start from oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix spotRef -- optional, used for ancestor field refs """ result = [] for child in node.childList: try: field = child.formatRef.fieldDict[self.name] except KeyError: pass else: result.append(field.outputText(child, oneLine, noHtml, formatHtml, spotRef)) outputSep = node.formatRef.outputSeparator return outputSep.join(result) def sepName(self): """Return the name enclosed with {* *} separators """ return '{{*&{0}*}}'.format(self.name) class DescendantCountField(TextField): """Placeholder format for count of descendants at a given level. """ typeName = 'DescendantCount' def __init__(self, name, descendantLevel=1): """Initialize a field format placeholder type. Arguments: name -- the field name string descendantLevel -- the level to descend to """ super().__init__(name, {}) self.descendantLevel = descendantLevel def outputText(self, node, oneLine, noHtml, formatHtml, spotRef=None): """Return formatted output text for this field in this node. Returns a count of descendants at the approriate level. Arguments: node -- the tree node to start from oneLine -- if True, returns only first line of output (for titles) noHtml -- if True, removes all HTML markup (for titles, etc.) formatHtml -- if False, escapes HTML from prefix & suffix spotRef -- optional, used for ancestor field refs """ newNodes = [node] for i in range(self.descendantLevel): prevNodes = newNodes newNodes = [] for child in prevNodes: newNodes.extend(child.childList) return repr(len(newNodes)) def sepName(self): """Return the name enclosed with {* *} separators """ return '{{*#{0}*}}'.format(self.name) #### Utility Functions #### def removeMarkup(text): """Return text with all HTML Markup removed and entities unescaped. Any
    tags are replaced with newlines. """ text = _lineBreakRegEx.sub('\n', text) text = _stripTagRe.sub('', text) return saxutils.unescape(text) def adjOutDateFormat(dateFormat): """Replace Linux lead zero removal with Windows version in date formats. Arguments: dateFormat -- the format to modify """ if sys.platform.startswith('win'): dateFormat = dateFormat.replace('%-', '%#') return dateFormat def adjInDateFormat(dateFormat): """Remove lead zero formatting in date formats for reading dates. Arguments: dateFormat -- the format to modify """ return dateFormat.replace('%-', '%') def adjTimeAmPm(timeFormat, time): """Add AM/PM to timeFormat if in format and locale skips it. Arguments: timeFormat -- the format to modify time -- the datetime object to check for AM/PM """ if '%p' in timeFormat and time.strftime('%I (%p)').endswith('()'): amPm = 'AM' if time.hour < 12 else 'PM' timeFormat = re.sub(r'(?/. """ def __init__(self, boolStr='true'): """Initialize a GenBoolean object with any format from _formatDict. Raises ValueError with an inappropriate argument. Arguments: boolStr -- the string to evaluate """ self.setBool(boolStr) def setBool(self, boolStr): """Initialize a GenBoolean object with any format from _formatDict. Raises ValueError with an inappropriate argument. Arguments: boolStr -- the string to evaluate """ try: self.value = _formatDict[boolStr.lower()] except KeyError: raise ValueError def setFromStr(self, boolStr, strFormat='yes/no'): """Set boolean value based on given format string. Raises ValueError with an inappropriate argument. Returns self. Arguments: boolStr -- the string to evaluate strFormat -- a text format in True/False style """ try: self.value = self.customFormatDict(strFormat)[boolStr.lower()] except KeyError: raise ValueError return self @staticmethod def customFormatDict(strFormat): """Return a dictionary based on the format. The dictionary includes conversions in both directions. String keys are in lower case. Double editSep's are not split (become single). Raises ValueError with an inappropriate format. Arguments: strFormat -- a text format in True/False style """ strFormat = strFormat.replace('//', '\0') trueVal, falseVal = strFormat.split('/', 1) trueVal = trueVal.replace('\0', '/') falseVal = falseVal.replace('\0', '/') if not trueVal or not falseVal or trueVal == falseVal: raise ValueError return {trueVal.lower():True, falseVal.lower():False, True:trueVal, False:falseVal} def boolStr(self, strFormat='yes/no'): """Return the boolean string in the given strFormat. Arguments: Format: strFormat -- a text format in True/False style """ return self.customFormatDict(strFormat)[self.value] def clone(self): """Return cloned instance. """ return self.__class__(self.value) def __repr__(self): """Outputs in general string fomat. """ return repr(self.value) def __eq__(self, other): """Equality test. """ try: return self.value == other.value except AttributeError: return self.value == other def __ne__(self, other): """Non-equality test. """ try: return self.value != other.value except AttributeError: return self.value != other def __hash__(self): """Allow use as dictionary key. """ return hash(self.value) def __nonzero(self): """Allow truth testing. """ return self.value TreeLine-3.2.1/source/gennumber.py000066400000000000000000000246711506556630100171010ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # gennumber.py, provides a class for number formating # # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import math class GenNumber: """Class to store & format number values. Uses a simple syntax (sequence of '#', '0', etc.) for formatting. """ def __init__(self, num=0): """Initialize a GenNumber object with a number, string or a GenNumber. Raises ValueError with an inappropriate argument. Accepts one of the following arguments as num to initialize: 1. int value 2. float value 3. string in common int or float format 4. GenNumber instance """ self.setNumber(num) def setNumber(self, num): """Sets the number value from an int, float, string or a GenNumber. Raises ValueError with an inappropriate argument. Arguments: num -- the value in int, float, string or GenNumber format """ try: self.num = int(str(num)) except ValueError: self.num = float(str(num)) def setFromStr(self, numStr, strFormat=r'#\,###'): """Set number value based on given format string. Removes the extra characters from format and uses format's radix char. Returns self. Arguments: numStr -- the string to evaluate strFormat -- the format to use to interpret the number string """ radix = _getRadix(strFormat) strFormat = _unescapeFormat(radix, strFormat).strip() extraChar = re.sub(r'[#0\seE\-\+{}]'.format(re.escape(radix)), '', strFormat) if extraChar: numStr = re.sub('[{}]'.format(re.escape(extraChar)), '', numStr) if radix == ',': numStr = numStr.replace(',', '.') self.setNumber(numStr) return self def numStr(self, strFormat='#.##'): """Return the number string in the given format, including exponents. Format: # = optional digit 0 = required digit e = exponent - = optional sign + = required sign space (external) = digit or space space (internal) = thousands sep \\, = thousands separator \\. = thousands separator Arguments: strFormat -- format for number export """ formMain, formExp = _doubleSplit('eE', strFormat) if not formExp: return self.basicNumStr(strFormat) exp = math.floor(math.log10(abs(self.num))) num = self.num / 10**exp totPlcs = len(re.findall(r'[#0]', formMain)) num = round(num, totPlcs - 1 if totPlcs > 0 else 0) radix = _getRadix(strFormat) wholePlcs = len(re.findall(r'[#0]', _doubleSplit(radix, formMain)[0])) expChg = wholePlcs - int(math.floor(math.log10(abs(num)))) - 1 num = num * 10**expChg exp -= expChg c = 'e' if 'e' in strFormat else 'E' return '{0}{1}{2}'.format(GenNumber(num).basicNumStr(formMain), c, GenNumber(exp).basicNumStr(formExp)) def basicNumStr(self, strFormat='#.##'): """Return number string in the given format, without exponent support. Format: # = optional digit 0 = required digit - = optional sign + = required sign space (external) = digit or space space (internal) = thousands sep \\, = thousands separator \\. = thousands separator Arguments: strFormat -- format for number export """ radix = _getRadix(strFormat) strFormat = _unescapeFormat(radix, strFormat) formWhole, formFract = _doubleSplit(radix, strFormat) decPlcs = len(re.findall(r'[#0]', formFract)) numWhole, numFract = _doubleSplit('.', '{0:.{1}f}'.format(self.num, decPlcs)) numFract = numFract.rstrip('0') numWhole, numFract = list(numWhole), list(numFract) formWhole, formFract = list(formWhole), list(formFract) sign = '+' if numWhole[0] == '-': sign = numWhole.pop(0) result = [] while numWhole or formWhole: c = formWhole.pop() if formWhole else '' if c and c not in '#0 +-': if numWhole or '0' in formWhole: result.insert(0, c) elif numWhole and c != ' ': result.insert(0, numWhole.pop()) if c and c in '+-': formWhole.append(c) elif c in '0 ': result.insert(0, c) elif c in '+-': if sign == '-' or c == '+': result.insert(0, sign) sign = '' if sign == '-': if result[0] == ' ': result = [re.sub(r'\s(?!\s)', '-', ''.join(result), 1)] else: result.insert(0, '-') if formFract or (strFormat and strFormat[-1] == radix): result.append(radix) while formFract: c = formFract.pop(0) if c not in '#0 ': if numFract or '0' in formFract: result.append(c) elif numFract: result.append(numFract.pop(0)) elif c in '0 ': result.append('0') return ''.join(result) def clone(self): """Return cloned instance. """ return self.__class__(self.num) def __repr__(self): """Outputs in general string fomat. """ return repr(self.num) def __eq__(self, other): """Equality test. """ try: return self.num == other.num except AttributeError: return self.num == other def __ne__(self, other): """Non-equality test. """ try: return self.num != other.num except AttributeError: return self.num != other def __lt__(self, other): """Less than test. """ try: return self.num < other.num except AttributeError: return self.num < other def __gt__(self, other): """Greater than test. """ try: return self.num > other.num except AttributeError: return self.num > other def __le__(self, other): """Less than or equal to test. """ try: return self.num <= other.num except AttributeError: return self.num <= other def __ge__(self, other): """Greater than or equal to test. """ try: return self.num >= other.num except AttributeError: return self.num >= other def __add__(self, other): """Addition operator. """ try: return self.num + other.num except AttributeError: return self.num + other def __radd__(self, other): """Reverse addition operator. """ return other + self.num def __sub__(self, other): """Subtraction operator. """ try: return self.num - other.num except AttributeError: return self.num - other def __rsub__(self, other): """Reverse subtraction operator. """ return other - self.num def __mul__(self, other): """Multiplication operator. """ try: return self.num * other.num except AttributeError: return self.num * other def __rmul__(self, other): """Reverse multiplication operator. """ return other * self.num def __truediv__(self, other): """True division operator. """ try: return self.num / other.num except AttributeError: return self.num / other def __rtruediv__(self, other): """Reverse true division operator. """ return other / self.num def __floordiv__(self, other): """Floor division operator. """ try: return self.num // other.num except AttributeError: return self.num // other def __rfloordiv__(self, other): """Reverse floor division operator. """ return other // self.num def __int__(self): """Return integer value. """ return int(self.num) def __float__(self): """Return float value. """ return float(self.num) def __round__(self): """Return rounded value. """ return round(self.num) def __hash__(self): """Allow use as dictionary key. """ return hash(self.num) ######### Utility Functions ########## def _doubleSplit(sepChars, string): """Return tuple of string split in two, separated by one of sepChars. Returns a tuple, size 2, with the second entry empty if no sep found. Arguments: sepChars -- a string of separator characters string -- the string to split """ for sep in sepChars: result = string.split(sep, 1) if len(result) == 2: return result return (string, '') def _getRadix(strFormat): """Return the radix character (. or ,) used in format. Infers from use of slashed separators and non-slashed radix. Assumes radix is "." if ambiguous. Arguments: strFormat -- the string format to evaluate """ if not r'\,' in strFormat and (r'\.' in strFormat or (',' in strFormat and not '.' in strFormat)): return ',' return '.' def _unescapeFormat(radix, strFormat): """Return format with escapes removed from non-radix separators. Arguments: radix -- the current radix character strFormat - the string format to modify """ if radix == '.': return strFormat.replace(r'\,', ',') return strFormat.replace(r'\.', '.') TreeLine-3.2.1/source/globalref.py000066400000000000000000000035531506556630100170500ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # globalref.py, provides a module for access to a few global variables # # TreeLine, an information storage program # Copyright (C) 2017, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** mainControl = None genOptions = None miscOptions = None histOptions = None toolbarOptions = None keyboardOptions = None toolIcons = None treeIcons = None localTextEncoding = '' lang = '' fileFilters = {'trlnopen': '{} (*.trln *.trln.gz *.trl)'. format(_('All TreeLine Files')), 'trlnv3': '{} (*.trln *.trln.gz)'.format(_('TreeLine Files')), 'trlnsave': '{} (*.trln)'.format(_('TreeLine Files')), 'trlngz': '{} (*.trln *.trln.gz)'. format(_('TreeLine Files - Compressed')), 'trlnenc': '{} (*.trln)'. format(_('TreeLine Files - Encrypted')), 'trl': '{} (*.trl *.xml)'.format(_('Old TreeLine Files')), 'all': '{} (*)'.format(_('All Files')), 'html': '{} (*.html *.htm)'.format(_('HTML Files')), 'txt': '{} (*.txt)'.format(_('Text Files')), 'xml': '{} (*.xml)'.format(_('XML Files')), 'csv': '{} (*.csv)'.format(_('CSV (Comma Delimited) Files')), 'odt': '{} (*.odt)'.format(_('ODF Text Files')), 'hjt': '{} (*.hjt)'.format(_('Treepad Files')), 'pdf': '{} (*.pdf)'.format(_('PDF Files'))} TreeLine-3.2.1/source/helpview.py000066400000000000000000000126051506556630100167340ustar00rootroot00000000000000#!/usr/bin/env python3 #**************************************************************************** # helpview.py, provides a window for viewing an html help file # # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #***************************************************************************** from PyQt6.QtCore import QUrl, Qt from PyQt6.QtGui import (QAction, QTextDocument) from PyQt6.QtWidgets import (QLabel, QLineEdit, QMainWindow, QMenu, QStatusBar, QTextBrowser) import dataeditors class HelpView(QMainWindow): """Main window for viewing an html help file. """ def __init__(self, pathObj, caption, icons, parent=None): """Helpview initialize with text. Arguments: pathObj -- a path object for the help file caption -- the window caption icons -- dict of view icons """ QMainWindow.__init__(self, parent) self.setAttribute(Qt.WidgetAttribute.WA_QuitOnClose, False) self.setWindowFlags(Qt.WindowType.Window) self.setStatusBar(QStatusBar()) self.textView = HelpViewer(self) self.setCentralWidget(self.textView) self.textView.setSearchPaths([str(pathObj.parent)]) self.textView.setSource(QUrl(pathObj.as_uri())) self.resize(520, 440) self.setWindowTitle(caption) tools = self.addToolBar(_('Tools')) self.menu = QMenu(self.textView) self.textView.highlighted.connect(self.showLink) backAct = QAction(_('&Back'), self) backAct.setIcon(icons['helpback']) tools.addAction(backAct) self.menu.addAction(backAct) backAct.triggered.connect(self.textView.backward) backAct.setEnabled(False) self.textView.backwardAvailable.connect(backAct.setEnabled) forwardAct = QAction(_('&Forward'), self) forwardAct.setIcon(icons['helpforward']) tools.addAction(forwardAct) self.menu.addAction(forwardAct) forwardAct.triggered.connect(self.textView.forward) forwardAct.setEnabled(False) self.textView.forwardAvailable.connect(forwardAct.setEnabled) homeAct = QAction(_('&Home'), self) homeAct.setIcon(icons['helphome']) tools.addAction(homeAct) self.menu.addAction(homeAct) homeAct.triggered.connect(self.textView.home) tools.addSeparator() tools.addSeparator() findLabel = QLabel(_(' Find: '), self) tools.addWidget(findLabel) self.findEdit = QLineEdit(self) tools.addWidget(self.findEdit) self.findEdit.textEdited.connect(self.findTextChanged) self.findEdit.returnPressed.connect(self.findNext) self.findPreviousAct = QAction(_('Find &Previous'), self) self.findPreviousAct.setIcon(icons['helpprevious']) tools.addAction(self.findPreviousAct) self.menu.addAction(self.findPreviousAct) self.findPreviousAct.triggered.connect(self.findPrevious) self.findPreviousAct.setEnabled(False) self.findNextAct = QAction(_('Find &Next'), self) self.findNextAct.setIcon(icons['helpnext']) tools.addAction(self.findNextAct) self.menu.addAction(self.findNextAct) self.findNextAct.triggered.connect(self.findNext) self.findNextAct.setEnabled(False) def showLink(self, url): """Send link text to the statusbar. Arguments: url -- the QUrl link to show """ self.statusBar().showMessage(url.toString()) def findTextChanged(self, text): """Update find controls based on text in text edit. Arguments: text -- the search text """ self.findPreviousAct.setEnabled(len(text) > 0) self.findNextAct.setEnabled(len(text) > 0) def findPrevious(self): """Command to find the previous string. """ if self.textView.find(self.findEdit.text(), QTextDocument.FindFlag.FindBackward): self.statusBar().clearMessage() else: self.statusBar().showMessage(_('Text string not found')) def findNext(self): """Command to find the next string. """ if self.textView.find(self.findEdit.text()): self.statusBar().clearMessage() else: self.statusBar().showMessage(_('Text string not found')) class HelpViewer(QTextBrowser): """Shows an html help file. """ def __init__(self, parent=None): """Initialize the viewer. Arguments: parent -- the parent widget, if given """ QTextBrowser.__init__(self, parent) def doSetSource(self, url, resType): """Called when user clicks on a URL. Arguments: url -- the clicked on QUrl """ name = url.toString() if name.startswith('http'): dataeditors.openExtUrl(name) else: super().doSetSource(url, resType) def contextMenuEvent(self, event): """Init popup menu on right click"". Arguments: event -- the menu event """ self.parentWidget().menu.exec(event.globalPos()) TreeLine-3.2.1/source/icondict.py000066400000000000000000000104621506556630100167040ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # icondict.py, provides a class to load and store icons # # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** from PyQt6.QtGui import QIcon, QPixmap _iconExtension = ('.png', '.bmp', '.ico', '.gif') defaultName = 'default' noneName = 'NoIcon' class IconDict(dict): """Loads and stores icons by name. """ def __init__(self, pathObjList, subPaths=None): """Set icon paths and initialize variables. The first potential path that has icons is used. Arguments: pathObjList -- a list of path objects to check for icons subPaths -- a list of optional subpaths under the base paths """ super().__init__() self.pathObjList = [] self.subPaths = [''] self.addIconPath(pathObjList, subPaths) self.allLoaded = False self[noneName] = None def addIconPath(self, pathObjList, subPaths=None): """Add an icon path and set the subPaths if given. Arguments: pathObjList -- a list of path objects to check for icons subPaths -- a list of optional subpaths under the base paths """ if subPaths: self.subPaths = subPaths for mainPath in pathObjList: for subPath in self.subPaths: dirPath = mainPath / subPath try: for fullPath in dirPath.iterdir(): pixmap = QPixmap(str(fullPath)) if not pixmap.isNull(): if mainPath not in self.pathObjList: self.pathObjList.append(mainPath) break except OSError: pass def getIcon(self, name, substitute=False): """Return an icon matching the name. Load the icon if it isn't already loaded. If not found, return None or substitute a default icon. Arguments: name -- the name of the icon to retrieve substitute -- if True, return a default icon if not found """ try: icon = self[name] except KeyError: icon = self.loadIcon(name) if not icon and substitute: icon = self.getIcon(defaultName) return icon def loadIcon(self, name): """Load an icon from the icon path, add to dict and return the icon. Return None if not found. Arguments: name -- the name of the icon to load """ icon = QIcon() for path in self.pathObjList: for ext in _iconExtension: fileName = name + ext for subPath in self.subPaths: pixmap = QPixmap(str(path.joinpath(subPath, fileName))) if not pixmap.isNull(): icon.addPixmap(pixmap) if not icon.isNull(): self[name] = icon return icon return None def loadIcons(self, nameList): """Load icons based on a name list. Arguments: nameList -- the list of names to load """ for name in nameList: self.loadIcon(name) def loadAllIcons(self): """Load all of the icons available on path list. """ self.clear() self[noneName] = None for mainPath in self.pathObjList: for subPath in self.subPaths: dirPath = mainPath / subPath try: for fullPath in dirPath.iterdir(): pixmap = QPixmap(str(fullPath)) if not pixmap.isNull(): name = fullPath.stem icon = self.setdefault(name, QIcon()) icon.addPixmap(pixmap) except OSError: pass self.allLoaded = True TreeLine-3.2.1/source/imports.py000066400000000000000000001263631506556630100166150ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # imports.py, provides classes for a file import dialog and import functions # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import pathlib import re import collections import zipfile import csv import html.parser import xml.sax.saxutils from xml.etree import ElementTree from PyQt6.QtCore import Qt from PyQt6.QtWidgets import QApplication, QDialog, QFileDialog, QMessageBox import miscdialogs import treenode import treestructure import treemodel import nodeformat import treeformats import urltools import globalref methods = collections.OrderedDict() methods.update([(_('Text'), None), (_('&Tab indented text, one node per line'), 'importTabbedText'), (_('Co&mma delimited (CSV) text table with level column && ' 'header row'), 'importTableCsvLevels'), (_('Comma delimited (CSV) text table &with header row'), 'importTableCsv'), (_('Tab delimited text table with header &row'), 'importTableTabbed'), (_('Plain text, one &node per line (CR delimited)'), 'importTextLines'), (_('Plain text ¶graphs (blank line delimited)'), 'importTextPara'), (_('Bookmarks'), None), (_('&HTML bookmarks (Mozilla Format)'), 'importMozilla'), (_('&XML bookmarks (XBEL format)'), 'importXbel'), (_('Other'), None), (_('Old Tree&Line File (1.x or 2.x)'), 'importOldTreeLine'), (_('Treepad &file (text nodes only)'), 'importTreePad'), (_('&Generic XML (non-TreeLine file)'), 'importXml'), (_('Open &Document (ODF) outline'), 'importOdfText')]) fileFilters = {'importTabbedText': 'txt', 'importTableCsvLevels': 'csv', 'importTableCsv': 'csv', 'importTableTabbed': 'txt', 'importTextLines': 'txt', 'importTextPara': 'txt', 'importMozilla': 'html', 'importXbel': 'xml', 'importOldTreeLine': 'trl', 'importTreePad': 'hjt', 'importXml': 'xml', 'importOdfText': 'odt'} oldDateTimeConv = {'d': '%-d', 'dd': '%d', 'ddd': '%a', 'dddd': '%A', 'M': '%-m', 'MM': '%m', 'MMM': '%b', 'MMMM': '%B', 'yy': '%y', 'yyyy': '%Y', 'H': '%-H', 'HH': '%H', 'h': '%-I', 'hh': '%I', 'm': '%-M', 'mm': '%M', 's': '%-S', 'ss': '%S', 'zzz': '%f', 'AP': '%p', 'ap': '%p'} bookmarkFolderTypeName = _('FOLDER') bookmarkLinkTypeName = _('BOOKMARK') bookmarkSeparatorTypeName = _('SEPARATOR') bookmarkLinkFieldName = _('Link') textFieldName = _('Text') genericXmlTextFieldName = 'Element_Data' htmlUnescapeDict = {'amp': '&', 'lt': '<', 'gt': '>', 'quot': '"'} class ImportControl: """Control file imports of alt file types. """ def __init__(self, pathObj=None): """Initialize the import control object. Arguments: pathObj -- the path object to import if given, o/w prompt user """ self.pathObj = pathObj self.errorMessage = '' # below members for old TreeLine file imports self.treeLineImportVersion = [] self.treeLineRootAttrib = {} self.treeLineOldFieldAttr = {} def interactiveImport(self, addWarning=False): """Prompt the user for import type & proceed with import. Return the structure if import is successful, otherwise None Arguments: addWarning - if True, add non-valid file warning to dialog """ dialog = miscdialogs.RadioChoiceDialog(_('Import File'), _('Choose Import Method'), methods.items(), QApplication. activeWindow()) if addWarning: fileName = self.pathObj.name dialog.addLabelBox(_('Invalid File'), _('"{0}" is not a valid TreeLine file.\n\n' 'Use an import filter?').format(fileName)) if dialog.exec() != QDialog.DialogCode.Accepted: return None method = dialog.selectedButton() if not self.pathObj: filters = ';;'.join((globalref.fileFilters[fileFilters[method]], globalref.fileFilters['all'])) defaultFilePath = str(globalref.mainControl.defaultPathObj(True)) filePath, selFltr = QFileDialog.getOpenFileName(QApplication. activeWindow(), _('TreeLine - Import File'), defaultFilePath, filters) if not filePath: return None self.pathObj = pathlib.Path(filePath) self.errorMessage = '' try: QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) structure = getattr(self, method)() QApplication.restoreOverrideCursor() except IOError: QApplication.restoreOverrideCursor() QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - could not read file {0}'). format(self.pathObj)) return None except UnicodeDecodeError: prevEncoding = globalref.localTextEncoding globalref.localTextEncoding = 'utf-8' structure = getattr(self, method)() globalref.localTextEncoding = prevEncoding QApplication.restoreOverrideCursor() if not structure: message = _('Error - improper format in {0}').format(self.pathObj) if self.errorMessage: message = '{0}\n{1}'.format(message, self.errorMessage) self.errorMessage = '' QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', message) return structure def importTabbedText(self): """Import a file with tabbed title structure. Return the structure if import is successful, otherwise None """ structure = treestructure.TreeStructure(addDefaults=True, addSpots=False) formatRef = structure.childList[0].formatRef structure.removeNodeDictRef(structure.childList[0]) structure.childList = [] nodeList = [] with self.pathObj.open(encoding=globalref.localTextEncoding) as f: for line in f: text = line.strip() if text: level = line.count('\t', 0, len(line) - len(line.lstrip())) node = treenode.TreeNode(formatRef) node.setTitle(text) structure.addNodeDictRef(node) nodeList.append((node, level)) if nodeList and structure.loadChildNodeLevels(nodeList): structure.generateSpots(None) return structure return None def importTableCsvLevels(self): """Import a CSV-delimited table file with level column, header row. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure(addSpots=False) tableFormat = nodeformat.NodeFormat(_('TABLE'), structure.treeFormats) structure.treeFormats.addTypeIfMissing(tableFormat) nodeList = [] with self.pathObj.open(newline='', encoding=globalref.localTextEncoding) as f: reader = csv.reader(f) try: headings = [self.correctFieldName(name) for name in next(reader)][1:] if not headings: self.errorMessage = (_('No headings found')); return None # abort tableFormat.addFieldList(headings, True, True) for entries in reader: if entries: node = treenode.TreeNode(tableFormat) structure.addNodeDictRef(node) try: level = int(entries.pop(0)) except ValueError: self.errorMessage = (_('Invalid level number on ' 'line {0}'). format(reader.line_num)) return None # abort nodeList.append((node, level)) try: for heading in headings: node.data[heading] = entries.pop(0) except IndexError: pass # fewer entries than headings is OK if entries: self.errorMessage = (_('Too many entries on ' 'Line {0}'). format(reader.line_num)) return None # abort if too few headings except csv.Error: self.errorMessage = (_('Bad CSV format on Line {0}'). format(reader.line_num)) return None # abort if nodeList: if structure.loadChildNodeLevels(nodeList): structure.generateSpots(None) return structure self.errorMessage = (_('Invalid level structure')) return None def importTableCsv(self): """Import a file with a CSV-delimited table with header row. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure(addDefaults=True, addSpots=False) tableFormat = nodeformat.NodeFormat(_('TABLE'), structure.treeFormats) structure.treeFormats.addTypeIfMissing(tableFormat) with self.pathObj.open(newline='', encoding=globalref.localTextEncoding) as f: reader = csv.reader(f) try: headings = [self.correctFieldName(name) for name in next(reader)] if not headings: self.errorMessage = (_('No headings found')); return None # abort tableFormat.addFieldList(headings, True, True) for entries in reader: if entries: node = treenode.TreeNode(tableFormat) structure.childList[0].childList.append(node) structure.addNodeDictRef(node) try: for heading in headings: node.data[heading] = entries.pop(0) except IndexError: pass # fewer entries than headings is OK if entries: self.errorMessage = (_('Too many entries on ' 'Line {0}'). format(reader.line_num)) return None # abort if too few headings except csv.Error: self.errorMessage = (_('Bad CSV format on Line {0}'). format(reader.line_num)) return None # abort structure.generateSpots(None) return structure def importTableTabbed(self): """Import a file with a tab-delimited table with header row. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure(addDefaults=True, addSpots=False) tableFormat = nodeformat.NodeFormat(_('TABLE'), structure.treeFormats) structure.treeFormats.addTypeIfMissing(tableFormat) with self.pathObj.open(encoding=globalref.localTextEncoding) as f: headings = [self.correctFieldName(name) for name in f.readline().split('\t')] tableFormat.addFieldList(headings, True, True) lineNum = 1 for line in f: lineNum += 1 if line.strip(): entries = line.split('\t') node = treenode.TreeNode(tableFormat) structure.childList[0].childList.append(node) structure.addNodeDictRef(node) try: for heading in headings: node.data[heading] = entries.pop(0) except IndexError: pass # fewer entries than headings is OK if entries: self.errorMessage = (_('Too many entries on Line {0}'). format(lineNum)) return None # abort if too few headings structure.generateSpots(None) return structure @staticmethod def correctFieldName(name): """Return the field name with any illegal characters removed. Arguments: name -- the name to modify """ name = re.sub(r'[^\w_\-.]', '_', name.strip()) if not name: return 'X' if not name[0].isalpha() or name[:3].lower() == 'xml': name = 'X' + name return name def importTextLines(self): """Import a text file, creating one node per line. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure(addDefaults=True, addSpots=False) nodeFormat = structure.childList[0].formatRef structure.removeNodeDictRef(structure.childList[0]) structure.childList = [] with self.pathObj.open(encoding=globalref.localTextEncoding) as f: for line in f: line = line.strip() if line: node = treenode.TreeNode(nodeFormat) structure.childList.append(node) structure.addNodeDictRef(node) node.data[nodeformat.defaultFieldName] = line structure.generateSpots(None) return structure def importTextPara(self): """Import a text file, creating one node per paragraph. Blank line delimited. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure(addDefaults=True, addSpots=False) nodeFormat = structure.childList[0].formatRef structure.removeNodeDictRef(structure.childList[0]) structure.childList = [] with self.pathObj.open(encoding=globalref.localTextEncoding) as f: text = f.read() paraList = text.split('\n\n') for para in paraList: para = para.strip() if para: node = treenode.TreeNode(nodeFormat) structure.childList.append(node) structure.addNodeDictRef(node) node.data[nodeformat.defaultFieldName] = para structure.generateSpots(None) return structure def importOldTreeLine(self): """Import an old TreeLine File (1.x or 2.x). Return the structure if import is successful, otherwise None. """ tree = ElementTree.ElementTree() try: tree.parse(str(self.pathObj)) except ElementTree.ParseError: tree = None if not tree or not tree.getroot().get('item') == 'y': fileObj = self.pathObj.open('rb') # decompress before decrypt to support TreeLine 1.4 and earlier fileObj, compressed = globalref.mainControl.decompressFile(fileObj) fileObj, encrypted = globalref.mainControl.decryptFile(fileObj) if not fileObj: return None if encrypted and not compressed: fileObj, compressed = (globalref.mainControl. decompressFile(fileObj)) if compressed or encrypted: tree = ElementTree.ElementTree() try: tree.parse(fileObj) except ElementTree.ParseError: tree = None fileObj.close() if not tree or not tree.getroot().get('item') == 'y': return None version = tree.getroot().get('tlversion', '').split('.') try: self.treeLineImportVersion = [int(i) for i in version] except ValueError: pass self.treeLineRootAttrib = self.convertPrintData(tree.getroot().attrib) structure = treestructure.TreeStructure() idRefDict = {} linkList = [] self.loadOldTreeLineNode(tree.getroot(), structure, idRefDict, linkList, None) self.convertOldNodes(structure) linkRe = re.compile(r']*href="#(.*?)"[^>]*>.*?', re.I | re.S) for node, fieldName in linkList: text = node.data[fieldName] startPos = 0 while True: match = linkRe.search(text, startPos) if not match: break newId = idRefDict.get(match.group(1), '') if newId: text = text[:match.start(1)] + newId + text[match.end(1):] startPos = match.start(1) node.data[fieldName] = text structure.generateSpots(None) if nodeformat.FileInfoFormat.typeName in structure.treeFormats: fileFormat = structure.treeFormats[nodeformat.FileInfoFormat. typeName] structure.treeFormats.fileInfoFormat.duplicateFileInfo(fileFormat) del structure.treeFormats[nodeformat.FileInfoFormat.typeName] structure.treeFormats.updateDerivedRefs() for nodeFormat in structure.treeFormats.values(): nodeFormat.updateLineParsing() return structure def loadOldTreeLineNode(self, element, structure, idRefDict, linkList, parent=None): """Recursively load an old TreeLine ElementTree node and its children. Arguments: element -- an ElementTree node structure -- a ref to the new tree structure idRefDict -- a dict to relate old to new unique node IDs linkList -- internal link list ref with (node, fieldname) tuples parent -- the parent TreeNode (None for the root node only) """ try: typeFormat = structure.treeFormats[element.tag] except KeyError: formatData = self.convertOldNodeFormat(element.attrib) typeFormat = nodeformat.NodeFormat(element.tag, structure.treeFormats, formatData) structure.treeFormats[element.tag] = typeFormat self.treeLineOldFieldAttr[typeFormat.name] = {} if element.get('item') == 'y': node = treenode.TreeNode(typeFormat) oldId = element.attrib.get('uniqueid', '') if oldId: idRefDict[oldId] = node.uId if parent: parent.childList.append(node) else: structure.childList.append(node) structure.nodeDict[node.uId] = node cloneAttr = element.attrib.get('clones', '') if cloneAttr: for cloneId in cloneAttr.split(','): if cloneId in idRefDict: cloneNode = structure.nodeDict[idRefDict[cloneId]] node.data = cloneNode.data.copy() break else: # bare format (no nodes) node = None for child in element: if child.get('item') and node: self.loadOldTreeLineNode(child, structure, idRefDict, linkList, node) else: if node and child.text: node.data[child.tag] = child.text if child.get('linkcount'): linkList.append((node, child.tag)) if child.tag not in typeFormat.fieldDict: fieldData = self.convertOldFieldFormat(child.attrib) oldFormatDict = self.treeLineOldFieldAttr[typeFormat.name] oldFormatDict[child.tag] = fieldData typeFormat.addField(child.tag, fieldData) def convertPrintData(self, attrib): """Return JSON print data from old root attributes. Arguments: attrib -- old root print data attributes """ for key in ('printlines', 'printwidowcontrol', 'printportrait'): if key in attrib: attrib[key] = not attrib[key].startswith('n') for key in ('printindentfactor', 'printpaperwidth', 'printpaperheight', 'printheadermargin', 'printfootermargin', 'printcolumnspace'): if key in attrib: attrib[key] = float(attrib[key]) if 'printmargins' in attrib: attrib['printmargins'] = [float(margin) for margin in attrib['printmargins'].split()] if 'printnumcolumns' in attrib: attrib['printnumcolumns'] = int(attrib['printnumcolumns']) return attrib def convertOldNodeFormat(self, attrib): """Return JSON format data from old node format attributes. Arguments: attrib -- old node format attrib dict """ for key in ('spacebetween', 'formathtml', 'bullets', 'tables'): if key in attrib: attrib[key] = attrib[key].startswith('y') attrib['titleline'] = attrib.get('line0', '') lineKeyRe = re.compile(r'line\d+$') lineNums = sorted([int(key[4:]) for key in attrib.keys() if lineKeyRe.match(key)]) if lineNums and lineNums[0] == 0: del lineNums[0] attrib['outputlines'] = [attrib['line{0}'.format(keyNum)] for keyNum in lineNums] if self.treeLineImportVersion < [1, 9]: # for very old TL versions attrib['spacebetween'] = not (self.treeLineRootAttrib. get('nospace', '').startswith('y')) attrib['formathtml'] = not (self.treeLineRootAttrib. get('nohtml', '').startswith('y')) return attrib def convertOldFieldFormat(self, attrib): """Return JSON format data from old field format attributes. Arguments: attrib -- old field node format attrib dict """ fieldType = attrib.get('type', '') if fieldType: attrib['fieldtype'] = fieldType fieldFormat = attrib.get('format', '') if self.treeLineImportVersion < [1, 9]: # for very old TL versions if fieldType in ('URL', 'Path', 'ExecuteLink', 'Email'): attrib['oldfieldtype'] = fieldType fieldType = 'ExternalLink' attrib['fieldtype'] = fieldType if fieldType == 'Date': fieldFormat = fieldFormat.replace('w', 'd') fieldFormat = fieldFormat.replace('m', 'M') if fieldType == 'Time': fieldFormat = fieldFormat.replace('M', 'm') fieldFormat = fieldFormat.replace('s', 'z') fieldFormat = fieldFormat.replace('S', 's') fieldFormat = fieldFormat.replace('AA', 'AP') fieldFormat = fieldFormat.replace('aa', 'ap') if 'lines' in attrib: attrib['lines'] = int(attrib['lines']) if 'sortkeynum' in attrib: attrib['sortkeynum'] = int(attrib['sortkeynum']) if 'sortkeydir' in attrib: attrib['sortkeyfwd'] = not attrib['sortkeydir'].startswith('r') if 'evalhtml' in attrib: attrib['evalhtml'] = attrib['evalhtml'].startswith('y') if fieldType in ('Date', 'Time', 'DateTime'): origFormat = fieldFormat fieldFormat = '' while origFormat: replLen = 4 while replLen > 0: if origFormat[:replLen] in oldDateTimeConv: fieldFormat += oldDateTimeConv[origFormat[:replLen]] origFormat = origFormat[replLen:] break replLen -= 1 if replLen == 0: fieldFormat += origFormat[0] origFormat = origFormat[1:] if fieldFormat: attrib['format'] = fieldFormat return attrib def convertOldNodes(self, structure): """Convert node data to new date and time formats. Arguments: structure -- the ref structure containing the data """ for node in structure.nodeDict.values(): for field in node.formatRef.fields(): text = node.data.get(field.name, '') if text: if field.typeName in ('Date', 'DateTime'): text = text.replace('/', '-') if field.typeName in ('Time', 'DateTime'): text = text + '.000000' if self.treeLineImportVersion < [1, 9]: # very old TL ver oldFormatDict = self.treeLineOldFieldAttr[node. formatRef.name] oldFieldAttr = oldFormatDict[field.name] if (field.typeName == 'Text' and not oldFieldAttr.get('html', '').startswith('y')): text = text.strip() text = xml.sax.saxutils.escape(text) text = text.replace('\n', '
    ') elif (field.typeName == 'ExternalLink' and oldFieldAttr.get('oldfieldtype', '')): oldType = oldFieldAttr['oldfieldtype'] linkAltField = oldFieldAttr.get('linkalt', '') dispName = node.data.get(linkAltField, '') if not dispName: dispName = text if oldType == 'URL': if not urltools.extractScheme(text): text = urltools.replaceScheme('http', text) elif oldType == 'Path': text = urltools.replaceScheme('file', text) elif oldType == 'ExecuteLink': if urltools.isRelative(text): fullPath = urltools.which(text) if fullPath: text = fullPath text = urltools.replaceScheme('file', text) elif oldType == 'Email': text = urltools.replaceScheme('mailto', text) text = '{1}'.format(text, dispName) elif field.typeName == 'InternalLink': linkAltField = oldFieldAttr.get('linkalt', '') dispName = node.data.get(linkAltField, '') if not dispName: dispName = text uniqueId = text.strip().split('\n', 1)[0] uniqueId = uniqueId.replace(' ', '_').lower() uniqueId = re.sub(r'[^a-zA-Z0-9_-]+', '', uniqueId) text = '{1}'.format(uniqueId, dispName) elif field.typeName == 'Picture': text = ''.format(text) node.data[field.name] = text def importTreePad(self): """Import a Treepad file, text nodes only. Return the model if import is successful, otherwise None. """ structure = treestructure.TreeStructure(addDefaults=True, addSpots=False) structure.removeNodeDictRef(structure.childList[0]) structure.childList = [] tpFormat = structure.treeFormats[treeformats.defaultTypeName] tpFormat.addFieldList([textFieldName], False, True) tpFormat.fieldDict[textFieldName].changeType('SpacedText') try: with self.pathObj.open(encoding=globalref.localTextEncoding) as f: textList = f.read().split(' 5P9i0s8y19Z') except UnicodeDecodeError: with self.pathObj.open(encoding='latin-1') as f: textList = f.read().split(' 5P9i0s8y19Z') except UnicodeDecodeError: return None nodeList = [] for text in textList: text = text.strip() if text: try: text = text.split('', 1)[1].lstrip() lines = text.split('\n') title = lines[0] level = int(lines[1]) lines = lines[2:] except (ValueError, IndexError): return None node = treenode.TreeNode(tpFormat) node.data[nodeformat.defaultFieldName] = title node.data[textFieldName] = '\n'.join(lines) node.level = level nodeList.append(node) structure.addNodeDictRef(node) parentList = [] for node in nodeList: if node.level != 0: parentList = parentList[:node.level] node.parent = parentList[-1] parentList[-1].childList.append(node) parentList.append(node) structure.childList = [nodeList[0]] structure.generateSpots(None) return structure def importXml(self): """Import a non-treeline generic XML file. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure() tree = ElementTree.ElementTree() try: tree.parse(str(self.pathObj)) self.loadXmlNode(tree.getroot(), structure, None) except ElementTree.ParseError: return None for elemFormat in structure.treeFormats.values(): if not elemFormat.getTitleLine(): # fix formats if required elemFormat.changeTitleLine(elemFormat.name) for fieldName in elemFormat.fieldNames(): elemFormat.addOutputLine('{0}="{{*{1}*}}"'. format(fieldName, fieldName)) if not elemFormat.fieldDict: elemFormat.addField(genericXmlTextFieldName) if structure.childList: structure.generateSpots(None) return structure return None def loadXmlNode(self, element, structure, parent=None): """Recursively load a generic XML ElementTree node and its children. Arguments: element -- an XML ElementTree node structure -- a ref to the TreeLine structure parent -- the parent TreeNode (None for the root node only) """ elemFormat = structure.treeFormats.get(element.tag, None) if not elemFormat: elemFormat = nodeformat.NodeFormat(element.tag, structure.treeFormats) structure.treeFormats[element.tag] = elemFormat node = treenode.TreeNode(elemFormat) structure.addNodeDictRef(node) if not parent: parent = structure parent.childList.append(node) if element.text and element.text.strip(): if genericXmlTextFieldName not in elemFormat.fieldDict: elemFormat.addFieldList([genericXmlTextFieldName], True, True) text = element.text.strip() text = xml.sax.saxutils.escape(text) text = text.replace('\n', '
    ') node.data[genericXmlTextFieldName] = text for key, value in element.items(): elemFormat.addFieldIfNew(key) node.data[key] = value for child in element: self.loadXmlNode(child, structure, node) def importOdfText(self): """Import an ODF format text file outline. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure(addDefaults=True, addSpots=False) structure.removeNodeDictRef(structure.childList[0]) structure.childList = [] odfFormat = structure.treeFormats[treeformats.defaultTypeName] odfFormat.addField(textFieldName) odfFormat.changeOutputLines(['{{*{0}*}}'. format(nodeformat.defaultFieldName), '{{*{0}*}}'.format(textFieldName)]) odfFormat.formatHtml = True try: with zipfile.ZipFile(str(self.pathObj), 'r') as f: text = f.read('content.xml') except (zipfile.BadZipFile, KeyError): return None try: rootElement = ElementTree.fromstring(text) except ElementTree.ParseError: return None nameSpace = '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}' headerTag = '{0}h'.format(nameSpace) paraTag = '{0}p'.format(nameSpace) numRegExp = re.compile(r'.*?(\d+)$') parents = [structure] prevLevel = 0 for elem in rootElement.iter(): if elem.tag == headerTag: style = elem.get('{0}style-name'.format(nameSpace), '') try: level = int(numRegExp.match(style).group(1)) except AttributeError: return None if level < 1 or level > prevLevel + 1: return None parents = parents[:level] node = treenode.TreeNode(odfFormat) structure.addNodeDictRef(node) parents[-1].childList.append(node) node.data[nodeformat.defaultFieldName] = ''.join(elem. itertext()) parents.append(node) prevLevel = level elif elem.tag == paraTag: text = ''.join(elem.itertext()) origText = node.data.get(textFieldName, '') if origText: text = '{0}
    {1}'.format(origText, text) node.data[textFieldName] = text structure.generateSpots(None) return structure def createBookmarkFormat(self): """Return a set of node formats for bookmark imports. """ treeFormats = treeformats.TreeFormats() folderFormat = nodeformat.NodeFormat(bookmarkFolderTypeName, treeFormats, addDefaultField=True) folderFormat.iconName = 'folder_3' treeFormats[folderFormat.name] = folderFormat linkFormat = nodeformat.NodeFormat(bookmarkLinkTypeName, treeFormats, addDefaultField=True) linkFormat.addField(bookmarkLinkFieldName, {'fieldtype': 'ExternalLink'}) linkFormat.addOutputLine('{{*{0}*}}'.format(bookmarkLinkFieldName)) linkFormat.iconName = 'bookmark' treeFormats[linkFormat.name] = linkFormat sepFormat = nodeformat.NodeFormat(bookmarkSeparatorTypeName, treeFormats, {'formathtml': True}, True) sepFormat.changeTitleLine('------------------') sepFormat.changeOutputLines(['
    ']) treeFormats[sepFormat.name] = sepFormat return treeFormats def importMozilla(self): """Import an HTML mozilla-format bookmark file. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure() structure.treeFormats = self.createBookmarkFormat() with self.pathObj.open(encoding='utf-8') as f: text = f.read() try: handler = HtmlBookmarkHandler(structure) handler.feed(text) handler.close() except ValueError: return None structure.generateSpots(None) return structure def importXbel(self): """Import an XBEL format bookmark file. Return the structure if import is successful, otherwise None. """ structure = treestructure.TreeStructure() structure.treeFormats = self.createBookmarkFormat() tree = ElementTree.ElementTree() try: tree.parse(str(self.pathObj)) except ElementTree.ParseError: return None self.loadXbelNode(tree.getroot(), structure, None) if structure.childList: structure.generateSpots(None) return structure return None def loadXbelNode(self, element, structure, parent=None): """Recursively load an XBEL ElementTree node and its children. Arguments: element -- an XBEL ElementTree node model -- a ref to the TreeLine model parent -- the parent TreeNode (None for the root node only) """ if element.tag in ('xbel', 'folder'): node = treenode.TreeNode(structure. treeFormats[bookmarkFolderTypeName]) structure.addNodeDictRef(node) if parent: parent.childList.append(node) else: structure.childList.append(node) for child in element: self.loadXbelNode(child, structure, node) elif element.tag == 'bookmark': node = treenode.TreeNode(structure. treeFormats[bookmarkLinkTypeName]) structure.addNodeDictRef(node) parent.childList.append(node) link = element.get('href').strip() if link: node.data[bookmarkLinkFieldName] = ('{1}'. format(link, link)) for child in element: self.loadXbelNode(child, structure, node) elif element.tag == 'title': parent.setTitle(element.text) elif element.tag == 'separator': node = treenode.TreeNode(structure. treeFormats[bookmarkSeparatorTypeName]) structure.addNodeDictRef(node) parent.childList.append(node) else: # unsupported tags pass class HtmlBookmarkHandler(html.parser.HTMLParser): """Handler to parse HTML mozilla bookmark format. """ def __init__(self, structure): """Initialize the HTML parser object. Arguments: structure -- a reference to the tree structure """ super().__init__() self.structure = structure rootNode = treenode.TreeNode(self.structure. treeFormats[bookmarkFolderTypeName]) rootNode.data[nodeformat.defaultFieldName] = _('Bookmarks') self.structure.addNodeDictRef(rootNode) self.structure.childList = [rootNode] self.currentNode = rootNode self.parents = [] self.text = '' def handle_starttag(self, tag, attrs): """Called by the reader at each open tag. Arguments: tag -- the tag label attrs -- any tag attributes """ if tag == 'dt' or tag == 'h1': # start any entry self.text = '' elif tag == 'dl': # start indent self.parents.append(self.currentNode) self.currentNode = None elif tag == 'h3': # start folder if not self.parents: raise ValueError self.currentNode = treenode.TreeNode(self.structure. treeFormats[bookmarkFolderTypeName]) self.structure.addNodeDictRef(self.currentNode) self.parents[-1].childList.append(self.currentNode) elif tag == 'a': # start link if not self.parents: raise ValueError self.currentNode = treenode.TreeNode(self.structure. treeFormats[bookmarkLinkTypeName]) self.structure.addNodeDictRef(self.currentNode) self.parents[-1].childList.append(self.currentNode) for name, value in attrs: if name == 'href': link = '{0}'.format(value) self.currentNode.data[bookmarkLinkFieldName] = link elif tag == 'hr': # separator if not self.parents: raise ValueError node = treenode.TreeNode(self.structure. treeFormats[bookmarkSeparatorTypeName]) self.structure.addNodeDictRef(node) self.parents[-1].childList.append(node) self.currentNode = None def handle_endtag(self, tag): """Called by the reader at each end tag. Arguments: tag -- the tag label """ if tag == 'dl': # end indented section self.parents = self.parents[:-1] self.currentNode = None elif tag == 'h3' or tag == 'a': # end folder or link if not self.currentNode: raise ValueError self.currentNode.data[nodeformat.defaultFieldName] = self.text elif tag == 'h1': # end main title self.structure.childList[0].data[nodeformat. defaultFieldName] = self.text def handle_data(self, data): """Called by the reader to process text. Arguments: data -- the new text """ self.text += data def handle_entityref(self, name): """Convert escaped entity ref to char. Arguments: name -- the name of the escaped entity """ self.text += htmlUnescapeDict.get(name, '') TreeLine-3.2.1/source/matheval.py000066400000000000000000000525031506556630100167130ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # matheval.py, provides a safe eval of mathematical expressions # # TreeLine, an information storage program # Copyright (C) 2020, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import ast import enum import datetime import builtins import fieldformat import gennumber from math import * _nowDateString = 'Now_Date' _nowTimeString = 'Now_Time' _nowDateTimeString = 'Now_Date_Time' def sum(*args): """Override the builtin sum function to handle multiple arguments. Arguments: *args -- lists of numbers or individual numbers """ fullList = [] for arg in args: if hasattr(arg, 'extend'): fullList.extend(arg) else: fullList.append(arg) return builtins.sum(fullList) def max(*args): """Override the builtin max function to expand list arguments. Arguments: *args -- lists of numbers or individual numbers """ fullList = [] for arg in args: if hasattr(arg, 'extend'): fullList.extend(arg) else: fullList.append(arg) if not fullList: return 0 return builtins.max(fullList) def min(*args): """Override the builtin min function to expand list arguments. Arguments: *args -- lists of numbers or individual numbers """ fullList = [] for arg in args: if hasattr(arg, 'extend'): fullList.extend(arg) else: fullList.append(arg) if not fullList: return 0 return builtins.min(fullList) def mean(*args): """Added function to calculate the arithmetic average. Arguments: *args -- lists of numbers or individual numbers """ fullList = [] for arg in args: if hasattr(arg, 'extend'): fullList.extend(arg) else: fullList.append(arg) if not fullList: return 0 return builtins.sum(fullList) / len(fullList) # don't use pow() function from math library pow = builtins.pow def startswith(text, firstText): """Added compare function, returns true if text starts with firstText. Arguments: text -- the string to check firstText -- the starting text """ return str(text).startswith(str(firstText)) def endswith(text, firstText): """Added compare function, returns true if text ends with firstText. Arguments: text -- the string to check firstText -- the ending text """ return str(text).endswith(str(firstText)) def contains(text, innerText): """Added compare function, returns true if text contains innerText. Arguments: text -- the string to check innerText -- the inside text """ return str(innerText) in str(text) def join(sep, *args): """Added text function to combine strings. Arguments: sep -- the separator string *args -- lists of strings or individual strings to combine """ fullList = [] for arg in args: if hasattr(arg, 'extend'): fullList.extend(arg) else: fullList.append(arg) return sep.join([str(i) for i in fullList if str(i)]) def upper(text): """Added text function for upper case. Arguments: text -- the string to modify """ return str(text).upper() def lower(text): """Added text function for lower case. Arguments: text -- the string to modify """ return str(text).lower() def replace(text, oldText, newText): """Added text function to replace strings. Arguments: text -- the string to modify oldText -- the string to be replaced newText -- the replacement string """ return str(text).replace(str(oldText), str(newText)) def count(text): """Added text function to count words. Arguments: text -- the string to analyze """ return len(re.findall(r'\w+', str(text))) _fieldSplitRe = re.compile(r'{\*(\*|\$|&|#|\b)([\w_\-.]+)\*}') class MathEquation: """Class to parse, check, store and evaluate a Math field equation. """ def __init__(self, eqnText=''): """Initialize the MathEquation. Arguments: eqnText -- the text of an equation to be parsed """ self.fieldRefs = [] self.formattedEqnText = '' self.parseEquation(eqnText) def equationText(self): """Return the text representation of the equation. """ fieldNames = ['{{*{0}{1}*}}'.format(ref.tagPrefix, ref.fieldName) for ref in self.fieldRefs] return self.formattedEqnText.format(*fieldNames) def validate(self): """Check if the equation is valid (or empty). Use ones as fake input and use ast to verify legality. Raises a ValueError if the equation is not valid. """ if not self.formattedEqnText: return inputs = [ref.testValue for ref in self.fieldRefs] checker = SafeEvalChecker() try: eqn = self.formattedEqnText.format(*inputs) except IndexError: raise ValueError(_('Illegal "{}" characters')) except KeyError: raise ValueError(_('Invalid field modifiers')) checker.check(eqn) try: result = eval(eqn) if isinstance(result, list): raise TypeError('list result not allowed') except NameError as err: raise ValueError(err) except TypeError as err: if 'list' in str(err) and '&' in [ref.tagPrefix for ref in self.fieldRefs]: msg = _('Child references must be combined in a function') raise ValueError(msg) except ZeroDivisionError: pass def equationValue(self, eqnNode, resultType, zeroValue=0, noMarkup=True): """Return a value for the equation in the given node. Return None if references are invalid. Raise a ValueError for illegal math operations. Arguments: eqnNode -- the node containing the equation to evaluate resultType -- the result type from fieldformat zeroValue -- the value to use for blanks noMarkup -- if true, remove html markup """ zeroBlanks = eqnNode.treeStructureRef().mathZeroBlanks checker = SafeEvalChecker() inputs = [] for ref in self.fieldRefs: inp = ref.referenceValue(eqnNode, zeroBlanks, zeroValue, noMarkup) if inp == None and not zeroBlanks: return None if (resultType == fieldformat.MathResult.number and hasattr(inp, 'format')): try: checker.check(inp) inp = eval(inp) except Exception: inp = repr(inp) else: inp = repr(inp) inputs.append(inp) eqn = self.formattedEqnText.format(*inputs) try: return eval(eqn) except Exception as err: raise ValueError(err) def parseEquation(self, eqnText): """Replace the stored equation by parsing the given text. Creates formatted equation text and a list of field references. Arguments: eqnText -- the text of an equation to be parsed """ self.fieldRefs = [] self.formattedEqnText = _fieldSplitRe.sub(self._replFunc, eqnText) def _replFunc(self, matchObj): """Adds a field ref for each field match from the parser. Returns a string format placeholder as the replacement text. Arguments: matchObj -- the field match object """ fieldRefType = matchObj.group(1) fieldRefName = matchObj.group(2) fieldRefSelector = {'': EquationFieldRef, '*': EquationParentRef, '$': EquationRootRef, '&': EquationChildRef, '#': EquationChildCountRef} fieldRef = fieldRefSelector[fieldRefType](fieldRefName) self.fieldRefs.append(fieldRef) return '{}' # recursive equation ref eval directions EvalDir = enum.IntEnum('EvalDir', 'downward upward optional') class EquationFieldRef: """Class to store and eval individual field references in a Math equation. This base class handles references within the same node. """ tagPrefix = '' testValue = 1 evalDirection = EvalDir.optional def __init__(self, fieldName): """Initialize the field references. Arguments: fieldName -- the name of the referenced field """ self.fieldName = fieldName self.eqnNodeTypeName = '' self.eqnFieldName = '' def referenceValue(self, eqnNode, zeroBlanks=True, zeroValue=0, noMarkup=True): """Return the value of the field referenced in a given node. Return None if blank or doesn't exist and not zeroBlanks, raise a ValueError if it isn't a number. Arguments: eqnNode -- the node containing the equation to evaluate zeroBlanks -- replace blank fields with zeroValue if True zeroValue -- the value to use for blanks noMarkup -- if true, remove html markup """ try: return (eqnNode.formatRef.fieldDict[self.fieldName]. mathValue(eqnNode, zeroBlanks, noMarkup)) except KeyError: if self.fieldName == _nowDateString: return (datetime.date.today() - fieldformat.DateField.refDate).days elif self.fieldName == _nowTimeString: now = datetime.datetime.combine(fieldformat.DateField.refDate, datetime.datetime.now().time()) ref = datetime.datetime.combine(fieldformat.DateField.refDate, fieldformat.TimeField.refTime) return (now - ref).seconds elif self.fieldName == _nowDateTimeString: return (datetime.datetime.now() - fieldformat.DateTimeField.refDateTime).total_seconds() return zeroValue if zeroBlanks else None def dependentEqnNodes(self, refNode): """Return a list of equation node(s) that reference the given node. Arguments: refNode -- the node containing the referenced field """ if refNode.formatRef.name == self.eqnNodeTypeName: return [refNode] return [] class EquationParentRef(EquationFieldRef): """Class to store and eval parent field references in a Math equation. """ tagPrefix = '*' testValue = 1 evalDirection = EvalDir.downward def referenceValue(self, eqnNode, zeroBlanks=True, zeroValue=0, noMarkup=True): """Return the parent field value referenced from a given node. Return None if blank or doesn't exist and not zeroBlanks, raise a ValueError if it isn't a number. Arguments: eqnNode -- the node containing the equation to evaluate zeroBlanks -- replace blank fields with zeroValue if True zeroValue -- the value to use for blanks noMarkup -- if true, remove html markup """ node = eqnNode.spotByNumber(0).parentSpot.nodeRef if not node.formatRef: return zeroValue if zeroBlanks else None try: return (node.formatRef.fieldDict[self.fieldName]. mathValue(node, zeroBlanks, noMarkup)) except KeyError: return zeroValue if zeroBlanks else None def dependentEqnNodes(self, refNode): """Return a list of equation node(s) that reference the given node. Arguments: refNode -- the node containing the referenced field """ return [node for node in refNode.childList if node.formatRef.name == self.eqnNodeTypeName] class EquationRootRef(EquationFieldRef): """Class to store and eval root node field references in a Math equation. """ tagPrefix = '$' testValue = 1 evalDirection = EvalDir.downward def referenceValue(self, eqnNode, zeroBlanks=True, zeroValue=0, noMarkup=True): """Return the root field value referenced from a given node. Return None if blank or doesn't exist and not zeroBlanks, raise a ValueError if it isn't a number. Arguments: eqnNode -- the node containing the equation to evaluate zeroBlanks -- replace blank fields with zeroValue if True zeroValue -- the value to use for blanks noMarkup -- if true, remove html markup """ node = eqnNode.spotByNumber(0).spotChain()[0].nodeRef try: return (node.formatRef.fieldDict[self.fieldName]. mathValue(node, zeroBlanks, noMarkup)) except KeyError: return zeroValue if zeroBlanks else None def dependentEqnNodes(self, refNode): """Return a list of equation node(s) that reference the given node. Arguments: refNode -- the node containing the referenced field """ if 1 not in {len(spot.spotChain()) for spot in refNode.spotRefs}: # not a root node return [] refs = [node for node in refNode.descendantGen() if node.formatRef.name == self.eqnNodeTypeName] if refs and refs[0] is refNode: refs = refs[1:] return refs class EquationChildRef(EquationFieldRef): """Class to store and eval child field references in a Math equation. """ tagPrefix = '&' testValue = [1] evalDirection = EvalDir.upward def referenceValue(self, eqnNode, zeroBlanks=True, zeroValue=0, noMarkup=True): """Return a list with child field values referenced from a given node. Return None if there are blanks and zeroBlanks is false, raise a ValueError if any aren't a number. Arguments: eqnNode -- the node containing the equation to evaluate zeroBlanks -- replace blank fields with zeroValue if True zeroValue -- the value to use for blanks """ result = [] for node in eqnNode.childList: try: num = (node.formatRef.fieldDict[self.fieldName]. mathValue(node, zeroBlanks, noMarkup)) if num == None: return None result.append(num) except KeyError: if not zeroBlanks: return None if not result: result = [zeroValue] return result def dependentEqnNodes(self, refNode): """Return a list of equation node(s) that reference the given node. Arguments: refNode -- the node containing the referenced field """ node = refNode.spotByNumber(0).parentSpot.nodeRef if node.formatRef and node.formatRef.name == self.eqnNodeTypeName: return [node] return [] class EquationChildCountRef(EquationFieldRef): """Class to store and eval child count references in a Math equation. """ tagPrefix = '#' testValue = 1 evalDirection = EvalDir.optional def referenceValue(self, eqnNode, zeroBlanks=True, zeroValue=0, noMarkup=True): """Return the child count referenced from the given node. Arguments: eqnNode -- the node containing the equation to evaluate zeroBlanks -- replace blank fields with zeroValue if True zeroValue -- the value to use for blanks noMarkup -- if true, remove html markup """ return len(eqnNode.childList) def dependentEqnNodes(self, refNode): """Return a list of equation node(s) that reference the given node. Arguments: refNode -- the node containing the referenced field """ node = refNode.spotByNumber(0).parentSpot.nodeRef if node and node.formatRef.name == self.eqnNodeTypeName: return [node] return [] class RecursiveEqnRef: """Class to store a references to other equations in a tree structure. Resolves sequence and direction of global evaluations. """ recursiveRefDict = {} def __init__(self, eqnTypeName, eqnField): """Initialize the RecursiveEquationRef. Arguments: eqnTypeName -- the type format name contining the equation field eqnField -- the field with the equation to eval for other eqn refs """ self.eqnTypeName = eqnTypeName self.eqnField = eqnField self.evalSequence = 0 self.evalDirection = EvalDir.optional def setPriorities(self, visitedFields=None): """Recursively set sequence and direction for evaluation. Arguments: visitedFields -- set of used eqn field names to check circular refs """ if self.evalSequence != 0: return if visitedFields == None: visitedFields = set() visitedFields = visitedFields.copy() visitedFields.add(self.eqnField.name) self.evalSequence = 1 for fieldRef in self.eqnField.equation.fieldRefs: if (fieldRef.fieldName in visitedFields and fieldRef.tagPrefix != '#' and (self.eqnField.name != fieldRef.fieldName or fieldRef.evalDirection == EvalDir.optional)): raise CircularMathError() for eqnRef in self.recursiveRefDict.get(fieldRef.fieldName, []): eqnRef.setPriorities(visitedFields) if eqnRef.evalSequence >= self.evalSequence: self.evalDirection = fieldRef.evalDirection self.evalSequence = eqnRef.evalSequence if (self.evalDirection != eqnRef.evalDirection or self.evalDirection == EvalDir.optional): self.evalSequence += 1 def __lt__(self, other): """Use sequence and direction as comparison keys for sorting. Arguments: other -- the equation ref to compare """ return ((self.evalSequence, self.evalDirection) < (other.evalSequence, other.evalDirection)) class CircularMathError(Exception): """Exception raised when circular references are found in math fields. """ pass allowedFunctions = set(['abs', 'float', 'int', 'len', 'max', 'min', 'pow', 'round', 'sum', 'mean', 'ceil', 'fabs', 'factorial', 'floor', 'fmod', 'fsum', 'trunc', 'exp', 'log', 'log10', 'pow', 'sqrt', 'acos', 'asin', 'atan', 'cos', 'sin', 'tan', 'hypot', 'degrees', 'radians', 'pi', 'e', 'startswith', 'endswith', 'contains', 'join', 'upper', 'lower', 'replace', 'count']) allowedNodeTypes = set(['Module', 'Expr', 'Name', 'NameConstant', 'Constant', 'Load', 'IfExp', 'Compare', 'Num', 'Str', 'Tuple', 'List', 'BinOp', 'UnaryOp', 'Add', 'Sub', 'Mult', 'Div', 'Mod', 'Pow', 'FloorDiv', 'Invert', 'Not', 'UAdd', 'USub', 'Eq', 'NotEq', 'Lt', 'LtE', 'Gt', 'GtE', 'Is', 'IsNot', 'In', 'NotIn', 'BoolOp', 'And', 'Or']) class SafeEvalChecker(ast.NodeVisitor): """Class to check that only safe functions are used in an eval expression. Raises a ValueError if unsafe or non-numeric operations are present. Ref. stackoverflow.com questions 10661079 and 12523516 """ def check(self, expr): """Check the given expression for non-numeric operations. Arguments: expr -- the expression string to check """ try: tree = ast.parse(expr) except SyntaxError: raise ValueError(_('Illegal syntax in equation')) self.visit(tree) def visit_Call(self, node): """Check for allowed functions only. Arguments: node -- the ast node being checked """ if node.func.id in allowedFunctions: super().generic_visit(node) else: raise ValueError(_('Illegal function present: {0}'). format(node.func.id)) def generic_visit(self, node): """Check for allowed node types and operators. Arguments: node -- the ast node being checked """ if type(node).__name__ in allowedNodeTypes: super().generic_visit(node) else: raise ValueError(_('Illegal object type or operator: {0}'). format(type(node).__name__)) if __name__ == '__main__': checker = SafeEvalChecker() try: print('Enter expression: ') expr = input() checker.check(expr) except ValueError as err: print(err) else: print(eval(expr)) TreeLine-3.2.1/source/miscdialogs.py000066400000000000000000002356461506556630100174230ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # miscdialogs.py, provides classes for various control dialogs # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import enum import re import sys import operator import collections import datetime import platform import traceback from PyQt6.QtCore import Qt, pyqtSignal, PYQT_VERSION_STR, qVersion from PyQt6.QtGui import QFont, QKeySequence, QTextDocument, QTextOption from PyQt6.QtWidgets import (QAbstractItemView, QApplication, QButtonGroup, QCheckBox, QComboBox, QDialog, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem, QMenu, QMessageBox, QPlainTextEdit, QPushButton, QRadioButton, QScrollArea, QSpinBox, QTabWidget, QTextEdit, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget) import options import printdialogs import undo import globalref try: from __main__ import __version__ except ImportError: __version__ = '' class RadioChoiceDialog(QDialog): """Dialog for choosing between a list of text items (radio buttons). Dialog title, group heading, button text and return text can be set. """ def __init__(self, title, heading, choiceList, parent=None): """Create the radio choice dialog. Arguments: title -- the window title heading -- the groupbox text choiceList -- tuples of button text and return values parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(title) topLayout = QVBoxLayout(self) self.setLayout(topLayout) groupBox = QGroupBox(heading) topLayout.addWidget(groupBox) groupLayout = QVBoxLayout(groupBox) self.buttonGroup = QButtonGroup(self) for text, value in choiceList: if value != None: button = QRadioButton(text) button.returnValue = value groupLayout.addWidget(button) self.buttonGroup.addButton(button) else: # add heading if no return value label = QLabel('{0}:'.format(text)) groupLayout.addWidget(label) self.buttonGroup.buttons()[0].setChecked(True) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) groupBox.setFocus() def addLabelBox(self, heading, text): """Add a group box with text above the radio button group. Arguments: heading -- the groupbox text text - the label text """ labelBox = QGroupBox(heading) self.layout().insertWidget(0, labelBox) labelLayout = QVBoxLayout(labelBox) label = QLabel(text) labelLayout.addWidget(label) def selectedButton(self): """Return the value of the selected button. """ return self.buttonGroup.checkedButton().returnValue class FieldSelectDialog(QDialog): """Dialog for selecting a sequence from a list of field names. """ def __init__(self, title, heading, fieldList, parent=None): """Create the field select dialog. Arguments: title -- the window title heading -- the groupbox text fieldList -- the list of field names to select parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(title) self.selectedFields = [] topLayout = QVBoxLayout(self) self.setLayout(topLayout) groupBox = QGroupBox(heading) topLayout.addWidget(groupBox) groupLayout = QVBoxLayout(groupBox) self.listView = QTreeWidget() groupLayout.addWidget(self.listView) self.listView.setHeaderLabels(['#', _('Fields')]) self.listView.setRootIsDecorated(False) self.listView.setSortingEnabled(False) self.listView.setSelectionMode(QAbstractItemView.SelectionMode. MultiSelection) for field in fieldList: QTreeWidgetItem(self.listView, ['', field]) self.listView.resizeColumnToContents(0) self.listView.resizeColumnToContents(1) self.listView.itemSelectionChanged.connect(self.updateSelectedFields) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) self.okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(self.okButton) self.okButton.clicked.connect(self.accept) self.okButton.setEnabled(False) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.listView.setFocus() def updateSelectedFields(self): """Update the TreeView and the list of selected fields. """ itemList = [self.listView.topLevelItem(i) for i in range(self.listView.topLevelItemCount())] for item in itemList: if item.isSelected(): if item.text(1) not in self.selectedFields: self.selectedFields.append(item.text(1)) elif item.text(1) in self.selectedFields: self.selectedFields.remove(item.text(1)) for item in itemList: if item.isSelected(): item.setText(0, str(self.selectedFields.index(item.text(1)) + 1)) else: item.setText(0, '') self.okButton.setEnabled(len(self.selectedFields)) class FilePropertiesDialog(QDialog): """Dialog for setting file parameters like compression and encryption. """ def __init__(self, localControl, parent=None): """Create the file properties dialog. Arguments: localControl -- a reference to the file's local control parent -- the parent window """ super().__init__(parent) self.localControl = localControl self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('File Properties')) topLayout = QVBoxLayout(self) self.setLayout(topLayout) groupBox = QGroupBox(_('File Storage')) topLayout.addWidget(groupBox) groupLayout = QVBoxLayout(groupBox) self.compressCheck = QCheckBox(_('&Use file compression')) self.compressCheck.setChecked(localControl.compressed) groupLayout.addWidget(self.compressCheck) self.encryptCheck = QCheckBox(_('Use file &encryption')) self.encryptCheck.setChecked(localControl.encrypted) groupLayout.addWidget(self.encryptCheck) groupBox = QGroupBox(_('Spell Check')) topLayout.addWidget(groupBox) groupLayout = QHBoxLayout(groupBox) label = QLabel(_('Language code or\ndictionary (optional)')) groupLayout.addWidget(label) self.spellCheckEdit = QLineEdit() self.spellCheckEdit.setText(self.localControl.spellCheckLang) groupLayout.addWidget(self.spellCheckEdit) groupBox = QGroupBox(_('Math Fields')) topLayout.addWidget(groupBox) groupLayout = QVBoxLayout(groupBox) self.zeroBlanks = QCheckBox(_('&Treat blank fields as zeros')) self.zeroBlanks.setChecked(localControl.structure.mathZeroBlanks) groupLayout.addWidget(self.zeroBlanks) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) def accept(self): """Store the results. """ if (self.localControl.compressed != self.compressCheck.isChecked() or self.localControl.encrypted != self.encryptCheck.isChecked() or self.localControl.spellCheckLang != self.spellCheckEdit.text() or self.localControl.structure.mathZeroBlanks != self.zeroBlanks.isChecked()): undo.ParamUndo(self.localControl.structure.undoList, [(self.localControl, 'compressed'), (self.localControl, 'encrypted'), (self.localControl, 'spellCheckLang'), (self.localControl.structure, 'mathZeroBlanks')]) self.localControl.compressed = self.compressCheck.isChecked() self.localControl.encrypted = self.encryptCheck.isChecked() self.localControl.spellCheckLang = self.spellCheckEdit.text() self.localControl.structure.mathZeroBlanks = (self.zeroBlanks. isChecked()) super().accept() else: super().reject() class PasswordDialog(QDialog): """Dialog for password entry and optional re-entry. """ remember = True def __init__(self, retype=True, fileLabel='', parent=None): """Create the password dialog. Arguments: retype -- require a 2nd password entry if True fileLabel -- file name to show if given parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Encrypted File Password')) self.password = '' topLayout = QVBoxLayout(self) self.setLayout(topLayout) if fileLabel: prompt = _('Type Password for "{0}":').format(fileLabel) else: prompt = _('Type Password:') self.editors = [self.addEditor(prompt, topLayout)] self.editors[0].setFocus() if retype: self.editors.append(self.addEditor(_('Re-Type Password:'), topLayout)) self.editors[0].returnPressed.connect(self.editors[1].setFocus) self.editors[-1].returnPressed.connect(self.accept) self.rememberCheck = QCheckBox(_('Remember password during this ' 'session')) self.rememberCheck.setChecked(PasswordDialog.remember) topLayout.addWidget(self.rememberCheck) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) okButton = QPushButton(_('&OK')) okButton.setAutoDefault(False) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) cancelButton.setAutoDefault(False) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) def addEditor(self, labelText, layout): """Add a password editor to this dialog and return it. Arguments: labelText -- the text for the label layout -- the layout to append it """ label = QLabel(labelText) layout.addWidget(label) editor = QLineEdit() editor.setEchoMode(QLineEdit.EchoMode.Password) layout.addWidget(editor) return editor def accept(self): """Check for valid password and store the result. """ self.password = self.editors[0].text() PasswordDialog.remember = self.rememberCheck.isChecked() if not self.password: QMessageBox.warning(self, 'TreeLine', _('Zero-length passwords are not permitted')) elif len(self.editors) > 1 and self.editors[1].text() != self.password: QMessageBox.warning(self, 'TreeLine', _('Re-typed password did not match')) else: super().accept() for editor in self.editors: editor.clear() self.editors[0].setFocus() class ExtModDialog(QDialog): """Dialog for how to hanlde a file that was externally modified. """ def __init__(self, modTime, parent=None): """Cretate the external mod dialog. Arguments: modTime -- the datetime of the external mod parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Externally Modified File')) topLayout = QVBoxLayout(self) self.setLayout(topLayout) label = QLabel(_('File was externally modified at {}'). format(modTime.isoformat(' ', 'seconds'))) topLayout.addWidget(label) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) overwriteButton = QPushButton(_('&Overwrite File')) overwriteButton.setAutoDefault(False) ctrlLayout.addWidget(overwriteButton) overwriteButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel Save')) cancelButton.setAutoDefault(False) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) class TemplateFileItem: """Helper class to store template paths and info. """ nameExp = re.compile(r'(\d+)([a-zA-Z]+?)_(.+)') def __init__(self, pathObj): """Initialize the path. Arguments: pathObj -- the full path object """ self.pathObj = pathObj self.number = sys.maxsize self.name = '' self.displayName = '' self.langCode = '' if pathObj: self.name = pathObj.stem match = TemplateFileItem.nameExp.match(self.name) if match: num, self.langCode, self.name = match.groups() self.number = int(num) self.displayName = self.name.replace('_', ' ') def sortKey(self): """Return a key for sorting the items by number then name. """ return (self.number, self.displayName) def __eq__(self, other): """Comparison to detect equivalent items. Arguments: other -- the TemplateFileItem to compare """ return (self.displayName == other.displayName and self.langCode == other.langCode) def __hash__(self): """Return a hash code for use in sets and dictionaries. """ return hash((self.langCode, self.displayName)) class TemplateFileDialog(QDialog): """Dialog for listing available template files. """ def __init__(self, title, heading, searchPaths, addDefault=True, parent=None): """Create the template dialog. Arguments: title -- the window title heading -- the groupbox text searchPaths -- list of path objects with available templates addDefault -- if True, add a default (no path) entry parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(title) self.templateItems = [] if addDefault: item = TemplateFileItem(None) item.number = -1 item.displayName = _('Default - Single Line Text') self.templateItems.append(item) topLayout = QVBoxLayout(self) self.setLayout(topLayout) groupBox = QGroupBox(heading) topLayout.addWidget(groupBox) boxLayout = QVBoxLayout(groupBox) self.listBox = QListWidget() boxLayout.addWidget(self.listBox) self.listBox.itemDoubleClicked.connect(self.accept) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) self.okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(self.okButton) self.okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.readTemplates(searchPaths) self.loadListBox() def readTemplates(self, searchPaths): """Read template file paths into the templateItems list. Arguments: searchPaths -- list of path objects with available templates """ templateItems = set() for path in searchPaths: for templatePath in path.glob('*.trln'): templateItem = TemplateFileItem(templatePath) if templateItem not in templateItems: templateItems.add(templateItem) availLang = set([item.langCode for item in templateItems]) if len(availLang) > 1: lang = 'en' if globalref.lang[:2] in availLang: lang = globalref.lang[:2] templateItems = [item for item in templateItems if item.langCode == lang or not item.langCode] self.templateItems.extend(list(templateItems)) self.templateItems.sort(key = operator.methodcaller('sortKey')) def loadListBox(self): """Load the list box with items from the templateItems list. """ self.listBox.clear() self.listBox.addItems([item.displayName for item in self.templateItems]) self.listBox.setCurrentRow(0) self.okButton.setEnabled(self.listBox.count() > 0) def selectedPath(self): """Return the path object from the selected item. """ item = self.templateItems[self.listBox.currentRow()] return item.pathObj def selectedName(self): """Return the displayed name with underscores from the selected item. """ item = self.templateItems[self.listBox.currentRow()] return item.name class ExceptionDialog(QDialog): """Dialog for showing debug info from an unhandled exception. """ def __init__(self, excType, value, tb, parent=None): """Initialize the exception dialog. Arguments: excType -- execption class value -- execption error text tb -- the traceback object """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.WindowStaysOnTopHint) self.setWindowTitle(_('TreeLine - Serious Error')) topLayout = QVBoxLayout(self) self.setLayout(topLayout) label = QLabel(_('A serious error has occurred. TreeLine could be ' 'in an unstable state.\n' 'Recommend saving any file changes under another ' 'filename and restart TreeLine.\n\n' 'The debugging info shown below can be copied ' 'and emailed to doug101@bellz.org along with\n' 'an explanation of the circumstances.\n')) topLayout.addWidget(label) textBox = QTextEdit() textBox.setReadOnly(True) pyVersion = '.'.join([repr(num) for num in sys.version_info[:3]]) textLines = ['When: {0}\n'.format(datetime.datetime.now(). isoformat(' ')), 'TreeLine Version: {0}\n'.format(__version__), 'Python Version: {0}\n'.format(pyVersion), 'Qt Version: {0}\n'.format(qVersion()), 'PyQt Version: {0}\n'.format(PYQT_VERSION_STR), 'OS: {0}\n'.format(platform.platform()), '\n'] textLines.extend(traceback.format_exception(excType, value, tb)) textBox.setPlainText(''.join(textLines)) topLayout.addWidget(textBox) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) closeButton = QPushButton(_('&Close')) ctrlLayout.addWidget(closeButton) closeButton.clicked.connect(self.close) FindScope = enum.IntEnum('FindScope', 'fullData titlesOnly') FindType = enum.IntEnum('FindType', 'keyWords fullWords fullPhrase regExp') class FindFilterDialog(QDialog): """Dialog for searching for text within tree titles and data. """ dialogShown = pyqtSignal(bool) def __init__(self, isFilterDialog=False, parent=None): """Initialize the find dialog. Arguments: isFilterDialog -- True for filter dialog, False for find dialog parent -- the parent window """ super().__init__(parent) self.isFilterDialog = isFilterDialog self.setAttribute(Qt.WidgetAttribute.WA_QuitOnClose, False) self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.WindowStaysOnTopHint) topLayout = QVBoxLayout(self) self.setLayout(topLayout) textBox = QGroupBox(_('&Search Text')) topLayout.addWidget(textBox) textLayout = QVBoxLayout(textBox) self.textEntry = QLineEdit() textLayout.addWidget(self.textEntry) self.textEntry.textEdited.connect(self.updateAvail) horizLayout = QHBoxLayout() topLayout.addLayout(horizLayout) whatBox = QGroupBox(_('What to Search')) horizLayout.addWidget(whatBox) whatLayout = QVBoxLayout(whatBox) self.whatButtons = QButtonGroup(self) button = QRadioButton(_('Full &data')) self.whatButtons.addButton(button, FindScope.fullData) whatLayout.addWidget(button) button = QRadioButton(_('&Titles only')) self.whatButtons.addButton(button, FindScope.titlesOnly) whatLayout.addWidget(button) self.whatButtons.button(FindScope.fullData).setChecked(True) howBox = QGroupBox(_('How to Search')) horizLayout.addWidget(howBox) howLayout = QVBoxLayout(howBox) self.howButtons = QButtonGroup(self) button = QRadioButton(_('&Key words')) self.howButtons.addButton(button, FindType.keyWords) howLayout.addWidget(button) button = QRadioButton(_('Key full &words')) self.howButtons.addButton(button, FindType.fullWords) howLayout.addWidget(button) button = QRadioButton(_('F&ull phrase')) self.howButtons.addButton(button, FindType.fullPhrase) howLayout.addWidget(button) button = QRadioButton(_('&Regular expression')) self.howButtons.addButton(button, FindType.regExp) howLayout.addWidget(button) self.howButtons.button(FindType.keyWords).setChecked(True) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) if not self.isFilterDialog: self.setWindowTitle(_('Find')) self.previousButton = QPushButton(_('Find &Previous')) ctrlLayout.addWidget(self.previousButton) self.previousButton.clicked.connect(self.findPrevious) self.nextButton = QPushButton(_('Find &Next')) self.nextButton.setDefault(True) ctrlLayout.addWidget(self.nextButton) self.nextButton.clicked.connect(self.findNext) self.resultLabel = QLabel() topLayout.addWidget(self.resultLabel) else: self.setWindowTitle(_('Filter')) self.filterButton = QPushButton(_('&Filter')) ctrlLayout.addWidget(self.filterButton) self.filterButton.clicked.connect(self.startFilter) self.endFilterButton = QPushButton(_('&End Filter')) ctrlLayout.addWidget(self.endFilterButton) self.endFilterButton.clicked.connect(self.endFilter) closeButton = QPushButton(_('&Close')) ctrlLayout.addWidget(closeButton) closeButton.clicked.connect(self.close) self.updateAvail('') def selectAllText(self): """Select all line edit text to prepare for a new entry. """ self.textEntry.selectAll() self.textEntry.setFocus() def updateAvail(self, text='', fileChange=False): """Make find buttons available if search text exists. Arguments: text -- placeholder for signal text (not used) fileChange -- True if window changed while dialog open """ hasEntry = len(self.textEntry.text().strip()) > 0 if not self.isFilterDialog: self.previousButton.setEnabled(hasEntry) self.nextButton.setEnabled(hasEntry) self.resultLabel.setText('') else: window = globalref.mainControl.activeControl.activeWindow if fileChange and window.treeFilterView: filterView = window.treeFilterView self.textEntry.setText(filterView.filterStr) self.whatButtons.button(filterView.filterWhat).setChecked(True) self.howButtons.button(filterView.filterHow).setChecked(True) self.filterButton.setEnabled(hasEntry) self.endFilterButton.setEnabled(window.treeFilterView != None) def find(self, forward=True): """Find another match in the indicated direction. Arguments: forward -- next if True, previous if False """ self.resultLabel.setText('') text = self.textEntry.text() titlesOnly = self.whatButtons.checkedId() == (FindScope.titlesOnly) control = globalref.mainControl.activeControl if self.howButtons.checkedId() == FindType.regExp: try: regExp = re.compile(text) except re.error: QMessageBox.warning(self, 'TreeLine', _('Error - invalid regular expression')) return result = control.findNodesByRegExp([regExp], titlesOnly, forward) elif self.howButtons.checkedId() == FindType.fullWords: regExpList = [] for word in text.lower().split(): regExpList.append(re.compile(r'(?i)\b{}\b'. format(re.escape(word)))) result = control.findNodesByRegExp(regExpList, titlesOnly, forward) elif self.howButtons.checkedId() == FindType.keyWords: wordList = text.lower().split() result = control.findNodesByWords(wordList, titlesOnly, forward) else: # full phrase wordList = [text.lower().strip()] result = control.findNodesByWords(wordList, titlesOnly, forward) if not result: self.resultLabel.setText(_('Search string "{0}" not found'). format(text)) def findPrevious(self): """Find the previous match. """ self.find(False) def findNext(self): """Find the next match. """ self.find(True) def startFilter(self): """Start filtering nodes. """ if self.howButtons.checkedId() == FindType.regExp: try: re.compile(self.textEntry.text()) except re.error: QMessageBox.warning(self, 'TreeLine', _('Error - invalid regular expression')) return filterView = (globalref.mainControl.activeControl.activeWindow. filterView()) filterView.filterWhat = self.whatButtons.checkedId() filterView.filterHow = self.howButtons.checkedId() filterView.filterStr = self.textEntry.text() filterView.updateContents() self.updateAvail() def endFilter(self): """Stop filtering nodes. """ globalref.mainControl.activeControl.activeWindow.removeFilterView() self.updateAvail() def closeEvent(self, event): """Signal that the dialog is closing. Arguments: event -- the close event """ self.dialogShown.emit(False) def reject(self): """Handle use of escape key to close this dialog. """ self.close() FindReplaceType = enum.IntEnum('FindReplaceType', 'anyMatch fullWord regExp') class FindReplaceDialog(QDialog): """Dialog for finding and replacing text in the node data. """ dialogShown = pyqtSignal(bool) def __init__(self, parent=None): """Initialize the find and replace dialog. Arguments: parent -- the parent window """ super().__init__(parent) self.setAttribute(Qt.WidgetAttribute.WA_QuitOnClose, False) self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.WindowStaysOnTopHint) self.setWindowTitle(_('Find and Replace')) self.matchedSpot = None topLayout = QGridLayout(self) self.setLayout(topLayout) textBox = QGroupBox(_('&Search Text')) topLayout.addWidget(textBox, 0, 0) textLayout = QVBoxLayout(textBox) self.textEntry = QLineEdit() textLayout.addWidget(self.textEntry) self.textEntry.textEdited.connect(self.clearMatch) replaceBox = QGroupBox(_('Replacement &Text')) topLayout.addWidget(replaceBox, 0, 1) replaceLayout = QVBoxLayout(replaceBox) self.replaceEntry = QLineEdit() replaceLayout.addWidget(self.replaceEntry) howBox = QGroupBox(_('How to Search')) topLayout.addWidget(howBox, 1, 0, 2, 1) howLayout = QVBoxLayout(howBox) self.howButtons = QButtonGroup(self) button = QRadioButton(_('Any &match')) self.howButtons.addButton(button, FindReplaceType.anyMatch) howLayout.addWidget(button) button = QRadioButton(_('Full &words')) self.howButtons.addButton(button, FindReplaceType.fullWord) howLayout.addWidget(button) button = QRadioButton(_('Re&gular expression')) self.howButtons.addButton(button, FindReplaceType.regExp) howLayout.addWidget(button) self.howButtons.button(FindReplaceType.anyMatch).setChecked(True) self.howButtons.buttonClicked.connect(self.clearMatch) typeBox = QGroupBox(_('&Node Type')) topLayout.addWidget(typeBox, 1, 1) typeLayout = QVBoxLayout(typeBox) self.typeCombo = QComboBox() typeLayout.addWidget(self.typeCombo) self.typeCombo.currentIndexChanged.connect(self.loadFieldNames) fieldBox = QGroupBox(_('N&ode Fields')) topLayout.addWidget(fieldBox, 2, 1) fieldLayout = QVBoxLayout(fieldBox) self.fieldCombo = QComboBox() fieldLayout.addWidget(self.fieldCombo) self.fieldCombo.currentIndexChanged.connect(self.clearMatch) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout, 3, 0, 1, 2) self.previousButton = QPushButton(_('Find &Previous')) ctrlLayout.addWidget(self.previousButton) self.previousButton.clicked.connect(self.findPrevious) self.nextButton = QPushButton(_('&Find Next')) self.nextButton.setDefault(True) ctrlLayout.addWidget(self.nextButton) self.nextButton.clicked.connect(self.findNext) self.replaceButton = QPushButton(_('&Replace')) ctrlLayout.addWidget(self.replaceButton) self.replaceButton.clicked.connect(self.replace) self.replaceAllButton = QPushButton(_('Replace &All')) ctrlLayout.addWidget(self.replaceAllButton) self.replaceAllButton.clicked.connect(self.replaceAll) closeButton = QPushButton(_('&Close')) ctrlLayout.addWidget(closeButton) closeButton.clicked.connect(self.close) self.resultLabel = QLabel() topLayout.addWidget(self.resultLabel, 4, 0, 1, 2) self.loadTypeNames() self.updateAvail() def updateAvail(self): """Set find & replace buttons available if search text & matches exist. """ hasEntry = (len(self.textEntry.text().strip()) > 0 or self.howButtons.checkedId() == FindReplaceType.anyMatch) self.previousButton.setEnabled(hasEntry) self.nextButton.setEnabled(hasEntry) match = bool(self.matchedSpot and self.matchedSpot is globalref.mainControl.activeControl. currentSelectionModel().currentSpot()) self.replaceButton.setEnabled(match) self.replaceAllButton.setEnabled(match) self.resultLabel.setText('') def clearMatch(self): """Remove reference to matched node if search criteria changes. """ self.matchedSpot = None globalref.mainControl.activeControl.findReplaceSpotRef = (None, 0) self.updateAvail() def loadTypeNames(self): """Load format type names into combo box. """ origTypeName = self.typeCombo.currentText() nodeFormats = globalref.mainControl.activeControl.structure.treeFormats self.typeCombo.blockSignals(True) self.typeCombo.clear() typeNames = nodeFormats.typeNames() self.typeCombo.addItems([_('[All Types]')] + typeNames) origPos = self.typeCombo.findText(origTypeName) if origPos >= 0: self.typeCombo.setCurrentIndex(origPos) self.typeCombo.blockSignals(False) self.loadFieldNames() def loadFieldNames(self): """Load field names into combo box. """ origFieldName = self.fieldCombo.currentText() nodeFormats = globalref.mainControl.activeControl.structure.treeFormats typeName = self.typeCombo.currentText() fieldNames = [] if typeName.startswith('['): for typeName in nodeFormats.typeNames(): for fieldName in nodeFormats[typeName].fieldNames(): if fieldName not in fieldNames: fieldNames.append(fieldName) else: fieldNames.extend(nodeFormats[typeName].fieldNames()) self.fieldCombo.clear() self.fieldCombo.addItems([_('[All Fields]')] + fieldNames) origPos = self.fieldCombo.findText(origFieldName) if origPos >= 0: self.fieldCombo.setCurrentIndex(origPos) self.matchedSpot = None self.updateAvail() def findParameters(self): """Create search parameters based on the dialog settings. Return a tuple of searchText, regExpObj, typeName, and fieldName. """ text = self.textEntry.text() searchText = '' regExpObj = None if self.howButtons.checkedId() == FindReplaceType.anyMatch: searchText = text.lower().strip() elif self.howButtons.checkedId() == FindReplaceType.fullWord: regExpObj = re.compile(r'(?i)\b{}\b'.format(re.escape(text))) else: regExpObj = re.compile(text) typeName = self.typeCombo.currentText() if typeName.startswith('['): typeName = '' fieldName = self.fieldCombo.currentText() if fieldName.startswith('['): fieldName = '' return (searchText, regExpObj, typeName, fieldName) def find(self, forward=True): """Find another match in the indicated direction. Arguments: forward -- next if True, previous if False """ self.matchedSpot = None try: searchText, regExpObj, typeName, fieldName = self.findParameters() except re.error: QMessageBox.warning(self, 'TreeLine', _('Error - invalid regular expression')) self.updateAvail() return control = globalref.mainControl.activeControl if control.findNodesForReplace(searchText, regExpObj, typeName, fieldName, forward): self.matchedSpot = control.currentSelectionModel().currentSpot() self.updateAvail() else: self.updateAvail() self.resultLabel.setText(_('Search text "{0}" not found'). format(self.textEntry.text())) def findPrevious(self): """Find the previous match. """ self.find(False) def findNext(self): """Find the next match. """ self.find(True) def replace(self): """Replace the currently found text. """ searchText, regExpObj, typeName, fieldName = self.findParameters() replaceText = self.replaceEntry.text() control = globalref.mainControl.activeControl if control.replaceInCurrentNode(searchText, regExpObj, typeName, fieldName, replaceText): self.find() else: QMessageBox.warning(self, 'TreeLine', _('Error - replacement failed')) self.matchedSpot = None self.updateAvail() def replaceAll(self): """Replace all text matches. """ searchText, regExpObj, typeName, fieldName = self.findParameters() replaceText = self.replaceEntry.text() control = globalref.mainControl.activeControl qty = control.replaceAll(searchText, regExpObj, typeName, fieldName, replaceText) self.matchedSpot = None self.updateAvail() self.resultLabel.setText(_('Replaced {0} matches').format(qty)) def closeEvent(self, event): """Signal that the dialog is closing. Arguments: event -- the close event """ self.dialogShown.emit(False) def reject(self): """Handle use of escape key to close this dialog. """ self.close() SortWhat = enum.IntEnum('SortWhat', 'fullTree selectBranch selectChildren selectSiblings') SortMethod = enum.IntEnum('SortMethod', 'fieldSort titleSort') SortDirection = enum.IntEnum('SortDirection', 'forward reverse') class SortDialog(QDialog): """Dialog for defining sort operations. """ dialogShown = pyqtSignal(bool) def __init__(self, parent=None): """Initialize the sort dialog. Arguments: parent -- the parent window """ super().__init__(parent) self.setAttribute(Qt.WidgetAttribute.WA_QuitOnClose, False) self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.WindowStaysOnTopHint) self.setWindowTitle(_('Sort Nodes')) topLayout = QVBoxLayout(self) self.setLayout(topLayout) horizLayout = QHBoxLayout() topLayout.addLayout(horizLayout) whatBox = QGroupBox(_('What to Sort')) horizLayout.addWidget(whatBox) whatLayout = QVBoxLayout(whatBox) self.whatButtons = QButtonGroup(self) button = QRadioButton(_('&Entire tree')) self.whatButtons.addButton(button, SortWhat.fullTree) whatLayout.addWidget(button) button = QRadioButton(_('Selected &branches')) self.whatButtons.addButton(button, SortWhat.selectBranch) whatLayout.addWidget(button) button = QRadioButton(_('Selection\'s childre&n')) self.whatButtons.addButton(button, SortWhat.selectChildren) whatLayout.addWidget(button) button = QRadioButton(_('Selection\'s &siblings')) self.whatButtons.addButton(button, SortWhat.selectSiblings) whatLayout.addWidget(button) self.whatButtons.button(SortWhat.fullTree).setChecked(True) vertLayout = QVBoxLayout() horizLayout.addLayout(vertLayout) methodBox = QGroupBox(_('Sort Method')) vertLayout.addWidget(methodBox) methodLayout = QVBoxLayout(methodBox) self.methodButtons = QButtonGroup(self) button = QRadioButton(_('&Predefined Key Fields')) self.methodButtons.addButton(button, SortMethod.fieldSort) methodLayout.addWidget(button) button = QRadioButton(_('Node &Titles')) self.methodButtons.addButton(button, SortMethod.titleSort) methodLayout.addWidget(button) self.methodButtons.button(SortMethod.fieldSort).setChecked(True) directionBox = QGroupBox(_('Sort Direction')) vertLayout.addWidget(directionBox) directionLayout = QVBoxLayout(directionBox) self.directionButtons = QButtonGroup(self) button = QRadioButton(_('&Forward')) self.directionButtons.addButton(button, SortDirection.forward) directionLayout.addWidget(button) button = QRadioButton(_('&Reverse')) self.directionButtons.addButton(button, SortDirection.reverse) directionLayout.addWidget(button) self.directionButtons.button(SortDirection.forward).setChecked(True) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.sortAndClose) applyButton = QPushButton(_('&Apply')) ctrlLayout.addWidget(applyButton) applyButton.clicked.connect(self.sortNodes) closeButton = QPushButton(_('&Close')) ctrlLayout.addWidget(closeButton) closeButton.clicked.connect(self.close) self.updateCommandsAvail() def updateCommandsAvail(self): """Set what to sort options available based on tree selections. """ selModel = globalref.mainControl.activeControl.currentSelectionModel() hasChild = False hasSibling = False for spot in selModel.selectedSpots(): if spot.nodeRef.childList: hasChild = True if spot.parentSpot and len(spot.parentSpot.nodeRef.childList) > 1: hasSibling = True self.whatButtons.button(SortWhat.selectBranch).setEnabled(hasChild) self.whatButtons.button(SortWhat.selectChildren).setEnabled(hasChild) self.whatButtons.button(SortWhat.selectSiblings).setEnabled(hasSibling) if not self.whatButtons.checkedButton().isEnabled(): self.whatButtons.button(SortWhat.fullTree).setChecked(True) def sortNodes(self): """Perform the sorting operation. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) control = globalref.mainControl.activeControl selSpots = control.currentSelectionModel().selectedSpots() if self.whatButtons.checkedId() == SortWhat.fullTree: selSpots = [control.structure.spotByNumber(0)] elif self.whatButtons.checkedId() == SortWhat.selectSiblings: selSpots = [spot.parentSpot for spot in selSpots] if self.whatButtons.checkedId() in (SortWhat.fullTree, SortWhat.selectBranch): rootSpots = selSpots[:] selSpots = [] for root in rootSpots: for spot in root.spotDescendantGen(): if spot.nodeRef.childList: selSpots.append(spot) undo.ChildListUndo(control.structure.undoList, [spot.nodeRef for spot in selSpots]) forward = self.directionButtons.checkedId() == SortDirection.forward if self.methodButtons.checkedId() == SortMethod.fieldSort: for spot in selSpots: spot.nodeRef.sortChildrenByField(False, forward) # reset temporary sort field storage for nodeFormat in control.structure.treeFormats.values(): nodeFormat.sortFields = [] else: for spot in selSpots: spot.nodeRef.sortChildrenByTitle(False, forward) control.updateAll() QApplication.restoreOverrideCursor() def sortAndClose(self): """Perform the sorting operation and close the dialog. """ self.sortNodes() self.close() def closeEvent(self, event): """Signal that the dialog is closing. Arguments: event -- the close event """ self.dialogShown.emit(False) def reject(self): """Handle use of escape key to close this dialog. """ self.close() NumberingScope = enum.IntEnum('NumberingScope', 'fullTree selectBranch selectChildren') NumberingNoField = enum.IntEnum('NumberingNoField', 'ignoreNoField restartAfterNoField reserveNoField') class NumberingDialog(QDialog): """Dialog for updating node nuumbering fields. """ dialogShown = pyqtSignal(bool) def __init__(self, parent=None): """Initialize the numbering dialog. Arguments: parent -- the parent window """ super().__init__(parent) self.setAttribute(Qt.WidgetAttribute.WA_QuitOnClose, False) self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.WindowStaysOnTopHint) self.setWindowTitle(_('Update Node Numbering')) topLayout = QVBoxLayout(self) self.setLayout(topLayout) whatBox = QGroupBox(_('What to Update')) topLayout.addWidget(whatBox) whatLayout = QVBoxLayout(whatBox) self.whatButtons = QButtonGroup(self) button = QRadioButton(_('&Entire tree')) self.whatButtons.addButton(button, NumberingScope.fullTree) whatLayout.addWidget(button) button = QRadioButton(_('Selected &branches')) self.whatButtons.addButton(button, NumberingScope.selectBranch) whatLayout.addWidget(button) button = QRadioButton(_('&Selection\'s children')) self.whatButtons.addButton(button, NumberingScope.selectChildren) whatLayout.addWidget(button) self.whatButtons.button(NumberingScope.fullTree).setChecked(True) rootBox = QGroupBox(_('Root Node')) topLayout.addWidget(rootBox) rootLayout = QVBoxLayout(rootBox) self.rootCheck = QCheckBox(_('Include top-level nodes')) rootLayout.addWidget(self.rootCheck) self.rootCheck.setChecked(True) noFieldBox = QGroupBox(_('Handling Nodes without Numbering ' 'Fields')) topLayout.addWidget(noFieldBox) noFieldLayout = QVBoxLayout(noFieldBox) self.noFieldButtons = QButtonGroup(self) button = QRadioButton(_('&Ignore and skip')) self.noFieldButtons.addButton(button, NumberingNoField.ignoreNoField) noFieldLayout.addWidget(button) button = QRadioButton(_('&Restart numbers for next siblings')) self.noFieldButtons.addButton(button, NumberingNoField.restartAfterNoField) noFieldLayout.addWidget(button) button = QRadioButton(_('Reserve &numbers')) self.noFieldButtons.addButton(button, NumberingNoField.reserveNoField) noFieldLayout.addWidget(button) self.noFieldButtons.button(NumberingNoField. ignoreNoField).setChecked(True) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.numberAndClose) applyButton = QPushButton(_('&Apply')) ctrlLayout.addWidget(applyButton) applyButton.clicked.connect(self.updateNumbering) closeButton = QPushButton(_('&Close')) ctrlLayout.addWidget(closeButton) closeButton.clicked.connect(self.close) self.updateCommandsAvail() def updateCommandsAvail(self): """Set branch numbering available based on tree selections. """ selNodes = globalref.mainControl.activeControl.currentSelectionModel() hasChild = False for node in selNodes.selectedNodes(): if node.childList: hasChild = True self.whatButtons.button(NumberingScope. selectChildren).setEnabled(hasChild) if not self.whatButtons.checkedButton().isEnabled(): self.whatButtons.button(NumberingScope.fullTree).setChecked(True) def checkForNumberingFields(self): """Check that the tree formats have numbering formats. Return a dict of numbering field names by node format name. If not found, warn user. """ fieldDict = (globalref.mainControl.activeControl.structure.treeFormats. numberingFieldDict()) if not fieldDict: QMessageBox.warning(self, _('TreeLine Numbering'), _('No numbering fields were found in data types')) return fieldDict def updateNumbering(self): """Perform the numbering update operation. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) fieldDict = self.checkForNumberingFields() if fieldDict: control = globalref.mainControl.activeControl selNodes = control.currentSelectionModel().selectedNodes() if (self.whatButtons.checkedId() == NumberingScope.fullTree or len(selNodes) == 0): selNodes = control.structure.childList undo.DataUndo(control.structure.undoList, selNodes, addBranch=True) reserveNums = (self.noFieldButtons.checkedId() == NumberingNoField.reserveNoField) restartSetting = (self.noFieldButtons.checkedId() == NumberingNoField.restartAfterNoField) includeRoot = self.rootCheck.isChecked() if self.whatButtons.checkedId() == NumberingScope.selectChildren: levelLimit = 2 else: levelLimit = sys.maxsize startNum = [1] completedClones = set() for node in selNodes: node.updateNumbering(fieldDict, startNum, levelLimit, completedClones, includeRoot, reserveNums, restartSetting) control.updateAll() QApplication.restoreOverrideCursor() def numberAndClose(self): """Perform the numbering update operation and close the dialog. """ self.updateNumbering() self.close() def closeEvent(self, event): """Signal that the dialog is closing. Arguments: event -- the close event """ self.dialogShown.emit(False) def reject(self): """Handle use of escape key to close this dialog. """ self.close() menuNames = collections.OrderedDict([(N_('File Menu'), _('File')), (N_('Edit Menu'), _('Edit')), (N_('Node Menu'), _('Node')), (N_('Data Menu'), _('Data')), (N_('Tools Menu'), _('Tools')), (N_('Format Menu'), _('Format')), (N_('View Menu'), _('View')), (N_('Window Menu'), _('Window')), (N_('Help Menu'), _('Help'))]) class CustomShortcutsDialog(QDialog): """Dialog for customizing keyboard commands. """ def __init__(self, allActions, parent=None): """Create a shortcuts selection dialog. Arguments: allActions -- dict of all actions from a window parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Keyboard Shortcuts')) topLayout = QVBoxLayout(self) self.setLayout(topLayout) scrollArea = QScrollArea() topLayout.addWidget(scrollArea) viewport = QWidget() viewLayout = QGridLayout(viewport) scrollArea.setWidget(viewport) scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) scrollArea.setWidgetResizable(True) self.editors = [] for i, keyOption in enumerate(globalref.keyboardOptions.values()): category = menuNames.get(keyOption.category, _('No menu')) try: action = allActions[keyOption.name] except KeyError: pass else: text = '{0} > {1}'.format(category, action.toolTip()) label = QLabel(text) viewLayout.addWidget(label, i, 0) editor = KeyLineEdit(keyOption, action, self) viewLayout.addWidget(editor, i, 1) self.editors.append(editor) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) restoreButton = QPushButton(_('&Restore Defaults')) ctrlLayout.addWidget(restoreButton) restoreButton.clicked.connect(self.restoreDefaults) ctrlLayout.addStretch(0) self.okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(self.okButton) self.okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.editors[0].setFocus() def restoreDefaults(self): """Restore all default keyboard shortcuts. """ for editor in self.editors: editor.loadDefaultKey() def accept(self): """Save any changes to options and actions before closing. """ modified = False for editor in self.editors: if editor.modified: editor.saveChange() modified = True if modified: globalref.keyboardOptions.writeFile() super().accept() class KeyLineEdit(QLineEdit): """Line editor for keyboad sequence entry. """ usedKeySet = set() blankText = ' ' * 8 def __init__(self, keyOption, action, parent=None): """Create a key editor. Arguments: keyOption -- the KeyOptionItem for this editor action -- the action to update on changes parent -- the parent dialog """ super().__init__(parent) self.keyOption = keyOption self.keyAction = action self.key = None self.modified = False self.setReadOnly(True) self.loadKey() def loadKey(self): """Load the initial key shortcut from the option. """ key = self.keyOption.value if key: self.setKey(key) else: self.setText(KeyLineEdit.blankText) def loadDefaultKey(self): """Change to the default key shortcut from the option. Arguments: useDefault -- if True, load the default key """ key = self.keyOption.defaultValue if key == self.key: return if key: self.setKey(key) self.modified = True else: self.clearKey(False) def setKey(self, key): """Set this editor to the given key and add to the used key set. Arguments: key - the QKeySequence to add """ keyText = key.toString(QKeySequence.SequenceFormat.NativeText) self.setText(keyText) self.key = key KeyLineEdit.usedKeySet.add(keyText) def clearKey(self, staySelected=True): """Remove any existing key. """ self.setText(KeyLineEdit.blankText) if staySelected: self.selectAll() if self.key: KeyLineEdit.usedKeySet.remove(self.key.toString(QKeySequence. SequenceFormat. NativeText)) self.key = None self.modified = True def saveChange(self): """Save any change to the option and action. """ if self.modified: self.keyOption.setValue(self.key) if self.key: self.keyAction.setShortcut(self.key) else: self.keyAction.setShortcut(QKeySequence()) def keyPressEvent(self, event): """Capture key strokes and update the editor if valid. Arguments: event -- the key press event """ if event.key() in (Qt.Key.Key_Shift, Qt.Key.Key_Control, Qt.Key.Key_Meta, Qt.Key.Key_Alt, Qt.Key.Key_AltGr, Qt.Key.Key_CapsLock, Qt.Key.Key_NumLock, Qt.Key.Key_ScrollLock, Qt.Key.Key_Pause, Qt.Key.Key_Print, Qt.Key.Key_Cancel): event.ignore() elif event.key() in (Qt.Key.Key_Backspace, Qt.Key.Key_Escape): self.clearKey() event.accept() else: key = QKeySequence(event.keyCombination()) if key != self.key: keyText = key.toString(QKeySequence.SequenceFormat.NativeText) if keyText not in KeyLineEdit.usedKeySet: if self.key: KeyLineEdit.usedKeySet.remove(self.key. toString(QKeySequence. SequenceFormat. NativeText)) self.setKey(key) self.selectAll() self.modified = True else: text = _('Key {0} is already used').format(keyText) QMessageBox.warning(self.parent(), 'TreeLine', text) event.accept() def contextMenuEvent(self, event): """Change to a context menu with a clear command. Arguments: event -- the menu event """ menu = QMenu(self) menu.addAction(_('Clear &Key'), self.clearKey) menu.exec(event.globalPos()) def mousePressEvent(self, event): """Capture mouse clicks to avoid selection loss. Arguments: event -- the mouse event """ event.accept() def mouseReleaseEvent(self, event): """Capture mouse clicks to avoid selection loss. Arguments: event -- the mouse event """ event.accept() def mouseMoveEvent(self, event): """Capture mouse clicks to avoid selection loss. Arguments: event -- the mouse event """ event.accept() def mouseDoubleClickEvent(self, event): """Capture mouse clicks to avoid selection loss. Arguments: event -- the mouse event """ event.accept() def focusInEvent(self, event): """Select contents when focussed. Arguments: event -- the focus event """ self.selectAll() super().focusInEvent(event) class CustomToolbarDialog(QDialog): """Dialog for customizing toolbar buttons. """ separatorString = _('--Separator--') def __init__(self, allActions, updateFunction, parent=None): """Create a toolbar buttons customization dialog. Arguments: allActions -- dict of all actions from a window updateFunction -- a function ref for updating window toolbars parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Customize Toolbars')) self.allActions = allActions self.updateFunction = updateFunction self.availableCommands = [] self.modified = False self.numToolbars = 0 self.availableCommands = [] self.toolbarLists = [] topLayout = QVBoxLayout(self) self.setLayout(topLayout) gridLayout = QGridLayout() topLayout.addLayout(gridLayout) sizeBox = QGroupBox(_('Toolbar &Size')) gridLayout.addWidget(sizeBox, 0, 0, 1, 2) sizeLayout = QVBoxLayout(sizeBox) self.sizeCombo = QComboBox() sizeLayout.addWidget(self.sizeCombo) self.sizeCombo.addItems([_('Small Icons'), _('Large Icons')]) self.sizeCombo.currentIndexChanged.connect(self.setModified) numberBox = QGroupBox(_('Toolbar Quantity')) gridLayout.addWidget(numberBox, 0, 2) numberLayout = QHBoxLayout(numberBox) self.quantitySpin = QSpinBox() numberLayout.addWidget(self.quantitySpin) self.quantitySpin.setRange(0, 20) numberlabel = QLabel(_('&Toolbars')) numberLayout.addWidget(numberlabel) numberlabel.setBuddy(self.quantitySpin) self.quantitySpin.valueChanged.connect(self.changeQuantity) availableBox = QGroupBox(_('A&vailable Commands')) gridLayout.addWidget(availableBox, 1, 0) availableLayout = QVBoxLayout(availableBox) menuCombo = QComboBox() availableLayout.addWidget(menuCombo) menuCombo.addItems([_(name) for name in menuNames.keys()]) menuCombo.currentIndexChanged.connect(self.updateAvailableCommands) self.availableListWidget = QListWidget() availableLayout.addWidget(self.availableListWidget) buttonLayout = QVBoxLayout() gridLayout.addLayout(buttonLayout, 1, 1) self.addButton = QPushButton('>>') buttonLayout.addWidget(self.addButton) self.addButton.setMaximumWidth(self.addButton.sizeHint().height()) self.addButton.clicked.connect(self.addTool) self.removeButton = QPushButton('<<') buttonLayout.addWidget(self.removeButton) self.removeButton.setMaximumWidth(self.removeButton.sizeHint(). height()) self.removeButton.clicked.connect(self.removeTool) toolbarBox = QGroupBox(_('Tool&bar Commands')) gridLayout.addWidget(toolbarBox, 1, 2) toolbarLayout = QVBoxLayout(toolbarBox) self.toolbarCombo = QComboBox() toolbarLayout.addWidget(self.toolbarCombo) self.toolbarCombo.currentIndexChanged.connect(self. updateToolbarCommands) self.toolbarListWidget = QListWidget() toolbarLayout.addWidget(self.toolbarListWidget) self.toolbarListWidget.currentRowChanged.connect(self. setButtonsAvailable) moveLayout = QHBoxLayout() toolbarLayout.addLayout(moveLayout) self.moveUpButton = QPushButton(_('Move &Up')) moveLayout.addWidget(self.moveUpButton) self.moveUpButton.clicked.connect(self.moveUp) self.moveDownButton = QPushButton(_('Move &Down')) moveLayout.addWidget(self.moveDownButton) self.moveDownButton.clicked.connect(self.moveDown) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) restoreButton = QPushButton(_('&Restore Defaults')) ctrlLayout.addWidget(restoreButton) restoreButton.clicked.connect(self.restoreDefaults) ctrlLayout.addStretch() self.okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(self.okButton) self.okButton.clicked.connect(self.accept) self.applyButton = QPushButton(_('&Apply')) ctrlLayout.addWidget(self.applyButton) self.applyButton.clicked.connect(self.applyChanges) self.applyButton.setEnabled(False) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.updateAvailableCommands(0) self.loadToolbars() def setModified(self): """Set modified flag and make apply button available. """ self.modified = True self.applyButton.setEnabled(True) def setButtonsAvailable(self): """Enable or disable buttons based on toolbar list state. """ toolbarNum = numCommands = commandNum = 0 if self.numToolbars: toolbarNum = self.toolbarCombo.currentIndex() numCommands = len(self.toolbarLists[toolbarNum]) if self.toolbarLists[toolbarNum]: commandNum = self.toolbarListWidget.currentRow() self.addButton.setEnabled(self.numToolbars > 0) self.removeButton.setEnabled(self.numToolbars and numCommands) self.moveUpButton.setEnabled(self.numToolbars and numCommands > 1 and commandNum > 0) self.moveDownButton.setEnabled(self.numToolbars and numCommands > 1 and commandNum < numCommands - 1) def loadToolbars(self, defaultOnly=False): """Load all toolbar data from options. Arguments: defaultOnly -- if True, load default settings """ size = (globalref.toolbarOptions['ToolbarSize'] if not defaultOnly else globalref.toolbarOptions.getDefaultValue('ToolbarSize')) self.sizeCombo.blockSignals(True) if size < 24: self.sizeCombo.setCurrentIndex(0) else: self.sizeCombo.setCurrentIndex(1) self.sizeCombo.blockSignals(False) self.numToolbars = (globalref.toolbarOptions['ToolbarQuantity'] if not defaultOnly else globalref.toolbarOptions. getDefaultValue('ToolbarQuantity')) self.quantitySpin.blockSignals(True) self.quantitySpin.setValue(self.numToolbars) self.quantitySpin.blockSignals(False) self.toolbarLists = [] commands = (globalref.toolbarOptions['ToolbarCommands'] if not defaultOnly else globalref.toolbarOptions. getDefaultValue('ToolbarCommands')) self.toolbarLists = [cmd.split(',') for cmd in commands] # account for toolbar quantity mismatch (should not happen) del self.toolbarLists[self.numToolbars:] while len(self.toolbarLists) < self.numToolbars: self.toolbarLists.append([]) self.updateToolbarCombo() def updateToolbarCombo(self): """Fill combo with toolbar numbers for current quantity. """ self.toolbarCombo.clear() if self.numToolbars: self.toolbarCombo.addItems(['Toolbar {0}'.format(num + 1) for num in range(self.numToolbars)]) else: self.toolbarListWidget.clear() self.setButtonsAvailable() def updateAvailableCommands(self, menuNum): """Fill in available command list for given menu. Arguments: menuNum -- the index of the current menu selected """ menuName = list(menuNames.keys())[menuNum] self.availableCommands = [] self.availableListWidget.clear() for option in globalref.keyboardOptions.values(): if option.category == menuName: action = self.allActions[option.name] icon = action.icon() if not icon.isNull(): self.availableCommands.append(option.name) QListWidgetItem(icon, action.toolTip(), self.availableListWidget) QListWidgetItem(CustomToolbarDialog.separatorString, self.availableListWidget) self.availableListWidget.setCurrentRow(0) def updateToolbarCommands(self, toolbarNum): """Fill in toolbar commands for given toolbar. Arguments: toolbarNum -- the number of the toolbar to update """ self.toolbarListWidget.clear() if self.numToolbars == 0: return for command in self.toolbarLists[toolbarNum]: if command: action = self.allActions[command] QListWidgetItem(action.icon(), action.toolTip(), self.toolbarListWidget) else: # separator QListWidgetItem(CustomToolbarDialog.separatorString, self.toolbarListWidget) if self.toolbarLists[toolbarNum]: self.toolbarListWidget.setCurrentRow(0) self.setButtonsAvailable() def changeQuantity(self, qty): """Change the toolbar quantity based on a spin box signal. Arguments: qty -- the new toolbar quantity """ self.numToolbars = qty while qty > len(self.toolbarLists): self.toolbarLists.append([]) self.updateToolbarCombo() self.setModified() def addTool(self): """Add the selected command to the current toolbar. """ toolbarNum = self.toolbarCombo.currentIndex() try: command = self.availableCommands[self.availableListWidget. currentRow()] action = self.allActions[command] item = QListWidgetItem(action.icon(), action.toolTip()) except IndexError: command = '' item = QListWidgetItem(CustomToolbarDialog.separatorString) if self.toolbarLists[toolbarNum]: pos = self.toolbarListWidget.currentRow() + 1 else: pos = 0 self.toolbarLists[toolbarNum].insert(pos, command) self.toolbarListWidget.insertItem(pos, item) self.toolbarListWidget.setCurrentRow(pos) self.toolbarListWidget.scrollToItem(item) self.setModified() def removeTool(self): """Remove the selected command from the current toolbar. """ toolbarNum = self.toolbarCombo.currentIndex() pos = self.toolbarListWidget.currentRow() del self.toolbarLists[toolbarNum][pos] self.toolbarListWidget.takeItem(pos) if self.toolbarLists[toolbarNum]: if pos == len(self.toolbarLists[toolbarNum]): pos -= 1 self.toolbarListWidget.setCurrentRow(pos) self.setModified() def moveUp(self): """Raise the selected command. """ toolbarNum = self.toolbarCombo.currentIndex() pos = self.toolbarListWidget.currentRow() command = self.toolbarLists[toolbarNum].pop(pos) self.toolbarLists[toolbarNum].insert(pos - 1, command) item = self.toolbarListWidget.takeItem(pos) self.toolbarListWidget.insertItem(pos - 1, item) self.toolbarListWidget.setCurrentRow(pos - 1) self.toolbarListWidget.scrollToItem(item) self.setModified() def moveDown(self): """Lower the selected command. """ toolbarNum = self.toolbarCombo.currentIndex() pos = self.toolbarListWidget.currentRow() command = self.toolbarLists[toolbarNum].pop(pos) self.toolbarLists[toolbarNum].insert(pos + 1, command) item = self.toolbarListWidget.takeItem(pos) self.toolbarListWidget.insertItem(pos + 1, item) self.toolbarListWidget.setCurrentRow(pos + 1) self.toolbarListWidget.scrollToItem(item) self.setModified() def restoreDefaults(self): """Restore all default toolbar settings. """ self.loadToolbars(True) self.setModified() def applyChanges(self): """Apply any changes from the dialog. """ size = 16 if self.sizeCombo.currentIndex() == 0 else 32 globalref.toolbarOptions.changeValue('ToolbarSize', size) globalref.toolbarOptions.changeValue('ToolbarQuantity', self.numToolbars) del self.toolbarLists[self.numToolbars:] commands = [','.join(cmds) for cmds in self.toolbarLists] globalref.toolbarOptions.changeValue('ToolbarCommands', commands) globalref.toolbarOptions.writeFile() self.modified = False self.applyButton.setEnabled(False) self.updateFunction() def accept(self): """Apply changes and close the dialog. """ if self.modified: self.applyChanges() super().accept() class CustomFontData: """Class to store custom font settings. Acts as a stand-in for PrintData class in the font page of the dialog. """ def __init__(self, fontOption, useAppDefault=True): """Initialize the font data. Arguments: fontOption -- the name of the font setting to retrieve useAppDefault -- use app default if true, o/w use sys default """ self.fontOption = fontOption if useAppDefault: self.defaultFont = QTextDocument().defaultFont() else: self.defaultFont = QFont(globalref.mainControl.systemFont) self.useDefaultFont = True self.mainFont = QFont(self.defaultFont) fontName = globalref.miscOptions[self.fontOption] if fontName: self.mainFont.fromString(fontName) self.useDefaultFont = False def recordChanges(self): """Record the updated font info to the option settings. """ if self.useDefaultFont: globalref.miscOptions.changeValue(self.fontOption, '') else: globalref.miscOptions.changeValue(self.fontOption, self.mainFont.toString()) class CustomFontDialog(QDialog): """Dialog for selecting custom fonts. Uses the print setup dialog's font page for the details. """ updateRequired = pyqtSignal() def __init__(self, parent=None): """Create a font customization dialog. Arguments: parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Customize Fonts')) topLayout = QVBoxLayout(self) self.setLayout(topLayout) self.tabs = QTabWidget() topLayout.addWidget(self.tabs) self.tabs.setUsesScrollButtons(False) self.tabs.currentChanged.connect(self.updateTabDefault) self.pages = [] defaultLabel = _('&Use system default font') appFontPage = printdialogs.FontPage(CustomFontData('AppFont', False), defaultLabel) self.pages.append(appFontPage) self.tabs.addTab(appFontPage, _('App Default Font')) defaultLabel = _('&Use app default font') treeFontPage = printdialogs.FontPage(CustomFontData('TreeFont'), defaultLabel) self.pages.append(treeFontPage) self.tabs.addTab(treeFontPage, _('Tree View Font')) outputFontPage = printdialogs.FontPage(CustomFontData('OutputFont'), defaultLabel) self.pages.append(outputFontPage) self.tabs.addTab(outputFontPage, _('Output View Font')) editorFontPage = printdialogs.FontPage(CustomFontData('EditorFont'), defaultLabel) self.pages.append(editorFontPage) self.tabs.addTab(editorFontPage, _('Editor View Font')) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() self.okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(self.okButton) self.okButton.clicked.connect(self.accept) self.applyButton = QPushButton(_('&Apply')) ctrlLayout.addWidget(self.applyButton) self.applyButton.clicked.connect(self.applyChanges) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) def updateTabDefault(self): """Update the default font on the newly shown page. """ appFontWidget = self.tabs.widget(0) currentWidget = self.tabs.currentWidget() if appFontWidget is not currentWidget: if appFontWidget.defaultCheck.isChecked(): defaultFont = QFont(globalref.mainControl.systemFont) else: defaultFont = appFontWidget.readFont() if defaultFont: currentWidget.printData.defaultFont = defaultFont if currentWidget.defaultCheck.isChecked(): currentWidget.printData.mainFont = QFont(defaultFont) currentWidget.currentFont = (currentWidget.printData. mainFont) currentWidget.setFont(defaultFont) def applyChanges(self): """Apply any changes from the dialog. """ modified = False for page in self.pages: if page.saveChanges(): page.printData.recordChanges() modified = True if modified: globalref.miscOptions.writeFile() self.updateRequired.emit() def accept(self): """Apply changes and close the dialog. """ self.applyChanges() super().accept() class AboutDialog(QDialog): """Show program info in a text box. """ def __init__(self, title, textLines, icon=None, parent=None): """Create the dialog. Arguments: title -- the window title text textLines -- a list of lines to show icon -- an icon to show if given parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(title) topLayout = QVBoxLayout(self) self.setLayout(topLayout) mainLayout = QHBoxLayout() topLayout.addLayout(mainLayout) iconLabel = QLabel() iconLabel.setPixmap(icon.pixmap(128, 128)) mainLayout.addWidget(iconLabel) textBox = QPlainTextEdit() textBox.setReadOnly(True) textBox.setWordWrapMode(QTextOption.WrapMode.NoWrap) textBox.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) textBox.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) text = '\n'.join(textLines) textBox.setPlainText(text) size = textBox.fontMetrics().size(0, text) size.setHeight(size.height() + 10) size.setWidth(size.width() + 10) textBox.setMinimumSize(size) mainLayout.addWidget(textBox) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) TreeLine-3.2.1/source/nodeformat.py000066400000000000000000000606551506556630100172570ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # nodeformat.py, provides a class to handle node format objects # # TreeLine, an information storage program # Copyright (C) 2023, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import collections import os.path import sys import copy import operator import datetime import xml.sax.saxutils if not sys.platform.startswith('win'): import pwd import fieldformat import conditional defaultFieldName = _('Name') _defaultOutputSeparator = ', ' _fieldSplitRe = re.compile(r'({\*(?:\**|\?|!|&|#)[\w_\-.]+\*})') _fieldPartRe = re.compile(r'{\*(\**|\?|!|&|#)([\w_\-.]+)\*}') _endTagRe = re.compile(r'.*(|||)$') _levelFieldRe = re.compile(r'[^0-9]+([0-9]+)$') class NodeFormat: """Class to handle node format info Stores node field lists and line formatting. Provides methods to return formatted data. """ def __init__(self, name, parentFormats, formatData=None, addDefaultField=False): """Initialize a tree format. Arguments: name -- the type name string parentFormats -- a ref to TreeFormats class for outside field refs formatData -- the JSON dict for this format addDefaultField -- if true, adds a default initial field """ self.name = name self.parentFormats = parentFormats self.savedConditionText = {} self.conditional = None self.childTypeLimit = set() self.readFormat(formatData) self.siblingPrefix = '' self.siblingSuffix = '' self.derivedTypes = [] self.origOutputLines = [] # lines without bullet or table modifications self.sortFields = [] # temporary storage while sorting if addDefaultField: self.addFieldIfNew(defaultFieldName) self.titleLine = ['{{*{0}*}}'.format(defaultFieldName)] self.outputLines = [['{{*{0}*}}'.format(defaultFieldName)]] self.updateLineParsing() if self.useBullets: self.addBullets() if self.useTables: self.addTables() def readFormat(self, formatData=None): """Read JSON format data into this format. Arguments: formatData -- JSON dict for this format (None for default settings) """ self.fieldDict = collections.OrderedDict() if formatData: for fieldData in formatData.get('fields', []): fieldName = fieldData['fieldname'] self.addField(fieldName, fieldData) else: formatData = {} self.titleLine = [formatData.get('titleline', '')] self.outputLines = [[line] for line in formatData.get('outputlines', [])] self.spaceBetween = formatData.get('spacebetween', True) self.formatHtml = formatData.get('formathtml', False) self.useBullets = formatData.get('bullets', False) self.useTables = formatData.get('tables', False) self.childType = formatData.get('childtype', '') self.genericType = formatData.get('generic', '') if 'condition' in formatData: self.conditional = conditional.Conditional(formatData['condition']) if 'childTypeLimit' in formatData: self.childTypeLimit = set(formatData['childTypeLimit']) else: self.childTypeLimit = set() self.iconName = formatData.get('icon', '') self.outputSeparator = formatData.get('outputsep', _defaultOutputSeparator) for key in formatData.keys(): if key.startswith('cond-'): self.savedConditionText[key[5:]] = formatData[key] def storeFormat(self): """Return JSON format data for this format. """ formatData = {} formatData['formatname'] = self.name formatData['fields'] = [field.formatData() for field in self.fields()] formatData['titleline'] = self.getTitleLine() formatData['outputlines'] = self.getOutputLines() if not self.spaceBetween: formatData['spacebetween'] = False if self.formatHtml: formatData['formathtml'] = True if self.useBullets: formatData['bullets'] = True if self.useTables: formatData['tables'] = True if self.childType: formatData['childtype'] = self.childType if self.genericType: formatData['generic'] = self.genericType if self.conditional: formatData['condition'] = self.conditional.conditionStr() if self.childTypeLimit: formatData['childTypeLimit'] = sorted(list(self.childTypeLimit)) if self.iconName: formatData['icon'] = self.iconName if self.outputSeparator != _defaultOutputSeparator: formatData['outputsep'] = self.outputSeparator for key, text in self.savedConditionText.items(): formatData['cond-' + key] = text return formatData def copySettings(self, sourceFormat): """Copy all settings from another format to this one. Arguments: sourceFormat -- the format to copy """ self.name = sourceFormat.name self.readFormat(sourceFormat.storeFormat()) self.siblingPrefix = sourceFormat.siblingPrefix self.siblingSuffix = sourceFormat.siblingSuffix self.outputLines = sourceFormat.getOutputLines(False) self.origOutputLines = sourceFormat.getOutputLines() self.updateLineParsing() def fields(self): """Return list of all fields. """ return self.fieldDict.values() def fieldNames(self): """Return list of names of all fields. """ return list(self.fieldDict.keys()) def formatTitle(self, node, spotRef=None): """Return a string with formatted title data. Arguments: node -- the node used to get data for fields spotRef -- optional, used for ancestor field refs """ line = ''.join([part.outputText(node, True, True, self.formatHtml) if hasattr(part, 'outputText') else part for part in self.titleLine]) return line.strip() def formatOutput(self, node, plainText=False, keepBlanks=False, spotRef=None): """Return a list of formatted text output lines. Arguments: node -- the node used to get data for fields plainText -- if True, remove HTML markup from fields and formats keepBlanks -- if True, keep lines with empty fields spotRef -- optional, used for ancestor field refs """ result = [] for lineData in self.outputLines: line = '' numEmptyFields = 0 numFullFields = 0 for part in lineData: if hasattr(part, 'outputText'): text = part.outputText(node, False, plainText, self.formatHtml) if text: numFullFields += 1 else: numEmptyFields += 1 line += text else: if not self.formatHtml and not plainText: part = xml.sax.saxutils.escape(part) elif self.formatHtml and plainText: part = fieldformat.removeMarkup(part) line += part if keepBlanks or numFullFields or not numEmptyFields: result.append(line) elif self.formatHtml and not plainText and result: # add ending HTML tag from skipped line back to previous line endTagMatch = _endTagRe.match(line) if endTagMatch: result[-1] += endTagMatch.group(1) return result def addField(self, name, fieldData=None): """Add a field type with its format to the field list. Arguments: name -- the field name string fieldData -- the dict that defines this field's format """ if not fieldData: fieldData = {} typeName = '{}Field'.format(fieldData.get('fieldtype', 'Text')) fieldClass = getattr(fieldformat, typeName, fieldformat.TextField) field = fieldClass(name, fieldData) self.fieldDict[name] = field def addFieldIfNew(self, name, fieldData=None): """Add a field type to the field list if not already there. Arguments: name -- the field name string fieldData -- the dict that defines this field's format """ if name not in self.fieldDict: self.addField(name, fieldData) def addFieldList(self, nameList, addFirstTitle=False, addToOutput=False): """Add text fields with names given in list. Also add to title and output lines if addOutput is True. Arguments: nameList -- the list of names to add addFirstTitle -- if True, use first field for title output format addToOutput -- replace output lines with all fields if True """ for name in nameList: self.addFieldIfNew(name) if addFirstTitle: self.changeTitleLine('{{*{0}*}}'.format(nameList[0])) if addToOutput: self.changeOutputLines(['{{*{0}*}}'.format(name) for name in nameList]) def reorderFields(self, fieldNameList): """Change the order of fieldDict to match the given list. Arguments: fieldNameList -- a list of existing field names in a desired order """ newFieldDict = collections.OrderedDict() for fieldName in fieldNameList: newFieldDict[fieldName] = self.fieldDict[fieldName] self.fieldDict = newFieldDict def removeField(self, field): """Remove all occurances of field from title and output lines. Arguments: field -- the field to be removed """ while field in self.titleLine: self.titleLine.remove(field) for lineData in self.outputLines: while field in lineData: lineData.remove(field) self.outputLines = [line for line in self.outputLines if line] # if len(self.lineList) == 0: # self.lineList.append(['']) def setInitDefaultData(self, data, overwrite=False): """Add initial default data from fields into supplied data dict. Arguments: data -- the data dict to modify overwrite -- if true, replace previous data entries """ for field in self.fields(): text = field.getInitDefault() if text and (overwrite or not data.get(field.name, '')): data[field.name] = text def updateLineParsing(self): """Update the fields parsed in the output lines. Converts lines back to whole lines with embedded field names, then parse back to individual fields and text. """ self.titleLine = self.parseLine(self.getTitleLine()) self.outputLines = [self.parseLine(line) for line in self.getOutputLines(False)] if self.origOutputLines: self.origOutputLines = [self.parseLine(line) for line in self.getOutputLines(True)] def parseLine(self, text): """Parse text format line, return list of field types and text. Splits the line into field and text segments. Arguments: text -- the raw format text line to be parsed """ text = ' '.join(text.split()) segments = (part for part in _fieldSplitRe.split(text) if part) return [self.parseField(part) for part in segments] def parseField(self, text): """Parse text field, return field type or plain text if not a field. Arguments: text -- the raw format text (could be a field) """ fieldMatch = _fieldPartRe.match(text) if fieldMatch: modifier = fieldMatch.group(1) fieldName = fieldMatch.group(2) try: if not modifier: return self.fieldDict[fieldName] elif modifier == '*' * len(modifier): return fieldformat.AncestorLevelField(fieldName, len(modifier)) elif modifier == '?': return fieldformat.AnyAncestorField(fieldName) elif modifier == '&': return fieldformat.ChildListField(fieldName) elif modifier == '#': match = _levelFieldRe.match(fieldName) if match and match.group(1) != '0': level = int(match.group(1)) return fieldformat.DescendantCountField(fieldName, level) elif modifier == '!': return (self.parentFormats.fileInfoFormat. fieldDict[fieldName]) except KeyError: pass return text def getTitleLine(self): """Return text of title format with field names embedded. """ return ''.join([part.sepName() if hasattr(part, 'sepName') else part for part in self.titleLine]) def getOutputLines(self, useOriginal=True): """Return text list of output format lines with field names embedded. Arguments: useOriginal -- use original line list, wothout bullet or table mods """ lines = self.outputLines if useOriginal and self.origOutputLines: lines = self.origOutputLines lines = [''.join([part.sepName() if hasattr(part, 'sepName') else part for part in line]) for line in lines] return lines if lines else [''] def changeTitleLine(self, text): """Replace the title format line. Arguments: text -- the new title format line """ self.titleLine = self.parseLine(text) if not self.titleLine: self.titleLine = [''] def changeOutputLines(self, lines, keepBlanks=False): """Replace the output format lines with given list. Arguments: lines -- a list of replacement format lines keepBlanks -- if False, ignore blank lines """ self.outputLines = [] for line in lines: newLine = self.parseLine(line) if keepBlanks or newLine: self.outputLines.append(newLine) if self.useBullets: self.origOutputLines = self.outputLines[:] self.addBullets() if self.useTables: self.origOutputLines = self.outputLines[:] self.addTables() def addOutputLine(self, line): """Add an output format line after existing lines. Arguments: line -- the text line to add """ newLine = self.parseLine(line) if newLine: self.outputLines.append(newLine) def extractTitleData(self, titleString, data): """Modifies the data dictionary based on a title string. Match the title format to the string, return True if successful. Arguments: title -- the string with the new title data -- the data dictionary to be modified """ fields = [] pattern = '' extraText = '' for seg in self.titleLine: if hasattr(seg, 'name'): # a field segment fields.append(seg) pattern += '(.*)' else: # a text separator pattern += re.escape(seg) extraText += seg match = re.match(pattern, titleString) try: if match: for num, field in enumerate(fields): text = match.group(num + 1) data[field.name] = field.storedTextFromTitle(text) elif not extraText.strip(): # assign to 1st field if sep is only spaces text = fields[0].storedTextFromTitle(titleString) data[fields[0].name] = text for field in fields[1:]: data[field.name] = '' else: return False except ValueError: return False return True def updateDerivedTypes(self): """Update derived types after changes to this generic type. """ for derivedType in self.derivedTypes: derivedType.updateFromGeneric(self) def updateFromGeneric(self, genericType=None, formatsRef=None): """Update fields and field types to match a generic type. Does nothing if self is not a derived type. Must provide either the genericType or a formatsRef. Arguments: genericType -- the type to update from formatsRef -- the tree formats dict to update from """ if not self.genericType: return if not genericType: genericType = formatsRef[self.genericType] newFields = collections.OrderedDict() for field in genericType.fieldDict.values(): fieldMatch = self.fieldDict.get(field.name, None) if fieldMatch and field.typeName == fieldMatch.typeName: newFields[field.name] = fieldMatch else: newFields[field.name] = copy.deepcopy(field) self.fieldDict = newFields self.updateLineParsing() def addBullets(self): """Add bullet HTML tags to sibling prefix, suffix and output lines. """ self.siblingPrefix = '
      ' self.siblingSuffix = '
    ' lines = self.getOutputLines() if lines != ['']: lines[0] = '
  • ' + lines[0] lines[-1] += '
  • ' self.origOutputLines = self.outputLines[:] self.outputLines = lines self.updateLineParsing() def addTables(self): """Add table HTML tags to sibling prefix, suffix and output lines. """ lines = [line for line in self.getOutputLines() if line] newLines = [] headings = [] for line in lines: head = '' firstPart = self.parseLine(line)[0] if hasattr(firstPart, 'split') and ':' in firstPart: head, line = line.split(':', 1) newLines.append(line.strip()) headings.append(head.strip()) self.siblingPrefix = '' if [head for head in headings if head]: self.siblingPrefix += '' for head in headings: self.siblingPrefix = ('{0}'. format(self.siblingPrefix, head)) self.siblingPrefix += '' self.siblingSuffix = '
    {1}
    ' newLines = ['{0}'.format(line) for line in newLines] newLines[0] = '' + newLines[0] newLines[-1] += '' self.origOutputLines = self.outputLines[:] self.outputLines = newLines self.updateLineParsing() def clearBulletsAndTables(self): """Remove any HTML tags for bullets and tables. """ self.siblingPrefix = '' self.siblingSuffix = '' if self.origOutputLines: self.outputLines = self.origOutputLines self.updateLineParsing() self.origOutputLines = [] def numberingFieldList(self): """Return a list of numbering field names. """ return [field.name for field in self.fieldDict.values() if field.typeName == 'Numbering'] def loadSortFields(self): """Add sort fields to temporarily stored list. Only used for efficiency while sorting. """ self.sortFields = [field for field in self.fields() if field.sortKeyNum > 0] self.sortFields.sort(key = operator.attrgetter('sortKeyNum')) if not self.sortFields: self.sortFields = [list(self.fields())[0]] class FileInfoFormat(NodeFormat): """Node format class to store and update special file info fields. Fields used in print header/footer and in outputs of other node types. """ typeName = 'INT_TL_FILE_DATA_FORM' fileFieldName = 'File_Name' pathFieldName = 'File_Path' sizeFieldName = 'File_Size' dateFieldName = 'File_Mod_Date' timeFieldName = 'File_Mod_Time' ownerFieldName = 'File_Owner' pageNumFieldName = 'Page_Number' numPagesFieldName = 'Number_of_Pages' def __init__(self, parentFormats): """Create a file info format. """ super().__init__(FileInfoFormat.typeName, parentFormats) self.fieldFormatModified = False self.addField(FileInfoFormat.fileFieldName) self.addField(FileInfoFormat.pathFieldName) self.addField(FileInfoFormat.sizeFieldName, {'fieldtype': 'Number'}) self.addField(FileInfoFormat.dateFieldName, {'fieldtype': 'Date'}) self.addField(FileInfoFormat.timeFieldName, {'fieldtype': 'Time'}) if not sys.platform.startswith('win'): self.addField(FileInfoFormat.ownerFieldName) # page info only for print header: self.addField(FileInfoFormat.pageNumFieldName) self.fieldDict[FileInfoFormat.pageNumFieldName].showInDialog = False self.addField(FileInfoFormat.numPagesFieldName) self.fieldDict[FileInfoFormat.numPagesFieldName].showInDialog = False for field in self.fields(): field.useFileInfo = True def updateFileInfo(self, fileObj, fileInfoNode): """Update data of file info node. Arguments: fileObj -- the TreeLine file path object fileInfoNode -- the node to update """ try: status = fileObj.stat() except (AttributeError, OSError): fileInfoNode.data = {} return fileInfoNode.data[FileInfoFormat.fileFieldName] = fileObj.name fileInfoNode.data[FileInfoFormat.pathFieldName] = fileObj.parent fileInfoNode.data[FileInfoFormat.sizeFieldName] = str(status.st_size) modDateTime = datetime.datetime.fromtimestamp(status.st_mtime) modDate = modDateTime.date().strftime(fieldformat.DateField.isoFormat) modTime = modDateTime.time().strftime(fieldformat.TimeField.isoFormat) fileInfoNode.data[FileInfoFormat.dateFieldName] = modDate fileInfoNode.data[FileInfoFormat.timeFieldName] = modTime if not sys.platform.startswith('win'): try: owner = pwd.getpwuid(status.st_uid)[0] except KeyError: owner = repr(status.st_uid) fileInfoNode.data[FileInfoFormat.ownerFieldName] = owner def duplicateFileInfo(self, altFileFormat): """Copy field format settings from alternate file format. Arguments: altFileFormat -- the file info format to copy from """ for field in self.fields(): altField = altFileFormat.fieldDict.get(field.name) if altField: if field.format != altField.format: field.setFormat(altField.format) self.fieldFormatModified = True if altField.prefix: field.prefix = altField.prefix self.fieldFormatModified = True if altField.suffix: field.suffix = altField.suffix self.fieldFormatModified = True class DescendantCountFormat(NodeFormat): """Placeholder format for child count fields. Should not show up in main format type list. """ countFieldName = 'Level' def __init__(self): super().__init__('CountFormat', None) for level in range(3): name = '{0}{1}'.format(DescendantCountFormat.countFieldName, level + 1) field = fieldformat.DescendantCountField(name, level + 1) self.fieldDict[name] = field TreeLine-3.2.1/source/numbering.py000066400000000000000000000155531506556630100171040ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # numbering.py, provides classes to format node numbering # # TreeLine, an information storage program # Copyright (C) 2019, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re class NumberingGroup: """Class to store a multi-level numbering format and apply it. """ def __init__(self, numFormat=''): """Initialize a multi-level numbering format. Arguments: numFormat -- a string describing the format """ self.basicFormats = [] self.sectionStyle = False if numFormat: self.setFormat(numFormat) def setFormat(self, numFormat): """Set a new number format. Arguments: numFormat -- a string describing the format """ self.sectionStyle = False formats = _splitText(numFormat.replace('..', '.'), '/') if len(formats) < 2: formats = _splitText(numFormat.replace('//', '/'), '.') if len(formats) > 1: self.sectionStyle = True self.basicFormats = [BasicNumbering(numFormat) for numFormat in formats] def numString(self, inputNumStr): """Return a number string for the given level and input. The current numbering level is the segment length of the input. Raises ValueError on a bad input string. Arguments: inputNumStr -- a dot-separated string of integers """ if not inputNumStr: return '' inputNums = [int(num) for num in inputNumStr.split('.')] if self.sectionStyle: basicFormats = self.basicFormats[:] if len(basicFormats) < len(inputNums): basicFormats.extend([basicFormats[-1]] * (len(inputNums) - len(basicFormats))) results = [basicFormat.numString(num) for basicFormat, num in zip(basicFormats, inputNums)] return '.'.join(results) else: level = len(inputNums) - 1 try: basicFormat = self.basicFormats[level] except IndexError: basicFormat = self.basicFormats[-1] return basicFormat.numString(inputNums[level]) _formatRegEx = re.compile(r'(.*?)([1AaIi]{1,2})(\W*)$') class BasicNumbering: """Class to store an individaul numbering format and apply it. """ def __init__(self, numFormat=''): """Initialize a basic numbering format. Arguments: numFormat -- a string describing the format """ self.numFunction = _stringFromNum self.upperCase = True self.prefix = '' self.suffix = '' if numFormat: self.setFormat(numFormat) def setFormat(self, numFormat): """Set a new number format. Arguments: numFormat -- a string describing the format """ match = _formatRegEx.match(numFormat) if match: self.prefix, series, self.suffix = match.groups() if series == '1': self.numFunction = _stringFromNum elif series in 'Aa': self.numFunction = _alphaFromNum elif series in 'AAaa': self.numFunction = _alpha2FromNum else: self.numFunction = _romanFromNum self.upperCase = series.isupper() else: self.prefix = numFormat self.numFunction = _stringFromNum def numString(self, num): """Return a number string for the given integer. Arguments: num -- the integer to convert """ return '{0}{1}{2}'.format(self.prefix, self.numFunction(num, self.upperCase), self.suffix) def _stringFromNum(num, case=None): """Return a number string from an integer. Arguments: num -- the integer to convert case -- an unused placeholder """ if num > 0: return repr(num) return '' def _alphaFromNum(num, upperCase=True): """Return an alphabetic string from an integer. Sequence is 'A', 'B' ... 'Z', 'AA', 'BB' ... 'ZZ', 'AAA', 'BBB' ... Arguments: num -- the integer to convert upperCase -- return an upper case string if true """ if num <= 0: return '' result = '' charPos = (num - 1) % 26 char = chr(charPos + ord('A')) qty = (num - 1) // 26 + 1 result = char * qty if not upperCase: result = result.lower() return result def _alpha2FromNum(num, upperCase=True): """Return an alphabetic string from an integer. Sequence is 'AA', 'BB' ... 'ZZ', 'AAA', 'BBB' ... 'ZZZ', 'AAAA', 'BBBB' ... Arguments: num -- the integer to convert upperCase -- return an upper case string if true """ if num <= 0: return '' result = '' charPos = (num - 1) % 26 char = chr(charPos + ord('A')) qty = (num - 1) // 26 + 2 result = char * qty if not upperCase: result = result.lower() return result _romanDict = {0: '', 1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V', 6: 'VI', 7: 'VII', 8: 'VIII', 9: 'IX', 10: 'X', 20: 'XX', 30: 'XXX', 40: 'XL', 50: 'L', 60: 'LX', 70: 'LXX', 80: 'LXXX', 90: 'XC', 100: 'C', 200: 'CC', 300: 'CCC', 400: 'CD', 500: 'D', 600: 'DC', 700: 'DCC', 800: 'DCCC', 900: 'CM', 1000: 'M', 2000: 'MM', 3000: 'MMM'} def _romanFromNum(num, upperCase=True): """Return a roman numeral string from an integer. Arguments: num -- the integer to convert upperCase -- return an upper case string if true """ if num <= 0 or num >= 4000: return '' result = '' factor = 1000 while num: digit = num - (num % factor) result += _romanDict[digit] factor = factor // 10 num -= digit if not upperCase: result = result.lower() return result def _splitText(textStr, delimitChar): """Split text using the given delimitter and return a list. Double delimitters are not split and empty parts are ignored. Arguments: textStr -- the text to split delimitChar -- the delimitter """ result = [] textStr = textStr.replace(delimitChar * 2, '\0') for text in textStr.split(delimitChar): text = text.replace('\0', delimitChar) if text: result.append(text) return result TreeLine-3.2.1/source/optiondefaults.py000066400000000000000000000364131506556630100201540ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # optiondefaults.py, defines defaults for config options # # TreeLine, an information storage program # Copyright (C) 2022, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import options daysOfWeek = [_('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday'), _('Sunday')] # colorThemes = [_('Normal'), _('Dark')] def setGenOptionDefaults(generalOptions): """Set defaults for general config options. """ StringOptionItem = options.StringOptionItem IntOptionItem = options.IntOptionItem BoolOptionItem = options.BoolOptionItem ListOptionItem = options.ListOptionItem BoolOptionItem(generalOptions, 'AutoFileOpen', False, _('Startup Condition'), _('Automatically open last file used')) BoolOptionItem(generalOptions, 'InitShowBreadcrumb', True, _('Startup Condition'), _('Show breadcrumb ancestor view')) BoolOptionItem(generalOptions, 'InitShowChildPane', True, _('Startup Condition'), _('Show child pane in right hand views')) BoolOptionItem(generalOptions, 'InitShowDescendants', False, _('Startup Condition'), _('Show descendants in output view')) BoolOptionItem(generalOptions, 'SaveTreeStates', True, _('Startup Condition'), _('Restore tree view states of recent files')) BoolOptionItem(generalOptions, 'PurgeRecentFiles', True, _('Startup Condition'), _('Remove inaccessible recent file entries')) BoolOptionItem(generalOptions, 'SaveWindowGeom', True, _('Startup Condition'), _('Restore previous window geometry')) BoolOptionItem(generalOptions, 'OpenNewWindow', True, _('Features Available'), _('Open files in new windows')) BoolOptionItem(generalOptions, 'MinToSysTray', False, _('Features Available'), _('Minimize application to system tray')) BoolOptionItem(generalOptions, 'EditorOnHover', True, _('Features Available'), _('Activate data editors on mouse hover')) BoolOptionItem(generalOptions, 'EditorLimitHeight', True, _('Features Available'), _('Limit data editor height to window size')) BoolOptionItem(generalOptions, 'ClickRename', True, _('Features Available'), _('Click node to rename')) BoolOptionItem(generalOptions, 'RenameNewNodes', True, _('Features Available'), _('Rename new nodes when created')) BoolOptionItem(generalOptions, 'DragTree', True, _('Features Available'), _('Tree drag && drop available')) BoolOptionItem(generalOptions, 'PrettyPrint', False, _('Features Available'), _('Indent (pretty print) TreeLine JSON files')) BoolOptionItem(generalOptions, 'ShowTreeIcons', True, _('Features Available'), _('Show icons in the tree view')) BoolOptionItem(generalOptions, 'ShowMath', True, _('Features Available'), _('Show math fields in the Data Edit view')) BoolOptionItem(generalOptions, 'EditNumbering', False, _('Features Available'), _('Show numbering fields in the Data Edit view')) IntOptionItem(generalOptions, 'UndoLevels', 5, 0, 999, _('Undo Memory'), _('Number of undo levels'), 1) IntOptionItem(generalOptions, 'AutoSaveMinutes', 0, 0, 999, _('Auto Save'), _('Minutes between saves\n(set to 0 to disable)'), 1) IntOptionItem(generalOptions, 'RecentFiles', 4, 0, 99, _('Recent Files'), _('Number of recent files \nin the file menu'), 1) StringOptionItem(generalOptions, 'EditTimeFormat', '%-H:%M:%S', False, True, _('Data Editor Formats'), _('Times'), 1) StringOptionItem(generalOptions, 'EditDateFormat', '%m/%d/%y', False, True, _('Data Editor Formats'), _('Dates'), 1) ListOptionItem(generalOptions, 'WeekStart', daysOfWeek[-1], daysOfWeek, _('Data Editor Formats'), _('First day\nof week'), 1) IntOptionItem(generalOptions, 'IndentOffset', 2, 0, 99, _('Appearance'), _('Child indent offset\n(in font height units) '), 1) # ListOptionItem(generalOptions, 'ColorTheme', colorThemes[0], colorThemes, # _('Appearance'), _('Color Theme'), 1) def setMiscOptionDefaults(miscOptions): """Set defaults for miscellaneous config options. """ StringOptionItem = options.StringOptionItem StringOptionItem(miscOptions, 'PrintUnits', 'in', False, True) StringOptionItem(miscOptions, 'SpellCheckPath', '') StringOptionItem(miscOptions, 'AppFont', '', True, True) StringOptionItem(miscOptions, 'TreeFont', '', True, True) StringOptionItem(miscOptions, 'OutputFont', '', True, True) StringOptionItem(miscOptions, 'EditorFont', '', True, True) StringOptionItem(miscOptions, 'ColorTheme', 'system', False, True) StringOptionItem(miscOptions, 'WindowColor', '', True, True) StringOptionItem(miscOptions, 'WindowTextColor', '', True, True) StringOptionItem(miscOptions, 'BaseColor', '', True, True) StringOptionItem(miscOptions, 'TextColor', '', True, True) StringOptionItem(miscOptions, 'HighlightColor', '', True, True) StringOptionItem(miscOptions, 'HighlightedTextColor', '', True, True) StringOptionItem(miscOptions, 'LinkColor', '', True, True) StringOptionItem(miscOptions, 'ToolTipBaseColor', '', True, True) StringOptionItem(miscOptions, 'ToolTipTextColor', '', True, True) StringOptionItem(miscOptions, 'ButtonColor', '', True, True) StringOptionItem(miscOptions, 'ButtonTextColor', '', True, True) StringOptionItem(miscOptions, 'Text-DisabledColor', '', True, True) StringOptionItem(miscOptions, 'ButtonText-DisabledColor', '', True, True) def setHistOptionDefaults(historyOptions): """Set defaults for history config options. """ IntOptionItem = options.IntOptionItem DataListOptionItem = options.DataListOptionItem IntOptionItem(historyOptions, 'WindowXSize', 640, 10, 10000) IntOptionItem(historyOptions, 'WindowYSize', 640, 10, 10000) IntOptionItem(historyOptions, 'WindowXPos', -1000, -1000, 10000) IntOptionItem(historyOptions, 'WindowYPos', -1000, -1000, 10000) IntOptionItem(historyOptions, 'WindowTopMargin', 0, 0, 1000) IntOptionItem(historyOptions, 'WindowOtherMargin', 0, 0, 1000) IntOptionItem(historyOptions, 'CrumbSplitPercent', 10, 1, 99) IntOptionItem(historyOptions, 'TreeSplitPercent', 40, 1, 99) IntOptionItem(historyOptions, 'OutputSplitPercent', 20, 1, 99) IntOptionItem(historyOptions, 'EditorSplitPercent', 25, 1, 99) IntOptionItem(historyOptions, 'TitleSplitPercent', 10, 1, 99) IntOptionItem(historyOptions, 'ActiveRightView', 0, 0, 2) IntOptionItem(historyOptions, 'PrintPrevXSize', 0, 0, 10000) IntOptionItem(historyOptions, 'PrintPrevYSize', 0, 0, 10000) IntOptionItem(historyOptions, 'PrintPrevXPos', -1000, -1000, 10000) IntOptionItem(historyOptions, 'PrintPrevYPos', -1000, -1000, 10000) DataListOptionItem(historyOptions, 'RecentFiles', []) def setToolbarOptionDefaults(toolbarOptions): """Set defaults for toolbar geometry and buttons. """ StringOptionItem = options.StringOptionItem DataListOptionItem = options.DataListOptionItem IntOptionItem = options.IntOptionItem IntOptionItem(toolbarOptions, 'ToolbarQuantity', 2, 0, 20) IntOptionItem(toolbarOptions, 'ToolbarSize', 16, 1, 128) StringOptionItem(toolbarOptions, 'ToolbarPosition', '') DataListOptionItem(toolbarOptions, 'ToolbarCommands', ['FileNew,FileOpen,FileSave,,FilePrintPreview,' 'FilePrint,,EditUndo,EditRedo,,EditCut,EditCopy,' 'EditPaste,,DataConfigType,ToolsFindText', 'NodeInsertAfter,NodeAddChild,,NodeDelete,NodeIndent,' 'NodeUnindent,,NodeMoveUp,NodeMoveDown,,' 'ViewExpandBranch,ViewCollapseBranch,,' 'ViewPrevSelect,ViewNextSelect,,ViewShowDescend']) def setKeyboardOptionDefaults(keyboardOptions): """Set defaults for keyboard shortcuts. """ KeyOptionItem = options.KeyOptionItem KeyOptionItem(keyboardOptions, 'FileNew', 'Ctrl+N', 'File Menu') KeyOptionItem(keyboardOptions, 'FileOpen', 'Ctrl+O', 'File Menu') KeyOptionItem(keyboardOptions, 'FileOpenSample', '', 'File Menu') KeyOptionItem(keyboardOptions, 'FileImport', '', 'File Menu') KeyOptionItem(keyboardOptions, 'FileSave', 'Ctrl+S', 'File Menu') KeyOptionItem(keyboardOptions, 'FileSaveAs', '', 'File Menu') KeyOptionItem(keyboardOptions, 'FileExport', '', 'File Menu') KeyOptionItem(keyboardOptions, 'FileProperties', '', 'File Menu') KeyOptionItem(keyboardOptions, 'FilePrintSetup', '', 'File Menu') KeyOptionItem(keyboardOptions, 'FilePrintPreview', '', 'File Menu') KeyOptionItem(keyboardOptions, 'FilePrint', 'Ctrl+P', 'File Menu') KeyOptionItem(keyboardOptions, 'FilePrintPdf', '', 'File Menu') KeyOptionItem(keyboardOptions, 'FileQuit', 'Ctrl+Q', 'File Menu') KeyOptionItem(keyboardOptions, 'EditUndo', 'Ctrl+Z', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditRedo', 'Ctrl+Y', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditCut', 'Ctrl+X', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditCopy', 'Ctrl+C', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditPaste', 'Ctrl+V', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditPastePlain', '', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditPasteChild', '', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditPasteBefore', '', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditPasteAfter', '', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditPasteCloneChild', '', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditPasteCloneBefore', '', 'Edit Menu') KeyOptionItem(keyboardOptions, 'EditPasteCloneAfter', '', 'Edit Menu') KeyOptionItem(keyboardOptions, 'NodeRename', 'Ctrl+R', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeAddChild', 'Ctrl+A', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeInsertBefore', 'Ctrl+B', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeInsertAfter', 'Ctrl+I', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeDelete', 'Del', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeIndent', 'Ctrl+Shift+Right', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeUnindent', 'Ctrl+Shift+Left', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeMoveUp', 'Ctrl+Shift+Up', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeMoveDown', 'Ctrl+Shift+Down', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeMoveFirst', '', 'Node Menu') KeyOptionItem(keyboardOptions, 'NodeMoveLast', '', 'Node Menu') KeyOptionItem(keyboardOptions, 'DataNodeType', 'Ctrl+T', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataConfigType', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataCopyType', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataVisualConfig', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataSortNodes', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataNumbering', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataRegenRefs', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataCloneMatches', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataDetachClones', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataFlatCategory', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataAddCategory', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'DataSwapCategory', '', 'Data Menu') KeyOptionItem(keyboardOptions, 'ToolsFindText', 'Ctrl+F', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsFindCondition', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsFindReplace', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsFilterText', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsFilterCondition', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsSpellCheck', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsGenOptions', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsShortcuts', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsToolbars', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsFonts', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'ToolsColors', '', 'Tools Menu') KeyOptionItem(keyboardOptions, 'FormatBoldFont', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatItalicFont', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatUnderlineFont', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatStrikethroughFont', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatFontSize', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatFontColor', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatExtLink', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatIntLink', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatInsertDate', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatSelectAll', 'Ctrl+L', 'Format Menu') KeyOptionItem(keyboardOptions, 'FormatClearFormat', '', 'Format Menu') KeyOptionItem(keyboardOptions, 'ViewExpandBranch', 'Ctrl+Right', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewCollapseBranch', 'Ctrl+Left', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewPrevSelect', 'Ctrl+Shift+P', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewNextSelect', 'Ctrl+Shift+N', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewDataOutput', 'Ctrl+Shift+O', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewDataEditor', 'Ctrl+Shift+E', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewTitleList', 'Ctrl+Shift+T', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewBreadcrumb', '', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewShowChildPane', 'Ctrl+Shift+C', 'View Menu') KeyOptionItem(keyboardOptions, 'ViewShowDescend', 'Ctrl+Shift+D', 'View Menu') KeyOptionItem(keyboardOptions, 'WinNewWindow', '', 'Window Menu') KeyOptionItem(keyboardOptions, 'WinCloseWindow', '', 'Window Menu') KeyOptionItem(keyboardOptions, 'HelpBasic', '', 'Help Menu') KeyOptionItem(keyboardOptions, 'HelpFull', '', 'Help Menu') KeyOptionItem(keyboardOptions, 'HelpAbout', '', 'Help Menu') KeyOptionItem(keyboardOptions, 'IncremSearchStart', 'Ctrl+/', 'No Menu') KeyOptionItem(keyboardOptions, 'IncremSearchNext', 'F3', 'No Menu') KeyOptionItem(keyboardOptions, 'IncremSearchPrev', 'Shift+F3', 'No Menu') TreeLine-3.2.1/source/options.py000066400000000000000000000656551506556630100166210ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # options.py, provides a class to manage config options # # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** from collections import OrderedDict import sys import re import pathlib import os.path import json from PyQt6.QtCore import Qt from PyQt6.QtGui import QKeySequence from PyQt6.QtWidgets import (QButtonGroup, QCheckBox, QComboBox, QDialog, QDoubleSpinBox, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QPushButton, QRadioButton, QSpinBox, QVBoxLayout) import miscdialogs multipleSpaceRegEx = re.compile(r' {2,}') class StringOptionItem: """Class to store and control a string-based config option entry. Stores the name, value, category and description, provides validation, config file output and dialog controls. """ def __init__(self, optionDict, name, value, emptyOK=True, stripSpaces=False, category='', description='', columnNum=0): """Set the parameters and initial value and add to optionDict. Raises a ValueError if initial validation fails. Arguments: optionDict -- a dictionary to add this option item to name -- the string key for the option value -- the string value emptyOK -- if False, does not allow empty string stripSpaces -- if True, remove leading, trailing & double spaces category -- a string for the option group this belongs to description -- a string for use in the control dialog columnNum -- the column position for this control in the dialog """ self.name = name self.category = category self.description = description self.columnNum = columnNum self.emptyOK = emptyOK self.stripSpaces = stripSpaces self.dialogControl = None self.value = None self.setValue(value) self.defaultValue = self.value optionDict[name] = self def setValue(self, value): """Sets the value and validates, returns True if OK. Returns False if validation fails but the old value is OK, or if the value is unchanged. Raises a ValueError if validation fails without an old value. Arguments: value -- the string value to set """ value = str(value) if self.stripSpaces: value = multipleSpaceRegEx.sub(' ', value.strip()) if value != self.value and (value or self.emptyOK): self.value = value return True if self.value == None: raise ValueError return False def storedValue(self): """Return the value to be stored in the JSON file. """ return self.value def addDialogControl(self, groupBox): """Add the labels and controls to a dialog box for this option item. Arguments: groupBox -- the current group box """ gridLayout = groupBox.layout() row = gridLayout.rowCount() label = QLabel(self.description, groupBox) gridLayout.addWidget(label, row, 0) self.dialogControl = QLineEdit(self.value, groupBox) gridLayout.addWidget(self.dialogControl, row, 1) def updateFromDialog(self): """Set the value of this item from the dialog contents. Return True if successfully set. """ return self.setValue(self.dialogControl.text()) class IntOptionItem(StringOptionItem): """Class to store and control an integer-based config option entry. Stores the name, value, category and description, provides validation, config file output and dialog controls. """ def __init__(self, optionDict, name, value, minimum=None, maximum=None, category='', description='', columnNum=0): """Set the parameters and initial value and add to optionDict. Raises a ValueError if initial validation fails. Arguments: optionDict -- a dictionary to add this option item to name -- the string key for the option value -- a numeric or string-based value minimum -- optional minimum value maximum -- optional maximum value category -- a string for the option group this belongs to description -- a string for use in the control dialog columnNum -- the column position for this control in the dialog """ self.minimum = minimum self.maximum = maximum super().__init__(optionDict, name, value, False, False, category, description, columnNum) def setValue(self, value): """Sets the value and validates, returns True if OK. Returns False if validation fails but the old value is OK, or if the value is unchanged. Raises a ValueError if validation fails without an old value. Arguments: value -- a numeric or string-based value to set """ try: value = int(value) if self.minimum != None and value < self.minimum: raise ValueError if self.maximum != None and value > self.maximum: raise ValueError except ValueError: if self.value == None: raise return False if value != self.value: self.value = value return True return False def addDialogControl(self, groupBox): """Add the labels and controls to a dialog box for this option item. Arguments: groupBox -- the current group box """ gridLayout = groupBox.layout() row = gridLayout.rowCount() label = QLabel(self.description, groupBox) gridLayout.addWidget(label, row, 0) self.dialogControl = QSpinBox(groupBox) self.dialogControl.setValue(self.value) if self.minimum != None: self.dialogControl.setMinimum(self.minimum) if self.maximum != None: self.dialogControl.setMaximum(self.maximum) gridLayout.addWidget(self.dialogControl, row, 1) def updateFromDialog(self): """Set the value of this item from the dialog contents. Return True if successfully set. """ return self.setValue(self.dialogControl.value()) class FloatOptionItem(StringOptionItem): """Class to store and control a float-based config option entry. Stores the name, value, category and description, provides validation, config file output and dialog controls. """ def __init__(self, optionDict, name, value, minimum=None, maximum=None, category='', description='', columnNum=0): """Set the parameters and initial value and add to optionDict. Raises a ValueError if initial validation fails. Arguments: optionDict -- a dictionary to add this option item to name -- the string key for the option value -- a numeric or string-based value minimum -- optional minimum value maximum -- optional maximum value category -- a string for the option group this belongs to description -- a string for use in the control dialog columnNum -- the column position for this control in the dialog """ self.minimum = minimum self.maximum = maximum super().__init__(optionDict, name, value, False, False, category, description, columnNum) def setValue(self, value): """Sets the value and validates, returns True if OK. Returns False if validation fails but the old value is OK, or if the value is unchanged. Raises a ValueError if validation fails without an old value. Arguments: value -- a numeric or string-based value to set """ try: value = float(value) if self.minimum != None and value < self.minimum: raise ValueError if self.maximum != None and value > self.maximum: raise ValueError except ValueError: if self.value == None: raise return False if value != self.value: self.value = value return True return False def addDialogControl(self, groupBox): """Add the labels and controls to a dialog box for this option item. Arguments: groupBox -- the current group box """ gridLayout = groupBox.layout() row = gridLayout.rowCount() label = QLabel(self.description, groupBox) gridLayout.addWidget(label, row, 0) self.dialogControl = QDoubleSpinBox(groupBox) self.dialogControl.setValue(self.value) if self.minimum != None: self.dialogControl.setMinimum(self.minimum) if self.maximum != None: self.dialogControl.setMaximum(self.maximum) gridLayout.addWidget(self.dialogControl, row, 1) def updateFromDialog(self): """Set the value of this item from the dialog contents. Return True if successfully set. """ return self.setValue(self.dialogControl.value()) class BoolOptionItem(StringOptionItem): """Class to store and control a boolean config option entry. Stores the name, value, category and description, provides validation, config file output and dialog controls. """ def __init__(self, optionDict, name, value, category='', description='', columnNum=0): """Set the parameters and initial value and add to optionDict. Raises a ValueError if initial validation fails. Arguments: optionDict -- a dictionary to add this option item to name -- the string key for the option value -- the boolean or string value category -- a string for the option group this belongs to description -- a string for use in the control dialog columnNum -- the column position for this control in the dialog """ super().__init__(optionDict, name, value, False, False, category, description, columnNum) def setValue(self, value): """Sets the value and validates, returns True if OK. Returns False if validation fails but the old value is OK, or if the value is unchanged. Raises a ValueError if validation fails without an old value. Arguments: value -- a boolean or string-based value to set """ if hasattr(value, 'lower'): if value.lower() in ('yes', 'y', 'true'): value = True elif value.lower() in ('no', 'n', 'false'): value = False else: value = bool(value) if value in (True, False) and value != self.value: self.value = value return True if self.value == None: raise ValueError return False def addDialogControl(self, groupBox): """Add the labels and controls to a dialog box for this option item. Arguments: groupBox -- the current group box """ gridLayout = groupBox.layout() row = gridLayout.rowCount() self.dialogControl = QCheckBox(self.description, groupBox) self.dialogControl.setChecked(self.value) gridLayout.addWidget(self.dialogControl, row, 0, 1, 2) def updateFromDialog(self): """Set the value of this item from the dialog contents. Return True if successfully set. """ return self.setValue(self.dialogControl.isChecked()) class ListOptionItem(StringOptionItem): """Class to store and control a pull-down list config option entry. Stores the name, value, category and description, provides validation, config file output and dialog controls. """ def __init__(self, optionDict, name, value, choices, category='', description='', columnNum=0): """Set the parameters and initial value and add to optionDict. Raises a ValueError if initial validation fails. Arguments: optionDict -- a dictionary to add this option item to name -- the string key for the option value -- the string value choices -- a list of acceptable entries category -- a string for the option group this belongs to description -- a string for use in the control dialog columnNum -- the column position for this control in the dialog """ self.choices = choices super().__init__(optionDict, name, value, False, False, category, description, columnNum) def setValue(self, value): """Sets the value and validates, returns True if OK. Returns False if validation fails but the old value is OK, or if the value is unchanged. Raises a ValueError if validation fails without an old value. Arguments: value -- the string value to set """ value = str(value) if value in self.choices and value != self.value: self.value = value return True if self.value == None: raise ValueError return False def addDialogControl(self, groupBox): """Add the labels and controls to a dialog box for this option item. Arguments: groupBox -- the current group box """ gridLayout = groupBox.layout() row = gridLayout.rowCount() label = QLabel(self.description, groupBox) gridLayout.addWidget(label, row, 0) self.dialogControl = QComboBox(groupBox) self.dialogControl.addItems(self.choices) self.dialogControl.setCurrentIndex(self.choices.index(self.value)) gridLayout.addWidget(self.dialogControl, row, 1) def updateFromDialog(self): """Set the value of this item from the dialog contents. Return True if successfully set. """ return self.setValue(self.dialogControl.currentText()) class ChoiceOptionItem(StringOptionItem): """Class to store and control a radio button choice config option entry. Stores the name, value, category and description, provides validation, config file output and dialog controls. """ def __init__(self, optionDict, name, value, choices, category='', columnNum=0): """Set the parameters and initial value and add to optionDict. Raises a ValueError if initial validation fails. Arguments: optionDict -- a dictionary to add this option item to name -- the string key for the option value -- the string value choices -- a list of acceptable entries category -- a string for the option group this belongs to columnNum -- the column position for this control in the dialog """ self.choices = choices super().__init__(optionDict, name, value, False, False, category, '', columnNum) def setValue(self, value): """Sets the value and validates, returns True if OK. Returns False if validation fails but the old value is OK, or if the value is unchanged. Raises a ValueError if validation fails without an old value. Arguments: value -- the string value to set """ value = str(value) if value in self.choices and value != self.value: self.value = value return True if self.value == None: raise ValueError return False def addDialogControl(self, groupBox): """Add the labels and controls to a dialog box for this option item. Arguments: groupBox -- the current group box """ rowLayout.addWidget(groupBox) QGridLayout(groupBox) gridLayout = groupBox.layout() self.dialogControl = QButtonGroup(groupBox) row = 0 for choice in self.choices: button = QRadioButton(choice, groupBox) self.dialogControl.addButton(button) gridLayout.addWidget(button, row, 0, 1, 2) row += 1 def updateFromDialog(self): """Set the value of this item from the dialog contents. Return True if successfully set. """ return self.setValue(self.dialogControl.checkedButton().text()) class KeyOptionItem(StringOptionItem): """Class to store and control a keyboard key based config option entry. Stores the name, value and category, provides validation and config file output. """ def __init__(self, optionDict, name, value, category=''): """Set the parameters and initial value and add to optionDict. Raises a ValueError if initial validation fails. Arguments: optionDict -- a dictionary to add this option item to name -- the string key for the option value -- a numeric or string-based value category -- a string for the option group this belongs to """ super().__init__(optionDict, name, value, True, False, category) def setValue(self, value): """Sets the value and validates, returns True if OK. Returns False if validation fails but the old value is OK, or if the value is unchanged. Raises a ValueError if validation fails without an old value. Arguments: value -- a key string value to set """ key = QKeySequence(value) if value and key.isEmpty(): if self.value == None: raise ValueError return False if value != self.value: self.value = key return True return False def storedValue(self): """Return the value to be stored in the JSON file. """ return self.value.toString() class DataListOptionItem(StringOptionItem): """Class to store an arbitrary length list containing various data. Stores the name and value, provides validation and config file output. """ def __init__(self, optionDict, name, value): """Set the parameters and initial value and add to optionDict. Raises a ValueError if initial validation fails. Arguments: optionDict -- a dictionary to add this option item to name -- the string key for the option value -- a list containg other basic data types """ super().__init__(optionDict, name, value) def setValue(self, value): """Sets the value and validates, returns True if OK. Returns False if validation fails but the old value is OK, or if the value is unchanged. Raises a ValueError if validation fails without an old value. Arguments: value -- a list containg other basic data types """ if isinstance(value, list) and value != self.value: self.value = value return True if self.value == None: raise ValueError return False class Options(OrderedDict): """Class to store and control the config options for a program. """ basePath = None def __init__(self, fileName='', progName='', version='', coDirName=''): """Initialize and set the path to the config file. Creates the path dir structure if necessary (if fileName is given). On Windows, uses the module path's config directory if it exists. Arguments: fileName -- the config file name, excluding the extension progName -- the program name, for dialog headings & config dir name version -- a version string, for config dir names coDirName -- the company name for the config dir in Windows OS """ super().__init__() self.modified = False self.path = pathlib.Path() if not fileName: return # no storage without fileName (temporary options only) if not version: version = '0' appDirName = '{0}-{1}'.format(progName.lower(), version) fileNameSuffix = '.ini' if sys.platform.startswith('win') else 'rc' if not Options.basePath and progName and coDirName: if sys.platform.startswith('win'): # Windows userPath = (pathlib.Path(os.environ.get('APPDATA', '')) / coDirName / appDirName) else: # Linux, etc. userPath = (pathlib.Path(os.path.expanduser('~')) / ('.' + appDirName)) if userPath.is_dir(): Options.basePath = userPath else: # use abspath() - pathlib's resolve() buggy with network drives modPath = pathlib.Path(os.path.abspath(sys.path[0])) if modPath.is_file(): modPath = modPath.parent # for frozen binary modConfigPath = modPath / 'config' if modConfigPath.is_dir(): Options.basePath = modConfigPath elif os.access(str(modPath), os.W_OK): dialog = miscdialogs.RadioChoiceDialog(progName, _('Choose configuration file location'), [(_('User\'s home directory (recommended)'), 0), (_('Program directory (for portable use)'), 1)]) if dialog.exec() != QDialog.DialogCode.Accepted: sys.exit(0) if dialog.selectedButton() == 1: Options.basePath = modConfigPath if not Options.basePath: Options.basePath = userPath try: if not Options.basePath.is_dir(): Options.basePath.mkdir(parents=True) iconPath = Options.basePath / 'icons' if not iconPath.is_dir(): iconPath.mkdir() templatePath = Options.basePath / 'templates' if not templatePath.is_dir(): templatePath.mkdir() templateExportPath = templatePath / 'exports' if not templateExportPath.is_dir(): templateExportPath.mkdir() except OSError: Options.basePath = None if Options.basePath: self.path = Options.basePath / (fileName + fileNameSuffix) def __getitem__(self, name): """Return the value of an option when called as options[name]. Arguments: name -- the string key for the option """ return self.get(name).value def getDefaultValue(self, name): """Return the initially set default value from the given option key. Arguments: name -- the string key for the option """ return self.get(name).defaultValue def changeValue(self, name, value): """Set a new value for the given option key. Return True if sucessful. Arguments: name -- the string key for the option value -- a value or a string defining the value """ if self.get(name).setValue(value): self.modified = True return True return False def resetToDefaults(self, keyList): """Reset all options with the given keys to original default values. Arguments: keyList -- a list of option names to reset """ for key in keyList: self.get(key).setValue(self.get(key).defaultValue) self.modified = True def removeValue(self, name): """Remove the value from the option list if possible. If not, fail silently. Arguments: name -- the string key for the option to be removed """ try: del self[name] except KeyError: return self.modified = True def readFile(self): """Read config options from the file on self.path. Create the file if it isn't found, raise IOError if this fails. Only updates existing config items. """ try: with self.path.open('r', encoding='utf-8') as f: data = json.load(f) for key, value in data.items(): try: self.get(key).setValue(value) except AttributeError: pass except (IOError, ValueError): if not self.writeFile(): raise IOError def writeFile(self): """Write current options to the file on self.path. Returns False on failure. """ try: with self.path.open('w', encoding='utf-8') as f: data = OrderedDict([(key, obj.storedValue()) for (key, obj) in self.items()]) json.dump(data, f, indent=0) self.modified = False except IOError: return False return True class OptionDialog(QDialog): """Provides a dialog with controls for all options in an Options instance. """ def __init__(self, options, parent=None): super().__init__(parent) self.options = options self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) topLayout = QVBoxLayout(self) self.setLayout(topLayout) columnLayout = QHBoxLayout() topLayout.addLayout(columnLayout) rowLayout = QVBoxLayout() columnLayout.addLayout(rowLayout) groupBox = None for option in self.options.values(): if option.columnNum > columnLayout.count() - 1: rowLayout = QVBoxLayout() columnLayout.addLayout(rowLayout) if not groupBox or groupBox.title() != option.category: groupBox = QGroupBox(option.category) rowLayout.addWidget(groupBox) QGridLayout(groupBox) option.addDialogControl(groupBox) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch(0) okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) def accept(self): """Updates the options from the controls when the OK button is pressed. """ for option in self.options.values(): if option.updateFromDialog(): self.options.modified = True super().accept() TreeLine-3.2.1/source/outputview.py000066400000000000000000000140071506556630100173420ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # outputview.py, provides a class for the data output view # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** from PyQt6.QtCore import Qt from PyQt6.QtGui import QPalette, QTextCursor from PyQt6.QtWidgets import QTextBrowser, QTextEdit import treeoutput import urltools import dataeditors import globalref class OutputView(QTextBrowser): """Class override for the data output view. Sets view defaults and updates the content. """ def __init__(self, treeView, isChildView=True, parent=None): """Initialize the output view. Arguments: treeView - the tree view, needed for the current selection model isChildView -- shows selected nodes if false, child nodes if true parent -- the parent main window """ super().__init__(parent) self.treeView = treeView self.isChildView = isChildView self.hideChildView = not globalref.genOptions['InitShowChildPane'] self.showDescendants = globalref.genOptions['InitShowDescendants'] self.setFocusPolicy(Qt.FocusPolicy.NoFocus) def updateContents(self): """Reload the view's content if the view is shown. Avoids update if view is not visible or has zero height or width. """ selSpots = self.treeView.selectionModel().selectedSpots() if self.isChildView: if (len(selSpots) > 1 or self.hideChildView or (selSpots and not selSpots[0].nodeRef.childList)): self.hide() return if not selSpots: # use top node childList from tree structure selSpots = [globalref.mainControl.activeControl.structure. structSpot()] elif not selSpots: self.hide() return self.show() if not self.isVisible() or self.height() == 0 or self.width() == 0: return if self.isChildView: if self.showDescendants: outputGroup = treeoutput.OutputGroup(selSpots, False, True) if outputGroup.hasPrefixes(): outputGroup.combineAllSiblings() outputGroup.addBlanksBetween() outputGroup.addAbsoluteIndents() else: outputGroup = treeoutput.OutputGroup(selSpots[0].childSpots()) outputGroup.addBlanksBetween() outputGroup.addSiblingPrefixes() else: outputGroup = treeoutput.OutputGroup(selSpots) outputGroup.addBlanksBetween() outputGroup.addSiblingPrefixes() self.setHtml('\n'.join(outputGroup.getLines())) self.setSearchPaths([str(globalref.mainControl.defaultPathObj(True))]) def doSetSource(self, url, resType): """Called when a user clicks on a URL link. Selects an internal link or opens an external browser. Arguments: url -- the QUrl that is clicked """ name = url.toString() if name.startswith('#'): if not self.treeView.selectionModel().selectNodeById(name[1:]): super().doSetSource(url, resType) else: if urltools.isRelative(name): # check for relative path defaultPath = globalref.mainControl.defaultPathObj(True) name = urltools.toAbsolute(name, str(defaultPath)) dataeditors.openExtUrl(name) def hasSelectedText(self): """Return True if text is selected. """ return self.textCursor().hasSelection() def highlightSearch(self, wordList=None, regExpList=None): """Highlight any found search terms. Arguments: wordList -- list of words to highlight regExpList -- a list of regular expression objects to highlight """ backColor = self.palette().brush(QPalette.ColorGroup.Active, QPalette.ColorRole.Highlight) foreColor = self.palette().brush(QPalette.ColorGroup.Active, QPalette.ColorRole.HighlightedText) if wordList is None: wordList = [] if regExpList is None: regExpList = [] for regExp in regExpList: for match in regExp.finditer(self.toPlainText()): matchText = match.group() if matchText not in wordList: wordList.append(matchText) selections = [] for word in wordList: while self.find(word): extraSel = QTextEdit.ExtraSelection() extraSel.cursor = self.textCursor() extraSel.format.setBackground(backColor) extraSel.format.setForeground(foreColor) selections.append(extraSel) cursor = QTextCursor(self.document()) self.setTextCursor(cursor) # reset main cursor/selection self.setExtraSelections(selections) def contextMenuEvent(self, event): """Add a popup menu for select all and copy actions. Arguments: event -- the menu event """ menu = self.createStandardContextMenu() menu.removeAction(menu.actions()[1]) #remove copy link location menu.exec(event.globalPos()) def resizeEvent(self, event): """Update view if was collaped by splitter. """ if ((event.oldSize().height() == 0 and event.size().height()) or (event.oldSize().width() == 0 and event.size().width())): self.updateContents() return super().resizeEvent(event) TreeLine-3.2.1/source/p3.py000066400000000000000000000121521506556630100154300ustar00rootroot00000000000000#!/usr/bin/env python3 # Simple p3 encryption "algorithm": it's just SHA used as a stream # cipher in output feedback mode. # Author: Paul Rubin, Fort GNOX Cryptography, . # Algorithmic advice from David Wagner, Richard Parker, Bryan # Olson, and Paul Crowley on sci.crypt is gratefully acknowledged. # Copyright 2002,2003 by Paul Rubin # Copying license: same as Python 2.3 license # Please include this revision number in any bug reports: $Revision: 1.2 $. # Modified by Doug Bell to be compatible with Python 3 from array import array from time import time import struct import hashlib shaHash = hashlib.sha1 class CryptError(Exception): pass def _hash(text): return shaHash(text).digest() _ivlen = 16 _maclen = 8 _state = _hash(repr(time()).encode()) # added by Doug Bell for compatibility with 64-bit systems _arraytype = [t for t in 'LIH' if struct.calcsize(t) == 4][0] try: import os _pid = repr(os.getpid()).encode() except (ImportError, AttributeError): _pid = '' def _expand_key(key, clen): blocks = (clen+19)//20 xkey=[] seed=key for i in range(blocks): seed=shaHash(key+seed).digest() xkey.append(seed) j = b''.join(xkey) return array(_arraytype, j) def p3_encrypt(plain,key): global _state H = _hash # change _state BEFORE using it to compute nonce, in case there's # a thread switch between computing the nonce and folding it into # the state. This way if two threads compute a nonce from the # same data, they won't both get the same nonce. (There's still # a small danger of a duplicate nonce--see below). _state = b'X'+_state # Attempt to make nlist unique for each call, so we can get a # unique nonce. It might be good to include a process ID or # something, but I don't know if that's portable between OS's. # Since is based partly on both the key and plaintext, in the # worst case (encrypting the same plaintext with the same key in # two separate Python instances at the same time), you might get # identical ciphertexts for the identical plaintexts, which would # be a security failure in some applications. Be careful. nlist = [repr(time()).encode(), _pid, _state, repr(len(plain)).encode(),plain, key] nonce = H(b','.join(nlist))[:_ivlen] _state = H(b'update2'+_state+nonce) k_enc, k_auth = H(b'enc'+key+nonce), H(b'auth'+key+nonce) n=len(plain) # cipher size not counting IV stream = array(_arraytype, plain+b'0000'[n&3:]) # pad to fill 32-bit words xkey = _expand_key(k_enc, n+4) for i in range(len(stream)): stream[i] = stream[i] ^ xkey[i] ct = nonce + stream.tobytes()[:n] auth = _hmac(ct, k_auth) return ct + auth[:_maclen] def p3_decrypt(cipher,key): H = _hash n=len(cipher)-_ivlen-_maclen # length of ciphertext if n < 0: raise CryptError("invalid ciphertext") nonce,stream,auth = \ cipher[:_ivlen], cipher[_ivlen:-_maclen]+b'0000'[n&3:],cipher[-_maclen:] k_enc, k_auth = H(b'enc'+key+nonce), H(b'auth'+key+nonce) vauth = _hmac (cipher[:-_maclen], k_auth)[:_maclen] if auth != vauth: raise CryptError("invalid key or ciphertext") stream = array(_arraytype, stream) xkey = _expand_key (k_enc, n+4) for i in range (len(stream)): stream[i] = stream[i] ^ xkey[i] plain = stream.tobytes()[:n] return plain # RFC 2104 HMAC message authentication code # This implementation is faster than Python 2.2's hmac.py, and also works in # old Python versions (at least as old as 1.5.2). def _hmac_setup(): global _ipad, _opad, _itrans, _otrans _itrans = array('B',[0]*256) _otrans = array('B',[0]*256) for i in range(256): _itrans[i] = i ^ 0x36 _otrans[i] = i ^ 0x5c _itrans = _itrans.tobytes() _otrans = _otrans.tobytes() _ipad = b'\x36'*64 _opad = b'\x5c'*64 def _hmac(msg, key): if len(key)>64: key=shaHash(key).digest() ki = (key.translate(_itrans)+_ipad)[:64] # inner ko = (key.translate(_otrans)+_opad)[:64] # outer return shaHash(ko+shaHash(ki+msg).digest()).digest() # # benchmark and unit test # def _time_p3(n=1000,len=20): plain="a"*len t=time() for i in range(n): p3_encrypt(plain,b"abcdefgh") dt=time()-t print("plain p3:", n,len,dt,"sec =",n*len//dt,"bytes/sec") def _speed(): _time_p3(len=5) _time_p3() _time_p3(len=200) _time_p3(len=2000,n=100) def _test(): e=p3_encrypt d=p3_decrypt plain=b"test plaintext" key = b"test key" c1 = e(plain,key) c2 = e(plain,key) assert c1!=c2 assert d(c2,key)==plain assert d(c1,key)==plain c3 = c2[:20]+chr(1+c2[20]).encode()+c2[21:] # change one ciphertext char try: print(d(c3,key)) # should throw exception print("auth verification failure") except CryptError: pass try: print(d(c2,b'wrong key')) # should throw exception print("test failure") except CryptError: pass _hmac_setup() # _test() # _speed() # uncomment to run speed test TreeLine-3.2.1/source/printdata.py000066400000000000000000000662211506556630100171020ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # printdata.py, provides a class for printing # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import os.path import enum from PyQt6.QtCore import QMarginsF, QSizeF, Qt from PyQt6.QtGui import (QAbstractTextDocumentLayout, QFontMetrics, QPageLayout, QPageSize, QPainter, QPalette, QTextDocument) from PyQt6.QtWidgets import QApplication, QDialog, QFileDialog, QMessageBox from PyQt6.QtPrintSupport import QPrintDialog, QPrinter import treeoutput import printdialogs import globalref PrintScope = enum.IntEnum('PrintScope', 'entireTree selectBranch selectNode') _defaultMargin = 0.5 _defaultHeaderPos = 0.2 _defaultColumnSpace = 0.5 class PrintData: """Class to handle printing of tree output data. Stores print data and main printing functions. """ def __init__(self, localControl): """Initialize the print data. Arguments: localControl -- a reference to the parent local control """ self.localControl = localControl self.outputGroup = None self.printWhat = PrintScope.entireTree self.includeRoot = True self.openOnly = False self.printer = QPrinter(QPrinter.PrinterMode.HighResolution) self.pageLayout = self.printer.pageLayout() self.setDefaults() self.adjustSpacing() def setDefaults(self): """Set all paparmeters saved in TreeLine files to default values. """ self.drawLines = True self.widowControl = True self.indentFactor = 2.0 self.pageLayout.setUnits(QPageLayout.Unit.Inch) self.pageLayout.setPageSize(QPageSize(QPageSize.PageSizeId.Letter)) self.pageLayout.setOrientation(QPageLayout.Orientation.Portrait) self.pageLayout.setMargins(QMarginsF(*(_defaultMargin,) * 4)) self.headerMargin = _defaultHeaderPos self.footerMargin = _defaultHeaderPos self.numColumns = 1 self.columnSpacing = _defaultColumnSpace self.headerText = '' self.footerText = '' self.useDefaultFont = True self.setDefaultFont() def setDefaultFont(self): """Set the default font initially and based on an output font change. """ self.defaultFont = QTextDocument().defaultFont() fontName = globalref.miscOptions['OutputFont'] if fontName: self.defaultFont.fromString(fontName) if self.useDefaultFont: self.mainFont = self.defaultFont def adjustSpacing(self): """Adjust line spacing & indent size based on font & indent factor. """ self.lineSpacing = QFontMetrics(self.mainFont, self.printer).lineSpacing() self.indentSize = self.indentFactor * self.lineSpacing def fileData(self): """Return a dictionary of non-default settings for storage. """ data = {} if not self.drawLines: data['printlines'] = False if not self.widowControl: data['printwidowcontrol'] = False if self.indentFactor != 2.0: data['printindentfactor'] = self.indentFactor pageSizeId = self.pageLayout.pageSize().id() if pageSizeId == QPageSize.PageSizeId.Custom: paperWidth, paperHeight = self.roundedPaperSize() data['printpaperwidth'] = paperWidth data['printpaperheight'] = paperHeight elif pageSizeId != QPageSize.PageSizeId.Letter: data['printpapersize'] = self.paperSizeName(pageSizeId) if self.pageLayout.orientation() != QPageLayout.Orientation.Portrait: data['printportrait'] = False if self.roundedMargins() != (_defaultMargin,) * 4: data['printmargins'] = list(self.roundedMargins()) if self.headerMargin != _defaultHeaderPos: data['printheadermargin'] = self.headerMargin if self.footerMargin != _defaultHeaderPos: data['printfootermargin'] = self.footerMargin if self.numColumns > 1: data['printnumcolumns'] = self.numColumns if self.columnSpacing != _defaultColumnSpace: data['printcolumnspace'] = self.columnSpacing if self.headerText: data['printheadertext'] = self.headerText if self.footerText: data['printfootertext'] = self.footerText if not self.useDefaultFont: data['printfont'] = self.mainFont.toString() return data def readData(self, data): """Restore saved settings from a dictionary. Arguments: data -- a dictionary of stored non-default settings """ self.setDefaults() # necessary for undo/redo self.drawLines = data.get('printlines', True) self.widowControl = data.get('printwidowcontrol', True) self.indentFactor = data.get('printindentfactor', 2.0) if 'printpapersize' in data: self.pageLayout.setPageSize(QPageSize(getattr(QPageSize.PageSizeId, data['printpapersize']))) self.pageLayout.setMargins(QMarginsF(*(_defaultMargin,) * 4)) if 'printpaperwidth' in data and 'printpaperheight' in data: width = data['printpaperwidth'] height = data['printpaperheight'] self.pageLayout.setPageSize(QPageSize(QSizeF(width, height), QPageSize.Unit.Inch)) self.pageLayout.setMargins(QMarginsF(*(_defaultMargin,) * 4)) if not data.get('printportrait', True): self.pageLayout.setOrientation(QPageLayout.Orientation.Landscape) if 'printmargins' in data: margins = data['printmargins'] self.pageLayout.setMargins(QMarginsF(*margins)) self.headerMargin = data.get('printheadermargin', _defaultHeaderPos) self.footerMargin = data.get('printfootermargin', _defaultHeaderPos) self.numColumns = data.get('printnumcolumns', 1) self.columnSpacing = data.get('printcolumnspace', _defaultColumnSpace) self.headerText = data.get('printheadertext', '') self.footerText = data.get('printfootertext', '') if 'printfont' in data: self.useDefaultFont = False self.mainFont.fromString(data['printfont']) self.adjustSpacing() def roundedMargins(self): """Return a tuple of rounded page margins in inches. Rounds to nearest .01" to avoid Qt unit conversion artifacts. """ margins = self.pageLayout.margins(QPageLayout.Unit.Inch) return tuple(round(margin, 2) for margin in (margins.left(), margins.top(), margins.right(), margins.bottom())) def roundedPaperSize(self): """Return a tuple of rounded paper width and height. Rounds to nearest .01" to avoid Qt unit conversion artifacts. """ size = self.pageLayout.fullRect(QPageLayout.Unit.Inch) return (round(size.width(), 2), round(size.height(), 2)) def paperSizeName(self, sizeId=None): """Return a QPageSize attribute name matching the paper size ID. Arguments: sizeId -- the Qt size ID, if None, use current size """ if sizeId == None: sizeId = self.pageLayout.pageSize().id() matches = [] for name, num in vars(QPageSize.PageSizeId).items(): if num == sizeId: matches.append(name) if not matches: return 'Custom' if len(matches) > 1: text = QPageSize(sizeId).name().split(None, 1)[0] for name in matches: if name == text: return name return matches[0] def setupData(self): """Load data to be printed and set page info. """ if self.printWhat == PrintScope.entireTree: selSpots = self.localControl.structure.rootSpots() else: selSpots = (self.localControl.currentSelectionModel(). selectedSpots()) if not selSpots: selSpots = self.localControl.structure.rootSpots() self.outputGroup = treeoutput.OutputGroup(selSpots, self.includeRoot, self.printWhat != PrintScope.selectNode, self.openOnly) self.paginate() def paginate(self): """Define the pages and locations of output items and set page range. """ pageNum = 1 columnNum = 0 pagePos = 0 itemSplit = False self.checkPageLayout() heightAvail = (self.pageLayout.paintRect().height() * self.printer.logicalDpiY()) columnSpacing = int(self.columnSpacing * self.printer.logicalDpiX()) widthAvail = ((self.pageLayout.paintRect().width() * self.printer.logicalDpiX() - columnSpacing * (self.numColumns - 1)) // self.numColumns) newGroup = treeoutput.OutputGroup([]) while self.outputGroup: item = self.outputGroup.pop(0) widthRemain = widthAvail - item.level * self.indentSize if pagePos != 0 and (newGroup[-1].addSpace or item.addSpace): pagePos += self.lineSpacing if item.siblingPrefix: siblings = treeoutput.OutputGroup([]) siblings.append(item) while True: item = siblings.combineLines() item.setDocHeight(self.printer, widthRemain, self.mainFont, True) if pagePos + item.height > heightAvail: self.outputGroup.insert(0, siblings.pop()) item = (siblings.combineLines() if siblings else None) break if (self.outputGroup and item.level == self.outputGroup[0].level and item.equalPrefix(self.outputGroup[0])): siblings.append(self.outputGroup.pop(0)) else: break if item: item.setDocHeight(self.printer, widthRemain, self.mainFont, True) if item.height > heightAvail and not itemSplit: item, newItem = item.splitDocHeight(heightAvail - pagePos, heightAvail, self.printer, widthRemain, self.mainFont) if newItem: self.outputGroup.insert(0, newItem) itemSplit = True if item and (pagePos + item.height <= heightAvail or pagePos == 0): item.pageNum = pageNum item.columnNum = columnNum item.pagePos = pagePos newGroup.append(item) pagePos += item.height else: if columnNum + 1 < self.numColumns: columnNum += 1 else: pageNum += 1 columnNum = 0 pagePos = 0 itemSplit = False if item: self.outputGroup.insert(0, item) if self.widowControl and not item.siblingPrefix: moveItems = [] moveHeight = 0 level = item.level while (newGroup and not newGroup[-1].siblingPrefix and newGroup[-1].level == level - 1 and ((newGroup[-1].pageNum == pageNum - 1 and newGroup[-1].columnNum == columnNum) or (newGroup[-1].pageNum == pageNum and newGroup[-1].columnNum == columnNum - 1))): moveItems.insert(0, newGroup.pop()) moveHeight += moveItems[0].height level -= 1 if (moveItems and newGroup and moveHeight < (heightAvail // 5)): self.outputGroup[0:0] = moveItems else: newGroup.extend(moveItems) self.outputGroup = newGroup self.outputGroup.loadFamilyRefs() self.printer.setFromTo(1, pageNum) def checkPageLayout(self): """Check and set the page layout on the current printer. Verify that the layout settings match the printer, adjust if required. """ if not self.printer.setPageLayout(self.pageLayout): tempPrinter = QPrinter() tempPageLayout = tempPrinter.pageLayout() tempPageLayout.setUnits(QPageLayout.Unit.Inch) pageSizeIssue = False defaultPageSize = tempPageLayout.pageSize() tempPageLayout.setPageSize(self.pageLayout.pageSize()) if not tempPrinter.setPageLayout(tempPageLayout): pageSizeIssue = True tempPageLayout.setPageSize(defaultPageSize) marginIssue = not (tempPageLayout.setMargins(self.pageLayout. margins()) and tempPrinter.setPageLayout(tempPageLayout)) if marginIssue: margin = 0.1 while True: if (tempPageLayout.setMargins(QMarginsF(*(margin,) * 4)) and tempPrinter.setPageLayout(tempPageLayout)): break margin += 0.1 newMargins = [] for oldMargin in self.roundedMargins(): newMargins.append(oldMargin if oldMargin >= margin else margin) tempPageLayout.setMargins(QMarginsF(*newMargins)) tempPageLayout.setOrientation(self.pageLayout.orientation()) self.printer.setPageLayout(tempPageLayout) if not pageSizeIssue and not marginIssue: return if pageSizeIssue and marginIssue: msg = _('Warning: Page size and margin settings unsupported ' 'on current printer.\nSave page adjustments?') elif pageSizeIssue: msg = _('Warning: Page size setting unsupported ' 'on current printer.\nSave adjustment?') else: msg = _('Warning: Margin settings unsupported ' 'on current printer.\nSave adjustments?') ans = QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', msg, QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.Yes) if ans == QMessageBox.StandardButton.Yes: self.pageLayout = tempPageLayout def paintData(self, printer): """Paint data to be printed to the printer. """ pageNum = 1 try: maxPageNum = self.outputGroup[-1].pageNum except IndexError: # printing empty branch maxPageNum = 1 if self.printer.printRange() != QPrinter.PrintRange.AllPages: pageNum = self.printer.fromPage() maxPageNum = self.printer.toPage() painter = QPainter() if not painter.begin(self.printer): QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error initializing printer')) QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) while True: self.paintPage(pageNum, painter) if pageNum == maxPageNum: QApplication.restoreOverrideCursor() return pageNum += 1 self.printer.newPage() def paintPage(self, pageNum, painter): """Paint data for the given page to the printer. Arguments: pageNum -- the page number to be printed painter -- the painter for this print job """ paintContext = QAbstractTextDocumentLayout.PaintContext() # set context text color to black to wrok with dark app themes paintContext.palette = QPalette() paintContext.palette.setColor(QPalette.ColorRole.Text, Qt.GlobalColor.black) try: totalNumPages = self.outputGroup[-1].pageNum except IndexError: # printing empty branch totalNumPages = 1 headerDoc = self.headerFooterDoc(True, pageNum, totalNumPages) if headerDoc: layout = headerDoc.documentLayout() layout.setPaintDevice(self.printer) headerDoc.setTextWidth(self.pageLayout.paintRect().width() * self.printer.logicalDpiX()) painter.save() # set a pen as a workaround to initialize color with a dark theme. pen = painter.pen() pen.setWidth(6) painter.setPen(pen) topMargin = self.pageLayout.margins(QPageLayout.Unit.Inch).top() headerDelta = ((self.headerMargin - topMargin) * self.printer.logicalDpiX()) painter.translate(0, int(headerDelta)) layout.draw(painter, paintContext) painter.restore() painter.save() columnSpacing = int(self.columnSpacing * self.printer.logicalDpiX()) columnDelta = ((self.pageLayout.paintRect().width() * self.printer.logicalDpiX() - columnSpacing * (self.numColumns - 1)) / self.numColumns) + columnSpacing for columnNum in range(self.numColumns): if columnNum > 0: painter.translate(columnDelta, 0) self.paintColumn(pageNum, columnNum, painter, paintContext) painter.restore() footerDoc = self.headerFooterDoc(False, pageNum, totalNumPages) if footerDoc: layout = footerDoc.documentLayout() layout.setPaintDevice(self.printer) footerDoc.setTextWidth(self.pageLayout.paintRect().width() * self.printer.logicalDpiX()) painter.save() bottomMargin = self.pageLayout.margins(QPageLayout. Unit.Inch).bottom() footerDelta = ((bottomMargin - self.footerMargin) * self.printer.logicalDpiX()) painter.translate(0, self.pageLayout.paintRect().height() * self.printer.logicalDpiX() + int(footerDelta) - self.lineSpacing) layout.draw(painter, paintContext) painter.restore() def paintColumn(self, pageNum, columnNum, painter, paintContext): """Paint data for the given column to the printer. Arguments: pageNum -- the page number to be printed columnNum -- the column number to be printed painter -- the painter for this print job """ columnItems = [item for item in self.outputGroup if item.pageNum == pageNum and item.columnNum == columnNum] for item in columnItems: layout = item.doc.documentLayout() painter.save() # set a pen as a workaround to initialize color with a dark theme. pen = painter.pen() pen.setWidth(6) painter.setPen(pen) painter.translate(item.level * self.indentSize, item.pagePos) layout.draw(painter, paintContext) painter.restore() if self.drawLines: self.addPrintLines(pageNum, columnNum, columnItems, painter) def addPrintLines(self, pageNum, columnNum, columnItems, painter): """Paint lines between parent and child items on the page. Arguments: pageNum -- the page number to be printed columnNum -- the column number to be printed columnItems -- a list of items in this column painter -- the painter for this print job """ parentsDrawn = set() horizOffset = self.indentSize // 2 vertOffset = self.lineSpacing // 2 heightAvail = (self.pageLayout.paintRect().height() * self.printer.logicalDpiY()) painter.save() pen = painter.pen() pen.setWidth(6) painter.setPen(pen) for item in columnItems: if item.level > 0: indent = item.level * self.indentSize vertPos = item.pagePos + vertOffset painter.drawLine(int(indent - horizOffset), int(vertPos), int(indent - self.lineSpacing // 4), int(vertPos)) parent = item.parentItem while parent: if parent in parentsDrawn: break lineStart = 0 lineEnd = heightAvail if (parent.pageNum == pageNum and parent.columnNum == columnNum): lineStart = parent.pagePos + parent.height if (parent.lastChildItem.pageNum == pageNum and parent.lastChildItem.columnNum == columnNum): lineEnd = parent.lastChildItem.pagePos + vertOffset if (parent.lastChildItem.pageNum > pageNum or (parent.lastChildItem.pageNum == pageNum and parent.lastChildItem.columnNum >= columnNum)): horizPos = ((parent.level + 1) * self.indentSize - horizOffset) painter.drawLine(int(horizPos), int(lineStart), int(horizPos), int(lineEnd)) parentsDrawn.add(parent) parent = parent.parentItem painter.restore() def formatHeaderFooter(self, header=True, pageNum=1, numPages=1): """Return an HTML table formatted header or footer. Return an empty string if no header/footer is defined. Arguments: header -- return header if True, footer if false """ if header: textParts = printdialogs.splitHeaderFooter(self.headerText) else: textParts = printdialogs.splitHeaderFooter(self.footerText) if not textParts: return '' fileInfoFormat = self.localControl.structure.treeFormats.fileInfoFormat fileInfoNode = self.localControl.structure.fileInfoNode fileInfoFormat.updateFileInfo(self.localControl.filePathObj, fileInfoNode) fileInfoNode.data[fileInfoFormat.pageNumFieldName] = repr(pageNum) fileInfoNode.data[fileInfoFormat.numPagesFieldName] = repr(numPages) fileInfoFormat.changeOutputLines(textParts, keepBlanks=True) textParts = fileInfoFormat.formatOutput(fileInfoNode, keepBlanks=True) alignments = ('left', 'center', 'right') result = [''] for text, align in zip(textParts, alignments): if text: result.append(''.format(align, text)) if len(result) > 1: result.append('
    {1}
    ') return '\n'.join(result) return '' def headerFooterDoc(self, header=True, pageNum=1, numPages=1): """Return a text document for the header or footer. Return None if no header/footer is defined. Arguments: header -- return header if True, footer if false """ text = self.formatHeaderFooter(header, pageNum, numPages) if text: doc = QTextDocument() doc.setHtml(text) doc.setDefaultFont(self.mainFont) frameFormat = doc.rootFrame().frameFormat() frameFormat.setBorder(0) frameFormat.setMargin(0) frameFormat.setPadding(0) doc.rootFrame().setFrameFormat(frameFormat) return doc return None def printSetup(self): """Show a dialog to set margins, page size and other printing options. """ setupDialog = printdialogs.PrintSetupDialog(self, True, QApplication. activeWindow()) setupDialog.exec() def printPreview(self): """Show a preview of printing results. """ self.setupData() previewDialog = printdialogs.PrintPreviewDialog(self,QApplication. activeWindow()) previewDialog.previewWidget.paintRequested.connect(self.paintData) if globalref.genOptions['SaveWindowGeom']: previewDialog.restoreDialogGeom() previewDialog.exec() def filePrint(self): """Show dialog and print tree output based on current options. """ self.printer.setOutputFormat(QPrinter.OutputFormat.NativeFormat) self.setupData() printDialog = QPrintDialog(self.printer, QApplication.activeWindow()) if printDialog.exec() == QDialog.DialogCode.Accepted: self.paintData(self.printer) def filePrintPdf(self): """Export to a PDF file with current options. """ filters = ';;'.join((globalref.fileFilters['pdf'], globalref.fileFilters['all'])) defaultFilePath = str(globalref.mainControl.defaultPathObj()) defaultFilePath = os.path.splitext(defaultFilePath)[0] if os.path.basename(defaultFilePath): defaultFilePath = '{0}.{1}'.format(defaultFilePath, 'pdf') filePath, selectFilter = QFileDialog.getSaveFileName(QApplication. activeWindow(), _('TreeLine - Export PDF'), defaultFilePath, filters) if not filePath: return if not os.path.splitext(filePath)[1]: filePath = '{0}.{1}'.format(filePath, 'pdf') origFormat = self.printer.outputFormat() self.printer.setOutputFormat(QPrinter.OutputFormat.PdfFormat) self.printer.setOutputFileName(filePath) self.adjustSpacing() self.setupData() self.paintData(self.printer) self.printer.setOutputFormat(origFormat) self.printer.setOutputFileName('') self.adjustSpacing() TreeLine-3.2.1/source/printdialogs.py000066400000000000000000001616371506556630100176220ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # printdialogs.py, provides print preview and print settings dialogs # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import collections from PyQt6.QtCore import (QMarginsF, QPoint, QRect, QSize, QSizeF, Qt, pyqtSignal) from PyQt6.QtGui import (QAction, QFontDatabase, QFontInfo, QFontMetrics, QIntValidator, QPageLayout, QPageSize) from PyQt6.QtWidgets import (QAbstractItemView, QButtonGroup, QCheckBox, QComboBox, QDialog, QDoubleSpinBox, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListWidget, QMenu, QMessageBox, QPushButton, QRadioButton, QSpinBox, QTabWidget, QToolBar, QVBoxLayout, QWidget) from PyQt6.QtPrintSupport import (QPrintPreviewWidget, QPrinter, QPrinterInfo) import printdata import configdialog import treeformats import undo import globalref class PrintPreviewDialog(QDialog): """Dialog for print previews. Similar to QPrintPreviewDialog but calls a custom page setup dialog. """ def __init__(self, printData, parent=None): """Create the print preview dialog. Arguments: printData -- the PrintData object parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Print Preview')) self.printData = printData topLayout = QVBoxLayout(self) self.setLayout(topLayout) toolBar = QToolBar(self) topLayout.addWidget(toolBar) self.previewWidget = QPrintPreviewWidget(printData.printer, self) topLayout.addWidget(self.previewWidget) self.previewWidget.previewChanged.connect(self.updateControls) self.zoomWidthAct = QAction(_('Fit Width'), self, checkable=True) icon = globalref.toolIcons.getIcon('printpreviewzoomwidth') if icon: self.zoomWidthAct.setIcon(icon) self.zoomWidthAct.triggered.connect(self.zoomWidth) toolBar.addAction(self.zoomWidthAct) self.zoomAllAct = QAction(_('Fit Page'), self, checkable=True) icon = globalref.toolIcons.getIcon('printpreviewzoomall') if icon: self.zoomAllAct.setIcon(icon) self.zoomAllAct.triggered.connect(self.zoomAll) toolBar.addAction(self.zoomAllAct) toolBar.addSeparator() self.zoomCombo = QComboBox(self) self.zoomCombo.setEditable(True) self.zoomCombo.setInsertPolicy(QComboBox.InsertPolicy.NoInsert) self.zoomCombo.addItems([' 12%', ' 25%', ' 50%', ' 75%', ' 100%', ' 125%', ' 150%', ' 200%', ' 400%', ' 800%']) self.zoomCombo.currentTextChanged.connect(self.zoomToValue) self.zoomCombo.lineEdit().returnPressed.connect(self.zoomToValue) toolBar.addWidget(self.zoomCombo) zoomInAct = QAction(_('Zoom In'), self) icon = globalref.toolIcons.getIcon('printpreviewzoomin') if icon: zoomInAct.setIcon(icon) zoomInAct.triggered.connect(self.zoomIn) toolBar.addAction(zoomInAct) zoomOutAct = QAction(_('Zoom Out'), self) icon = globalref.toolIcons.getIcon('printpreviewzoomout') if icon: zoomOutAct.setIcon(icon) zoomOutAct.triggered.connect(self.zoomOut) toolBar.addAction(zoomOutAct) toolBar.addSeparator() self.previousAct = QAction(_('Previous Page'), self) icon = globalref.toolIcons.getIcon('printpreviewprevious') if icon: self.previousAct.setIcon(icon) self.previousAct.triggered.connect(self.previousPage) toolBar.addAction(self.previousAct) self.pageNumEdit = QLineEdit(self) self.pageNumEdit.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter) width = QFontMetrics(self.pageNumEdit.font()).size(Qt.TextFlag. TextSingleLine, '0000').width() self.pageNumEdit.setMaximumWidth(width) self.pageNumEdit.returnPressed.connect(self.setPageNum) toolBar.addWidget(self.pageNumEdit) self.maxPageLabel = QLabel(' / 000 ', self) toolBar.addWidget(self.maxPageLabel) self.nextAct = QAction(_('Next Page'), self) icon = globalref.toolIcons.getIcon('printpreviewnext') if icon: self.nextAct.setIcon(icon) self.nextAct.triggered.connect(self.nextPage) toolBar.addAction(self.nextAct) toolBar.addSeparator() self.onePageAct = QAction(_('Single Page'), self, checkable=True) icon = globalref.toolIcons.getIcon('printpreviewsingle') if icon: self.onePageAct.setIcon(icon) self.onePageAct.triggered.connect(self.previewWidget. setSinglePageViewMode) toolBar.addAction(self.onePageAct) self.twoPageAct = QAction(_('Facing Pages'), self, checkable=True) icon = globalref.toolIcons.getIcon('printpreviewdouble') if icon: self.twoPageAct.setIcon(icon) self.twoPageAct.triggered.connect(self.previewWidget. setFacingPagesViewMode) toolBar.addAction(self.twoPageAct) toolBar.addSeparator() pageSetupAct = QAction(_('Print Setup'), self) icon = globalref.toolIcons.getIcon('fileprintsetup') if icon: pageSetupAct.setIcon(icon) pageSetupAct.triggered.connect(self.printSetup) toolBar.addAction(pageSetupAct) filePrintAct = QAction(_('Print'), self) icon = globalref.toolIcons.getIcon('fileprint') if icon: filePrintAct.setIcon(icon) filePrintAct.triggered.connect(self.filePrint) toolBar.addAction(filePrintAct) def updateControls(self): """Update control availability and status based on a change signal. """ self.zoomWidthAct.setChecked(self.previewWidget.zoomMode() == QPrintPreviewWidget.ZoomMode.FitToWidth) self.zoomAllAct.setChecked(self.previewWidget.zoomMode() == QPrintPreviewWidget.ZoomMode.FitInView) zoom = self.previewWidget.zoomFactor() * 100 self.zoomCombo.setEditText('{0:4.0f}%'.format(zoom)) self.previousAct.setEnabled(self.previewWidget.currentPage() > 1) self.nextAct.setEnabled(self.previewWidget.currentPage() < self.previewWidget.pageCount()) self.pageNumEdit.setText(str(self.previewWidget.currentPage())) self.maxPageLabel.setText(' / {0} '.format(self.previewWidget. pageCount())) self.onePageAct.setChecked(self.previewWidget.viewMode() == QPrintPreviewWidget.ViewMode.SinglePageView) self.twoPageAct.setChecked(self.previewWidget.viewMode() == QPrintPreviewWidget.ViewMode. FacingPagesView) def zoomWidth(self, checked=True): """Set the fit to width zoom mode if checked. Arguments: checked -- set this mode if True """ if checked: self.previewWidget.setZoomMode(QPrintPreviewWidget.ZoomMode. FitToWidth) else: self.previewWidget.setZoomMode(QPrintPreviewWidget.ZoomMode. CustomZoom) self.updateControls() def zoomAll(self, checked=True): """Set the fit in view zoom mode if checked. Arguments: checked -- set this mode if True """ if checked: self.previewWidget.setZoomMode(QPrintPreviewWidget.ZoomMode.FitInView) else: self.previewWidget.setZoomMode(QPrintPreviewWidget.ZoomMode. CustomZoom) self.updateControls() def zoomToValue(self, factorStr=''): """Zoom to the given combo box string value. Arguments: factorStr -- the zoom factor as a string, often with a % suffix """ if not factorStr: factorStr = self.zoomCombo.lineEdit().text() try: factor = float(factorStr.strip(' %')) / 100 self.previewWidget.setZoomFactor(factor) except ValueError: pass self.updateControls() def zoomIn(self): """Increase the zoom level by an increment. """ self.previewWidget.zoomIn() self.updateControls() def zoomOut(self): """Decrease the zoom level by an increment. """ self.previewWidget.zoomOut() self.updateControls() def previousPage(self): """Go to the previous page of the preview. """ self.previewWidget.setCurrentPage(self.previewWidget.currentPage() - 1) self.updateControls() def nextPage(self): """Go to the next page of the preview. """ self.previewWidget.setCurrentPage(self.previewWidget.currentPage() + 1) self.updateControls() def setPageNum(self): """Go to a page number from the line editor based on a signal. """ try: self.previewWidget.setCurrentPage(int(self.pageNumEdit.text())) except ValueError: pass self.updateControls() def printSetup(self): """Show a dialog to set margins, page size and other printing options. """ setupDialog = PrintSetupDialog(self.printData, False, self) if setupDialog.exec() == QDialog.DialogCode.Accepted: self.printData.setupData() self.previewWidget.updatePreview() def filePrint(self): """Show dialog and print tree output based on current options. """ self.close() if (self.printData.printer.outputFormat() == QPrinter.OutputFormat.NativeFormat): self.printData.filePrint() else: self.printData.filePrintPdf() def sizeHint(self): """Return a larger default height. """ size = super().sizeHint() size.setHeight(600) return size def restoreDialogGeom(self): """Restore dialog window geometry from history options. """ rect = QRect(globalref.histOptions['PrintPrevXPos'], globalref.histOptions['PrintPrevYPos'], globalref.histOptions['PrintPrevXSize'], globalref.histOptions['PrintPrevYSize']) if rect.height() and rect.width(): self.setGeometry(rect) def saveDialogGeom(self): """Savedialog window geometry to history options. """ globalref.histOptions.changeValue('PrintPrevXSize', self.width()) globalref.histOptions.changeValue('PrintPrevYSize', self.height()) globalref.histOptions.changeValue('PrintPrevXPos', self.geometry().x()) globalref.histOptions.changeValue('PrintPrevYPos', self.geometry().y()) def closeEvent(self, event): """Save dialog geometry at close. Arguments: event -- the close event """ if globalref.genOptions['SaveWindowGeom']: self.saveDialogGeom() class PrintSetupDialog(QDialog): """Base dialog for setting the print configuration. Pushes most options to the PrintData class. """ def __init__(self, printData, showExtraButtons=True, parent=None): """Create the printing setup dialog. Arguments: printData -- a reference to the PrintData class showExtraButtons -- add print preview and print shortcut buttons parent -- the parent window """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Printing Setup')) self.printData = printData topLayout = QVBoxLayout(self) self.setLayout(topLayout) tabs = QTabWidget() topLayout.addWidget(tabs) generalPage = GeneralPage(self.printData) tabs.addTab(generalPage, _('&General Options')) pageSetupPage = PageSetupPage(self.printData, generalPage.currentPrinterName) tabs.addTab(pageSetupPage, _('Page &Setup')) fontPage = FontPage(self.printData) tabs.addTab(fontPage, _('&Font Selection')) headerPage = HeaderPage(self.printData) tabs.addTab(headerPage, _('&Header/Footer')) generalPage.printerChanged.connect(pageSetupPage.changePrinter) self.tabPages = [generalPage, pageSetupPage, fontPage, headerPage] ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() if showExtraButtons: previewButton = QPushButton(_('Print Pre&view...')) ctrlLayout.addWidget(previewButton) previewButton.clicked.connect(self.preview) printButton = QPushButton(_('&Print...')) ctrlLayout.addWidget(printButton) printButton.clicked.connect(self.quickPrint) okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) def quickPrint(self): """Accept this dialog and go to print dialog. """ self.accept() if (self.printData.printer.outputFormat() == QPrinter.OutputFormat.NativeFormat): self.printData.filePrint() else: self.printData.filePrintPdf() def preview(self): """Accept this dialog and go to print preview dialog. """ self.accept() self.printData.printPreview() def accept(self): """Store results before closing dialog. """ if not self.tabPages[1].checkValid(): QMessageBox.warning(self, 'TreeLine', _('Error: Page size or margins are invalid')) return changed = False control = self.printData.localControl undoObj = undo.StateSettingUndo(control.structure.undoList, self.printData.fileData, self.printData.readData) for page in self.tabPages: if page.saveChanges(): changed = True if changed: self.printData.adjustSpacing() control.setModified() else: control.structure.undoList.removeLastUndo(undoObj) super().accept() _pdfPrinterName = _('TreeLine PDF Printer') class GeneralPage(QWidget): """Dialog page for misc. print options. """ printerChanged = pyqtSignal(str) def __init__(self, printData, parent=None): """Create the general settings page. Arguments: printData -- a reference to the PrintData class parent -- the parent dialog """ super().__init__(parent) self.printData = printData self.printerList = QPrinterInfo.availablePrinterNames() self.printerList.insert(0, _pdfPrinterName) self.currentPrinterName = self.printData.printer.printerName() if not self.currentPrinterName: self.currentPrinterName = _pdfPrinterName topLayout = QHBoxLayout(self) self.setLayout(topLayout) leftLayout = QVBoxLayout() topLayout.addLayout(leftLayout) whatGroupBox = QGroupBox(_('What to print')) leftLayout.addWidget(whatGroupBox) whatLayout = QVBoxLayout(whatGroupBox) self.whatButtons = QButtonGroup(self) treeButton = QRadioButton(_('&Entire tree')) self.whatButtons.addButton(treeButton, printdata.PrintScope.entireTree) whatLayout.addWidget(treeButton) branchButton = QRadioButton(_('Selected &branches')) self.whatButtons.addButton(branchButton, printdata.PrintScope.selectBranch) whatLayout.addWidget(branchButton) nodeButton = QRadioButton(_('Selected &nodes')) self.whatButtons.addButton(nodeButton, printdata.PrintScope.selectNode) whatLayout.addWidget(nodeButton) self.whatButtons.button(self.printData.printWhat).setChecked(True) self.whatButtons.buttonClicked.connect(self.updateCmdAvail) includeBox = QGroupBox(_('Included Nodes')) leftLayout.addWidget(includeBox) includeLayout = QVBoxLayout(includeBox) self.rootButton = QCheckBox(_('&Include root node')) includeLayout.addWidget(self.rootButton) self.rootButton.setChecked(self.printData.includeRoot) self.openOnlyButton = QCheckBox(_('Onl&y open node children')) includeLayout.addWidget(self.openOnlyButton) self.openOnlyButton.setChecked(self.printData.openOnly) leftLayout.addStretch() rightLayout = QVBoxLayout() topLayout.addLayout(rightLayout) printerBox = QGroupBox(_('Select &Printer')) rightLayout.addWidget(printerBox) printerLayout = QVBoxLayout(printerBox) printerCombo = QComboBox() printerLayout.addWidget(printerCombo) printerCombo.addItems(self.printerList) printerCombo.setCurrentIndex(self.printerList.index(self. currentPrinterName)) printerCombo.currentIndexChanged.connect(self.changePrinter) featureBox = QGroupBox(_('Features')) rightLayout.addWidget(featureBox) featureLayout = QVBoxLayout(featureBox) self.linesButton = QCheckBox(_('&Draw lines to children')) featureLayout.addWidget(self.linesButton) self.linesButton.setChecked(self.printData.drawLines) self.widowButton = QCheckBox(_('&Keep first child with parent')) featureLayout.addWidget(self.widowButton) self.widowButton.setChecked(self.printData.widowControl) indentBox = QGroupBox(_('Indent')) rightLayout.addWidget(indentBox) indentLayout = QHBoxLayout(indentBox) indentLabel = QLabel(_('Indent Offse&t\n(line height units)')) indentLayout.addWidget(indentLabel) self.indentSpin = QDoubleSpinBox() indentLayout.addWidget(self.indentSpin) indentLabel.setBuddy(self.indentSpin) self.indentSpin.setMinimum(0.5) self.indentSpin.setSingleStep(0.5) self.indentSpin.setDecimals(1) self.indentSpin.setValue(self.printData.indentFactor) rightLayout.addStretch() self.updateCmdAvail() def updateCmdAvail(self): """Update options available based on print what settings. """ if self.whatButtons.checkedId() == printdata.PrintScope.selectNode: self.rootButton.setChecked(True) self.rootButton.setEnabled(False) self.openOnlyButton.setChecked(False) self.openOnlyButton.setEnabled(False) else: self.rootButton.setEnabled(True) self.openOnlyButton.setEnabled(True) def changePrinter(self, printerNum): """Change the current printer based on a combo box signal. Arguments: printerNum -- the printer number from the combo box """ self.currentPrinterName = self.printerList[printerNum] self.printerChanged.emit(self.currentPrinterName) def saveChanges(self): """Update print data with current dialog settings. Return True if saved settings have changed, False otherwise. """ self.printData.printWhat = self.whatButtons.checkedId() self.printData.includeRoot = self.rootButton.isChecked() self.printData.openOnly = self.openOnlyButton.isChecked() if self.currentPrinterName != _pdfPrinterName: self.printData.printer.setPrinterName(self.currentPrinterName) else: self.printData.printer.setPrinterName('') changed = False if self.printData.drawLines != self.linesButton.isChecked(): self.printData.drawLines = self.linesButton.isChecked() changed = True if self.printData.widowControl != self.widowButton.isChecked(): self.printData.widowControl = self.widowButton.isChecked() changed = True if self.printData.indentFactor != self.indentSpin.value(): self.printData.indentFactor = self.indentSpin.value() changed = True return changed _paperSizes = collections.OrderedDict([('Letter', _('Letter (8.5 x 11 in.)')), ('Legal', _('Legal (8.5 x 14 in.)'),), ('Tabloid', _('Tabloid (11 x 17 in.)')), ('A3', _('A3 (279 x 420 mm)')), ('A4', _('A4 (210 x 297 mm)')), ('A5', _('A5 (148 x 210 mm)')), ('Custom', _('Custom Size'))]) _units = collections.OrderedDict([('in', _('Inches (in)')), ('mm', _('Millimeters (mm)')), ('cm', _('Centimeters (cm)'))]) _unitValues = {'in': 1.0, 'cm': 2.54, 'mm': 25.4} _unitDecimals = {'in': 2, 'cm': 1, 'mm': 0} class PageSetupPage(QWidget): """Dialog page for page setup options. """ def __init__(self, printData, currentPrinterName, parent=None): """Create the page setup settings page. Arguments: printData -- a reference to the PrintData class currentPrinterName -- the selected printer for validation parent -- the parent dialog """ super().__init__(parent) self.printData = printData self.currentPrinterName = currentPrinterName topLayout = QHBoxLayout(self) self.setLayout(topLayout) leftLayout = QVBoxLayout() topLayout.addLayout(leftLayout) unitsBox = QGroupBox(_('&Units')) leftLayout.addWidget(unitsBox) unitsLayout = QVBoxLayout(unitsBox) unitsCombo = QComboBox() unitsLayout.addWidget(unitsCombo) unitsCombo.addItems(list(_units.values())) self.currentUnit = globalref.miscOptions['PrintUnits'] if self.currentUnit not in _units: self.currentUnit = 'in' unitsCombo.setCurrentIndex(list(_units.keys()).index(self.currentUnit)) unitsCombo.currentIndexChanged.connect(self.changeUnits) paperSizeBox = QGroupBox(_('Paper &Size')) leftLayout.addWidget(paperSizeBox) paperSizeLayout = QGridLayout(paperSizeBox) spacing = paperSizeLayout.spacing() paperSizeLayout.setVerticalSpacing(0) paperSizeLayout.setRowMinimumHeight(1, spacing) paperSizeCombo = QComboBox() paperSizeLayout.addWidget(paperSizeCombo, 0, 0, 1, 2) paperSizeCombo.addItems(list(_paperSizes.values())) self.currentPaperSize = self.printData.paperSizeName() if self.currentPaperSize not in _paperSizes: self.currentPaperSize = 'Custom' paperSizeCombo.setCurrentIndex(list(_paperSizes.keys()). index(self.currentPaperSize)) paperSizeCombo.currentIndexChanged.connect(self.changePaper) widthLabel = QLabel(_('&Width:')) paperSizeLayout.addWidget(widthLabel, 2, 0) self.paperWidthSpin = UnitSpinBox(self.currentUnit) paperSizeLayout.addWidget(self.paperWidthSpin, 3, 0) widthLabel.setBuddy(self.paperWidthSpin) paperWidth, paperHeight = self.printData.roundedPaperSize() self.paperWidthSpin.setInchValue(paperWidth) heightlabel = QLabel(_('Height:')) paperSizeLayout.addWidget(heightlabel, 2, 1) self.paperHeightSpin = UnitSpinBox(self.currentUnit) paperSizeLayout.addWidget(self.paperHeightSpin, 3, 1) heightlabel.setBuddy(self.paperHeightSpin) self.paperHeightSpin.setInchValue(paperHeight) if self.currentPaperSize != 'Custom': self.paperWidthSpin.setEnabled(False) self.paperHeightSpin.setEnabled(False) orientbox = QGroupBox(_('Orientation')) leftLayout.addWidget(orientbox) orientLayout = QVBoxLayout(orientbox) portraitButton = QRadioButton(_('Portra&it')) orientLayout.addWidget(portraitButton) landscapeButton = QRadioButton(_('Lan&dscape')) orientLayout.addWidget(landscapeButton) self.portraitOrient = (self.printData.pageLayout.orientation() == QPageLayout.Orientation.Portrait) if self.portraitOrient: portraitButton.setChecked(True) else: landscapeButton.setChecked(True) portraitButton.toggled.connect(self.changeOrient) rightLayout = QVBoxLayout() topLayout.addLayout(rightLayout) marginsBox = QGroupBox(_('Margins')) rightLayout.addWidget(marginsBox) marginsLayout = QGridLayout(marginsBox) spacing = marginsLayout.spacing() marginsLayout.setVerticalSpacing(0) marginsLayout.setRowMinimumHeight(2, spacing) marginsLayout.setRowMinimumHeight(5, spacing) leftLabel = QLabel(_('&Left:')) marginsLayout.addWidget(leftLabel, 3, 0) leftMarginSpin = UnitSpinBox(self.currentUnit) marginsLayout.addWidget(leftMarginSpin, 4, 0) leftLabel.setBuddy(leftMarginSpin) topLabel = QLabel(_('&Top:')) marginsLayout.addWidget(topLabel, 0, 1) topMarginSpin = UnitSpinBox(self.currentUnit) marginsLayout.addWidget(topMarginSpin, 1, 1) topLabel.setBuddy(topMarginSpin) rightLabel = QLabel(_('&Right:')) marginsLayout.addWidget(rightLabel, 3, 2) rightMarginSpin = UnitSpinBox(self.currentUnit) marginsLayout.addWidget(rightMarginSpin, 4, 2) rightLabel.setBuddy(rightMarginSpin) bottomLabel = QLabel(_('&Bottom:')) marginsLayout.addWidget(bottomLabel, 6, 1) bottomMarginSpin = UnitSpinBox(self.currentUnit) marginsLayout.addWidget(bottomMarginSpin, 7, 1) bottomLabel.setBuddy(bottomMarginSpin) self.marginControls = (leftMarginSpin, topMarginSpin, rightMarginSpin, bottomMarginSpin) for control, value in zip(self.marginControls, self.printData.roundedMargins()): control.setInchValue(value) headerLabel = QLabel(_('He&ader:')) marginsLayout.addWidget(headerLabel, 0, 2) self.headerMarginSpin = UnitSpinBox(self.currentUnit) marginsLayout.addWidget(self.headerMarginSpin, 1, 2) headerLabel.setBuddy(self.headerMarginSpin) self.headerMarginSpin.setInchValue(self.printData.headerMargin) footerLabel = QLabel(_('Foot&er:')) marginsLayout.addWidget(footerLabel, 6, 2) self.footerMarginSpin = UnitSpinBox(self.currentUnit) marginsLayout.addWidget(self.footerMarginSpin, 7, 2) footerLabel.setBuddy(self.footerMarginSpin) self.footerMarginSpin.setInchValue(self.printData.footerMargin) columnsBox = QGroupBox(_('Columns')) rightLayout.addWidget(columnsBox) columnLayout = QGridLayout(columnsBox) numLabel = QLabel(_('&Number of columns')) columnLayout.addWidget(numLabel, 0, 0) self.columnSpin = QSpinBox() columnLayout.addWidget(self.columnSpin, 0, 1) numLabel.setBuddy(self.columnSpin) self.columnSpin.setMinimum(1) self.columnSpin.setMaximum(9) self.columnSpin.setValue(self.printData.numColumns) spaceLabel = QLabel(_('Space between colu&mns')) columnLayout.addWidget(spaceLabel, 1, 0) self.columnSpaceSpin = UnitSpinBox(self.currentUnit) columnLayout.addWidget(self.columnSpaceSpin, 1, 1) spaceLabel.setBuddy(self.columnSpaceSpin) self.columnSpaceSpin.setInchValue(self.printData.columnSpacing) def changePrinter(self, newPrinterName): """Change the currently selected printer. Arguments: newPrinterName -- new printer selection """ self.currentPrinterName = newPrinterName def changeUnits(self, unitNum): """Change the current unit and update conversions based on a signal. Arguments: unitNum -- the unit index number from the combobox """ oldUnit = self.currentUnit self.currentUnit = list(_units.keys())[unitNum] self.paperWidthSpin.changeUnit(self.currentUnit) self.paperHeightSpin.changeUnit(self.currentUnit) for control in self.marginControls: control.changeUnit(self.currentUnit) self.headerMarginSpin.changeUnit(self.currentUnit) self.footerMarginSpin.changeUnit(self.currentUnit) self.columnSpaceSpin.changeUnit(self.currentUnit) def changePaper(self, paperNum): """Change the current paper size based on a signal. Arguments: paperNum -- the paper size index number from the combobox """ self.currentPaperSize = list(_paperSizes.keys())[paperNum] if self.currentPaperSize != 'Custom': tempPrinter = QPrinter() pageLayout = tempPrinter.pageLayout() pageLayout.setPageSize(QPageSize(getattr(QPageSize.PageSizeId, self.currentPaperSize))) if not self.portraitOrient: pageLayout.setOrientation(QPageLayout.Orientation.Landscape) paperSize = pageLayout.fullRect(QPageLayout.Unit.Inch) self.paperWidthSpin.setInchValue(round(paperSize.width(), 2)) self.paperHeightSpin.setInchValue(round(paperSize.height(), 2)) self.paperWidthSpin.setEnabled(self.currentPaperSize == 'Custom') self.paperHeightSpin.setEnabled(self.currentPaperSize == 'Custom') def changeOrient(self, isPortrait): """Change the orientation based on a signal. Arguments: isPortrait -- true if portrait orientation is selected """ self.portraitOrient = isPortrait width = self.paperWidthSpin.inchValue height = self.paperHeightSpin.inchValue if (self.portraitOrient and width > height) or (not self.portraitOrient and width < height): self.paperWidthSpin.setInchValue(height) self.paperHeightSpin.setInchValue(width) def checkValid(self): """Return True if the current page size and margins appear to be valid. """ pageWidth = self.paperWidthSpin.inchValue pageHeight = self.paperHeightSpin.inchValue if pageWidth <= 0 or pageHeight <= 0: return False margins = tuple(control.inchValue for control in self.marginControls) if (margins[0] + margins[2] >= pageWidth or margins[1] + margins[3] >= pageHeight): return False return True def saveChanges(self): """Update print data with current dialog settings. Return True if saved settings have changed, False otherwise. """ if self.currentUnit != globalref.miscOptions['PrintUnits']: globalref.miscOptions.changeValue('PrintUnits', self.currentUnit) globalref.miscOptions.writeFile() changed = False pageLayout = self.printData.pageLayout if self.currentPaperSize != 'Custom': size = getattr(QPageSize.PageSizeId, self.currentPaperSize) if size != pageLayout.pageSize().id(): pageLayout.setPageSize(QPageSize(size)) changed = True else: size = (self.paperWidthSpin.inchValue, self.paperHeightSpin.inchValue) if size != self.printData.roundedPaperSize(): pageLayout.setPageSize(QPageSize(QSizeF(*size), QPageSize.Unit.Inch)) changed = True orient = (QPageLayout.Orientation.Portrait if self.portraitOrient else QPageLayout.Orientation.Landscape) if orient != pageLayout.orientation(): pageLayout.setOrientation(orient) changed = True margins = tuple(control.inchValue for control in self.marginControls) if margins != self.printData.roundedMargins(): pageLayout.setMargins(QMarginsF(*margins)) changed = True if self.printData.headerMargin != self.headerMarginSpin.inchValue: self.printData.headerMargin = self.headerMarginSpin.inchValue changed = True if self.printData.footerMargin != self.footerMarginSpin.inchValue: self.printData.footerMargin = self.footerMarginSpin.inchValue changed = True if self.printData.numColumns != self.columnSpin.value(): self.printData.numColumns = self.columnSpin.value() changed = True if self.printData.columnSpacing != self.columnSpaceSpin.inchValue: self.printData.columnSpacing = self.columnSpaceSpin.inchValue changed = True return changed class UnitSpinBox(QDoubleSpinBox): """Spin box with unit suffix that can convert the units of its contents. Stores the value at full precision to avoid round-trip rounding errors. """ def __init__(self, unit, parent=None): """Create the unit spin box. Arguments: unit -- the original unit (abbreviated string) parent -- the parent dialog if given """ super().__init__(parent) self.unit = unit self.inchValue = 0.0 self.setupUnit() self.valueChanged.connect(self.changeValue) def setupUnit(self): """Set the suffix, decimal places and maximum based on the unit. """ self.blockSignals(True) self.setSuffix(' {0}'.format(self.unit)) decPlaces = _unitDecimals[self.unit] self.setDecimals(decPlaces) # set maximum to 5 digits total self.setMaximum((10**5 - 1) / 10**decPlaces) self.blockSignals(False) def changeUnit(self, unit): """Change current unit. Arguments: unit -- the new unit (abbreviated string) """ self.unit = unit self.setupUnit() self.setInchValue(self.inchValue) def setInchValue(self, inchValue): """Set box to given value, converted to current unit. Arguments: inchValue -- the value to set in inches """ self.inchValue = inchValue value = self.inchValue * _unitValues[self.unit] self.blockSignals(True) self.setValue(value) self.blockSignals(False) if value < 4: self.setSingleStep(0.1) elif value > 50: self.setSingleStep(10) else: self.setSingleStep(1) def changeValue(self): """Change the stored inch value based on a signal. """ self.inchValue = round(self.value() / _unitValues[self.unit], 2) class SmallListWidget(QListWidget): """ListWidget with a smaller size hint. """ def __init__(self, parent=None): """Initialize the widget. Arguments: parent -- the parent, if given """ super().__init__(parent) def sizeHint(self): """Return smaller width. """ itemHeight = self.visualItemRect(self.item(0)).height() return QSize(100, itemHeight * 3) class FontPage(QWidget): """Font selection print option dialog page. """ def __init__(self, printData, defaultLabel='', parent=None): """Create the font settings page. Arguments: printData -- a reference to the PrintData class defaultLabel -- default font label if given, o/w TreeLine output parent -- the parent dialog """ super().__init__(parent) self.printData = printData self.currentFont = self.printData.mainFont topLayout = QVBoxLayout(self) self.setLayout(topLayout) defaultBox = QGroupBox(_('Default Font')) topLayout.addWidget(defaultBox) defaultLayout = QVBoxLayout(defaultBox) if not defaultLabel: defaultLabel = _('&Use TreeLine output view font') self.defaultCheck = QCheckBox(defaultLabel) defaultLayout.addWidget(self.defaultCheck) self.defaultCheck.setChecked(self.printData.useDefaultFont) self.defaultCheck.clicked.connect(self.setFontSelectAvail) self.fontBox = QGroupBox(_('Select Font')) topLayout.addWidget(self.fontBox) fontLayout = QGridLayout(self.fontBox) spacing = fontLayout.spacing() fontLayout.setSpacing(0) label = QLabel(_('&Font')) fontLayout.addWidget(label, 0, 0) label.setIndent(2) self.familyEdit = QLineEdit() fontLayout.addWidget(self.familyEdit, 1, 0) self.familyEdit.setReadOnly(True) self.familyList = SmallListWidget() fontLayout.addWidget(self.familyList, 2, 0) label.setBuddy(self.familyList) self.familyEdit.setFocusProxy(self.familyList) fontLayout.setColumnMinimumWidth(1, spacing) families = [family for family in QFontDatabase.families()] families.sort(key=str.lower) self.familyList.addItems(families) self.familyList.currentItemChanged.connect(self.updateFamily) label = QLabel(_('Font st&yle')) fontLayout.addWidget(label, 0, 2) label.setIndent(2) self.styleEdit = QLineEdit() fontLayout.addWidget(self.styleEdit, 1, 2) self.styleEdit.setReadOnly(True) self.styleList = SmallListWidget() fontLayout.addWidget(self.styleList, 2, 2) label.setBuddy(self.styleList) self.styleEdit.setFocusProxy(self.styleList) fontLayout.setColumnMinimumWidth(3, spacing) self.styleList.currentItemChanged.connect(self.updateStyle) label = QLabel(_('Si&ze')) fontLayout.addWidget(label, 0, 4) label.setIndent(2) self.sizeEdit = QLineEdit() fontLayout.addWidget(self.sizeEdit, 1, 4) self.sizeEdit.setFocusPolicy(Qt.FocusPolicy.ClickFocus) validator = QIntValidator(1, 512, self) self.sizeEdit.setValidator(validator) self.sizeList = SmallListWidget() fontLayout.addWidget(self.sizeList, 2, 4) label.setBuddy(self.sizeList) self.sizeList.currentItemChanged.connect(self.updateSize) fontLayout.setColumnStretch(0, 30) fontLayout.setColumnStretch(2, 25) fontLayout.setColumnStretch(4, 10) sampleBox = QGroupBox(_('Sample')) topLayout.addWidget(sampleBox) sampleLayout = QVBoxLayout(sampleBox) self.sampleEdit = QLineEdit() sampleLayout.addWidget(self.sampleEdit) self.sampleEdit.setAlignment(Qt.AlignmentFlag.AlignCenter) self.sampleEdit.setText(_('AaBbCcDdEeFfGg...TtUuVvWvXxYyZz')) self.sampleEdit.setFixedHeight(self.sampleEdit.sizeHint().height() * 2) self.setFontSelectAvail() def setFontSelectAvail(self): """Disable font selection if default font is checked. Also set the controls with the current or default fonts. """ if self.defaultCheck.isChecked(): font = self.readFont() if font: self.currentFont = font self.setFont(self.printData.defaultFont) self.fontBox.setEnabled(False) else: self.setFont(self.currentFont) self.fontBox.setEnabled(True) def setFont(self, font): """Set the font selector to the given font. Arguments: font -- the QFont to set. """ fontInfo = QFontInfo(font) family = fontInfo.family() matches = self.familyList.findItems(family, Qt.MatchFlag.MatchExactly) if matches: self.familyList.setCurrentItem(matches[0]) self.familyList.scrollToItem(matches[0], QAbstractItemView.ScrollHint. PositionAtTop) style = QFontDatabase.styleString(fontInfo) matches = self.styleList.findItems(style, Qt.MatchFlag.MatchExactly) if matches: self.styleList.setCurrentItem(matches[0]) self.styleList.scrollToItem(matches[0]) else: self.styleList.setCurrentRow(0) self.styleList.scrollToItem(self.styleList.currentItem()) size = repr(fontInfo.pointSize()) matches = self.sizeList.findItems(size, Qt.MatchFlag.MatchExactly) if matches: self.sizeList.setCurrentItem(matches[0]) self.sizeList.scrollToItem(matches[0]) def updateFamily(self, currentItem, previousItem): """Update the family edit box and adjust the style and size options. Arguments: currentItem -- the new list widget family item previousItem -- the previous list widget item """ family = currentItem.text() self.familyEdit.setText(family) if self.familyEdit.hasFocus(): self.familyEdit.selectAll() prevStyle = self.styleEdit.text() prevSize = self.sizeEdit.text() styles = [style for style in QFontDatabase.styles(family)] self.styleList.clear() self.styleList.addItems(styles) if prevStyle: try: num = styles.index(prevStyle) except ValueError: num = 0 self.styleList.setCurrentRow(num) self.styleList.scrollToItem(self.styleList.currentItem()) sizes = [repr(size) for size in QFontDatabase.pointSizes(family)] self.sizeList.clear() self.sizeList.addItems(sizes) if prevSize: try: num = sizes.index(prevSize) except ValueError: num = 0 self.sizeList.setCurrentRow(num) self.sizeList.scrollToItem(self.sizeList.currentItem()) self.updateSample() def updateStyle(self, currentItem, previousItem): """Update the style edit box. Arguments: currentItem -- the new list widget style item previousItem -- the previous list widget item """ if currentItem: style = currentItem.text() self.styleEdit.setText(style) if self.styleEdit.hasFocus(): self.styleEdit.selectAll() self.updateSample() def updateSize(self, currentItem, previousItem): """Update the size edit box. Arguments: currentItem -- the new list widget size item previousItem -- the previous list widget item """ if currentItem: size = currentItem.text() self.sizeEdit.setText(size) if self.sizeEdit.hasFocus(): self.sizeEdit.selectAll() self.updateSample() def updateSample(self): """Update the font sample edit font. """ font = self.readFont() if font: self.sampleEdit.setFont(font) def readFont(self): """Return the selected font or None. """ family = self.familyEdit.text() style = self.styleEdit.text() size = self.sizeEdit.text() if family and style and size: return QFontDatabase.font(family, style, int(size)) return None def saveChanges(self): """Update print data with current dialog settings. Return True if saved settings have changed, False otherwise. """ if self.defaultCheck.isChecked(): if not self.printData.useDefaultFont: self.printData.useDefaultFont = True self.printData.mainFont = self.printData.defaultFont return True else: font = self.readFont() if font and (self.printData.useDefaultFont or font != self.printData.mainFont): self.printData.useDefaultFont = False self.printData.mainFont = font return True return False _headerNames = (_('&Header Left'), _('Header C&enter'), _('Header &Right')) _footerNames = (_('Footer &Left'), _('Footer Ce&nter'), _('Footer Righ&t')) class HeaderPage(QWidget): """Header/footer print option dialog page. """ def __init__(self, printData, parent=None): """Create the header/footer settings page. Arguments: printData -- a reference to the PrintData class parent -- the parent dialog """ super().__init__(parent) self.printData = printData self.focusedEditor = None topLayout = QGridLayout(self) fieldBox = QGroupBox(_('Fiel&ds')) topLayout.addWidget(fieldBox, 0, 0, 3, 1) fieldLayout = QVBoxLayout(fieldBox) self.fieldListWidget = FieldListWidget() fieldLayout.addWidget(self.fieldListWidget) fieldFormatButton = QPushButton(_('Field For&mat')) fieldLayout.addWidget(fieldFormatButton) fieldFormatButton.clicked.connect(self.showFieldFormatDialog) self.addFieldButton = QPushButton('>>') topLayout.addWidget(self.addFieldButton, 0, 1) self.addFieldButton.setMaximumWidth(self.addFieldButton.sizeHint(). height()) self.addFieldButton.clicked.connect(self.addField) self.delFieldButton = QPushButton('<<') topLayout.addWidget(self.delFieldButton, 1, 1) self.delFieldButton.setMaximumWidth(self.delFieldButton.sizeHint(). height()) self.delFieldButton.clicked.connect(self.delField) headerFooterBox = QGroupBox(_('Header and Footer')) topLayout.addWidget(headerFooterBox, 0, 2, 2, 1) headerFooterLayout = QGridLayout(headerFooterBox) spacing = headerFooterLayout.spacing() headerFooterLayout.setVerticalSpacing(0) headerFooterLayout.setRowMinimumHeight(2, spacing) self.headerEdits = self.addLineEdits(_headerNames, headerFooterLayout, 0) self.footerEdits = self.addLineEdits(_footerNames, headerFooterLayout, 3) self.loadContent() def addLineEdits(self, names, layout, startRow): """Add line edits for header or footer. Return a list of line edits added to the top layout. Arguments: names -- a list of label names layout -- the grid layout t use startRow -- the initial row number """ lineEdits = [] for num, name in enumerate(names): label = QLabel(name) layout.addWidget(label, startRow, num) lineEdit = configdialog.TitleEdit() layout.addWidget(lineEdit, startRow + 1, num) label.setBuddy(lineEdit) lineEdit.cursorPositionChanged.connect(self.setControlAvailability) lineEdit.focusIn.connect(self.setCurrentEditor) lineEdits.append(lineEdit) return lineEdits def loadContent(self): """Load field names and header/footer text into the controls. """ self.fieldListWidget.addItems(self.printData.localControl.structure. treeFormats.fileInfoFormat.fieldNames()) self.fieldListWidget.setCurrentRow(0) for text, lineEdit in zip(splitHeaderFooter(self.printData.headerText), self.headerEdits): lineEdit.blockSignals(True) lineEdit.setText(text) lineEdit.blockSignals(False) for text, lineEdit in zip(splitHeaderFooter(self.printData.footerText), self.footerEdits): lineEdit.blockSignals(True) lineEdit.setText(text) lineEdit.blockSignals(False) self.focusedEditor = self.headerEdits[0] self.headerEdits[0].setFocus() self.setControlAvailability() def setControlAvailability(self): """Set controls available based on text cursor movements. """ cursorInField = self.isCursorInField() self.addFieldButton.setEnabled(cursorInField == None) self.delFieldButton.setEnabled(cursorInField == True) def setCurrentEditor(self, sender): """Set focusedEditor based on editor focus change signal. Arguments: sender -- the line editor to focus """ self.focusedEditor = sender self.setControlAvailability() def isCursorInField(self, selectField=False): """Return True if a field pattern encloses the cursor/selection. Return False if the selection overlaps a field. Return None if there is no field at the cursor. Arguments: selectField -- select the entire field pattern if True. """ cursorPos = self.focusedEditor.cursorPosition() selectStart = self.focusedEditor.selectionStart() if selectStart < 0: selectStart = cursorPos elif selectStart == cursorPos: # backward selection cursorPos += len(self.focusedEditor.selectedText()) textLine = self.focusedEditor.text() for match in configdialog.fieldPattern.finditer(textLine): start = (match.start() if match.start() < selectStart < match.end() else None) end = (match.end() if match.start() < cursorPos < match.end() else None) if start != None and end != None: if selectField: self.focusedEditor.setSelection(start, end - start) return True if start != None or end != None: return False return None def addField(self): """Add selected field to cursor pos in current line editor. """ fieldName = self.fieldListWidget.currentItem().text() self.focusedEditor.insert('{{*!{0}*}}'.format(fieldName)) self.focusedEditor.setFocus() def delField(self): """Remove field from cursor pos in current line editor. """ if self.isCursorInField(True): self.focusedEditor.insert('') self.focusedEditor.setFocus() def showFieldFormatDialog(self): """Show thw dialog used to set file info field formats. """ fileInfoFormat = (self.printData.localControl.structure.treeFormats. fileInfoFormat) fieldName = self.fieldListWidget.currentItem().text() field = fileInfoFormat.fieldDict[fieldName] dialog = HeaderFieldFormatDialog(field, self.printData.localControl, self) dialog.exec() def saveChanges(self): """Update print data with current dialog settings. Return True if saved settings have changed, False otherwise. """ changed = False headerList = [lineEdit.text().replace('/', r'\/') for lineEdit in self.headerEdits] while len(headerList) > 1 and not headerList[-1]: del headerList[-1] text = '/'.join(headerList) if self.printData.headerText != text: self.printData.headerText = text changed = True footerList = [lineEdit.text().replace('/', r'\/') for lineEdit in self.footerEdits] while len(footerList) > 1 and not footerList[-1]: del footerList[-1] text = '/'.join(footerList) if self.printData.footerText != text: self.printData.footerText = text changed = True return changed class FieldListWidget(QListWidget): """List widget for fields with smaller width size hint. """ def __init__(self, parent=None): """Create the list widget. Arguments: parent -- the parent dialog """ super().__init__(parent) def sizeHint(self): """Return a size with a smaller width. """ return QSize(120, 100) class HeaderFieldFormatDialog(QDialog): """Dialog to modify file info field formats used in headers and footers. """ def __init__(self, field, localControl, parent=None): """Create the field format dialog. Arguments: field -- the field to be modified localControl -- a ref to the control to save changes and undo """ super().__init__(parent) self.field = field self.localControl = localControl self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Field Format for "{0}"').format(field.name)) topLayout = QVBoxLayout(self) self.setLayout(topLayout) self.formatBox = QGroupBox(_('Output &Format')) topLayout.addWidget(self.formatBox) formatLayout = QHBoxLayout(self.formatBox) self.formatEdit = QLineEdit() formatLayout.addWidget(self.formatEdit) self.helpButton = QPushButton(_('Format &Help')) formatLayout.addWidget(self.helpButton) self.helpButton.clicked.connect(self.formatHelp) extraBox = QGroupBox(_('Extra Text')) topLayout.addWidget(extraBox) extraLayout = QVBoxLayout(extraBox) spacing = extraLayout.spacing() extraLayout.setSpacing(0) prefixLabel = QLabel(_('&Prefix')) extraLayout.addWidget(prefixLabel) self.prefixEdit = QLineEdit() extraLayout.addWidget(self.prefixEdit) prefixLabel.setBuddy(self.prefixEdit) extraLayout.addSpacing(spacing) suffixLabel = QLabel(_('&Suffix')) extraLayout.addWidget(suffixLabel) self.suffixEdit = QLineEdit() extraLayout.addWidget(self.suffixEdit) suffixLabel.setBuddy(self.suffixEdit) ctrlLayout = QHBoxLayout() topLayout.addLayout(ctrlLayout) ctrlLayout.addStretch() okButton = QPushButton(_('&OK')) ctrlLayout.addWidget(okButton) okButton.clicked.connect(self.accept) cancelButton = QPushButton(_('&Cancel')) ctrlLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.prefixEdit.setText(self.field.prefix) self.suffixEdit.setText(self.field.suffix) self.formatEdit.setText(self.field.format) self.formatBox.setEnabled(self.field.defaultFormat != '') def formatHelp(self): """Provide a format help menu based on a button signal. """ menu = QMenu(self) self.formatHelpDict = {} for descript, key in self.field.getFormatHelpMenuList(): if descript: self.formatHelpDict[descript] = key menu.addAction(descript) else: menu.addSeparator() menu.popup(self.helpButton. mapToGlobal(QPoint(0, self.helpButton.height()))) menu.triggered.connect(self.insertFormat) def insertFormat(self, action): """Insert format text from help menu into edit box. Arguments: action -- the action from the help menu """ self.formatEdit.insert(self.formatHelpDict[action.text()]) def accept(self): """Set changes after OK is hit""" prefix = self.prefixEdit.text() suffix = self.suffixEdit.text() format = self.formatEdit.text() if (self.field.prefix != prefix or self.field.suffix != suffix or self.field.format != format): undo.FormatUndo(self.localControl.structure.undoList, self.localControl.structure.treeFormats, treeformats.TreeFormats()) self.field.prefix = prefix self.field.suffix = suffix self.field.format = format self.localControl.setModified() super().accept() _headerSplitRe = re.compile(r'(? _maxActionPathLength: truncLength = _maxActionPathLength - 3 pos = abbrevPath.find(os.sep, len(abbrevPath) - truncLength) if pos < 0: pos = len(abbrevPath) - truncLength abbrevPath = '...' + abbrevPath[pos:] text = '&{0:d} {1}'.format(posNum, abbrevPath) action = QAction(text, globalref.mainControl, statusTip=str(self.pathObj)) action.triggered.connect(self.openFile) return action def openFile(self): """Open this path using the main control method. """ globalref.mainControl.openFile(self.pathObj, checkModified=True) def recordTreeState(self, localControl): """Save the tree state of this item. Arguments: localControl -- the control to store """ self.stateTime = int(time.time()) treeView = localControl.activeWindow.treeView topSpot = treeView.spotAtTop() self.scrollPos = topSpot.spotId() if topSpot else '' self.selectSpots = [spot.spotId() for spot in treeView.selectionModel().selectedSpots()] self.openSpots = [spot.spotId() for spot in localControl.structure. structSpot().expandedSpotDescendantGen(treeView)] self.openSpots = self.openSpots[:_maxOpenNodesStored] def restoreTreeState(self, localControl): """Restore the tree state of this item. Return True if the state was restored. Arguments: localControl -- the control to set state """ fileModTime = self.pathObj.stat().st_mtime if self.stateTime == 0 or fileModTime > self.stateTime: return False # file modified externally treeView = localControl.activeWindow.treeView try: for spotId in self.openSpots: treeView.expandSpot(localControl.structure.spotById(spotId)) if self.scrollPos: treeView.scrollToSpot(localControl.structure. spotById(self.scrollPos)) if self.selectSpots: treeView.selectionModel().selectSpots([localControl.structure. spotById(spotId) for spotId in self.selectSpots]) return True except (KeyError, IndexError): # for old TreeLine import (spotIds don't match) return False def __eq__(self, other): """Test for equality between RecentFileItems and paths. Arguments: other -- either a RecentFileItem or a path string """ try: otherPath = other.pathObj except AttributeError: otherPath = other # use abspath() - pathlib's resolve() can be buggy with network drives return (os.path.abspath(str(self.pathObj)) == os.path.abspath(str(otherPath))) def __ne__(self, other): """Test for inequality between RecentFileItems and paths. Arguments: other -- either a RecentFileItem or a path string """ try: otherPath = other.pathObj except AttributeError: otherPath = other # use abspath() - pathlib's resolve() can be buggy with network drives return (os.path.abspath(str(self.pathObj)) != os.path.abspath(str(otherPath))) class RecentFileList(list): """A list of recent file items. """ def __init__(self): """Load the initial list from the options file. """ super().__init__() self.updateOptions() for data in globalref.histOptions['RecentFiles']: item = RecentFileItem(dataDict=data) if not self.purge or item.pathIsValid(): self.append(item) def updateOptions(self): """Get number of entries and check exists from general options. """ self.numEntries = globalref.genOptions['RecentFiles'] self.purge = globalref.genOptions['PurgeRecentFiles'] def writeItems(self): """Write the recent items to the options file. """ data = [item.dataDict() for item in self[:self.numEntries]] globalref.histOptions.changeValue('RecentFiles', data) def addItem(self, pathObj): """Add the given path at the start of the list. If the path is in the list, move it to the start, otherwise create a new item. Arguments: pathObj -- the new path object to search and/or create """ item = RecentFileItem(pathObj) try: item = self.pop(self.index(item)) except ValueError: pass self.insert(0, item) def removeItem(self, pathObj): """Remove the given path name if found. Arguments: pathObj -- the path to be removed """ try: self.remove(RecentFileItem(pathObj)) except ValueError: pass def getActions(self): """Return a list of actions for ech recent item. """ return [item.itemAction(i) for i, item in enumerate(self[:self.numEntries], 1)] def firstDir(self): """Return a path object of the first valid directory from recent items. """ for item in self: pathObj = item.pathObj.parent try: if pathObj.is_dir(): return pathObj except OSError: pass return None def firstPath(self): """Return the first full path from the recent items if valid. """ if self and self[0].pathIsValid(): return self[0].pathObj return None def saveTreeState(self, localControl): """Save the tree state of the item matching the localControl. Arguments: localControl -- the control to store """ try: item = self[self.index(localControl.filePathObj)] except (ValueError, TypeError, AttributeError, OSError): return item.recordTreeState(localControl) def retrieveTreeState(self, localControl): """Restore the saved tree state of the item matching the localControl. Return True if the state was restored. Arguments: localControl -- the control to restore state """ try: item = self[self.index(localControl.filePathObj)] except (ValueError, AttributeError): return False return item.restoreTreeState(localControl) TreeLine-3.2.1/source/setup.py000066400000000000000000000035611506556630100162520ustar00rootroot00000000000000#****************************************************************************** # setup.py, provides a distutils script for use with cx_Freeze # # Creates a standalone windows executable # # Run the build process by running the command 'python setup.py build' # # If everything works well you should find a subdirectory in the build # subdirectory that contains the files needed to run the application # # TreeLine, an information storage program # Copyright (C) 2018, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import sys from cx_Freeze import setup, Executable from treeline import __version__ base = None if sys.platform == 'win32': base = 'Win32GUI' extraFiles = [('../doc', 'doc'), ('../icons', 'icons'), ('../samples', 'samples'), ('../source', 'source'), ('../templates', 'templates'), ('../translations', 'translations'), ('../win', '.')] setup(name = 'treeline', version = __version__, description = 'TreeLine info storage program', options = {'build_exe': {'includes': ['atexit', 'PyQt5.sip'], 'include_files': extraFiles, 'excludes': ['*.pyc'], 'zip_include_packages': ['*'], 'zip_exclude_packages': [], 'include_msvcr': True, 'build_exe': '../../TreeLine-3.0'}}, executables = [Executable('treeline.py', base=base, icon='../win/treeline.ico')]) TreeLine-3.2.1/source/spellcheck.py000066400000000000000000000541031506556630100172250ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # spellcheck.py, provides classes for spell check interfaces and dialogs, # including interfaces to aspell, ispell, hunspell. # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import sys import subprocess import collections from PyQt6.QtCore import QSize, Qt, pyqtSignal from PyQt6.QtGui import QFontMetrics, QTextCursor from PyQt6.QtWidgets import (QApplication, QDialog, QFileDialog, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListWidget, QMessageBox, QPushButton, QTextEdit, QVBoxLayout) import undo import globalref _guessRe = re.compile(r'[&?] (\S+) \d+ (\d+): (.+)') _noGuessRe = re.compile(r'# (\S+) (\d+)') class SpellCheckInterface: """Interfaces with aspell, ispell or hunspell and stores session hooks. """ def __init__(self, spellPath='', langCode=''): """Create initial hooks to outside program. Arguments: spellPath -- use to find engine executable if given langCode -- language code to pass to aspell if given """ engineOptions = collections.OrderedDict() engineOptions.update([('aspell', ['-a -H --encoding=utf-8']), ('ispell', ['-a -h -Tutf8', '-a']), ('hunspell', ['-a -H -i utf-8'])]) langPrefix = {'aspell': 'l', 'ispell': 'd', 'hunspell': 'd'} if spellPath: newEngineOptions = {} for engine in engineOptions.keys(): if engine in spellPath: newEngineOptions[spellPath] = engineOptions[engine] engineOptions = newEngineOptions for engine, options in engineOptions.items(): if langCode: options.insert(0, '{0} -{1} {2}'.format(options[0], langPrefix[engine], langCode)) for option in options: cmd = '{0} {1}'.format(engine, option) try: p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.stdIn = p.stdin self.stdOut = p.stdout self.stdOut.readline() # read header # set terse mode (no correct returns) self.stdIn.write(b'!\n') self.stdIn.flush() return except IOError: pass raise SpellCheckError('Could not initialize aspell, ispell or ' 'hunspell') def checkLine(self, line, skipWords=None): """Check one (and only one) line of text. Return a list of tuples, each with the mispelled word, position in the line, and a list of suggestions. Arguments: line -- the text string to check skipWords -- a set of words to ignore if given """ if not skipWords: skipWords = set() self.stdIn.write('^{0}\n'.format(line).encode('utf-8')) self.stdIn.flush() outputs = [self.stdOut.readline()] while outputs[-1].strip(): outputs.append(self.stdOut.readline()) results = [] for output in outputs: output = output.decode('utf-8').strip() match = _guessRe.match(output) if match: guesses = match.group(3).split(', ') else: match = _noGuessRe.match(output) guesses = [] if match: word = match.group(1) if word not in skipWords: wordPos = int(match.group(2)) - 1 # work around unicode bug in older versions of aspell while (line[wordPos:wordPos + len(word)] != word and wordPos > 0): wordPos -= 1 results.append((word, wordPos, guesses)) return results def close(self): """Shut down hooks to outside program. """ self.stdIn.close() self.stdOut.close() def acceptWord(self, word): """Accept given word for the remainder of this session. Arguments: word -- the word to accept """ self.stdIn.write('@{0}\n'.format(word).encode('utf-8')) self.stdIn.flush() def addToDict(self, word, lowCase=False): """Add word to spell check engine's dictionary. Arguments: word -- the word to add lowCase -- if True, add the word as a lower case word """ if lowCase: self.stdIn.write('&{0}\n'.format(word).encode('utf-8')) else: self.stdIn.write('*{0}\n'.format(word).encode('utf-8')) self.stdIn.write(b'#\n') # saves dict self.stdIn.flush() class SpellCheckError(Exception): """Exception class for errors interfacing with the spell check engine. """ pass # console test for the spell check engine interface if __name__ == '__main__': try: sp = SpellCheckInterface() except SpellCheckError: print('Error - could not initialize aspell, ispell or hunspell') sys.exit() while True: s = input('Enter line-> ').strip() if not s: sys.exit() if s.startswith('Accept->'): sp.acceptWord(s[8:]) elif s.startswith('Add->'): sp.addToDict(s[5:]) elif s.startswith('AddLow->'): sp.addToDict(s[8:], True) else: for word, pos, suggests in sp.checkLine(s): print('{0} @{1}: {2}\n'.format(word, pos, ', '.join(suggests))) sp.close() class SpellCheckOperation: """Feeds tree node text to the spell check dialog. """ def __init__(self, controlRef): """Initialize the spell check engine interface. Arguments: controlRef - the local control """ self.controlRef = controlRef self.selectModel = controlRef.currentSelectionModel() self.currentSpot = None self.currentField = '' self.lineNum = 0 self.textLine = '' parentWidget = QApplication.activeWindow() path = globalref.miscOptions['SpellCheckPath'] while True: try: self.spellCheckInterface = SpellCheckInterface(path, self.controlRef. spellCheckLang) return except SpellCheckError: if path: path = '' else: if sys.platform.startswith('win'): prompt = (_('Could not find either aspell.exe, ' 'ispell.exe or hunspell.exe\n' 'Browse for location?')) ans = QMessageBox.warning(parentWidget, _('Spell Check Error'), prompt, QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.Cancel, QMessageBox.StandardButton.Yes) if ans == QMessageBox.StandardButton.Cancel: raise title = _('Locate aspell.exe, ipsell.exe or ' 'hunspell.exe') path, fltr = QFileDialog.getOpenFileName(parentWidget, title, '', _('Program (*.exe)')) if path: path = path[:-4] if ' ' in path: path = '"{0}"'.format(path) globalref.miscOptions.changeValue('SpellCheckPath', path) globalref.miscOptions.writeFile() else: prompt = (_('TreeLine Spell Check Error\nMake sure ' 'aspell, ispell or hunspell is installed')) QMessageBox.warning(parentWidget, 'TreeLine', prompt) raise def spellCheck(self): """Spell check starting with the selected branches. """ parentWidget = QApplication.activeWindow() spellCheckDialog = SpellCheckDialog(self.spellCheckInterface, parentWidget) spellCheckDialog.misspellFound.connect(self.updateSelection) spellCheckDialog.changeRequest.connect(self.changeNode) origBranches = self.selectModel.selectedBranchSpots() if not origBranches: origBranches = self.controlRef.structure.rootSpots() result = (spellCheckDialog. startSpellCheck(self.textLineGenerator(origBranches))) self.selectModel.selectSpots(origBranches, expandParents = True) if result and origBranches[0].parentSpot.parentSpot: prompt = _('Finished checking the branch\nContinue from the top?') ans = QMessageBox.information(parentWidget, _('TreeLine Spell Check'), prompt, QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) if ans == QMessageBox.StandardButton.Yes: generator = self.textLineGenerator(self.controlRef.structure. rootSpots()) result = spellCheckDialog.startSpellCheck(generator) self.selectModel.selectSpots(origBranches, expandParents = True) else: result = False if result: QMessageBox.information(parentWidget, _('TreeLine Spell Check'), _('Finished spell checking')) def updateSelection(self): """Change the tree selection to the node with a misspelled word. """ self.selectModel.selectSpots([self.currentSpot], expandParents = True) def changeNode(self, newTextLine): """Replace the current text line in the current node. Arguments: newTextLine -- the new text to use """ node = self.currentSpot.nodeRef undo.DataUndo(self.controlRef.structure.undoList, node) textLines = node.data.get(self.currentField, '').split('\n') textLines[self.lineNum] = newTextLine node.data[self.currentField] = '\n'.join(textLines) self.controlRef.updateTreeNode(node) def textLineGenerator(self, branches): """Yield next line to be checked. Arguments: branches -- a list of branch parent nodes to check. """ for parent in branches: for self.currentSpot in parent.spotDescendantGen(): node = self.currentSpot.nodeRef for self.currentField in node.formatRef.fieldNames(): text = node.data.get(self.currentField, '') if text: for self.lineNum, self.textLine in \ enumerate(text.split('\n')): yield self.textLine class SpellCheckDialog(QDialog): """Dialog to perform and control the spell check operation. """ misspellFound = pyqtSignal() changeRequest = pyqtSignal(str) def __init__(self, spellCheckInterface, parent=None): """Create the dialog. Arguments: spellCheckInterface -- a reference to the spell engine interface parent -- the parent dialog """ super().__init__(parent) self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint) self.setWindowTitle(_('Spell Check')) self.spellCheckInterface = spellCheckInterface self.textLineIter = None self.textLine = '' self.replaceAllDict = {} self.tmpIgnoreWords = set() self.word = '' self.postion = 0 topLayout = QHBoxLayout(self) leftLayout = QVBoxLayout() topLayout.addLayout(leftLayout) wordBox = QGroupBox(_('Not in Dictionary')) leftLayout.addWidget(wordBox) wordLayout = QVBoxLayout(wordBox) label = QLabel(_('Word:')) wordLayout.addWidget(label) self.wordEdit = QLineEdit() wordLayout.addWidget(self.wordEdit) self.wordEdit.textChanged.connect(self.updateFromWord) wordLayout.addSpacing(5) label = QLabel(_('Context:')) wordLayout.addWidget(label) self.contextEdit = SpellContextEdit() wordLayout.addWidget(self.contextEdit) self.contextEdit.textChanged.connect(self.updateFromContext) suggestBox = QGroupBox(_('Suggestions')) leftLayout.addWidget(suggestBox) suggestLayout = QVBoxLayout(suggestBox) self.suggestList = QListWidget() suggestLayout.addWidget(self.suggestList) self.suggestList.itemDoubleClicked.connect(self.replace) rightLayout = QVBoxLayout() topLayout.addLayout(rightLayout) ignoreButton = QPushButton(_('Ignor&e')) rightLayout.addWidget(ignoreButton) ignoreButton.clicked.connect(self.ignore) ignoreAllButton = QPushButton(_('&Ignore All')) rightLayout.addWidget(ignoreAllButton) ignoreAllButton.clicked.connect(self.ignoreAll) rightLayout.addStretch() addButton = QPushButton(_('&Add')) rightLayout.addWidget(addButton) addButton.clicked.connect(self.add) addLowerButton = QPushButton(_('Add &Lowercase')) rightLayout.addWidget(addLowerButton) addLowerButton.clicked.connect(self.addLower) rightLayout.addStretch() replaceButton = QPushButton(_('&Replace')) rightLayout.addWidget(replaceButton) replaceButton.clicked.connect(self.replace) self.replaceAllButton = QPushButton(_('Re&place All')) rightLayout.addWidget(self.replaceAllButton) self.replaceAllButton.clicked.connect(self.replaceAll) rightLayout.addStretch() cancelButton = QPushButton(_('&Cancel')) rightLayout.addWidget(cancelButton) cancelButton.clicked.connect(self.reject) self.widgetDisableList = [ignoreButton, ignoreAllButton, addButton, addLowerButton, self.suggestList] self.fullDisableList = (self.widgetDisableList + [self.replaceAllButton, self.wordEdit]) def startSpellCheck(self, textLineIter): """Spell check text lines given in the iterator. Block execution except for the dialog if mispellings are found. Return True if spell check completes, False if cancelled. Arguments: textLineIter -- an iterator of text lines to check """ self.textLineIter = textLineIter try: self.textLine = next(self.textLineIter) except StopIteration: return True if self.spellCheck(): if self.exec() == QDialog.DialogCode.Rejected: return False return True def continueSpellCheck(self): """Check lines, starting with current line. Exit the dialog if there are no more lines to check. """ if not self.spellCheck(): self.accept() def spellCheck(self): """Step through the iterator and spell check the lines. If results found, update the dialog with the results and return True. Return false if the end of the iterator is reached. """ while True: results = self.spellCheckInterface.checkLine(self.textLine, self.tmpIgnoreWords) if results: self.word, self.position, suggestions = results[0] newWord = self.replaceAllDict.get(self.word, '') if newWord: self.textLine = self.replaceWord(newWord) self.changeRequest.emit(self.textLine) else: self.misspellFound.emit() self.setWord(suggestions) return True try: self.textLine = next(self.textLineIter) self.tmpIgnoreWords.clear() except StopIteration: return False def setWord(self, suggestions): """Set dialog contents from the checked line and spell check results. Arguments: suggestions -- a list of suggested replacement words """ self.wordEdit.blockSignals(True) self.wordEdit.setText(self.word) self.wordEdit.blockSignals(False) self.contextEdit.blockSignals(True) self.contextEdit.setPlainText(self.textLine) self.contextEdit.setSelection(self.position, self.position + len(self.word)) self.contextEdit.blockSignals(False) self.suggestList.clear() self.suggestList.addItems(suggestions) self.suggestList.setCurrentItem(self.suggestList.item(0)) for widget in self.fullDisableList: widget.setEnabled(True) def replaceWord(self, newWord): """Return textLine with word replaced with newWord. Arguments: newWord -- the replacement word """ return (self.textLine[:self.position] + newWord + self.textLine[self.position + len(self.word):]) def ignore(self): """Set word to ignored (this check only) and continue spell check. """ self.tmpIgnoreWords.add(self.word) self.continueSpellCheck() def ignoreAll(self): """Add to dictionary's ignore list and continue spell check. """ self.spellCheckInterface.acceptWord(self.word) self.continueSpellCheck() def add(self): """Add misspelling to dictionary and continue spell check""" self.spellCheckInterface.addToDict(self.word, False) self.continueSpellCheck() def addLower(self): """Add misspelling to dictionary as lowercase and continue spell check. """ self.spellCheckInterface.addToDict(self.word, True) self.continueSpellCheck() def replace(self): """Replace misspelled word with suggestion or context edit box Then continue spell check. """ if self.suggestList.isEnabled(): newWord = self.suggestList.currentItem().text() self.textLine = self.replaceWord(newWord) else: self.textLine = self.contextEdit.toPlainText() self.changeRequest.emit(self.textLine) self.continueSpellCheck() def replaceAll(self): """Replace misspelled word with suggestion or word edit (in future too). Stores changed word in replaceAllDict and continues spell check. """ if self.suggestList.isEnabled(): newWord = self.suggestList.currentItem().text() else: newWord = self.wordEdit.text() self.textLine = self.replaceWord(newWord) self.replaceAllDict[self.word] = newWord self.changeRequest.emit(self.textLine) self.continueSpellCheck() def updateFromWord(self): """Update dialog after word line editor change. Disables suggests and ignore/add controls. Updates the context editor. """ for widget in self.widgetDisableList: widget.setEnabled(False) newWord = self.wordEdit.text() self.suggestList.clearSelection() self.contextEdit.blockSignals(True) self.contextEdit.setPlainText(self.replaceWord(newWord)) self.contextEdit.setSelection(self.position, self.position + len(newWord)) self.contextEdit.blockSignals(False) def updateFromContext(self): """Update dialog after context editor change. Disables controls except for replace. """ for widget in self.fullDisableList: widget.setEnabled(False) self.suggestList.clearSelection() class SpellContextEdit(QTextEdit): """Editor for spell check word context. Sets the size hint to 3 lines and simplifies selction. """ def __init__(self, parent=None): """Create the editor. Arguments: parent -- the parent widget """ super().__init__(parent) self.setTabChangesFocus(True) def sizeHint(self): """Set prefered size of 3 lines long. """ fontHeight = QFontMetrics(self.currentFont()).lineSpacing() return QSize(QTextEdit.sizeHint(self).width(), fontHeight * 3) def setSelection(self, fromPos, toPos): """Select the given range in first paragraph. Arguments: fromPos -- the starting position toPos -- the ending position """ cursor = self.textCursor() cursor.setPosition(fromPos) cursor.setPosition(toPos, QTextCursor.MoveMode.KeepAnchor) self.setTextCursor(cursor) self.ensureCursorVisible() TreeLine-3.2.1/source/titlelistview.py000066400000000000000000000234451506556630100200250ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # titlelistview.py, provides a class for the title list view # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** from PyQt6.QtCore import Qt, pyqtSignal from PyQt6.QtGui import QAction, QKeySequence, QPalette, QTextCursor from PyQt6.QtWidgets import QTextEdit import treenode import undo import globalref class TitleListView(QTextEdit): """Class override for the title list view. Sets view defaults and updates the content. """ nodeModified = pyqtSignal(treenode.TreeNode) treeModified = pyqtSignal() shortcutEntered = pyqtSignal(QKeySequence) def __init__(self, treeView, isChildView=True, parent=None): """Initialize the title list view. Arguments: treeView - the tree view, needed for the current selection model isChildView -- shows selected nodes if false, child nodes if true parent -- the parent main window """ super().__init__(parent) self.treeView = treeView self.isChildView = isChildView self.hideChildView = not globalref.genOptions['InitShowChildPane'] self.setAcceptRichText(False) self.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap) self.setTabChangesFocus(True) self.setUndoRedoEnabled(False) self.treeSelectAction = QAction(_('Select in Tree'), self) self.treeSelectAction.triggered.connect(self.selectLineInTree) self.textChanged.connect(self.readChange) def updateContents(self): """Reload the view's content if the view is shown. Avoids update if view is not visible or has zero height or width. """ selSpots = self.treeView.selectionModel().selectedSpots() if self.isChildView: if len(selSpots) > 1 or self.hideChildView: self.hide() return if not selSpots: # use top node childList from tree structure selSpots = [globalref.mainControl.activeControl.structure. structSpot()] elif not selSpots: self.hide() return self.show() if not self.isVisible() or self.height() == 0 or self.width() == 0: return if self.isChildView: selSpots = selSpots[0].childSpots() self.blockSignals(True) if selSpots: self.setPlainText('\n'.join(spot.nodeRef.title(spot) for spot in selSpots)) else: self.clear() self.blockSignals(False) def readChange(self): """Update nodes after edited by user. """ textList = [' '.join(text.split()) for text in self.toPlainText(). split('\n') if text.strip()] selSpots = self.treeView.selectionModel().selectedSpots() treeStructure = globalref.mainControl.activeControl.structure if self.isChildView: if not selSpots: selSpots = [treeStructure.structSpot()] parentSpot = selSpots[0] parent = parentSpot.nodeRef selSpots = parentSpot.childSpots() if len(selSpots) == len(textList): # collect changes first to skip false clone changes changes = [(spot.nodeRef, text) for spot, text in zip(selSpots, textList) if spot.nodeRef.title(spot) != text] for node, text in changes: undoObj = undo.DataUndo(treeStructure.undoList, node, skipSame=True) if node.setTitle(text): self.nodeModified.emit(node) else: treeStructure.undoList.removeLastUndo(undoObj) elif self.isChildView and (textList or parent != treeStructure): undo.ChildDataUndo(treeStructure.undoList, parent) # clear hover to avoid crash if deleted child item was hovered over self.treeView.clearHover() isDeleting = len(selSpots) > len(textList) control = globalref.mainControl.activeControl if isDeleting and len(control.windowList) > 1: # clear other window selections that are about to be deleted for window in control.windowList: if window != control.activeWindow: selectModel = window.treeView.selectionModel() ancestors = set() for spot in selectModel.selectedBranchSpots(): ancestors.update(set(spot.spotChain())) if ancestors & set(selSpots): selectModel.selectSpots([], False) expandState = self.treeView.savedExpandState(selSpots) parent.replaceChildren(textList, treeStructure) self.treeView.restoreExpandState(expandState) if self.treeView.selectionModel().selectedSpots(): self.treeView.expandSpot(parentSpot) self.treeModified.emit() else: self.updateContents() # remove illegal changes def selectLineInTree(self): """Select the node for the current line in the tree view. """ selSpots = self.treeView.selectionModel().selectedSpots() if not selSpots: selSpots = [treeStructure.structSpot()] spotList = selSpots[0].childSpots() cursor = self.textCursor() blockStart = cursor.block().position() # check for selection all on one line if (cursor.selectionStart() >= blockStart and cursor.selectionEnd() < blockStart + cursor.block().length()): lineNum = cursor.blockNumber() if len(spotList) > lineNum: self.treeView.selectionModel().selectSpots([spotList[lineNum]], True, True) def hasSelectedText(self): """Return True if text is selected. """ return self.textCursor().hasSelection() def highlightSearch(self, wordList=None, regExpList=None): """Highlight any found search terms. Arguments: wordList -- list of words to highlight regExpList -- a list of regular expression objects to highlight """ backColor = self.palette().brush(QPalette.ColorGroup.Active, QPalette.ColorRole.Highlight) foreColor = self.palette().brush(QPalette.ColorGroup.Active, QPalette.ColorRole.HighlightedText) if wordList is None: wordList = [] if regExpList is None: regExpList = [] for regExp in regExpList: for match in regExp.finditer(self.toPlainText()): matchText = match.group() if matchText not in wordList: wordList.append(matchText) selections = [] for word in wordList: while self.find(word): extraSel = QTextEdit.ExtraSelection() extraSel.cursor = self.textCursor() extraSel.format.setBackground(backColor) extraSel.format.setForeground(foreColor) selections.append(extraSel) cursor = QTextCursor(self.document()) self.setTextCursor(cursor) # reset main cursor/selection self.setExtraSelections(selections) def focusInEvent(self, event): """Handle focus-in to put cursor at end for tab-based focus. Arguments: event -- the focus in event """ if event.reason() in (Qt.FocusReason.TabFocusReason, Qt.FocusReason.BacktabFocusReason): self.moveCursor(QTextCursor.MoveOperation.End) super().focusInEvent(event) def contextMenuEvent(self, event): """Override popup menu to remove local undo. Arguments: event -- the menu event """ menu = self.createStandardContextMenu() menu.removeAction(menu.actions()[0]) menu.removeAction(menu.actions()[0]) menu.insertSeparator(menu.actions()[0]) menu.insertAction(menu.actions()[0], self.treeSelectAction) self.treeSelectAction.setEnabled(self.isChildView and len(self.toPlainText().strip()) > 0) menu.exec(event.globalPos()) def keyPressEvent(self, event): """Customize handling of return and control keys. Ignore return key if not in show children mode and emit a signal for app to handle control keys. Arguments: event -- the key press event """ if (event.modifiers() == Qt.KeyboardModifier.ControlModifier and Qt.Key.Key_A <= event.key() <= Qt.Key.Key_Z): key = QKeySequence(event.keyCombination()) self.shortcutEntered.emit(key) return if self.isChildView or event.key() not in (Qt.Key.Key_Enter, Qt.Key.Key_Return): super().keyPressEvent(event) def resizeEvent(self, event): """Update view if it was collaped by splitter. """ if ((event.oldSize().height() == 0 and event.size().height()) or (event.oldSize().width() == 0 and event.size().width())): self.updateContents() return super().resizeEvent(event) TreeLine-3.2.1/source/treeformats.py000066400000000000000000000454271506556630100174540ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treeformats.py, provides a class to store node format types and info # # TreeLine, an information storage program # Copyright (C) 2023, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import operator import copy import xml.sax.saxutils import nodeformat import matheval import conditional import treenode import treestructure defaultTypeName = _('DEFAULT') _showConfRootTypeName = _('FILE') _showConfTypeTypeName = _('TYPE') _showConfTypeTitleFieldName = _('TitleFormat') _showConfTypeOutputFieldName = _('OutputFormat') _showConfTypeSpaceFieldName = _('SpaceBetween') _showConfTypeHtmlFieldName = _('FormatHtml') _showConfTypeBulletsFieldName = _('Bullets') _showConfTypeTableFieldName = _('Table') _showConfTypeChildFieldName = _('ChildType') _showConfTypeIconFieldName = _('Icon') _showConfTypeGenericFieldName = _('GenericType') _showConfTypeConditionFieldName = _('ConditionalRule') _showConfTypeSeparatorFieldName = _('ListSeparator') _showConfTypeChildLimitFieldName = _('ChildTypeLimit') _showConfFieldTypeName = _('FIELD') _showConfFieldTypeFieldName = _('FieldType') _showConfFieldFormatFieldName = _('Format') _showConfFieldPrefixFieldName = _('Prefix') _showConfFieldSuffixFieldName = _('Suffix') _showConfFieldInitFieldName = _('InitialValue') _showConfFieldLinesFieldName = _('NumLines') _showConfFieldSortKeyFieldName = _('SortKeyNum') _showConfFieldSortDirFieldName = _('SortForward') _showConfFieldEvalHtmlFieldName = _('EvalHtml') class TreeFormats(dict): """Class to store node format types and info. Stores node formats by format name in a dictionary. Provides methods to change and update format data. """ def __init__(self, formatList=None, setDefault=False): """Initialize the format storage. Arguments: formatList -- the list of formats' file info setDefault - if true, initializes with a default format """ super().__init__() # new names for types renamed in the config dialog (orig names as keys) self.typeRenameDict = {} # nested dict for fields renamed, keys are type name then orig field self.fieldRenameDict = {} self.conditionalTypes = set() # set of math field names with deleted equations, keys are type names self.emptiedMathDict = {} self.mathFieldRefDict = {} # list of math eval levels, each is a dict by type name with lists of # equation fields self.mathLevelList = [] # for saving all-type find/filter conditionals self.savedConditionText = {} # used by copied configs in config dialog self.configModified = False self.fileInfoFormat = nodeformat.FileInfoFormat(self) if formatList: for formatData in formatList: name = formatData['formatname'] self[name] = nodeformat.NodeFormat(name, self, formatData) self.updateDerivedRefs() try: self.updateMathFieldRefs() except matheval.CircularMathError: # can see if types with math fields were copied from a 2nd file # handle the exception to avoid failure at file open print('Warning - Circular math fields detected') if nodeformat.FileInfoFormat.typeName in self: self.fileInfoFormat.duplicateFileInfo(self[nodeformat. FileInfoFormat. typeName]) del self[nodeformat.FileInfoFormat.typeName] if setDefault: self[defaultTypeName] = nodeformat.NodeFormat(defaultTypeName, self, addDefaultField=True) def storeFormats(self): """Return a list of formats stored in JSON data. """ formats = list(self.values()) if self.fileInfoFormat.fieldFormatModified: formats.append(self.fileInfoFormat) return sorted([nodeFormat.storeFormat() for nodeFormat in formats], key=operator.itemgetter('formatname')) def loadGlobalSavedConditions(self, propertyDict): """Load all-type saved conditionals from property dict. Arguments: propertyDict -- a JSON property dict """ for key in propertyDict.keys(): if key.startswith('glob-cond-'): self.savedConditionText[key[10:]] = propertyDict[key] def storeGlobalSavedConditions(self, propertyDict): """Save all-type saved conditionals to property dict. Arguments: propertyDict -- a JSON property dict """ for key, text in self.savedConditionText.items(): propertyDict['glob-cond-' + key] = text return propertyDict def copySettings(self, sourceFormats): """Copy all settings from other type formats to these formats. Copy any new formats and delete any missing formats. Arguments: sourceFormats -- the type formats to copy """ if sourceFormats.typeRenameDict: for oldName, newName in sourceFormats.typeRenameDict.items(): try: self[oldName].name = newName except KeyError: pass # skip if new type is renamed formats = list(self.values()) self.clear() for nodeFormat in formats: self[nodeFormat.name] = nodeFormat sourceFormats.typeRenameDict = {} for name in list(self.keys()): if name in sourceFormats: self[name].copySettings(sourceFormats[name]) else: del self[name] for name in sourceFormats.keys(): if name not in self: self[name] = copy.deepcopy(sourceFormats[name]) if (sourceFormats.fileInfoFormat.fieldFormatModified or self.fileInfoFormat.fieldFormatModified): self.fileInfoFormat.duplicateFileInfo(sourceFormats.fileInfoFormat) def typeNames(self): """Return a sorted list of type names. """ return sorted(list(self.keys())) def updateLineParsing(self): """Update the fields parsed in the output lines for each format type. """ for typeFormat in self.values(): typeFormat.updateLineParsing() def addTypeIfMissing(self, typeFormat): """Add format to available types if not a duplicate. Arguments: typeFormat -- the node format to add """ self.setdefault(typeFormat.name, typeFormat) def fieldNameDict(self): """Return a dictionary of field name sets using type names as keys. """ result = {} for typeFormat in self.values(): result[typeFormat.name] = set(typeFormat.fieldNames()) return result def updateDerivedRefs(self): """Update derived type lists (in generics) & the conditional type set. """ self.conditionalTypes = set() for typeFormat in self.values(): typeFormat.derivedTypes = [] if typeFormat.conditional: self.conditionalTypes.add(typeFormat) if typeFormat.genericType: self.conditionalTypes.add(self[typeFormat.genericType]) for typeFormat in self.values(): if typeFormat.genericType: genericType = self[typeFormat.genericType] genericType.derivedTypes.append(typeFormat) if genericType in self.conditionalTypes: self.conditionalTypes.add(typeFormat) for typeFormat in self.values(): if not typeFormat.genericType and not typeFormat.derivedTypes: typeFormat.conditional = None self.conditionalTypes.discard(typeFormat) def updateMathFieldRefs(self): """Update refs used to cycle thru math field evaluations. """ self.mathFieldRefDict = {} allRecursiveRefs = [] recursiveRefDict = {} matheval.RecursiveEqnRef.recursiveRefDict = recursiveRefDict for typeFormat in self.values(): for field in typeFormat.fields(): if field.typeName == 'Math' and field.equation: recursiveRef = matheval.RecursiveEqnRef(typeFormat.name, field) allRecursiveRefs.append(recursiveRef) recursiveRefDict.setdefault(field.name, []).append(recursiveRef) for fieldRef in field.equation.fieldRefs: fieldRef.eqnNodeTypeName = typeFormat.name fieldRef.eqnFieldName = field.name self.mathFieldRefDict.setdefault(fieldRef.fieldName, []).append(fieldRef) if not allRecursiveRefs: return for ref in allRecursiveRefs: ref.setPriorities() allRecursiveRefs.sort() self.mathLevelList = [{allRecursiveRefs[0].eqnTypeName: [allRecursiveRefs[0]]}] for prevRef, currRef in zip(allRecursiveRefs, allRecursiveRefs[1:]): if currRef.evalSequence == prevRef.evalSequence: if prevRef.evalDirection == matheval.EvalDir.optional: prevRef.evalDirection = currRef.evalDirection elif currRef.evalDirection == matheval.EvalDir.optional: currRef.evalDirection = prevRef.evalDirection if currRef.evalDirection != prevRef.evalDirection: self.mathLevelList.append({}) else: self.mathLevelList.append({}) self.mathLevelList[-1].setdefault(currRef.eqnTypeName, []).append(currRef) def numberingFieldDict(self): """Return a dict of numbering field names by node format name. """ result = {} for typeFormat in self.values(): numberingFields = typeFormat.numberingFieldList() if numberingFields: result[typeFormat.name] = numberingFields return result def commonFields(self, nodes): """Return a list of field names common to all given node formats. Retains the field sequence from one of the types. Arguments: nodes -- the nodes to check for common fields """ formats = set() for node in nodes: formats.add(node.formatRef.name) firstFields = self[formats.pop()].fieldNames() commonFields = set(firstFields) for formatName in formats: commonFields.intersection_update(self[formatName].fieldNames()) return [field for field in firstFields if field in commonFields] def savedConditions(self): """Return a dictionary with saved Conditonals from all type formats. """ savedConditions = {} # all-type conditions for name, text in self.savedConditionText.items(): cond = conditional.Conditional(text) savedConditions[name] = cond # specific type conditions for typeFormat in self.values(): for name, text in typeFormat.savedConditionText.items(): cond = conditional.Conditional(text, typeFormat.name) savedConditions[name] = cond return savedConditions def visualConfigStructure(self, fileName): """Export a TreeLine structure containing the config types and fields. Returns the structure. Arguments: fileName -- the name for the root node """ structure = treestructure.TreeStructure() structure.treeFormats = TreeFormats() rootFormat = nodeformat.NodeFormat(_showConfRootTypeName, structure.treeFormats, addDefaultField=True) structure.treeFormats[rootFormat.name] = rootFormat typeFormat = nodeformat.NodeFormat(_showConfTypeTypeName, structure.treeFormats, addDefaultField=True) typeFormat.addField(_showConfTypeTitleFieldName) typeFormat.addField(_showConfTypeOutputFieldName) typeFormat.addField(_showConfTypeSpaceFieldName, {'fieldtype': 'Boolean'}) typeFormat.addField(_showConfTypeHtmlFieldName, {'fieldtype': 'Boolean'}) typeFormat.addField(_showConfTypeBulletsFieldName, {'fieldtype': 'Boolean'}) typeFormat.addField(_showConfTypeTableFieldName, {'fieldtype': 'Boolean'}) typeFormat.addField(_showConfTypeChildFieldName) typeFormat.addField(_showConfTypeIconFieldName) typeFormat.addField(_showConfTypeGenericFieldName) typeFormat.addField(_showConfTypeConditionFieldName) typeFormat.addField(_showConfTypeSeparatorFieldName) typeFormat.addField(_showConfTypeChildLimitFieldName) structure.treeFormats[typeFormat.name] = typeFormat fieldFormat = nodeformat.NodeFormat(_showConfFieldTypeName, structure.treeFormats, addDefaultField=True) fieldFormat.addField(_showConfFieldTypeFieldName) fieldFormat.addField(_showConfFieldFormatFieldName) fieldFormat.addField(_showConfFieldPrefixFieldName) fieldFormat.addField(_showConfFieldSuffixFieldName) fieldFormat.addField(_showConfFieldInitFieldName) fieldFormat.addField(_showConfFieldLinesFieldName, {'fieldtype': 'Number'}) fieldFormat.addField(_showConfFieldSortKeyFieldName, {'fieldtype': 'Number'}) fieldFormat.addField(_showConfFieldSortDirFieldName, {'fieldtype': 'Boolean'}) fieldFormat.addField(_showConfFieldEvalHtmlFieldName, {'fieldtype': 'Boolean'}) line = '{{*{0}*}} ({{*{1}*}})'.format(nodeformat.defaultFieldName, _showConfFieldTypeFieldName) fieldFormat.changeTitleLine(line) fieldFormat.changeOutputLines([line]) structure.treeFormats[fieldFormat.name] = fieldFormat rootNode = treenode.TreeNode(rootFormat) structure.childList.append(rootNode) structure.addNodeDictRef(rootNode) rootNode.data[nodeformat.defaultFieldName] = fileName for typeName in self.typeNames(): typeNode = treenode.TreeNode(typeFormat) rootNode.childList.append(typeNode) structure.addNodeDictRef(typeNode) typeNode.data[nodeformat.defaultFieldName] = typeName titleLine = self[typeName].getTitleLine() outputList = self[typeName].getOutputLines() if self[typeName].formatHtml: titleLine = xml.sax.saxutils.escape(titleLine) outputList = [xml.sax.saxutils.escape(line) for line in outputList] outputLines = '
    \n'.join(outputList) typeNode.data[_showConfTypeTitleFieldName] = titleLine typeNode.data[_showConfTypeOutputFieldName] = outputLines spaceBetween = repr(self[typeName].spaceBetween) typeNode.data[_showConfTypeSpaceFieldName] = spaceBetween formatHtml = repr(self[typeName].formatHtml) typeNode.data[_showConfTypeHtmlFieldName] = formatHtml useBullets = repr(self[typeName].useBullets) typeNode.data[_showConfTypeBulletsFieldName] = useBullets useTables = repr(self[typeName].useTables) typeNode.data[_showConfTypeTableFieldName] = useTables typeNode.data[_showConfTypeChildFieldName] = (self[typeName]. childType) typeNode.data[_showConfTypeIconFieldName] = (self[typeName]. iconName) typeNode.data[_showConfTypeGenericFieldName] = (self[typeName]. genericType) if self[typeName].conditional: condition = self[typeName].conditional.conditionStr() typeNode.data[_showConfTypeConditionFieldName] = condition separator = self[typeName].outputSeparator typeNode.data[_showConfTypeSeparatorFieldName] = separator childLimit = ','.join(sorted(list(self[typeName].childTypeLimit))) typeNode.data[_showConfTypeChildLimitFieldName] = childLimit fieldSortKeyDict = {} fieldSortSet = False for field in self[typeName].fields(): fieldSortKeyDict[field.name] = repr(field.sortKeyNum) if field.sortKeyNum != 0: fieldSortSet = True if not fieldSortSet: sortField = list(self[typeName].fields())[0] fieldSortKeyDict[sortField.name] = repr(1) for field in self[typeName].fields(): fieldNode = treenode.TreeNode(fieldFormat) typeNode.childList.append(fieldNode) structure.addNodeDictRef(fieldNode) fieldNode.data[nodeformat.defaultFieldName] = field.name fieldNode.data[_showConfFieldTypeFieldName] = field.typeName fieldNode.data[_showConfFieldFormatFieldName] = field.format fieldNode.data[_showConfFieldPrefixFieldName] = field.prefix fieldNode.data[_showConfFieldSuffixFieldName] = field.suffix fieldNode.data[_showConfFieldInitFieldName] = field.initDefault numLines = repr(field.numLines) fieldNode.data[_showConfFieldLinesFieldName] = numLines sortKeyNum = fieldSortKeyDict[field.name] fieldNode.data[_showConfFieldSortKeyFieldName] = sortKeyNum sortKeyFwd = repr(field.sortKeyForward) fieldNode.data[_showConfFieldSortDirFieldName] = sortKeyFwd evalHtml = repr(field.evalHtml) fieldNode.data[_showConfFieldEvalHtmlFieldName] = evalHtml structure.generateSpots(None) return structure TreeLine-3.2.1/source/treeline.pro000066400000000000000000000027221506556630100170670ustar00rootroot00000000000000SOURCES = breadcrumbview.py \ conditional.py \ configdialog.py \ dataeditors.py \ dataeditview.py \ exports.py \ fieldformat.py \ genboolean.py \ gennumber.py \ globalref.py \ helpview.py \ icondict.py \ imports.py \ matheval.py \ miscdialogs.py \ nodeformat.py \ numbering.py \ optiondefaults.py \ options.py \ outputview.py \ p3.py \ printdata.py \ printdialogs.py \ recentfiles.py \ spellcheck.py \ titlelistview.py \ treeformats.py \ treeline.py \ treelocalcontrol.py \ treemaincontrol.py \ treemodel.py \ treenode.py \ treeoutput.py \ treeselection.py \ treespotlist.py \ treespot.py \ treestructure.py \ treeview.py \ treewindow.py \ undo.py \ urltools.py TRANSLATIONS = treeline_de.ts \ treeline_es.ts \ treeline_fr.ts \ treeline_it.ts \ treeline_pt.ts \ treeline_ru.ts \ treeline_xx.ts TreeLine-3.2.1/source/treeline.py000077500000000000000000000132121506556630100167160ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treeline.py, the main program file # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** __progname__ = 'TreeLine' __version__ = '3.2.1' __author__ = 'Doug Bell' docPath = None # modified by install script if required iconPath = None # modified by install script if required templatePath = None # modified by install script if required samplePath = None # modified by install script if required translationPath = 'translations' import sys import pathlib import os.path import argparse import locale import builtins from PyQt6.QtCore import QCoreApplication, QTranslator from PyQt6.QtWidgets import QApplication def loadTranslator(fileName, app): """Load and install qt translator, return True if sucessful. Arguments: fileName -- the translator file to load app -- the main QApplication """ translator = QTranslator(app) # use abspath() - pathlib's resolve() can be buggy with network drives modPath = pathlib.Path(os.path.abspath(sys.path[0])) if modPath.is_file(): modPath = modPath.parent # for frozen binary path = modPath / translationPath result = translator.load(fileName, str(path)) if not result: path = modPath.parent / translationPath result = translator.load(fileName, str(path)) if not result: path = modPath.parent / 'i18n' / translationPath result = translator.load(fileName, str(path)) if result: QCoreApplication.installTranslator(translator) return True else: print('Warning: translation file "{0}" could not be loaded'. format(fileName)) return False def setupTranslator(app, lang=''): """Set language, load translators and setup translator functions. Return the language setting Arguments: app -- the main QApplication lang -- language setting from the command line """ try: locale.setlocale(locale.LC_ALL, '') except locale.Error: pass if not lang: lang = os.environ.get('LC_MESSAGES', '') if not lang: lang = os.environ.get('LANG', '') if not lang: try: # This is deprecated, but getlocale() gives unusable # results (too verbose, not a language code???) lang = locale.getdefaultlocale()[0] except ValueError: pass if not lang: lang = '' numTranslators = 0 if lang and lang[:2] not in ['C', 'en']: numTranslators += loadTranslator('qt_{0}'.format(lang), app) numTranslators += loadTranslator('treeline_{0}'.format(lang), app) def translate(text, comment=''): """Translation function, sets context to calling module's filename. Arguments: text -- the text to be translated comment -- a comment used only as a guide for translators """ try: frame = sys._getframe(1) fileName = frame.f_code.co_filename finally: del frame context = pathlib.Path(fileName).stem return QCoreApplication.translate(context, text, comment) def markNoTranslate(text, comment=''): """Dummy translation function, only used to mark text. Arguments: text -- the text to be translated comment -- a comment used only as a guide for translators """ return text if numTranslators: builtins._ = translate else: builtins._ = markNoTranslate builtins.N_ = markNoTranslate return lang exceptDialog = None eventLoopRunning = False def handleException(excType, value, tb): """Handle uncaught exceptions, show debug info to the user. Called from sys.excepthook. Arguments: excType -- execption class value -- execption error text tb -- the traceback object """ import miscdialogs global exceptDialog exceptDialog = miscdialogs.ExceptionDialog(excType, value, tb) exceptDialog.show() global eventLoopRunning if not eventLoopRunning: eventLoopRunning = True QApplication.instance().exec() # start event loop if not running yet if __name__ == '__main__': """Main event loop for TreeLine """ app = QApplication(sys.argv) parser = argparse.ArgumentParser() parser.add_argument('--lang', help='language code for GUI translation') parser.add_argument('fileList', nargs='*', metavar='filename', help='input filename(s) to load') args = parser.parse_args() # use abspath() - pathlib's resolve() can be buggy with network drives pathObjects = [pathlib.Path(os.path.abspath(path)) for path in args.fileList] # must setup translator before any treeline module imports lang = setupTranslator(app, args.lang) import globalref globalref.localTextEncoding = locale.getpreferredencoding() globalref.lang = lang sys.excepthook = handleException import treemaincontrol treeMainControl = treemaincontrol.TreeMainControl(pathObjects) eventLoopRunning = True app.exec() TreeLine-3.2.1/source/treeline.spec000066400000000000000000000056361506556630100172300ustar00rootroot00000000000000# -*- mode: python -*- #****************************************************************************** # treeline.spec, provides settings for use with PyInstaller # # Creates a standalone windows executable # # Run the build process by running the command 'pyinstaller treeline.spec' # # If everything works well you should find a 'dist/treeline' subdirectory # that contains the files needed to run the application # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** block_cipher = None extraFiles = [('../doc', 'doc'), ('../icons', 'icons'), ('../samples', 'samples'), ('../source/*.py', 'source'), ('../source/*.pro', 'source'), ('../source/*.spec', 'source'), ('../templates', 'templates'), ('../translations', 'translations'), ('../win/*.*', '.')] a = Analysis(['treeline.py'], pathex=['C:\\git\\treeline\\devel\\source'], binaries=[], datas=extraFiles, hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, [], exclude_binaries=True, name='treeline', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, console=False, contents_directory='.', icon='..\\win\\treeline.ico') # a.binaries = a.binaries - TOC([('d3dcompiler_47.dll', None, None), # ('libcrypto-1_1.dll', None, None), # ('libeay32.dll', None, None), # ('libglesv2.dll', None, None), # ('libssl-1_1.dll', None, None), # ('opengl32sw.dll', None, None), # ('qt5dbus.dll', None, None), # ('qt5qml.dll', None, None), # ('qt5qmlmodels.dll', None, None), # ('qt5quick.dll', None, None), # ('qt5websockets.dll', None, None)]) coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, name='treeline') TreeLine-3.2.1/source/treelocalcontrol.py000066400000000000000000002323371506556630100204720ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treelocalcontrol.py, provides a class for the main tree commands # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import pathlib import json import os import sys import gzip import datetime import operator from itertools import chain from PyQt6.QtCore import QObject, QTimer, Qt, pyqtSignal from PyQt6.QtGui import QAction, QActionGroup from PyQt6.QtWidgets import (QApplication, QDialog, QFileDialog, QMenu, QMessageBox) import treemaincontrol import treestructure import treemodel import treeformats import treenode import treewindow import exports import miscdialogs import printdata import matheval import spellcheck import undo import p3 import globalref class TreeLocalControl(QObject): """Class to handle controls local to a model/view combination. Provides methods for all local controls and stores a model & windows. """ controlActivated = pyqtSignal(QObject) controlClosed = pyqtSignal(QObject) def __init__(self, allActions, fileObj=None, treeStruct=None, fileModTime=None, forceNewWindow=False, parent=None): """Initialize the local tree controls. Use an imported structure if given or open the file if path is given. Always creates a new window. Arguments: allActions -- a dict containing the upper level actions fileObj -- the path object or file object to open, if given treeStruct -- an imported tree structure file, if given fileModTime -- file modified time for external modification checks forceNewWindow -- if True, use a new window regardless of option parent -- a parent object if given """ super().__init__(parent) self.printData = printdata.PrintData(self) self.spellCheckLang = '' self.allActions = allActions.copy() self.setupActions() self.fileModTime = fileModTime self.filePathObj = (pathlib.Path(fileObj.name) if hasattr(fileObj, 'read') else fileObj) if treeStruct: self.structure = treeStruct elif fileObj: if hasattr(fileObj, 'read'): fileData = json.load(fileObj) else: with fileObj.open('r', encoding='utf-8') as f: fileData = json.load(f) self.structure = treestructure.TreeStructure(fileData) self.printData.readData(fileData['properties']) self.spellCheckLang = fileData['properties'].get('spellchk', '') else: self.structure = treestructure.TreeStructure(addDefaults=True) fileInfoFormat = self.structure.treeFormats.fileInfoFormat fileInfoFormat.updateFileInfo(self.filePathObj, self.structure.fileInfoNode) self.model = treemodel.TreeModel(self.structure) self.model.treeModified.connect(self.updateRightViews) self.modified = False self.imported = False self.compressed = False self.encrypted = False self.windowList = [] self.activeWindow = None self.findReplaceSpotRef = (None, 0) QApplication.clipboard().dataChanged.connect(self.updateCommandsAvail) self.structure.undoList = undo.UndoRedoList(self. allActions['EditUndo'], self) self.structure.redoList = undo.UndoRedoList(self. allActions['EditRedo'], self) self.structure.undoList.altListRef = self.structure.redoList self.structure.redoList.altListRef = self.structure.undoList self.autoSaveTimer = QTimer(self) self.autoSaveTimer.timeout.connect(self.autoSave) if not globalref.mainControl.activeControl: self.windowNew(offset=0) elif forceNewWindow or globalref.genOptions['OpenNewWindow']: self.windowNew() else: oldControl = globalref.mainControl.activeControl window = oldControl.activeWindow if len(oldControl.windowList) > 1: oldControl.windowList.remove(window) else: oldControl.controlClosed.emit(oldControl) window.resetTreeModel(self.model) self.setWindowSignals(window, True) window.updateActions(self.allActions) self.windowList.append(window) self.updateWindowCaptions() self.activeWindow = window if fileObj and self.structure.childRefErrorNodes: msg = _('Warning - file corruption!\n' 'Skipped bad child references in the following nodes:') for node in self.structure.childRefErrorNodes: msg += '\n "{}"'.format(node.title()) QMessageBox.warning(self.activeWindow, 'TreeLine', msg) self.structure.childRefErrorNodes = [] def setWindowSignals(self, window, removeOld=False): """Setup signals between the window and this controller. Arguments: window -- the window to link removeOld -- if True, remove old signals """ if removeOld: window.selectChanged.disconnect() window.nodeModified.disconnect() window.treeModified.disconnect() window.winActivated.disconnect() window.winClosing.disconnect() window.selectChanged.connect(self.updateCommandsAvail) window.nodeModified.connect(self.updateTreeNode) window.treeModified.connect(self.updateTree) window.winActivated.connect(self.setActiveWin) window.winClosing.connect(self.checkWindowClose) window.setExternalSignals() def updateTreeNode(self, node, setModified=True): """Update the full tree in all windows. Also update right views in secondary windows. Arguments: node -- the node to be updated setModified -- if True, set the modified flag for this file """ if node.setConditionalType(self.structure): self.activeWindow.updateRightViews(outputOnly=True) if (self.structure.treeFormats.mathFieldRefDict and node.updateNodeMathFields(self.structure.treeFormats)): self.activeWindow.updateRightViews(outputOnly=True) if globalref.genOptions['ShowMath']: self.activeWindow.refreshDataEditViews() for window in self.windowList: window.updateTreeNode(node) if window.treeFilterView: window.treeFilterView.updateItem(node) if setModified: self.setModified() def updateTree(self, setModified=True): """Update the full tree in all windows. Also update right views in secondary windows. Arguments: setModified -- if True, set the modified flag for this file """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) typeChanges = 0 if self.structure.treeFormats.conditionalTypes: for node in self.structure.childList: typeChanges += node.setDescendantConditionalTypes(self. structure) self.updateAllMathFields() for window in self.windowList: window.updateTree() if window != self.activeWindow or typeChanges: window.updateRightViews() if window.treeFilterView: window.treeFilterView.updateContents() if setModified: self.setModified() QApplication.restoreOverrideCursor() def updateRightViews(self, setModified=False, otherTrees=False): """Update the right-hand views in all windows. Arguments: setModified -- if True, set the modified flag for this file otherTrees -- if True, also update trees in non-active windows """ for window in self.windowList: window.updateRightViews() if otherTrees and window != self.activeWindow: window.updateTree() if setModified: self.setModified() def updateAll(self, setModified=True): """Update the full tree and right-hand views in all windows. Arguments: setModified -- if True, set the modified flag for this file """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if self.structure.treeFormats.conditionalTypes: for node in self.structure.childList: node.setDescendantConditionalTypes(self.structure) self.updateAllMathFields() for window in self.windowList: window.updateTree() if window.treeFilterView: window.treeFilterView.updateContents() window.updateRightViews() self.updateCommandsAvail() if setModified: self.setModified() # self.structure.debugCheck() QApplication.restoreOverrideCursor() def updateAllMathFields(self): """Recalculate all math fields in the entire tree. """ for eqnRefDict in self.structure.treeFormats.mathLevelList: if list(eqnRefDict.values())[0][0].evalDirection != (matheval. EvalDir. upward): for node in self.structure.descendantGen(): for eqnRef in eqnRefDict.get(node.formatRef.name, []): node.data[eqnRef.eqnField.name] = (eqnRef.eqnField. equationValue(node)) else: spot = self.structure.structSpot().lastDescendantSpot() while spot: node = spot.nodeRef for eqnRef in eqnRefDict.get(node.formatRef.name, []): node.data[eqnRef.eqnField.name] = (eqnRef.eqnField. equationValue(node)) spot = spot.prevTreeSpot() def updateCommandsAvail(self): """Set commands available based on node selections. """ selSpots = self.currentSelectionModel().selectedSpots() hasSelect = len(selSpots) > 0 rootSpots = [spot for spot in selSpots if not spot.parentSpot.parentSpot] hasPrevSibling = (len(selSpots) and None not in [spot.prevSiblingSpot() for spot in selSpots]) hasNextSibling = (len(selSpots) and None not in [spot.nextSiblingSpot() for spot in selSpots]) hasChildren = (sum([len(spot.nodeRef.childList) for spot in selSpots]) > 0) mime = QApplication.clipboard().mimeData() hasData = len(mime.data('application/json')) > 0 hasText = len(mime.data('text/plain')) > 0 self.allActions['EditPaste'].setEnabled(hasData or hasText) self.allActions['EditPasteChild'].setEnabled(hasData) self.allActions['EditPasteBefore'].setEnabled(hasData and hasSelect) self.allActions['EditPasteAfter'].setEnabled(hasData and hasSelect) self.allActions['EditPasteCloneChild'].setEnabled(hasData) self.allActions['EditPasteCloneBefore'].setEnabled(hasData and hasSelect) self.allActions['EditPasteCloneAfter'].setEnabled(hasData and hasSelect) self.allActions['NodeRename'].setEnabled(len(selSpots) == 1) self.allActions['NodeInsertBefore'].setEnabled(hasSelect) self.allActions['NodeInsertAfter'].setEnabled(hasSelect) self.allActions['NodeDelete'].setEnabled(hasSelect and len(rootSpots) < len(self.structure.childList)) self.allActions['NodeIndent'].setEnabled(hasPrevSibling) self.allActions['NodeUnindent'].setEnabled(hasSelect and len(rootSpots) == 0) self.allActions['NodeMoveUp'].setEnabled(hasPrevSibling) self.allActions['NodeMoveDown'].setEnabled(hasNextSibling) self.allActions['NodeMoveFirst'].setEnabled(hasPrevSibling) self.allActions['NodeMoveLast'].setEnabled(hasNextSibling) self.allActions['DataNodeType'].parent().setEnabled(hasSelect) self.allActions['DataFlatCategory'].setEnabled(hasChildren) self.allActions['DataAddCategory'].setEnabled(hasChildren) self.allActions['DataSwapCategory'].setEnabled(hasChildren) if self.activeWindow.treeFilterView: self.allActions['NodeInsertBefore'].setEnabled(False) self.allActions['NodeInsertAfter'].setEnabled(False) self.allActions['NodeAddChild'].setEnabled(False) self.allActions['NodeIndent'].setEnabled(False) self.allActions['NodeUnindent'].setEnabled(False) self.allActions['NodeMoveUp'].setEnabled(False) self.allActions['NodeMoveDown'].setEnabled(False) self.allActions['NodeMoveFirst'].setEnabled(False) self.allActions['NodeMoveLast'].setEnabled(False) else: self.allActions['NodeAddChild'].setEnabled(True) self.activeWindow.updateCommandsAvail() def updateWindowCaptions(self): """Update the caption for all windows. """ for window in self.windowList: window.setCaption(self.filePathObj, self.modified) def setModified(self, modified=True): """Set the modified flag on this file and update commands available. Arguments: modified -- the modified state to set """ if modified != self.modified: self.modified = modified self.allActions['FileSave'].setEnabled(modified) self.updateWindowCaptions() self.resetAutoSave() def expandRootNodes(self, maxNum=5): """Expand root node if there are fewer than the maximum. Arguments: maxNum -- only expand if there are fewer root nodes than this. """ if len(self.structure.childList) < maxNum: treeView = self.activeWindow.treeView for spot in self.structure.rootSpots(): treeView.expandSpot(spot) def selectRootSpot(self): """Select the first root spot in the tree. Does not signal an update. """ self.currentSelectionModel().selectSpots([self.structure. rootSpots()[0]], False) def currentSelectionModel(self): """Return the current tree's selection model. """ return self.activeWindow.treeView.selectionModel() def setActiveWin(self, window): """When a window is activated, stores it and emits a signal. Arguments: window -- the new active window """ self.activeWindow = window self.controlActivated.emit(self) self.updateCommandsAvail() def checkWindowClose(self, window): """Check for modified files and delete ref when a window is closing. Arguments: window -- the window being closed """ if len(self.windowList) > 1: self.windowList.remove(window) # set active to one not closing to avoid errors while changing self.activeWindow = self.windowList[0] window.allowCloseFlag = True elif self.checkSaveChanges(): window.allowCloseFlag = True self.controlClosed.emit(self) else: window.allowCloseFlag = False def checkSaveChanges(self): """Ask for save if doc modified, return True if OK to continue. Save this doc if directed. Return True if not modified, if saved or if discarded. Return False on cancel. """ if not self.modified or len(self.windowList) > 1: return True promptText = (_('Save changes to {}?').format(self.filePathObj) if self.filePathObj else _('Save changes?')) ans = QMessageBox.information(self.activeWindow, 'TreeLine', promptText, QMessageBox.StandardButton.Save | QMessageBox.StandardButton.Discard | QMessageBox.StandardButton.Cancel, QMessageBox.StandardButton.Save) if ans == QMessageBox.StandardButton.Save: self.fileSave() elif ans == QMessageBox.StandardButton.Cancel: return False else: self.deleteAutoSaveFile() return True def closeWindows(self): """Close this control's windows prior to quiting the application. """ for window in self.windowList: window.close() def autoSave(self): """Save a backup file if appropriate. Called from the timer. """ if self.filePathObj and not self.imported: self.fileSave(True) def resetAutoSave(self): """Start or stop the auto-save timer based on file modified status. Also delete old autosave files if file becomes unmodified. """ self.autoSaveTimer.stop() minutes = globalref.genOptions['AutoSaveMinutes'] if minutes and self.modified: self.autoSaveTimer.start(60000 * minutes) else: self.deleteAutoSaveFile() def deleteAutoSaveFile(self): """Delete an auto save file if it exists. """ filePath = pathlib.Path(str(self.filePathObj) + '~') if self.filePathObj and filePath.is_file(): try: filePath.unlink() except OSError: QMessageBox.warning(self.activeWindow, 'TreeLine', _('Error - could not delete backup file {}'). format(filePath)) def windowActions(self, startNum=1, active=False): """Return a list of window menu actions to select this file's windows. Arguments: startNum -- where to start numbering the action names active -- if True, activate the current active window """ actions = [] maxActionPathLength = 30 abbrevPath = str(self.filePathObj) if len(abbrevPath) > maxActionPathLength: truncLength = maxActionPathLength - 3 pos = abbrevPath.find(os.sep, len(abbrevPath) - truncLength) if pos < 0: pos = len(abbrevPath) - truncLength abbrevPath = '...' + abbrevPath[pos:] for window in self.windowList: action = QAction('&{0:d} {1}'.format(startNum, abbrevPath), self, statusTip=str(self.filePathObj), checkable=True) action.triggered.connect(window.activateAndRaise) if active and window == self.activeWindow: action.setChecked(True) actions.append(action) startNum += 1 return actions def setupActions(self): """Add the actions for contols at the local level. These actions affect an individual file, possibly in multiple windows. """ localActions = {} fileSaveAct = QAction(_('&Save'), self, toolTip=_('Save File'), statusTip=_('Save the current file')) fileSaveAct.setEnabled(False) fileSaveAct.triggered.connect(self.fileSave) localActions['FileSave'] = fileSaveAct fileSaveAsAct = QAction(_('Save &As...'), self, statusTip=_('Save the file with a new name')) fileSaveAsAct.triggered.connect(self.fileSaveAs) localActions['FileSaveAs'] = fileSaveAsAct fileExportAct = QAction(_('&Export...'), self, statusTip=_('Export the file in various other formats')) fileExportAct.triggered.connect(self.fileExport) localActions['FileExport'] = fileExportAct filePropertiesAct = QAction(_('Prop&erties...'), self, statusTip=_('Set file parameters like compression and encryption')) filePropertiesAct.triggered.connect(self.fileProperties) localActions['FileProperties'] = filePropertiesAct filePrintSetupAct = QAction(_('P&rint Setup...'), self, statusTip=_('Set margins, page size and other printing options')) filePrintSetupAct.triggered.connect(self.printData.printSetup) localActions['FilePrintSetup'] = filePrintSetupAct filePrintPreviewAct = QAction(_('Print Pre&view...'), self, statusTip=_('Show a preview of printing results')) filePrintPreviewAct.triggered.connect(self.printData.printPreview) localActions['FilePrintPreview'] = filePrintPreviewAct filePrintAct = QAction(_('&Print...'), self, statusTip=_('Print tree output based on current options')) filePrintAct.triggered.connect(self.printData.filePrint) localActions['FilePrint'] = filePrintAct filePrintPdfAct = QAction(_('Print &to PDF...'), self, statusTip=_('Export to PDF with current printing options')) filePrintPdfAct.triggered.connect(self.printData.filePrintPdf) localActions['FilePrintPdf'] = filePrintPdfAct editUndoAct = QAction(_('&Undo'), self, statusTip=_('Undo the previous action')) editUndoAct.triggered.connect(self.editUndo) localActions['EditUndo'] = editUndoAct editRedoAct = QAction(_('&Redo'), self, statusTip=_('Redo the previous undo')) editRedoAct.triggered.connect(self.editRedo) localActions['EditRedo'] = editRedoAct editCutAct = QAction(_('Cu&t'), self, statusTip=_('Cut the branch or text to the clipboard')) editCutAct.triggered.connect(self.editCut) localActions['EditCut'] = editCutAct editCopyAct = QAction(_('&Copy'), self, statusTip=_('Copy the branch or text to the clipboard')) editCopyAct.triggered.connect(self.editCopy) localActions['EditCopy'] = editCopyAct editPasteAct = QAction(_('&Paste'), self, statusTip=_('Paste nodes or text from the clipboard')) editPasteAct.triggered.connect(self.editPaste) localActions['EditPaste'] = editPasteAct editPastePlainAct = QAction(_('Pa&ste Plain Text'), self, statusTip=_('Paste non-formatted text from the clipboard')) editPastePlainAct.setEnabled(False) localActions['EditPastePlain'] = editPastePlainAct editPasteChildAct = QAction(_('Paste C&hild'), self, statusTip=_('Paste a child node from the clipboard')) editPasteChildAct.triggered.connect(self.editPasteChild) localActions['EditPasteChild'] = editPasteChildAct editPasteBeforeAct = QAction(_('Paste Sibling &Before'), self, statusTip=_('Paste a sibling before selection')) editPasteBeforeAct.triggered.connect(self.editPasteBefore) localActions['EditPasteBefore'] = editPasteBeforeAct editPasteAfterAct = QAction(_('Paste Sibling &After'), self, statusTip=_('Paste a sibling after selection')) editPasteAfterAct.triggered.connect(self.editPasteAfter) localActions['EditPasteAfter'] = editPasteAfterAct editPasteCloneChildAct = QAction(_('Paste Cl&oned Child'), self, statusTip=_('Paste a child clone from the clipboard')) editPasteCloneChildAct.triggered.connect(self.editPasteCloneChild) localActions['EditPasteCloneChild'] = editPasteCloneChildAct editPasteCloneBeforeAct = QAction(_('Paste Clo&ned Sibling Before'), self, statusTip=_('Paste a sibling clone before selection')) editPasteCloneBeforeAct.triggered.connect(self.editPasteCloneBefore) localActions['EditPasteCloneBefore'] = editPasteCloneBeforeAct editPasteCloneAfterAct = QAction(_('Paste Clone&d Sibling After'), self, statusTip=_('Paste a sibling clone after selection')) editPasteCloneAfterAct.triggered.connect(self.editPasteCloneAfter) localActions['EditPasteCloneAfter'] = editPasteCloneAfterAct nodeRenameAct = QAction(_('&Rename'), self, statusTip=_('Rename the current tree entry title')) nodeRenameAct.triggered.connect(self.nodeRename) localActions['NodeRename'] = nodeRenameAct nodeAddChildAct = QAction(_('Add &Child'), self, statusTip=_('Add new child to selected parent')) nodeAddChildAct.triggered.connect(self.nodeAddChild) localActions['NodeAddChild'] = nodeAddChildAct nodeInBeforeAct = QAction(_('Insert Sibling &Before'), self, statusTip=_('Insert new sibling before selection')) nodeInBeforeAct.triggered.connect(self.nodeInBefore) localActions['NodeInsertBefore'] = nodeInBeforeAct nodeInAfterAct = QAction(_('Insert Sibling &After'), self, statusTip=_('Insert new sibling after selection')) nodeInAfterAct.triggered.connect(self.nodeInAfter) localActions['NodeInsertAfter'] = nodeInAfterAct nodeDeleteAct = QAction(_('&Delete Node'), self, statusTip=_('Delete the selected nodes')) nodeDeleteAct.triggered.connect(self.nodeDelete) localActions['NodeDelete'] = nodeDeleteAct nodeIndentAct = QAction(_('&Indent Node'), self, statusTip=_('Indent the selected nodes')) nodeIndentAct.triggered.connect(self.nodeIndent) localActions['NodeIndent'] = nodeIndentAct nodeUnindentAct = QAction(_('&Unindent Node'), self, statusTip=_('Unindent the selected nodes')) nodeUnindentAct.triggered.connect(self.nodeUnindent) localActions['NodeUnindent'] = nodeUnindentAct nodeMoveUpAct = QAction(_('&Move Up'), self, statusTip=_('Move the selected nodes up')) nodeMoveUpAct.triggered.connect(self.nodeMoveUp) localActions['NodeMoveUp'] = nodeMoveUpAct nodeMoveDownAct = QAction(_('M&ove Down'), self, statusTip=_('Move the selected nodes down')) nodeMoveDownAct.triggered.connect(self.nodeMoveDown) localActions['NodeMoveDown'] = nodeMoveDownAct nodeMoveFirstAct = QAction(_('Move &First'), self, statusTip=_('Move the selected nodes to be the first children')) nodeMoveFirstAct.triggered.connect(self.nodeMoveFirst) localActions['NodeMoveFirst'] = nodeMoveFirstAct nodeMoveLastAct = QAction(_('Move &Last'), self, statusTip=_('Move the selected nodes to be the last children')) nodeMoveLastAct.triggered.connect(self.nodeMoveLast) localActions['NodeMoveLast'] = nodeMoveLastAct title = _('&Set Node Type') key = globalref.keyboardOptions['DataNodeType'] if not key.isEmpty(): title = '{0} ({1})'.format(title, key.toString()) self.typeSubMenu = QMenu(title, statusTip=_('Set the node type for selected nodes')) self.typeSubMenu.aboutToShow.connect(self.loadTypeSubMenu) self.typeSubMenu.triggered.connect(self.dataSetType) typeContextMenuAct = QAction(_('Set Node Type'), self.typeSubMenu) typeContextMenuAct.triggered.connect(self.showTypeContextMenu) localActions['DataNodeType'] = typeContextMenuAct dataCopyTypeAct = QAction(_('Copy Types from &File...'), self, statusTip=_('Copy the configuration from another TreeLine file')) dataCopyTypeAct.triggered.connect(self.dataCopyType) localActions['DataCopyType'] = dataCopyTypeAct dataRegenRefsAct = QAction(_('&Regenerate References'), self, statusTip=_('Force update of all conditional types & math fields')) dataRegenRefsAct.triggered.connect(self.dataRegenRefs) localActions['DataRegenRefs'] = dataRegenRefsAct dataCloneMatchesAct = QAction(_('Clone All &Matched Nodes'), self, statusTip=_('Convert all matching nodes into clones')) dataCloneMatchesAct.triggered.connect(self.dataCloneMatches) localActions['DataCloneMatches'] = dataCloneMatchesAct dataDetachClonesAct = QAction(_('&Detach Clones'), self, statusTip=_('Detach all cloned nodes in current branches')) dataDetachClonesAct.triggered.connect(self.dataDetachClones) localActions['DataDetachClones'] = dataDetachClonesAct dataFlatCatAct = QAction(_('Flatten &by Category'), self, statusTip=_('Collapse descendants by merging fields')) dataFlatCatAct.triggered.connect(self.dataFlatCategory) localActions['DataFlatCategory'] = dataFlatCatAct dataAddCatAct = QAction(_('Add Category &Level...'), self, statusTip=_('Insert category nodes above children')) dataAddCatAct.triggered.connect(self.dataAddCategory) localActions['DataAddCategory'] = dataAddCatAct dataSwapCatAct = QAction(_('S&wap Category Levels'), self, statusTip=_('Swap child and grandchild category nodes')) dataSwapCatAct.triggered.connect(self.dataSwapCategory) localActions['DataSwapCategory'] = dataSwapCatAct toolsSpellCheckAct = QAction(_('&Spell Check...'), self, statusTip=_('Spell check the tree\'s text data')) toolsSpellCheckAct.triggered.connect(self.toolsSpellCheck) localActions['ToolsSpellCheck'] = toolsSpellCheckAct formatBoldAct = QAction(_('&Bold Font'), self, statusTip=_('Set the current or selected font to bold'), checkable=True) formatBoldAct.setEnabled(False) localActions['FormatBoldFont'] = formatBoldAct formatItalicAct = QAction(_('&Italic Font'), self, statusTip=_('Set the current or selected font to italic'), checkable=True) formatItalicAct.setEnabled(False) localActions['FormatItalicFont'] = formatItalicAct formatUnderlineAct = QAction(_('U&nderline Font'), self, statusTip=_('Set the current or selected font to underline'), checkable=True) formatUnderlineAct.setEnabled(False) localActions['FormatUnderlineFont'] = formatUnderlineAct formatStrikethroughAct = QAction(_('St&rikethrough Font'), self, statusTip=_('Set the current or selected font to strikethough'), checkable=True) formatStrikethroughAct.setEnabled(False) localActions['FormatStrikethroughFont'] = formatStrikethroughAct title = _('&Font Size') key = globalref.keyboardOptions['FormatFontSize'] if not key.isEmpty(): title = '{0} ({1})'.format(title, key.toString()) self.fontSizeSubMenu = QMenu(title, statusTip=_('Set size of the current or selected text')) sizeActions = QActionGroup(self) for size in (_('Small'), _('Default'), _('Large'), _('Larger'), _('Largest')): action = QAction(size, sizeActions) action.setCheckable(True) self.fontSizeSubMenu.addActions(sizeActions.actions()) self.fontSizeSubMenu.setEnabled(False) fontSizeContextMenuAct = QAction(_('Set Font Size'), self.fontSizeSubMenu) localActions['FormatFontSize'] = fontSizeContextMenuAct formatColorAct = QAction(_('Font C&olor...'), self, statusTip=_('Set the color of the current or selected text')) formatColorAct.setEnabled(False) localActions['FormatFontColor'] = formatColorAct formatExtLinkAct = QAction(_('&External Link...'), self, statusTip=_('Add or modify an extrnal web link')) formatExtLinkAct.setEnabled(False) localActions['FormatExtLink'] = formatExtLinkAct formatIntLinkAct = QAction(_('Internal &Link...'), self, statusTip=_('Add or modify an internal node link')) formatIntLinkAct.setEnabled(False) localActions['FormatIntLink'] = formatIntLinkAct formatInsDateAct = QAction(_('Insert &Date'), self, statusTip=_('Insert current date as text')) formatInsDateAct.setEnabled(False) localActions['FormatInsertDate'] = formatInsDateAct formatClearFormatAct = QAction(_('Clear For&matting'), self, statusTip=_('Clear current or selected text formatting')) formatClearFormatAct.setEnabled(False) localActions['FormatClearFormat'] = formatClearFormatAct winNewAct = QAction(_('&New Window'), self, statusTip=_('Open a new window for the same file')) winNewAct.triggered.connect(self.windowNew) localActions['WinNewWindow'] = winNewAct for name, action in localActions.items(): icon = globalref.toolIcons.getIcon(name.lower()) if icon: action.setIcon(icon) key = globalref.keyboardOptions[name] if not key.isEmpty(): action.setShortcut(key) typeIcon = globalref.toolIcons.getIcon('DataNodeType'.lower()) if typeIcon: self.typeSubMenu.setIcon(typeIcon) fontIcon = globalref.toolIcons.getIcon('FormatFontSize'.lower()) if fontIcon: self.fontSizeSubMenu.setIcon(fontIcon) self.allActions.update(localActions) def fileSave(self, backupFile=False): """Save the currently active file. Arguments: backupFile -- if True, write auto-save backup file instead """ if not self.filePathObj or self.imported: self.fileSaveAs() return if not backupFile and self.fileModTime: fileSeconds = self.filePathObj.stat().st_mtime storedSeconds = self.fileModTime.timestamp() # check for an external file mod with a 10 second margin if fileSeconds > storedSeconds + 10: dialog = miscdialogs.ExtModDialog(datetime.datetime. fromtimestamp(fileSeconds), self.activeWindow) if dialog.exec() != QDialog.DialogCode.Accepted: # user cancelled the save return QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) savePathObj = self.filePathObj if backupFile: savePathObj = pathlib.Path(str(savePathObj) + '~') else: self.structure.purgeOldFieldData() fileData = self.structure.fileData() fileData['properties'].update(self.printData.fileData()) if self.spellCheckLang: fileData['properties']['spellchk'] = self.spellCheckLang if not self.compressed and not self.encrypted: indent = 3 if globalref.genOptions['PrettyPrint'] else 0 try: with savePathObj.open('w', encoding='utf-8', newline='\n') as f: json.dump(fileData, f, indent=indent, sort_keys=True) except IOError: QApplication.restoreOverrideCursor() QMessageBox.warning(self.activeWindow, 'TreeLine', _('Error - could not write to {}'). format(savePathObj)) return else: data = json.dumps(fileData, indent=0, sort_keys=True).encode() if self.compressed: data = gzip.compress(data) if self.encrypted: password = (globalref.mainControl.passwords. get(self.filePathObj, '')) if not password: QApplication.restoreOverrideCursor() dialog = miscdialogs.PasswordDialog(True, '', self.activeWindow) if dialog.exec() != QDialog.DialogCode.Accepted: return QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) password = dialog.password if miscdialogs.PasswordDialog.remember: globalref.mainControl.passwords[self. filePathObj] = password data = (treemaincontrol.encryptPrefix + p3.p3_encrypt(data, password.encode())) try: with savePathObj.open('wb') as f: f.write(data) except IOError: QApplication.restoreOverrideCursor() QMessageBox.warning(self.activeWindow, 'TreeLine', _('Error - could not write to {}'). format(savePathObj)) return QApplication.restoreOverrideCursor() if not backupFile: self.fileModTime = datetime.datetime.now() fileInfoFormat = self.structure.treeFormats.fileInfoFormat fileInfoFormat.updateFileInfo(self.filePathObj, self.structure.fileInfoNode) self.setModified(False) self.imported = False self.activeWindow.statusBar().showMessage(_('File saved'), 3000) def fileSaveAs(self): """Prompt for a new file name and save the file. """ oldPathObj = self.filePathObj oldModifiedFlag = self.modified oldImportFlag = self.imported self.modified = True self.imported = False filters = ';;'.join((globalref.fileFilters['trlnsave'], globalref.fileFilters['trlngz'], globalref.fileFilters['trlnenc'])) initFilter = globalref.fileFilters['trlnsave'] defaultPathObj = globalref.mainControl.defaultPathObj() if defaultPathObj.is_file(): defaultPathObj = defaultPathObj.with_suffix('.trln') newPath, selectFilter = (QFileDialog. getSaveFileName(self.activeWindow, _('TreeLine - Save As'), str(defaultPathObj), filters, initFilter)) if newPath: self.fileModTime = None self.filePathObj = pathlib.Path(newPath) if not self.filePathObj.suffix: self.filePathObj = self.filePathObj.with_suffix('.trln') if selectFilter != initFilter: self.compressed = (selectFilter == globalref.fileFilters['trlngz']) self.encrypted = (selectFilter == globalref.fileFilters['trlnenc']) self.fileSave() if not self.modified: globalref.mainControl.recentFiles.addItem(self.filePathObj) self.updateWindowCaptions() return self.filePathObj = oldPathObj self.modified = oldModifiedFlag self.imported = oldImportFlag def fileExport(self): """Export the file in various other formats. """ exportControl = exports.ExportControl(self.structure, self.currentSelectionModel(), globalref.mainControl. defaultPathObj(), self.printData) try: exportControl.interactiveExport() except IOError: QApplication.restoreOverrideCursor() QMessageBox.warning(self.activeWindow, 'TreeLine', _('Error - could not write to file')) def fileProperties(self): """Show dialog to set file parameters like compression and encryption. """ origZeroBlanks = self.structure.mathZeroBlanks dialog = miscdialogs.FilePropertiesDialog(self, self.activeWindow) if dialog.exec() == QDialog.DialogCode.Accepted: self.setModified() if self.structure.mathZeroBlanks != origZeroBlanks: self.updateAll(False) def editUndo(self): """Undo the previous action and update the views. """ self.structure.undoList.undo() self.updateAll(False) def editRedo(self): """Redo the previous undo and update the views. """ self.structure.redoList.undo() self.updateAll(False) def editCut(self): """Cut the branch or text to the clipboard. """ widget = QApplication.focusWidget() try: if widget.hasSelectedText(): widget.cut() return except AttributeError: pass self.currentSelectionModel().copySelectedNodes() selSpots = self.currentSelectionModel().selectedSpots() rootSpots = [spot for spot in selSpots if not spot.parentSpot.parentSpot] if selSpots and len(rootSpots) < len(self.structure.childList): self.nodeDelete() def editCopy(self): """Copy the branch or text to the clipboard. Copy from any selection in non-focused output view, or copy from any focused editor, or copy from tree. """ widgets = [QApplication.focusWidget()] splitter = self.activeWindow.rightTabs.currentWidget() if splitter == self.activeWindow.outputSplitter: widgets[0:0] = [splitter.widget(0), splitter.widget(1)] for widget in widgets: try: if widget.hasSelectedText(): widget.copy() return except AttributeError: pass self.currentSelectionModel().copySelectedNodes() def editPaste(self): """Paste nodes or text from the clipboard. """ if self.activeWindow.treeView.hasFocus(): self.editPasteChild() else: widget = QApplication.focusWidget() try: widget.paste() except AttributeError: pass def editPasteChild(self): """Paste a child node from the clipboard. """ if (self.currentSelectionModel().selectedSpots(). pasteChild(self.structure, self.activeWindow.treeView)): self.updateAll() globalref.mainControl.updateConfigDialog() def editPasteBefore(self): """Paste a sibling before selection. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([spot.parentSpot.childSpots() for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) if selSpots.pasteSibling(self.structure): treeView.restoreExpandState(expandState) self.currentSelectionModel().selectSpots(selSpots, False) self.updateAll() globalref.mainControl.updateConfigDialog() def editPasteAfter(self): """Paste a sibling after selection. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([spot.parentSpot.childSpots() for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) if selSpots.pasteSibling(self.structure, False): treeView.restoreExpandState(expandState) self.currentSelectionModel().selectSpots(selSpots, False) self.updateAll() globalref.mainControl.updateConfigDialog() def editPasteCloneChild(self): """Paste a child clone from the clipboard. """ if (self.currentSelectionModel().selectedSpots(). pasteCloneChild(self.structure, self.activeWindow.treeView)): self.updateAll() def editPasteCloneBefore(self): """Paste a sibling clone before selection. """ selSpots = self.currentSelectionModel().selectedSpots() if selSpots.pasteCloneSibling(self.structure): self.currentSelectionModel().selectSpots(selSpots, False) self.updateAll() def editPasteCloneAfter(self): """Paste a sibling clone after selection. """ selSpots = self.currentSelectionModel().selectedSpots() if selSpots.pasteCloneSibling(self.structure, False): self.currentSelectionModel().selectSpots(selSpots, False) self.updateAll() def nodeRename(self): """Start the rename editor in the selected tree node. """ if self.activeWindow.treeFilterView: self.activeWindow.treeFilterView.editItem(self.activeWindow. treeFilterView. currentItem()) else: self.activeWindow.treeView.endEditing() self.activeWindow.treeView.edit(self.currentSelectionModel(). currentIndex()) def nodeAddChild(self): """Add new child to selected parent. """ self.activeWindow.treeView.endEditing() selSpots = self.currentSelectionModel().selectedSpots() newSpots = selSpots.addChild(self.structure, self.activeWindow.treeView) self.updateAll() if globalref.genOptions['RenameNewNodes']: self.currentSelectionModel().selectSpots(newSpots) if len(newSpots) == 1: self.activeWindow.treeView.edit(newSpots[0].index(self.model)) def nodeInBefore(self): """Insert new sibling before selection. """ treeView = self.activeWindow.treeView treeView.endEditing() selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([spot.parentSpot.childSpots() for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) newSpots = selSpots.insertSibling(self.structure) treeView.restoreExpandState(expandState) self.updateAll() if globalref.genOptions['RenameNewNodes']: self.currentSelectionModel().selectSpots(newSpots) if len(newSpots) == 1: treeView.edit(newSpots[0].index(self.model)) def nodeInAfter(self): """Insert new sibling after selection. """ treeView = self.activeWindow.treeView treeView.endEditing() selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([spot.parentSpot.childSpots() for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) newSpots = selSpots.insertSibling(self.structure, False) treeView.restoreExpandState(expandState) self.updateAll() if globalref.genOptions['RenameNewNodes']: self.currentSelectionModel().selectSpots(newSpots) if len(newSpots) == 1: treeView.edit(newSpots[0].index(self.model)) def nodeDelete(self): """Delete the selected nodes. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedBranchSpots() if selSpots: # collapse deleted items to avoid crash for spot in selSpots: treeView.collapseSpot(spot) # clear hover to avoid crash if deleted child item was hovered over self.activeWindow.treeView.clearHover() # clear selection to avoid invalid multiple selection bug self.currentSelectionModel().selectSpots([], False) # clear selections in other windows that are about to be deleted for window in self.windowList: if window != self.activeWindow: selectModel = window.treeView.selectionModel() ancestors = set() for spot in selectModel.selectedBranchSpots(): ancestors.update(set(spot.spotChain())) if ancestors & set(selSpots): selectModel.selectSpots([], False) saveSpots = chain.from_iterable([spot.parentSpot.childSpots() for spot in selSpots]) saveSpots = set(saveSpots) - set(selSpots) expandState = treeView.savedExpandState(saveSpots) nextSel = selSpots.delete(self.structure) treeView.restoreExpandState(expandState) self.currentSelectionModel().selectSpots([nextSel]) self.updateAll() def nodeIndent(self): """Indent the selected nodes. Makes them children of their previous siblings. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([spot.parentSpot.childSpots() for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) newSpots = selSpots.indent(self.structure) treeView.restoreExpandState(expandState) for spot in selSpots: treeView.expandSpot(spot.parentSpot) self.currentSelectionModel().selectSpots(newSpots, False) self.updateAll() def nodeUnindent(self): """Unindent the selected nodes. Makes them their parent's next sibling. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([spot.parentSpot.childSpots() for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) newSpots = selSpots.unindent(self.structure) treeView.restoreExpandState(expandState) self.currentSelectionModel().selectSpots(newSpots, False) self.updateAll() def nodeMoveUp(self): """Move the selected nodes upward in the sibling list. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([(spot, spot.prevSiblingSpot()) for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) selSpots.move(self.structure) self.updateAll() treeView.restoreExpandState(expandState) self.currentSelectionModel().selectSpots(selSpots) def nodeMoveDown(self): """Move the selected nodes downward in the sibling list. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([(spot, spot.nextSiblingSpot()) for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) selSpots.move(self.structure, False) self.updateAll() treeView.restoreExpandState(expandState) self.currentSelectionModel().selectSpots(selSpots) def nodeMoveFirst(self): """Move the selected nodes to be the first children. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([(spot, spot.parentSpot.childSpots()[0]) for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) selSpots.moveToEnd(self.structure) self.updateAll() treeView.restoreExpandState(expandState) self.currentSelectionModel().selectSpots(selSpots) def nodeMoveLast(self): """Move the selected nodes to be the last children. """ treeView = self.activeWindow.treeView selSpots = self.currentSelectionModel().selectedSpots() saveSpots = chain.from_iterable([(spot, spot.parentSpot.childSpots()[-1]) for spot in selSpots]) expandState = treeView.savedExpandState(saveSpots) selSpots.moveToEnd(self.structure, False) self.updateAll() treeView.restoreExpandState(expandState) self.currentSelectionModel().selectSpots(selSpots) def dataSetType(self, action): """Change the type of selected nodes based on a menu selection. Arguments: action -- the menu action containing the new type name """ newType = action.toolTip() # gives menu name without the accelerator nodes = [node for node in self.currentSelectionModel().selectedNodes() if node.formatRef.name != newType] if nodes: undo.TypeUndo(self.structure.undoList, nodes) for node in nodes: node.changeDataType(self.structure.treeFormats[newType]) self.updateAll() def loadTypeSubMenu(self): """Update type select submenu with type names and check marks. """ selectTypeNames = set() typeLimitNames = set() for node in self.currentSelectionModel().selectedNodes(): selectTypeNames.add(node.formatRef.name) if typeLimitNames is not None: for parent in node.parents(): limit = (parent.formatRef.childTypeLimit if parent.formatRef else None) if (not limit or (typeLimitNames and limit != typeLimitNames)): typeLimitNames = None elif typeLimitNames is not None: typeLimitNames = limit if typeLimitNames: typeNames = sorted(list(typeLimitNames)) else: typeNames = self.structure.treeFormats.typeNames() self.typeSubMenu.clear() usedShortcuts = [] for name in typeNames: shortcutPos = 0 try: while [shortcutPos] in usedShortcuts: shortcutPos += 1 usedShortcuts.append(name[shortcutPos]) text = '{0}&{1}'.format(name[:shortcutPos], name[shortcutPos:]) except IndexError: text = name action = self.typeSubMenu.addAction(text) action.setCheckable(True) if name in selectTypeNames: action.setChecked(True) def showTypeContextMenu(self): """Show a type set menu at the current tree view item. """ self.activeWindow.treeView.showTypeMenu(self.typeSubMenu) def dataCopyType(self): """Copy the configuration from another TreeLine file. """ filters = ';;'.join((globalref.fileFilters['trlnv3'], globalref.fileFilters['all'])) fileName, selectFilter = QFileDialog.getOpenFileName(self.activeWindow, _('TreeLine - Open Configuration File'), str(globalref.mainControl. defaultPathObj(True)), filters) if not fileName: return QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) newStructure = None try: with open(fileName, 'r', encoding='utf-8') as f: fileData = json.load(f) newStructure = treestructure.TreeStructure(fileData, addSpots=False) except IOError: pass except (ValueError, KeyError, TypeError): fileObj = open(fileName, 'rb') fileObj, encrypted = globalref.mainControl.decryptFile(fileObj) if not fileObj: QApplication.restoreOverrideCursor() return fileObj, compressed = globalref.mainControl.decompressFile(fileObj) if compressed or encrypted: try: textFileObj = io.TextIOWrapper(fileObj, encoding='utf-8') fileData = json.load(textFileObj) textFileObj.close() newStructure = treestructure.TreeStructure(fileData, addSpots=False) except (ValueError, KeyError, TypeError): pass fileObj.close() if not newStructure: QApplication.restoreOverrideCursor() QMessageBox.warning(self.activeWindow, 'TreeLine', _('Error - could not read file {0}'). format(fileName)) return undo.FormatUndo(self.structure.undoList, self.structure.treeFormats, treeformats.TreeFormats()) for nodeFormat in newStructure.treeFormats.values(): self.structure.treeFormats.addTypeIfMissing(nodeFormat) QApplication.restoreOverrideCursor() self.updateAll() globalref.mainControl.updateConfigDialog() def dataRegenRefs(self): """Force update of all conditional types & math fields. """ self.updateAll(False) def dataCloneMatches(self): """Convert all matching nodes into clones. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) selSpots = self.currentSelectionModel().selectedSpots() titleDict = {} for node in self.structure.nodeDict.values(): titleDict.setdefault(node.title(), set()).add(node) undoObj = undo.ChildListUndo(self.structure.undoList, self.structure.childList, addBranch=True) numChanges = 0 for node in self.structure.descendantGen(): matches = titleDict[node.title()] if len(matches) > 1: matches = matches.copy() matches.remove(node) for matchedNode in matches: if node.isIdentical(matchedNode): numChanges += 1 if len(matchedNode.spotRefs) > len(node.spotRefs): tmpNode = node node = matchedNode matchedNode = tmpNode numSpots = len(matchedNode.spotRefs) for parent in matchedNode.parents(): pos = parent.childList.index(matchedNode) parent.childList[pos] = node node.addSpotRef(parent) for child in matchedNode.descendantGen(): if len(child.spotRefs) <= numSpots: titleDict[child.title()].remove(child) self.structure.removeNodeDictRef(child) child.removeInvalidSpotRefs(False) if numChanges: msg = _('Converted {0} branches into clones').format(numChanges) self.currentSelectionModel().selectSpots([spot for spot in selSpots if spot.isValid()], False) self.updateAll() else: msg = _('No identical nodes found') self.structure.undoList.removeLastUndo(undoObj) QApplication.restoreOverrideCursor() QMessageBox.information(self.activeWindow, 'TreeLine', msg) def dataDetachClones(self): """Detach all cloned nodes in current branches. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) selSpots = self.currentSelectionModel().selectedBranchSpots() undoObj = undo.ChildListUndo(self.structure.undoList, [spot.parentSpot.nodeRef for spot in selSpots], addBranch=True) numChanges = 0 for branchSpot in selSpots: for spot in branchSpot.spotDescendantGen(): if (len(spot.nodeRef.spotRefs) > 1 and len(spot.parentSpot.nodeRef.spotRefs) <= 1): numChanges += 1 linkedNode = spot.nodeRef linkedNode.spotRefs.remove(spot) newNode = treenode.TreeNode(linkedNode.formatRef) newNode.data = linkedNode.data.copy() newNode.childList = linkedNode.childList[:] newNode.spotRefs.add(spot) spot.nodeRef = newNode parent = spot.parentSpot.nodeRef pos = parent.childList.index(linkedNode) parent.childList[pos] = newNode self.structure.addNodeDictRef(newNode) if numChanges: self.updateAll() else: self.structure.undoList.removeLastUndo(undoObj) QApplication.restoreOverrideCursor() def dataFlatCategory(self): """Collapse descendant nodes by merging fields. Overwrites data in any fields with the same name. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) selectList = self.currentSelectionModel().selectedBranches() undo.ChildDataUndo(self.structure.undoList, selectList, True, self.structure.treeFormats) origFormats = self.structure.undoList[-1].treeFormats for node in selectList: node.flatChildCategory(origFormats, self.structure) self.updateAll() globalref.mainControl.updateConfigDialog() QApplication.restoreOverrideCursor() def dataAddCategory(self): """Insert category nodes above children. """ selectList = self.currentSelectionModel().selectedBranches() children = [] for node in selectList: children.extend(node.childList) fieldList = self.structure.treeFormats.commonFields(children) if not fieldList: QMessageBox.warning(self.activeWindow, 'TreeLine', _('Cannot expand without common fields')) return dialog = miscdialogs.FieldSelectDialog(_('Category Fields'), _('Select fields for new level'), fieldList, self.activeWindow) if dialog.exec() != QDialog.DialogCode.Accepted: return QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) undo.ChildDataUndo(self.structure.undoList, selectList, True, self.structure.treeFormats) for node in selectList: node.addChildCategory(dialog.selectedFields, self.structure) self.updateAll() globalref.mainControl.updateConfigDialog() QApplication.restoreOverrideCursor() def dataSwapCategory(self): """Swap child and grandchild category nodes. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) selectList = self.currentSelectionModel().selectedBranches() undo.ChildListUndo(self.structure.undoList, selectList, addBranch=True) doneNodes = set() for ancestor in selectList: for child in ancestor.childList[:]: for catNode in child.childList[:]: if catNode not in doneNodes: doneNodes.add(catNode) childSpots = [spot.parentSpot for spot in catNode.spotRefs] childSpots.sort(key=operator.methodcaller('sortKey')) children = [childSpot.nodeRef for childSpot in childSpots] catNode.childList[0:0] = children for ancestor in selectList: position = 0 doneNodes = set() for child in ancestor.childList[:]: for catNode in child.childList[:]: if catNode not in doneNodes: doneNodes.add(catNode) for catSpot in catNode.spotRefs: child = catSpot.parentSpot.nodeRef child.childList = [] if child in ancestor.childList: position = ancestor.childList.index(child) del ancestor.childList[position] ancestor.childList.insert(position, catNode) position += 1 catNode.addSpotRef(ancestor) catNode.removeInvalidSpotRefs() self.updateAll() QApplication.restoreOverrideCursor() def toolsSpellCheck(self): """Spell check the tree text data. """ try: spellCheckOp = spellcheck.SpellCheckOperation(self) except spellcheck.SpellCheckError: return spellCheckOp.spellCheck() def findNodesByWords(self, wordList, titlesOnly=False, forward=True): """Search for and select nodes that match the word list criteria. Called from the text find dialog. Returns True if found, otherwise False. Arguments: wordList -- a list of words or phrases to find titleOnly -- search only in the title text if True forward -- next if True, previous if False """ currentSpot = self.currentSelectionModel().currentSpot() spot = currentSpot while True: if self.activeWindow.treeFilterView: spot = self.activeWindow.treeFilterView.nextPrevSpot(spot, forward) else: if forward: spot = spot.nextTreeSpot(True) else: spot = spot.prevTreeSpot(True) if spot is currentSpot: return False if spot.nodeRef.wordSearch(wordList, titlesOnly, spot): self.currentSelectionModel().selectSpots([spot], True, True) rightView = self.activeWindow.rightParentView() if not rightView: # view update required if (and only if) view is newly shown QApplication.processEvents() rightView = self.activeWindow.rightParentView() if rightView: rightView.highlightSearch(wordList=wordList) QApplication.processEvents() return True def findNodesByRegExp(self, regExpList, titlesOnly=False, forward=True): """Search for and select nodes that match the regular exp criteria. Called from the text find dialog. Returns True if found, otherwise False. Arguments: regExpList -- a list of regular expression objects titleOnly -- search only in the title text if True forward -- next if True, previous if False """ currentSpot = self.currentSelectionModel().currentSpot() spot = currentSpot while True: if self.activeWindow.treeFilterView: spot = self.activeWindow.treeFilterView.nextPrevSpot(spot, forward) else: if forward: spot = spot.nextTreeSpot(True) else: spot = spot.prevTreeSpot(True) if spot is currentSpot: return False if spot.nodeRef.regExpSearch(regExpList, titlesOnly, spot): self.currentSelectionModel().selectSpots([spot], True, True) rightView = self.activeWindow.rightParentView() if not rightView: # view update required if (and only if) view is newly shown QApplication.processEvents() rightView = self.activeWindow.rightParentView() if rightView: rightView.highlightSearch(regExpList=regExpList) return True def findNodesByCondition(self, conditional, forward=True): """Search for and select nodes that match the regular exp criteria. Called from the conditional find dialog. Returns True if found, otherwise False. Arguments: conditional -- the Conditional object to be evaluated forward -- next if True, previous if False """ currentSpot = self.currentSelectionModel().currentSpot() spot = currentSpot while True: if self.activeWindow.treeFilterView: spot = self.activeWindow.treeFilterView.nextPrevSpot(spot, forward) else: if forward: spot = spot.nextTreeSpot(True) else: spot = spot.prevTreeSpot(True) if spot is currentSpot: return False if conditional.evaluate(spot.nodeRef): self.currentSelectionModel().selectSpots([spot], True, True) return True def findNodesForReplace(self, searchText='', regExpObj=None, typeName='', fieldName='', forward=True): """Search for & select nodes that match the criteria prior to replace. Called from the find replace dialog. Returns True if found, otherwise False. Arguments: searchText -- the text to find if no regexp is given regExpObj -- the regular expression to find if given typeName -- if given, verify that this node matches this type fieldName -- if given, only find matches under this type name forward -- next if True, previous if False """ currentSpot = self.currentSelectionModel().currentSpot() lastFoundSpot, currentNumMatches = self.findReplaceSpotRef numMatches = currentNumMatches if lastFoundSpot is not currentSpot: numMatches = 0 spot = currentSpot if not forward: if numMatches == 0: numMatches = -1 # find last one if backward elif numMatches == 1: numMatches = sys.maxsize # no match if on first one else: numMatches -= 2 while True: matchedField, numMatches, fieldPos = (spot.nodeRef. searchReplace(searchText, regExpObj, numMatches, typeName, fieldName)) if matchedField: fieldNum = (spot.nodeRef.formatRef.fieldNames(). index(matchedField)) self.currentSelectionModel().selectSpots([spot], True, True) self.activeWindow.rightTabs.setCurrentWidget(self.activeWindow. editorSplitter) dataView = self.activeWindow.rightParentView() if not dataView: # view update required if (and only if) view is newly shown QApplication.processEvents() dataView = self.activeWindow.rightParentView() if dataView: dataView.highlightMatch(searchText, regExpObj, fieldNum, fieldPos - 1) self.findReplaceSpotRef = (spot, numMatches) return True if self.activeWindow.treeFilterView: node = self.activeWindow.treeFilterView.nextPrevSpot(spot, forward) else: if forward: spot = spot.nextTreeSpot(True) else: spot = spot.prevTreeSpot(True) if spot is currentSpot and currentNumMatches == 0: self.findReplaceSpotRef = (None, 0) return False numMatches = 0 if forward else -1 def replaceInCurrentNode(self, searchText='', regExpObj=None, typeName='', fieldName='', replaceText=None): """Replace the current match in the current node. Called from the find replace dialog. Returns True if replaced, otherwise False. Arguments: searchText -- the text to find if no regexp is given regExpObj -- the regular expression to find if given typeName -- if given, verify that this node matches this type fieldName -- if given, only find matches under this type name replaceText -- if not None, replace a match with this string """ spot = self.currentSelectionModel().currentSpot() lastFoundSpot, numMatches = self.findReplaceSpotRef if numMatches > 0: numMatches -= 1 if lastFoundSpot is not spot: numMatches = 0 dataUndo = undo.DataUndo(self.structure.undoList, spot.nodeRef) matchedField, num1, num2 = (spot.nodeRef. searchReplace(searchText, regExpObj, numMatches, typeName, fieldName, replaceText)) if ((searchText and searchText in replaceText) or (regExpObj and r'\g<0>' in replaceText) or (regExpObj and regExpObj.pattern.startswith('(') and regExpObj.pattern.endswith(')') and r'\1' in replaceText)): numMatches += 1 # check for recursive matches self.findReplaceSpotRef = (spot, numMatches) if matchedField: self.updateTreeNode(spot.nodeRef) self.updateRightViews() return True self.structure.undoList.removeLastUndo(dataUndo) return False def replaceAll(self, searchText='', regExpObj=None, typeName='', fieldName='', replaceText=None): """Replace all matches in all nodes. Called from the find replace dialog. Returns number of matches replaced. Arguments: searchText -- the text to find if no regexp is given regExpObj -- the regular expression to find if given typeName -- if given, verify that this node matches this type fieldName -- if given, only find matches under this type name replaceText -- if not None, replace a match with this string """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) dataUndo = undo.DataUndo(self.structure.undoList, self.structure.childList, addBranch=True) totalMatches = 0 for node in self.structure.nodeDict.values(): field, matchQty, num = node.searchReplace(searchText, regExpObj, 0, typeName, fieldName, replaceText, True) totalMatches += matchQty self.findReplaceSpotRef = (None, 0) if totalMatches > 0: self.updateAll(True) else: self.structure.undoList.removeLastUndo(dataUndo) QApplication.restoreOverrideCursor() return totalMatches def windowNew(self, checked=False, offset=30): """Open a new window for this file. Arguments: checked -- unused parameter needed by QAction signal offset -- location offset from previously saved position """ window = treewindow.TreeWindow(self.model, self.allActions) self.setWindowSignals(window) window.winMinimized.connect(globalref.mainControl.trayMinimize) self.windowList.append(window) self.updateWindowCaptions() oldControl = globalref.mainControl.activeControl if oldControl: try: oldControl.activeWindow.saveWindowGeom() except RuntimeError: # possibly avoid rare error of deleted c++ TreeWindow pass window.restoreWindowGeom(offset) self.activeWindow = window self.expandRootNodes() self.selectRootSpot() window.show() window.updateRightViews() TreeLine-3.2.1/source/treemaincontrol.py000066400000000000000000001423641506556630100203240ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treemaincontrol.py, provides a class for global tree commands # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import sys import pathlib import os.path import ast import io import gzip import zlib import datetime import platform from PyQt6.QtCore import QIODevice, QObject, Qt, PYQT_VERSION_STR, qVersion from PyQt6.QtGui import QAction, QColor, QFont, QPalette from PyQt6.QtNetwork import QLocalServer, QLocalSocket from PyQt6.QtWidgets import (QApplication, QDialog, QFileDialog, QMessageBox, QStyleFactory, QSystemTrayIcon) import globalref import treelocalcontrol import options import optiondefaults import recentfiles import p3 import icondict import imports import configdialog import miscdialogs import conditional import colorset import helpview try: from __main__ import __version__, __author__ except ImportError: __version__ = '' __author__ = '' try: from __main__ import docPath, iconPath, templatePath, samplePath except ImportError: docPath = None iconPath = None templatePath = None samplePath = None encryptPrefix = b'>>TL+enc' class TreeMainControl(QObject): """Class to handle all global controls. Provides methods for all controls and stores local control objects. """ def __init__(self, pathObjects, parent=None): """Initialize the main tree controls Arguments: pathObjects -- a list of file objects to open parent -- the parent QObject if given """ super().__init__(parent) self.localControls = [] self.activeControl = None self.trayIcon = None self.isTrayMinimized = False self.configDialog = None self.sortDialog = None self.numberingDialog = None self.findTextDialog = None self.findConditionDialog = None self.findReplaceDialog = None self.filterTextDialog = None self.filterConditionDialog = None self.basicHelpView = None self.passwords = {} self.creatingLocalControlFlag = False globalref.mainControl = self self.allActions = {} try: # check for existing TreeLine session socket = QLocalSocket() socket.connectToServer('treeline3-session', QIODevice.OpenModeFlag.WriteOnly) # if found, send files to open and exit TreeLine if socket.waitForConnected(1000): socket.write(bytes(repr([str(path) for path in pathObjects]), 'utf-8')) if socket.waitForBytesWritten(1000): socket.close() sys.exit(0) # start local server to listen for attempt to start new session self.serverSocket = QLocalServer() # remove any old servers still around after a crash in linux self.serverSocket.removeServer('treeline3-session') self.serverSocket.listen('treeline3-session') self.serverSocket.newConnection.connect(self.getSocket) except AttributeError: print(_('Warning: Could not create local socket')) mainVersion = '.'.join(__version__.split('.')[:2]) globalref.genOptions = options.Options('general', 'TreeLine', mainVersion, 'bellz') optiondefaults.setGenOptionDefaults(globalref.genOptions) globalref.miscOptions = options.Options('misc') optiondefaults.setMiscOptionDefaults(globalref.miscOptions) globalref.histOptions = options.Options('history') optiondefaults.setHistOptionDefaults(globalref.histOptions) globalref.toolbarOptions = options.Options('toolbar') optiondefaults.setToolbarOptionDefaults(globalref.toolbarOptions) globalref.keyboardOptions = options.Options('keyboard') optiondefaults.setKeyboardOptionDefaults(globalref.keyboardOptions) try: globalref.genOptions.readFile() globalref.miscOptions.readFile() globalref.histOptions.readFile() globalref.toolbarOptions.readFile() globalref.keyboardOptions.readFile() except IOError: errorDir = options.Options.basePath if not errorDir: errorDir = _('missing directory') QMessageBox.warning(None, 'TreeLine', _('Error - could not write config file to {}'). format(errorDir)) options.Options.basePath = None iconPathList = self.findResourcePaths('icons', iconPath) globalref.toolIcons = icondict.IconDict([path / 'toolbar' for path in iconPathList], ['', '32x32', '16x16']) globalref.toolIcons.loadAllIcons() windowIcon = globalref.toolIcons.getIcon('treelogo') if windowIcon: QApplication.setWindowIcon(windowIcon) globalref.treeIcons = icondict.IconDict(iconPathList, ['', 'tree']) icon = globalref.treeIcons.getIcon('default') QApplication.setStyle(QStyleFactory.create('Fusion')) self.colorSet = colorset.ColorSet() if globalref.miscOptions['ColorTheme'] != 'system': self.colorSet.setAppColors() self.recentFiles = recentfiles.RecentFileList() if globalref.genOptions['AutoFileOpen'] and not pathObjects: recentPath = self.recentFiles.firstPath() if recentPath: pathObjects = [recentPath] self.setupActions() self.systemFont = QApplication.font() self.updateAppFont() if globalref.genOptions['MinToSysTray']: self.createTrayIcon() QApplication.instance().focusChanged.connect(self.updateActionsAvail) if pathObjects: for pathObj in pathObjects: self.openFile(pathObj, True) else: self.createLocalControl() def getSocket(self): """Open a socket from an attempt to open a second Treeline instance. Opens the file (or raise and focus if open) in this instance. """ socket = self.serverSocket.nextPendingConnection() if socket and socket.waitForReadyRead(1000): data = str(socket.readAll(), 'utf-8') try: paths = ast.literal_eval(data) if paths: for path in paths: pathObj = pathlib.Path(path) if pathObj != self.activeControl.filePathObj: self.openFile(pathObj, True) else: self.activeControl.activeWindow.activateAndRaise() else: self.activeControl.activeWindow.activateAndRaise() except(SyntaxError, ValueError, TypeError, RuntimeError): pass def findResourcePaths(self, resourceName, preferredPath=''): """Return list of potential non-empty pathlib objects for the resource. List includes preferred, module and user option paths. Arguments: resourceName -- the typical name of the resource directory preferredPath -- add this as the second path if given """ # use abspath() - pathlib's resolve() can be buggy with network drives modPath = pathlib.Path(os.path.abspath(sys.path[0])) if modPath.is_file(): modPath = modPath.parent # for frozen binary pathList = [modPath / '..' / resourceName, modPath / resourceName] if options.Options.basePath: basePath = pathlib.Path(options.Options.basePath) pathList.insert(0, basePath / resourceName) if preferredPath: pathList.insert(1, pathlib.Path(preferredPath)) return [pathlib.Path(os.path.abspath(str(path))) for path in pathList if path.is_dir() and list(path.iterdir())] def findResourceFile(self, fileName, resourceName, preferredPath=''): """Return a path object for a resource file. Add a language code before the extension if it exists. Arguments: fileName -- the name of the file to find resourceName -- the typical name of the resource directory preferredPath -- search this path first if given """ fileList = [fileName] if globalref.lang and globalref.lang != 'C': fileList[0:0] = [fileName.replace('.', '_{0}.'. format(globalref.lang)), fileName.replace('.', '_{0}.'. format(globalref.lang[:2]))] for fileName in fileList: for path in self.findResourcePaths(resourceName, preferredPath): if (path / fileName).is_file(): return path / fileName return None def defaultPathObj(self, dirOnly=False): """Return a reasonable default file path object. Used for open, save-as, import and export. Arguments: dirOnly -- if True, do not include basename of file """ pathObj = None if self.activeControl: pathObj = self.activeControl.filePathObj if not pathObj: pathObj = self.recentFiles.firstDir() if not pathObj: pathObj = pathlib.Path.home() if dirOnly: pathObj = pathObj.parent return pathObj def openFile(self, pathObj, forceNewWindow=False, checkModified=False, importOnFail=True): """Open the file given by path if not already open. If already open in a different window, focus and raise the window. Arguments: pathObj -- the path object to read forceNewWindow -- if True, use a new window regardless of option checkModified -- if True & not new win, prompt if file modified importOnFail -- if True, prompts for import on non-TreeLine files """ match = [control for control in self.localControls if pathObj == control.filePathObj] if match and self.activeControl not in match: control = match[0] control.activeWindow.activateAndRaise() self.updateLocalControlRef(control) return if checkModified and not (forceNewWindow or globalref.genOptions['OpenNewWindow'] or self.activeControl.checkSaveChanges()): return if not self.checkAutoSave(pathObj): if not self.localControls: self.createLocalControl() return QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) try: fileModTime = datetime.datetime.fromtimestamp(pathObj.stat(). st_mtime) self.createLocalControl(pathObj, None, forceNewWindow, fileModTime) self.recentFiles.addItem(pathObj) if not (globalref.genOptions['SaveTreeStates'] and self.recentFiles.retrieveTreeState(self.activeControl)): self.activeControl.expandRootNodes() self.activeControl.selectRootSpot() QApplication.restoreOverrideCursor() except IOError: QApplication.restoreOverrideCursor() QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - could not read file {0}'). format(pathObj)) self.recentFiles.removeItem(pathObj) except (ValueError, KeyError, TypeError): fileObj = pathObj.open('rb') fileObj, encrypted = self.decryptFile(fileObj) if not fileObj: if not self.localControls: self.createLocalControl() QApplication.restoreOverrideCursor() return fileObj, compressed = self.decompressFile(fileObj) if compressed or encrypted: try: textFileObj = io.TextIOWrapper(fileObj, encoding='utf-8') self.createLocalControl(textFileObj, None, forceNewWindow, fileModTime) fileObj.close() textFileObj.close() self.recentFiles.addItem(pathObj) if not (globalref.genOptions['SaveTreeStates'] and self.recentFiles.retrieveTreeState(self. activeControl)): self.activeControl.expandRootNodes() self.activeControl.selectRootSpot() self.activeControl.compressed = compressed self.activeControl.encrypted = encrypted QApplication.restoreOverrideCursor() return except (ValueError, KeyError, TypeError): pass fileObj.close() importControl = imports.ImportControl(pathObj) structure = importControl.importOldTreeLine() if structure: self.createLocalControl(pathObj, structure, forceNewWindow) self.activeControl.printData.readData(importControl. treeLineRootAttrib) self.recentFiles.addItem(pathObj) self.activeControl.expandRootNodes() self.activeControl.imported = True QApplication.restoreOverrideCursor() return QApplication.restoreOverrideCursor() if importOnFail: importControl = imports.ImportControl(pathObj) structure = importControl.interactiveImport(True) if structure: self.createLocalControl(pathObj, structure, forceNewWindow) self.activeControl.imported = True return else: QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - invalid TreeLine file {0}'). format(pathObj)) self.recentFiles.removeItem(pathObj) if not self.localControls: self.createLocalControl() def decryptFile(self, fileObj): """Check for encryption and decrypt the fileObj if needed. Return a tuple of the file object and True if it was encrypted. Return None for the file object if the user cancels. Arguments: fileObj -- the file object to check and decrypt """ if fileObj.read(len(encryptPrefix)) != encryptPrefix: fileObj.seek(0) return (fileObj, False) fileContents = fileObj.read() fileName = fileObj.name fileObj.close() while True: pathObj = pathlib.Path(fileName) password = self.passwords.get(pathObj, '') if not password: QApplication.restoreOverrideCursor() dialog = miscdialogs.PasswordDialog(False, pathObj.name, QApplication. activeWindow()) if dialog.exec() != QDialog.DialogCode.Accepted: return (None, True) QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) password = dialog.password if miscdialogs.PasswordDialog.remember: self.passwords[pathObj] = password try: text = p3.p3_decrypt(fileContents, password.encode()) fileIO = io.BytesIO(text) fileIO.name = fileName return (fileIO, True) except p3.CryptError: try: del self.passwords[pathObj] except KeyError: pass def decompressFile(self, fileObj): """Check for compression and decompress the fileObj if needed. Return a tuple of the file object and True if it was compressed. Arguments: fileObj -- the file object to check and decompress """ prefix = fileObj.read(2) fileObj.seek(0) if prefix != b'\037\213': return (fileObj, False) try: newFileObj = gzip.GzipFile(fileobj=fileObj) except zlib.error: return (fileObj, False) newFileObj.name = fileObj.name return (newFileObj, True) def checkAutoSave(self, pathObj): """Check for presence of auto save file & prompt user. Return True if OK to contimue, False if aborting or already loaded. Arguments: pathObj -- the base path object to search for a backup """ if not globalref.genOptions['AutoSaveMinutes']: return True basePath = pathObj pathObj = pathlib.Path(str(pathObj) + '~') if not pathObj.is_file(): return True msgBox = QMessageBox(QMessageBox.Icon.Information, 'TreeLine', _('Backup file "{}" exists.\nA previous ' 'session may have crashed'). format(pathObj), QMessageBox.StandardButton.NoButton, QApplication.activeWindow()) restoreButton = msgBox.addButton(_('&Restore Backup'), QMessageBox.ButtonRole.ApplyRole) deleteButton = msgBox.addButton(_('&Delete Backup'), QMessageBox.ButtonRole.DestructiveRole) cancelButton = msgBox.addButton(_('&Cancel File Open'), QMessageBox.ButtonRole.RejectRole) msgBox.exec() if msgBox.clickedButton() == restoreButton: self.openFile(pathObj) if self.activeControl.filePathObj != pathObj: return False try: basePath.unlink() pathObj.rename(basePath) except OSError: QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - could not rename "{0}" to "{1}"'). format(pathObj, basePath)) return False self.activeControl.filePathObj = basePath self.activeControl.updateWindowCaptions() self.recentFiles.removeItem(pathObj) self.recentFiles.addItem(basePath) return False elif msgBox.clickedButton() == deleteButton: try: pathObj.unlink() except OSError: QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - could not remove backup file {}'). format(pathObj)) else: # cancel button return False return True def createLocalControl(self, pathObj=None, treeStruct=None, forceNewWindow=False, fileModTime=None): """Create a new local control object and add it to the list. Use an imported structure if given or open the file if path is given. Arguments: pathObj -- the path object or file object for the control to open treeStruct -- the imported structure to use forceNewWindow -- if True, use a new window regardless of option fileModTime -- file modified time for external modification checks """ self.creatingLocalControlFlag = True localControl = treelocalcontrol.TreeLocalControl(self.allActions, pathObj, treeStruct, fileModTime, forceNewWindow) localControl.controlActivated.connect(self.updateLocalControlRef) localControl.controlClosed.connect(self.removeLocalControlRef) self.localControls.append(localControl) self.updateLocalControlRef(localControl) self.creatingLocalControlFlag = False localControl.updateRightViews() localControl.updateCommandsAvail() def updateLocalControlRef(self, localControl): """Set the given local control as active. Called by signal from a window becoming active. Also updates non-modal dialogs. Arguments: localControl -- the new active local control """ if localControl != self.activeControl: self.activeControl = localControl if self.configDialog and self.configDialog.isVisible(): self.configDialog.setRefs(self.activeControl) def removeLocalControlRef(self, localControl): """Remove ref to local control based on a closing signal. Also do application exit clean ups if last control closing. Arguments: localControl -- the local control that is closing """ try: self.localControls.remove(localControl) except ValueError: return # skip for unreporducible bug - odd race condition? if globalref.genOptions['SaveTreeStates']: self.recentFiles.saveTreeState(localControl) if not self.localControls and not self.creatingLocalControlFlag: if globalref.genOptions['SaveWindowGeom']: localControl.windowList[0].saveWindowGeom() else: localControl.windowList[0].resetWindowGeom() self.recentFiles.writeItems() localControl.windowList[0].saveToolbarPosition() globalref.histOptions.writeFile() if self.trayIcon: self.trayIcon.hide() # stop listening for session connections try: self.serverSocket.close() del self.serverSocket except AttributeError: pass if self.localControls: # make sure a window is active (may not be focused), to avoid # bugs due to a deleted current window newControl = self.localControls[0] newControl.setActiveWin(newControl.windowList[0]) localControl.deleteLater() def createTrayIcon(self): """Create a new system tray icon if not already created. """ if QSystemTrayIcon.isSystemTrayAvailable(): if not self.trayIcon: self.trayIcon = QSystemTrayIcon(QApplication.windowIcon()) self.trayIcon.activated.connect(self.toggleTrayShow) self.trayIcon.show() def trayMinimize(self): """Minimize to tray based on window minimize signal. """ if self.trayIcon and QSystemTrayIcon.isSystemTrayAvailable(): # skip minimize to tray if not all windows minimized for control in self.localControls: for window in control.windowList: if not window.isMinimized(): return for control in self.localControls: for window in control.windowList: window.hide() self.isTrayMinimized = True def toggleTrayShow(self): """Toggle show and hide application based on system tray icon click. """ if self.isTrayMinimized: for control in self.localControls: for window in control.windowList: window.show() window.showNormal() self.activeControl.activeWindow.treeView.setFocus() else: for control in self.localControls: for window in control.windowList: window.hide() self.isTrayMinimized = not self.isTrayMinimized def updateConfigDialog(self): """Update the config dialog for changes if it exists. """ if self.configDialog: self.configDialog.reset() def currentStatusBar(self): """Return the status bar from the current main window. """ return self.activeControl.activeWindow.statusBar() def windowActions(self): """Return a list of window menu actions from each local control. """ actions = [] for control in self.localControls: actions.extend(control.windowActions(len(actions) + 1, control == self.activeControl)) return actions def updateActionsAvail(self, oldWidget, newWidget): """Update command availability based on focus changes. Arguments: oldWidget -- the previously focused widget newWidget -- the newly focused widget """ self.allActions['FormatSelectAll'].setEnabled(hasattr(newWidget, 'selectAll') and not hasattr(newWidget, 'editTriggers')) def setupActions(self): """Add the actions for contols at the global level. """ fileNewAct = QAction(_('&New...'), self, toolTip=_('New File'), statusTip=_('Start a new file')) fileNewAct.triggered.connect(self.fileNew) self.allActions['FileNew'] = fileNewAct fileOpenAct = QAction(_('&Open...'), self, toolTip=_('Open File'), statusTip=_('Open a file from disk')) fileOpenAct.triggered.connect(self.fileOpen) self.allActions['FileOpen'] = fileOpenAct fileSampleAct = QAction(_('Open Sa&mple...'), self, toolTip=_('Open Sample'), statusTip=_('Open a sample file')) fileSampleAct.triggered.connect(self.fileOpenSample) self.allActions['FileOpenSample'] = fileSampleAct fileImportAct = QAction(_('&Import...'), self, statusTip=_('Open a non-TreeLine file')) fileImportAct.triggered.connect(self.fileImport) self.allActions['FileImport'] = fileImportAct fileQuitAct = QAction(_('&Quit'), self, statusTip=_('Exit the application')) fileQuitAct.triggered.connect(self.fileQuit) self.allActions['FileQuit'] = fileQuitAct dataConfigAct = QAction(_('&Configure Data Types...'), self, statusTip=_('Modify data types, fields & output lines'), checkable=True) dataConfigAct.triggered.connect(self.dataConfigDialog) self.allActions['DataConfigType'] = dataConfigAct dataVisualConfigAct = QAction(_('Show C&onfiguration Structure...'), self, statusTip=_('Show read-only visualization of type structure')) dataVisualConfigAct.triggered.connect(self.dataVisualConfig) self.allActions['DataVisualConfig'] = dataVisualConfigAct dataSortAct = QAction(_('Sor&t Nodes...'), self, statusTip=_('Define node sort operations'), checkable=True) dataSortAct.triggered.connect(self.dataSortDialog) self.allActions['DataSortNodes'] = dataSortAct dataNumberingAct = QAction(_('Update &Numbering...'), self, statusTip=_('Update node numbering fields'), checkable=True) dataNumberingAct.triggered.connect(self.dataNumberingDialog) self.allActions['DataNumbering'] = dataNumberingAct toolsFindTextAct = QAction(_('&Find Text...'), self, statusTip=_('Find text in node titles & data'), checkable=True) toolsFindTextAct.triggered.connect(self.toolsFindTextDialog) self.allActions['ToolsFindText'] = toolsFindTextAct toolsFindConditionAct = QAction(_('&Conditional Find...'), self, statusTip=_('Use field conditions to find nodes'), checkable=True) toolsFindConditionAct.triggered.connect(self.toolsFindConditionDialog) self.allActions['ToolsFindCondition'] = toolsFindConditionAct toolsFindReplaceAct = QAction(_('Find and &Replace...'), self, statusTip=_('Replace text strings in node data'), checkable=True) toolsFindReplaceAct.triggered.connect(self.toolsFindReplaceDialog) self.allActions['ToolsFindReplace'] = toolsFindReplaceAct toolsFilterTextAct = QAction(_('&Text Filter...'), self, statusTip=_('Filter nodes to only show text matches'), checkable=True) toolsFilterTextAct.triggered.connect(self.toolsFilterTextDialog) self.allActions['ToolsFilterText'] = toolsFilterTextAct toolsFilterConditionAct = QAction(_('C&onditional Filter...'), self, statusTip=_('Use field conditions to filter nodes'), checkable=True) toolsFilterConditionAct.triggered.connect(self. toolsFilterConditionDialog) self.allActions['ToolsFilterCondition'] = toolsFilterConditionAct toolsGenOptionsAct = QAction(_('&General Options...'), self, statusTip=_('Set user preferences for all files')) toolsGenOptionsAct.triggered.connect(self.toolsGenOptions) self.allActions['ToolsGenOptions'] = toolsGenOptionsAct toolsShortcutAct = QAction(_('Set &Keyboard Shortcuts...'), self, statusTip=_('Customize keyboard commands')) toolsShortcutAct.triggered.connect(self.toolsCustomShortcuts) self.allActions['ToolsShortcuts'] = toolsShortcutAct toolsToolbarAct = QAction(_('C&ustomize Toolbars...'), self, statusTip=_('Customize toolbar buttons')) toolsToolbarAct.triggered.connect(self.toolsCustomToolbars) self.allActions['ToolsToolbars'] = toolsToolbarAct toolsFontsAct = QAction(_('Customize Fo&nts...'), self, statusTip=_('Customize fonts in various views')) toolsFontsAct.triggered.connect(self.toolsCustomFonts) self.allActions['ToolsFonts'] = toolsFontsAct toolsColorsAct = QAction(_('Custo&mize Colors...'), self, statusTip=_('Customize GUI colors and themes')) toolsColorsAct.triggered.connect(self.toolsCustomColors) self.allActions['ToolsColors'] = toolsColorsAct formatSelectAllAct = QAction(_('&Select All'), self, statusTip=_('Select all text in an editor')) formatSelectAllAct.setEnabled(False) formatSelectAllAct.triggered.connect(self.formatSelectAll) self.allActions['FormatSelectAll'] = formatSelectAllAct helpBasicAct = QAction(_('&Basic Usage...'), self, statusTip=_('Display basic usage instructions')) helpBasicAct.triggered.connect(self.helpViewBasic) self.allActions['HelpBasic'] = helpBasicAct helpFullAct = QAction(_('&Full Documentation...'), self, statusTip=_('Open a TreeLine file with full documentation')) helpFullAct.triggered.connect(self.helpViewFull) self.allActions['HelpFull'] = helpFullAct helpAboutAct = QAction(_('&About TreeLine...'), self, statusTip=_('Display version info about this program')) helpAboutAct.triggered.connect(self.helpAbout) self.allActions['HelpAbout'] = helpAboutAct for name, action in self.allActions.items(): icon = globalref.toolIcons.getIcon(name.lower()) if icon: action.setIcon(icon) key = globalref.keyboardOptions[name] if not key.isEmpty(): action.setShortcut(key) def fileNew(self): """Start a new blank file. """ if (globalref.genOptions['OpenNewWindow'] or self.activeControl.checkSaveChanges()): searchPaths = self.findResourcePaths('templates', templatePath) if searchPaths: dialog = miscdialogs.TemplateFileDialog(_('New File'), _('&Select Template'), searchPaths) if dialog.exec() == QDialog.DialogCode.Accepted: self.createLocalControl(dialog.selectedPath()) self.activeControl.filePathObj = None self.activeControl.updateWindowCaptions() self.activeControl.expandRootNodes() else: self.createLocalControl() self.activeControl.selectRootSpot() def fileOpen(self): """Prompt for a filename and open it. """ if (globalref.genOptions['OpenNewWindow'] or self.activeControl.checkSaveChanges()): filters = ';;'.join((globalref.fileFilters['trlnopen'], globalref.fileFilters['all'])) fileName, selFilter = QFileDialog.getOpenFileName(QApplication. activeWindow(), _('TreeLine - Open File'), str(self.defaultPathObj(True)), filters) if fileName: self.openFile(pathlib.Path(fileName)) def fileOpenSample(self): """Open a sample file from the doc directories. """ if (globalref.genOptions['OpenNewWindow'] or self.activeControl.checkSaveChanges()): searchPaths = self.findResourcePaths('samples', samplePath) dialog = miscdialogs.TemplateFileDialog(_('Open Sample File'), _('&Select Sample'), searchPaths, False) if dialog.exec() == QDialog.DialogCode.Accepted: self.createLocalControl(dialog.selectedPath()) name = dialog.selectedName() + '.trln' self.activeControl.filePathObj = pathlib.Path(name) self.activeControl.updateWindowCaptions() self.activeControl.expandRootNodes() self.activeControl.imported = True def fileImport(self): """Prompt for an import type, then a file to import. """ importControl = imports.ImportControl() structure = importControl.interactiveImport() if structure: self.createLocalControl(importControl.pathObj, structure) if importControl.treeLineRootAttrib: self.activeControl.printData.readData(importControl. treeLineRootAttrib) self.activeControl.imported = True def fileQuit(self): """Close all windows to exit the applications. """ for control in self.localControls[:]: control.closeWindows() def dataConfigDialog(self, show): """Show or hide the non-modal data config dialog. Arguments: show -- true if dialog should be shown, false to hide it """ if show: if not self.configDialog: self.configDialog = configdialog.ConfigDialog() dataConfigAct = self.allActions['DataConfigType'] self.configDialog.dialogShown.connect(dataConfigAct.setChecked) self.configDialog.setRefs(self.activeControl, True) self.configDialog.show() else: self.configDialog.close() def dataVisualConfig(self): """Show a TreeLine file to visualize the config structure. """ structure = (self.activeControl.structure.treeFormats. visualConfigStructure(str(self.activeControl. filePathObj))) self.createLocalControl(treeStruct=structure, forceNewWindow=True) self.activeControl.filePathObj = pathlib.Path('structure.trln') self.activeControl.updateWindowCaptions() self.activeControl.expandRootNodes() self.activeControl.imported = True win = self.activeControl.activeWindow win.rightTabs.setCurrentWidget(win.outputSplitter) def dataSortDialog(self, show): """Show or hide the non-modal data sort nodes dialog. Arguments: show -- true if dialog should be shown, false to hide it """ if show: if not self.sortDialog: self.sortDialog = miscdialogs.SortDialog() dataSortAct = self.allActions['DataSortNodes'] self.sortDialog.dialogShown.connect(dataSortAct.setChecked) self.sortDialog.show() else: self.sortDialog.close() def dataNumberingDialog(self, show): """Show or hide the non-modal update node numbering dialog. Arguments: show -- true if dialog should be shown, false to hide it """ if show: if not self.numberingDialog: self.numberingDialog = miscdialogs.NumberingDialog() dataNumberingAct = self.allActions['DataNumbering'] self.numberingDialog.dialogShown.connect(dataNumberingAct. setChecked) self.numberingDialog.show() if not self.numberingDialog.checkForNumberingFields(): self.numberingDialog.close() else: self.numberingDialog.close() def toolsFindTextDialog(self, show): """Show or hide the non-modal find text dialog. Arguments: show -- true if dialog should be shown """ if show: if not self.findTextDialog: self.findTextDialog = miscdialogs.FindFilterDialog() toolsFindTextAct = self.allActions['ToolsFindText'] self.findTextDialog.dialogShown.connect(toolsFindTextAct. setChecked) self.findTextDialog.selectAllText() self.findTextDialog.show() else: self.findTextDialog.close() def toolsFindConditionDialog(self, show): """Show or hide the non-modal conditional find dialog. Arguments: show -- true if dialog should be shown """ if show: if not self.findConditionDialog: dialogType = conditional.FindDialogType.findDialog self.findConditionDialog = (conditional. ConditionDialog(dialogType, _('Conditional Find'))) toolsFindConditionAct = self.allActions['ToolsFindCondition'] (self.findConditionDialog.dialogShown. connect(toolsFindConditionAct.setChecked)) else: self.findConditionDialog.loadTypeNames() self.findConditionDialog.show() else: self.findConditionDialog.close() def toolsFindReplaceDialog(self, show): """Show or hide the non-modal find and replace text dialog. Arguments: show -- true if dialog should be shown """ if show: if not self.findReplaceDialog: self.findReplaceDialog = miscdialogs.FindReplaceDialog() toolsFindReplaceAct = self.allActions['ToolsFindReplace'] self.findReplaceDialog.dialogShown.connect(toolsFindReplaceAct. setChecked) else: self.findReplaceDialog.loadTypeNames() self.findReplaceDialog.show() else: self.findReplaceDialog.close() def toolsFilterTextDialog(self, show): """Show or hide the non-modal filter text dialog. Arguments: show -- true if dialog should be shown """ if show: if not self.filterTextDialog: self.filterTextDialog = miscdialogs.FindFilterDialog(True) toolsFilterTextAct = self.allActions['ToolsFilterText'] self.filterTextDialog.dialogShown.connect(toolsFilterTextAct. setChecked) self.filterTextDialog.selectAllText() self.filterTextDialog.show() else: self.filterTextDialog.close() def toolsFilterConditionDialog(self, show): """Show or hide the non-modal conditional filter dialog. Arguments: show -- true if dialog should be shown """ if show: if not self.filterConditionDialog: dialogType = conditional.FindDialogType.filterDialog self.filterConditionDialog = (conditional. ConditionDialog(dialogType, _('Conditional Filter'))) toolsFilterConditionAct = (self. allActions['ToolsFilterCondition']) (self.filterConditionDialog.dialogShown. connect(toolsFilterConditionAct.setChecked)) else: self.filterConditionDialog.loadTypeNames() self.filterConditionDialog.show() else: self.filterConditionDialog.close() def toolsGenOptions(self): """Set general user preferences for all files. """ oldAutoSaveMinutes = globalref.genOptions['AutoSaveMinutes'] dialog = options.OptionDialog(globalref.genOptions, QApplication.activeWindow()) dialog.setWindowTitle(_('General Options')) if (dialog.exec() == QDialog.DialogCode.Accepted and globalref.genOptions.modified): globalref.genOptions.writeFile() self.recentFiles.updateOptions() if globalref.genOptions['MinToSysTray']: self.createTrayIcon() elif self.trayIcon: self.trayIcon.hide() autoSaveMinutes = globalref.genOptions['AutoSaveMinutes'] for control in self.localControls: for window in control.windowList: window.updateWinGenOptions() control.structure.undoList.setNumLevels() control.updateAll(False) if autoSaveMinutes != oldAutoSaveMinutes: control.resetAutoSave() def toolsCustomShortcuts(self): """Show dialog to customize keyboard commands. """ actions = self.activeControl.activeWindow.allActions dialog = miscdialogs.CustomShortcutsDialog(actions, QApplication. activeWindow()) dialog.exec() def toolsCustomToolbars(self): """Show dialog to customize toolbar buttons. """ actions = self.activeControl.activeWindow.allActions dialog = miscdialogs.CustomToolbarDialog(actions, self.updateToolbars, QApplication. activeWindow()) dialog.exec() def updateToolbars(self): """Update toolbars after changes in custom toolbar dialog. """ for control in self.localControls: for window in control.windowList: window.setupToolbars() def toolsCustomFonts(self): """Show dialog to customize fonts in various views. """ dialog = miscdialogs.CustomFontDialog(QApplication. activeWindow()) dialog.updateRequired.connect(self.updateCustomFonts) dialog.exec() def toolsCustomColors(self): """Show dialog to customize GUI colors ans themes. """ self.colorSet.showDialog(QApplication.activeWindow()) def updateCustomFonts(self): """Update fonts in all windows based on a dialog signal. """ self.updateAppFont() for control in self.localControls: for window in control.windowList: window.updateFonts() control.printData.setDefaultFont() for control in self.localControls: control.updateAll(False) def updateAppFont(self): """Update application default font from settings. """ appFont = QFont(self.systemFont) appFontName = globalref.miscOptions['AppFont'] if appFontName: appFont.fromString(appFontName) QApplication.setFont(appFont) def formatSelectAll(self): """Select all text in any currently focused editor. """ try: QApplication.focusWidget().selectAll() except AttributeError: pass def helpViewBasic(self): """Display basic usage instructions. """ if not self.basicHelpView: path = self.findResourceFile('basichelp.html', 'doc', docPath) if not path: QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - basic help file not found')) return self.basicHelpView = helpview.HelpView(path, _('TreeLine Basic Usage'), globalref.toolIcons) self.basicHelpView.show() def helpViewFull(self): """Open a TreeLine file with full documentation. """ path = self.findResourceFile('documentation.trln', 'doc', docPath) if not path: QMessageBox.warning(QApplication.activeWindow(), 'TreeLine', _('Error - documentation file not found')) return self.createLocalControl(path, forceNewWindow=True) self.activeControl.filePathObj = pathlib.Path('documentation.trln') self.activeControl.updateWindowCaptions() self.activeControl.expandRootNodes() self.activeControl.imported = True win = self.activeControl.activeWindow win.rightTabs.setCurrentWidget(win.outputSplitter) def helpAbout(self): """ Display version info about this program. """ pyVersion = '.'.join([repr(num) for num in sys.version_info[:3]]) textLines = [_('TreeLine version {0}').format(__version__), _('written by {0}').format(__author__), '', _('Library versions:'), ' Python: {0}'.format(pyVersion), ' Qt: {0}'.format(qVersion()), ' PyQt: {0}'.format(PYQT_VERSION_STR), ' OS: {0}'.format(platform.platform())] dialog = miscdialogs.AboutDialog('TreeLine', textLines, QApplication.windowIcon(), QApplication.activeWindow()) dialog.exec() def setThemeColors(): """Set the app colors based on options setting. """ if globalref.genOptions['ColorTheme'] == optiondefaults.colorThemes[1]: # dark theme myDarkGray = QColor(53, 53, 53) myVeryDarkGray = QColor(25, 25, 25) myBlue = QColor(42, 130, 218) palette = QPalette() palette.setColor(QPalette.ColorRole.Window, myDarkGray) palette.setColor(QPalette.ColorRole.WindowText, Qt.GlobalColor.white) palette.setColor(QPalette.ColorRole.Base, myVeryDarkGray) palette.setColor(QPalette.ColorRole.AlternateBase, myDarkGray) palette.setColor(QPalette.ColorRole.ToolTipBase, Qt.GlobalColor.darkBlue) palette.setColor(QPalette.ColorRole.ToolTipText, Qt.GlobalColor.lightGray) palette.setColor(QPalette.ColorRole.Text, Qt.GlobalColor.white) palette.setColor(QPalette.ColorRole.Button, myDarkGray) palette.setColor(QPalette.ColorRole.ButtonText, Qt.GlobalColor.white) palette.setColor(QPalette.ColorRole.BrightText, Qt.GlobalColor.red) palette.setColor(QPalette.ColorRole.Link, myBlue) palette.setColor(QPalette.ColorRole.Highlight, myBlue) palette.setColor(QPalette.ColorRole.HighlightedText, Qt.GlobalColor.black) palette.setColor(QPalette.ColorGroup.Disabled, QPalette.ColorRole.Text, Qt.GlobalColor.darkGray) palette.setColor(QPalette.ColorGroup.Disabled, QPalette.ColorRole.ButtonText, Qt.GlobalColor.darkGray) QApplication.setPalette(palette) TreeLine-3.2.1/source/treemodel.py000066400000000000000000000212621506556630100170700ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treemodel.py, provides a class for the tree's data # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import json from PyQt6.QtCore import (QAbstractItemModel, QMimeData, QModelIndex, Qt, pyqtSignal) import undo import treestructure import globalref class TreeModel(QAbstractItemModel): """Class interfacing between the tree structure and the tree view. """ # first arg is set file modified, second is update trees in other views treeModified = pyqtSignal(bool, bool) def __init__(self, treeStructure, parent=None): """Initialize a TreeModel. Arguments: treeStructure -- a ref to the main tree structure parent -- optional QObject parent for the model """ super().__init__(parent) self.treeStructure = treeStructure def index(self, row, column, parentIndex): """Returns the index of a spot in the model based on the parent index. Uses createIndex() to generate the model indices. Arguments: row -- the row of the model node column -- the column (always 0 for now) parentIndex -- the parent's model index in the tree structure """ try: if not parentIndex.isValid(): node = self.treeStructure.childList[row] fakeSpot = list(self.treeStructure.spotRefs)[0] spot = node.matchedSpot(fakeSpot) return self.createIndex(row, column, spot) parentSpot = parentIndex.internalPointer() node = parentSpot.nodeRef.childList[row] return self.createIndex(row, column, node.matchedSpot(parentSpot)) except IndexError: return QModelIndex() def parent(self, index): """Returns the parent model index of the spot at the given index. Arguments: index -- the child model index """ try: parentSpot = index.internalPointer().parentSpot if parentSpot.parentSpot: return self.createIndex(parentSpot.row(), 0, parentSpot) except AttributeError: # attempt to fix an unreproducable bug deleting deep nodes pass return QModelIndex() def rowCount(self, parentIndex): """Returns the number of children for the spot at the given index. Arguments: parentIndex -- the parent model index """ try: parentSpot = parentIndex.internalPointer() return parentSpot.nodeRef.numChildren() except AttributeError: # top level if no parentIndex return len(self.treeStructure.childList) def columnCount(self, parentIndex): """The number of columns -- always 1 for now. """ return 1 def data(self, index, role=Qt.ItemDataRole.DisplayRole): """Return the output data for the node in the given role. Arguments: index -- the spot's model index role -- the type of data requested """ spot = index.internalPointer() if not spot: return None node = spot.nodeRef if role in (Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole): return node.title() if (role == Qt.ItemDataRole.DecorationRole and globalref.genOptions['ShowTreeIcons']): return globalref.treeIcons.getIcon(node.formatRef.iconName, True) return None def setData(self, index, value, role=Qt.ItemDataRole.EditRole): """Set node title after edit operation. Return True on success. Arguments: index -- the node's model index value -- the string result of the editing role -- the edit role of the data """ if role != Qt.ItemDataRole.EditRole: return super().setData(index, value, role) node = index.internalPointer().nodeRef dataUndo = undo.DataUndo(self.treeStructure.undoList, node) if node.setTitle(value): self.dataChanged.emit(index, index) self.treeModified.emit(True, False) return True self.treeStructure.undoList.removeLastUndo(dataUndo) return False def flags(self, index): """Return the flags for the node at the given index. Arguments: index -- the node's model index """ return (Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled) def mimeData(self, indexList): """Return a mime data object for the given node index branches. Arguments: indexList -- a list of node indexes to convert """ spots = [index.internalPointer() for index in indexList] # remove selections from the same branch TreeModel.storedDragSpots = [spot for spot in spots if spot.parentSpotSet(). isdisjoint(set(spots))] nodes = [spot.nodeRef for spot in TreeModel.storedDragSpots] TreeModel.storedDragModel = self struct = treestructure.TreeStructure(topNodes=nodes, addSpots=False) generics = {formatRef.genericType for formatRef in struct.treeFormats.values() if formatRef.genericType} for generic in generics: genericRef = self.treeStructure.treeFormats[generic] struct.treeFormats.addTypeIfMissing(genericRef) for formatRef in genericRef.derivedTypes: struct.treeFormats.addTypeIfMissing(formatRef) data = struct.fileData() dataStr = json.dumps(data, indent=0, sort_keys=True) mime = QMimeData() mime.setData('application/json', bytes(dataStr, encoding='utf-8')) return mime def mimeTypes(self): """Return a list of supported mime types for model objects. """ return ['application/json'] def supportedDropActions(self): """Return drop action enum values that are supported by this model. """ return Qt.DropAction.CopyAction | Qt.DropAction.MoveAction def dropMimeData(self, mimeData, dropAction, row, column, index): """Decode mime data and add as a child node to the given index. Return True if successful. Arguments: mimeData -- data for the node branch to be added dropAction -- a drop type enum value row -- a row number for the drop location column -- the column number for the drop location (normally 0) index -- the index of the parent node for the drop """ parent = (index.internalPointer().nodeRef if index.internalPointer() else self.treeStructure) isMove = (dropAction == Qt.DropAction.MoveAction and TreeModel.storedDragModel == self) undoParents = [parent] if isMove: moveParents = {spot.parentSpot.nodeRef for spot in TreeModel.storedDragSpots} undoParents.extend(list(moveParents)) newStruct = treestructure.structFromMimeData(mimeData) # check for valid structure and no circular clone ref and not siblings: if newStruct and (not isMove or (not parent.uId in newStruct.nodeDict and (row >= 0 or {node.uId for node in parent.childList}. isdisjoint({node.uId for node in newStruct.childList})))): undo.ChildListUndo(self.treeStructure.undoList, undoParents, treeFormats=self.treeStructure.treeFormats) if isMove: for spot in TreeModel.storedDragSpots: self.treeStructure.deleteNodeSpot(spot) newStruct.replaceClonedBranches(self.treeStructure) else: newStruct.replaceDuplicateIds(self.treeStructure.nodeDict) self.treeStructure.addNodesFromStruct(newStruct, parent, row) return True return False TreeLine-3.2.1/source/treenode.py000066400000000000000000000770161506556630100167250ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treenode.py, provides a class to store tree node data # # TreeLine, an information storage program # Copyright (C) 2020, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import uuid import operator import itertools import treespot import nodeformat _replaceBackrefRe = (re.compile(r'\\(\d+)'), re.compile(r'\\g<(\d+)>')) _origBackrefMatch = None class TreeNode: """Class to store tree node data and the tree's linked structure. Stores a data dict, lists of children and a format name string. Provides methods to get info on the structure and the data. """ def __init__(self, formatRef, fileData=None): """Initialize a tree node. Arguments: formatRef -- a ref to this node's format info fileData -- a dict with uid, data, child refs & parent refs """ self.formatRef = formatRef if not fileData: fileData = {} self.uId = fileData.get('uid', uuid.uuid1().hex) self.data = fileData.get('data', {}) self.tmpChildRefs = fileData.get('children', []) self.childList = [] self.spotRefs = set() def assignRefs(self, nodeDict): """Add actual refs to child nodes from data in self.tmpChildRefs. Any bad node refs (corrupt file data) are left in self.tmpChildRefs. Arguments: nodeDict -- all nodes stored by uid """ try: self.childList = [nodeDict[uid] for uid in self.tmpChildRefs] self.tmpChildRefs = [] except KeyError: # due to corrupt file data badChildRefs = [] for uid in self.tmpChildRefs: if uid in nodeDict: self.childList.append(nodeDict[uid]) else: badChildRefs.append(uid) self.tmpChildRefs = badChildRefs def generateSpots(self, parentSpot): """Recursively generate spot references for this branch. Arguments: parentSpot -- the parent spot reference """ spot = treespot.TreeSpot(self, parentSpot) self.spotRefs.add(spot) for child in self.childList: child.generateSpots(spot) def addSpotRef(self, parentNode, includeChildren=True): """Add a spot ref here to the given parent if not already there. If changed, propogate to descendant nodes. Arguments: parentNode -- the parent to ref in the new spot includeChildren -- if True, propogate to descendant nodes """ changed = False origParentSpots = {spot.parentSpot for spot in self.spotRefs} for parentSpot in parentNode.spotRefs: if parentSpot not in origParentSpots: self.spotRefs.add(treespot.TreeSpot(self, parentSpot)) changed = True if changed and includeChildren: for child in self.childList: child.addSpotRef(self) def removeInvalidSpotRefs(self, includeChildren=True, forceDesend=False): """Verify existing spot refs and remove any that aren't valid. If changed and includeChilderen, propogate to descendant nodes. Arguments: includeChildren -- if True, propogate to descendants if changes forceDesend -- if True, force propogate to descendant nodes """ goodSpotRefs = {spot for spot in self.spotRefs if (self in spot.parentSpot.nodeRef.childList and spot.parentSpot in spot.parentSpot.nodeRef.spotRefs)} changed = len(self.spotRefs) != len(goodSpotRefs) self.spotRefs = goodSpotRefs if includeChildren and (changed or forceDesend): for child in self.childList: child.removeInvalidSpotRefs(includeChildren) def spotByNumber(self, num): """Return the spot at the given rank in the spot sequence. Arguments: num -- the rank number to return """ spotList = sorted(list(self.spotRefs), key=operator.methodcaller('sortKey')) return spotList[num] def matchedSpot(self, parentSpot): """Return the spot for this node that matches a parent spot. Return None if not found. Arguments: parentSpot -- the parent to match """ for spot in self.spotRefs: if spot.parentSpot is parentSpot: return spot return None def setInitDefaultData(self, overwrite=False): """Add initial default data from fields into internal data. Arguments: overwrite -- if true, replace previous data entries """ self.formatRef.setInitDefaultData(self.data, overwrite) def parents(self): """Return a set of parent nodes for this node. Returns an empty set if called from the tree structure. """ try: return {spot.parentSpot.nodeRef for spot in self.spotRefs} except AttributeError: return set() def numChildren(self): """Return number of children. """ return len(self.childList) def descendantGen(self): """Return a generator to step through all nodes in this branch. Includes self and closed nodes. """ yield self for child in self.childList: for node in child.descendantGen(): yield node def ancestors(self): """Return a set of all ancestor nodes (including self). """ spots = set() for spot in self.spotRefs: spots.update(spot.spotChain()) return {spot.nodeRef for spot in spots} def treeStructureRef(self): """Return the tree structure based on the root spot ref. """ return next(iter(self.spotRefs)).rootSpot().nodeRef def fileData(self): """Return the file data dict for this node. """ children = [node.uId for node in self.childList] fileData = {'format': self.formatRef.name, 'uid': self.uId, 'data': self.data, 'children': children} return fileData def title(self, spotRef=None): """Return the title string for this node. If spotRef not given, ancestor fields assume first spot. Arguments: spotRef -- optional, used for ancestor field refs """ return self.formatRef.formatTitle(self, spotRef) def setTitle(self, title): """Change this node's data based on a new title string. Return True if successfully changed. """ if title == self.title(): return False return self.formatRef.extractTitleData(title, self.data) def output(self, plainText=False, keepBlanks=False, spotRef=None): """Return a list of formatted text output lines. If spotRef not given, ancestor fields assume first spot. Arguments: plainText -- if True, remove HTML markup from fields and formats keepBlanks -- if True, keep lines with empty fields spotRef -- optional, used for ancestor field refs """ return self.formatRef.formatOutput(self, plainText, keepBlanks, spotRef) def changeDataType(self, formatRef): """Change this node's data type to the given name. Set init default data and update the title if blank. Arguments: formatRef -- the new tree format type """ origTitle = self.title() self.formatRef = formatRef formatRef.setInitDefaultData(self.data) if not formatRef.formatTitle(self): formatRef.extractTitleData(origTitle, self.data) def setConditionalType(self, treeStructure): """Set self to type based on auto conditional settings. Return True if type is changed. Arguments: treeStructure -- a ref to the tree structure """ if self.formatRef not in treeStructure.treeFormats.conditionalTypes: return False if self.formatRef.genericType: genericFormat = treeStructure.treeFormats[self.formatRef. genericType] else: genericFormat = self.formatRef formatList = [genericFormat] + genericFormat.derivedTypes formatList.remove(self.formatRef) formatList.insert(0, self.formatRef) # reorder to give priority neutralResult = None newType = None for typeFormat in formatList: if typeFormat.conditional: if typeFormat.conditional.evaluate(self): newType = typeFormat break elif not neutralResult: neutralResult = typeFormat if not newType and neutralResult: newType = neutralResult if newType and newType is not self.formatRef: self.changeDataType(newType) return True return False def setDescendantConditionalTypes(self, treeStructure): """Set auto conditional types for self and all descendants. Return number of changes made. Arguments: treeStructure -- a ref to the tree structure """ if not treeStructure.treeFormats.conditionalTypes: return 0 changes = 0 for node in self.descendantGen(): if node.setConditionalType(treeStructure): changes += 1 return changes def setData(self, field, editorText): """Set the data entry for the given field to editorText. If the data does not match the format, sets to the raw text and raises a ValueError. Arguments: field-- the field object to be set editorText -- new text data from an editor """ try: self.data[field.name] = field.storedText(editorText) except ValueError as err: if len(err.args) >= 2: self.data[field.name] = err.args[1] else: self.data[field.name] = editorText raise ValueError def wordSearch(self, wordList, titleOnly=False, spotRef=None): """Return True if all words in wordlist are found in this node's data. Arguments: wordList -- a list of words or phrases to find titleOnly -- search only in the title text if True spotRef -- an optional spot reference for ancestor field refs """ dataStr = self.title(spotRef).lower() if not titleOnly: # join with null char so phrase matches don't cross borders dataStr = '{0}\0{1}'.format(dataStr, '\0'.join(self.data.values()).lower()) for word in wordList: if word not in dataStr: return False return True def regExpSearch(self, regExpList, titleOnly=False, spotRef=None): """Return True if the regular expression is found in this node's data. Arguments: regExpList -- a list of regular expression objects to find titleOnly -- search only in the title text if True spotRef -- an optional spot reference for ancestor field refs """ dataStr = self.title(spotRef) if not titleOnly: # join with null char so phrase matches don't cross borders dataStr = '{0}\0{1}'.format(dataStr, '\0'.join(self.data.values())) for regExpObj in regExpList: if not regExpObj.search(dataStr): return False return True def searchReplace(self, searchText='', regExpObj=None, skipMatches=0, typeName='', fieldName='', replaceText=None, replaceAll=False): """Find the search text in the field data and optionally replace it. Returns a tuple of the fieldName where found (empty string if not found), the node match number and the field match number. Returns the last match if skipMatches < 0 (not used with replace). Arguments: searchText -- the text to find if regExpObj is None regExpObj -- the regular expression to find if not None skipMatches -- number of already found matches to skip in this node typeName -- if given, verify that this node matches this type fieldName -- if given, only find matches under this type name replaceText -- if not None, replace a match with this string replaceAll -- if True, replace all matches (returns last fieldName) """ if typeName and typeName != self.formatRef.name: return ('', 0, 0) try: fields = ([self.formatRef.fieldDict[fieldName]] if fieldName else self.formatRef.fields()) except KeyError: return ('', 0, 0) # field not in this type matchedFieldname = '' findCount = 0 prevFieldFindCount = 0 for field in fields: try: fieldText = field.editorText(self) except ValueError: fieldText = self.data.get(field.name, '') fieldFindCount = 0 pos = 0 while True: if pos >= len(fieldText) and pos > 0: break if regExpObj: match = regExpObj.search(fieldText, pos) pos = match.start() if match else -1 else: pos = fieldText.lower().find(searchText, pos) if not searchText and fieldText: pos = -1 # skip invalid find of empty string if pos < 0: break findCount += 1 fieldFindCount += 1 prevFieldFindCount = fieldFindCount matchLen = (len(match.group()) if regExpObj else len(searchText)) if findCount > skipMatches: matchedFieldname = field.name if replaceText is not None: replace = replaceText if regExpObj: global _origBackrefMatch _origBackrefMatch = match for backrefRe in _replaceBackrefRe: replace = backrefRe.sub(self.replaceBackref, replace) fieldText = (fieldText[:pos] + replace + fieldText[pos + matchLen:]) try: self.setData(field, fieldText) except ValueError: pass if not replaceAll and skipMatches >= 0: return (field.name, findCount, fieldFindCount) pos = pos + matchLen if matchLen else pos + 1 if not matchedFieldname: findCount = prevFieldFindCount = 0 return (matchedFieldname, findCount, prevFieldFindCount) @staticmethod def replaceBackref(match): """Return the re match group from _origBackrefMatch for replacement. Used for reg exp backreference replacement. Arguments: match -- the backref match in the replacement string """ return _origBackrefMatch.group(int(match.group(1))) def addNewChild(self, treeStructure, posRefNode=None, insertBefore=True, newTitle=_('New')): """Add a new child node with this node as the parent. Insert the new node near the posRefNode or at the end if no ref node. Return the new node. Arguments: treeStructure -- a ref to the tree structure posRefNode -- a child reference for the new node's position insertBefore -- insert before the ref node if True, after if False """ try: newFormat = treeStructure.treeFormats[self.formatRef.childType] except (KeyError, AttributeError): if posRefNode: newFormat = posRefNode.formatRef elif self.childList: newFormat = self.childList[0].formatRef else: newFormat = self.formatRef newNode = TreeNode(newFormat) pos = len(self.childList) if posRefNode: pos = self.childList.index(posRefNode) if not insertBefore: pos += 1 self.childList.insert(pos, newNode) newNode.setInitDefaultData() newNode.addSpotRef(self) if newTitle and not newNode.title(): newNode.setTitle(newTitle) treeStructure.addNodeDictRef(newNode) return newNode def changeParent(self, oldParentSpot, newParentSpot, newPos=-1): """Move this node from oldParent to newParent. Used for indent and unindent commands. Arguments: oldParent -- the original parent spot newParent -- the new parent spot newPos -- the position in the new childList, -1 for append """ oldParent = oldParentSpot.nodeRef oldParent.childList.remove(self) newParent = newParentSpot.nodeRef if newPos >= 0: newParent.childList.insert(newPos, self) else: newParent.childList.append(self) # preserve one spot to maintain tree expand state self.matchedSpot(oldParentSpot).parentSpot = newParentSpot self.removeInvalidSpotRefs() self.addSpotRef(newParent) def replaceChildren(self, titleList, treeStructure): """Replace child nodes with titles from a text list. Nodes with matches in the titleList are kept, others are added or deleted as required. Arguments: titleList -- the list of new child titles treeStructure -- a ref to the tree structure """ try: newFormat = treeStructure.treeFormats[self.formatRef.childType] except (KeyError, AttributeError): newFormat = (self.childList[0].formatRef if self.childList else self.formatRef) matchList = [] remainTitles = [child.title() for child in self.childList] for title in titleList: try: match = self.childList.pop(remainTitles.index(title)) matchList.append((title, match)) remainTitles = [child.title() for child in self.childList] except ValueError: matchList.append((title, None)) newChildList = [] firstMiss = True for title, node in matchList: if not node: if (firstMiss and remainTitles and remainTitles[0].startswith(title)): # accept partial match on first miss for split tiles node = self.childList.pop(0) node.setTitle(title) else: node = TreeNode(newFormat) node.setTitle(title) node.setInitDefaultData() node.addSpotRef(self) treeStructure.addNodeDictRef(node) firstMiss = False newChildList.append(node) for child in self.childList: for oldNode in child.descendantGen(): if len(oldNode.spotRefs) <= 1: treeStructure.removeNodeDictRef(oldNode) else: oldNode.removeInvalidSpotRefs(False) self.childList = newChildList def replaceClonedBranches(self, origStruct): """Replace any duplicate IDs with clones from the given structure. Recursively search for duplicates. Arguments: origStruct -- the tree structure with the cloned nodes """ for i in range(len(self.childList)): if self.childList[i].uId in origStruct.nodeDict: self.childList[i] = origStruct.nodeDict[self.childList[i].uId] else: self.childList[i].replaceClonedBranches(origStruct) def loadChildNodeLevels(self, nodeList, initLevel=-1): """Recursively add children from a list of nodes and levels. Return True on success, False if data levels are not valid. Arguments: nodeList -- list of tuples with node and level initLevel -- the level of this node in the structure """ while nodeList: child, level = nodeList[0] if level == initLevel + 1: del nodeList[0] self.childList.append(child) if not child.loadChildNodeLevels(nodeList, level): return False else: return -1 < level <= initLevel return True def fieldSortKey(self, level=0): """Return a key used to sort by key fields. Arguments: level -- the sort key depth level for the current sort stage """ if len(self.formatRef.sortFields) > level: return self.formatRef.sortFields[level].sortKey(self) return ('',) def sortChildrenByField(self, recursive=True, forward=True): """Sort child nodes by predefined field keys. Arguments: recursive -- continue to sort recursively if true forward -- reverse the sort if false """ formats = set([child.formatRef for child in self.childList]) maxDepth = 0 directions = [] for nodeFormat in formats: if not nodeFormat.sortFields: nodeFormat.loadSortFields() maxDepth = max(maxDepth, len(nodeFormat.sortFields)) newDirections = [field.sortKeyForward for field in nodeFormat.sortFields] directions = [sum(i) for i in itertools.zip_longest(directions, newDirections, fillvalue= False)] if forward: directions = [bool(direct) for direct in directions] else: directions = [not bool(direct) for direct in directions] for level in range(maxDepth, 0, -1): self.childList.sort(key = operator.methodcaller('fieldSortKey', level - 1), reverse = not directions[level - 1]) if recursive: for child in self.childList: child.sortChildrenByField(True, forward) def titleSortKey(self): """Return a key used to sort by titles. """ return self.title().lower() def sortChildrenByTitle(self, recursive=True, forward=True): """Sort child nodes by titles. Arguments: recursive -- continue to sort recursively if true forward -- reverse the sort if false """ self.childList.sort(key = operator.methodcaller('titleSortKey'), reverse = not forward) if recursive: for child in self.childList: child.sortChildrenByTitle(True, forward) def updateNodeMathFields(self, treeFormats): """Recalculate math fields that depend on this node and so on. Return True if any data was changed. Arguments: treeFormats -- a ref to all of the formats """ changed = False for field in self.formatRef.fields(): for fieldRef in treeFormats.mathFieldRefDict.get(field.name, []): for node in fieldRef.dependentEqnNodes(self): if node.recalcMathField(fieldRef.eqnFieldName, treeFormats): changed = True return changed def recalcMathField(self, eqnFieldName, treeFormats): """Recalculate a math field, if changed, recalc depending math fields. Return True if any data was changed. Arguments: eqnFieldName -- the equation field in this node to update treeFormats -- a ref to all of the formats """ changed = False oldValue = self.data.get(eqnFieldName, '') newValue = self.formatRef.fieldDict[eqnFieldName].equationValue(self) if newValue != oldValue: self.data[eqnFieldName] = newValue changed = True for fieldRef in treeFormats.mathFieldRefDict.get(eqnFieldName, []): for node in fieldRef.dependentEqnNodes(self): node.recalcMathField(fieldRef.eqnFieldName, treeFormats) return changed def updateNumbering(self, fieldDict, currentSequence, levelLimit, completedClones, includeRoot=True, reserveNums=True, restartSetting=False): """Add auto incremented numbering to fields by type in the dict. Arguments: fieldDict -- numbering field name lists stored by type name currentSequence -- a list of int for the current numbering sequence levelLimit -- the number of child levels to include completedClones -- set of clone nodes already numbered includeRoot -- if Ture, number the current node reserveNums -- if true, increment number even without num field restartSetting -- if true, restart numbering after a no-field gap """ childSequence = currentSequence[:] if includeRoot: for fieldName in fieldDict.get(self.formatRef.name, []): self.data[fieldName] = '.'.join((repr(num) for num in currentSequence)) if self.formatRef.name in fieldDict or reserveNums: childSequence += [1] currentSequence[-1] += 1 if restartSetting and self.formatRef.name not in fieldDict: currentSequence[-1] = 1 if len(self.spotRefs) > 1: completedClones.add(self.uId) if levelLimit > 0: for child in self.childList: if len(child.spotRefs) > 1 and child.uId in completedClones: return child.updateNumbering(fieldDict, childSequence, levelLimit - 1, completedClones, True, reserveNums, restartSetting) def isIdentical(self, node, checkParents=True): """Return True if node format, data and descendants are identical. Also returns False if checkParents & the nodes have parents in common. Arguments: node -- the node to check """ if (self.formatRef != node.formatRef or len(self.childList) != len(node.childList) or self.data != node.data or (checkParents and not self.parents().isdisjoint(node.parents()))): return False for thisChild, otherChild in zip(self.childList, node.childList): if not thisChild.isIdentical(otherChild, False): return False return True def flatChildCategory(self, origFormats, structure): """Collapse descendant nodes by merging fields. Overwrites data in any fields with the same name. Arguments: origFormats -- copy of tree formats before any changes structure -- a ref to the tree structure """ thisSpot = self.spotByNumber(0) newChildList = [] for spot in thisSpot.spotDescendantOnlyGen(): if not spot.nodeRef.childList: oldParentSpot = spot.parentSpot while oldParentSpot != thisSpot: for field in origFormats[oldParentSpot.nodeRef.formatRef. name].fields(): data = oldParentSpot.nodeRef.data.get(field.name, '') if data: spot.nodeRef.data[field.name] = data spot.nodeRef.formatRef.addFieldIfNew(field.name, field.formatData()) oldParentSpot = oldParentSpot.parentSpot spot.parentSpot = thisSpot newChildList.append(spot.nodeRef) else: structure.removeNodeDictRef(spot.nodeRef) self.childList = newChildList def addChildCategory(self, catList, structure): """Insert category nodes above children. Arguments: catList -- the field names to add to the new level structure -- a ref to the tree structure """ newFormat = None catSet = set(catList) similarFormats = [nodeFormat for nodeFormat in structure.treeFormats.values() if catSet.issubset(set(nodeFormat.fieldNames()))] if similarFormats: similarFormat = min(similarFormats, key=lambda f: len(f.fieldDict)) if len(similarFormat.fieldDict) < len(self.childList[0]. formatRef.fieldDict): newFormat = similarFormat if not newFormat: newFormatName = '{0}_TYPE'.format(catList[0].upper()) num = 1 while newFormatName in structure.treeFormats: newFormatName = '{0}_TYPE_{1}'.format(catList[0].upper(), num) num += 1 newFormat = nodeformat.NodeFormat(newFormatName, structure.treeFormats) newFormat.addFieldList(catList, True, True) structure.treeFormats[newFormatName] = newFormat newParents = [] for child in self.childList: newParent = child.findEqualFields(catList, newParents) if not newParent: newParent = TreeNode(newFormat) for field in catList: data = child.data.get(field, '') if data: newParent.data[field] = data structure.addNodeDictRef(newParent) newParents.append(newParent) newParent.childList.append(child) self.childList = newParents for child in self.childList: child.removeInvalidSpotRefs(True, True) child.addSpotRef(self) def findEqualFields(self, fieldNames, nodes): """Return first node in nodes with same data in fieldNames as self. Arguments: fieldNames -- the list of fields to check nodes -- the nodes to search for a match """ for node in nodes: for field in fieldNames: if self.data.get(field, '') != node.data.get(field, ''): break else: # this for loop didn't hit break, so we have a match return node def exportTitleText(self, level=0): """Return a list of tabbed title lines for this node and descendants. Arguments: level -- indicates the indent level needed """ textList = ['\t' * level + self.title()] for child in self.childList: textList.extend(child.exportTitleText(level + 1)) return textList TreeLine-3.2.1/source/treeoutput.py000066400000000000000000000422751506556630100173370ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treeoutput.py, provides classes for output to views, html and printing # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import itertools from PyQt6.QtGui import QTextDocument import globalref _linkRe = re.compile(r']*href="#(.*?)"[^>]*>.*?', re.I | re.S) class OutputItem: """Class to store output for a single node. Stores text lines and original indent level. """ def __init__(self, spot, level): """Convert the spot's node into an output item. Create a blank item if spot is None. Arguments: spot -- the tree spot to convert level -- the node's original indent level """ if spot: node = spot.nodeRef nodeFormat = node.formatRef if not nodeFormat.useTables: self.textLines = [line + '
    ' for line in node.output(spotRef=spot)] else: self.textLines = node.output(keepBlanks=True, spotRef=spot) if not self.textLines: self.textLines = [''] self.addSpace = nodeFormat.spaceBetween self.siblingPrefix = nodeFormat.siblingPrefix self.siblingSuffix = nodeFormat.siblingSuffix if nodeFormat.useBullets and self.textLines: # remove
    extra space for bullets self.textLines[-1] = self.textLines[-1][:-6] self.uId = node.uId else: self.textLines = [''] self.addSpace = False self.siblingPrefix = '' self.siblingSuffix = '' self.uId = None self.level = level # following variables used by printdata only: self.height = 0 self.pageNum = 0 self.columnNum = 0 self.pagePos = 0 self.doc = None self.parentItem = None self.lastChildItem = None def duplicate(self): """Return an independent copy of this OutputItem. """ item = OutputItem(None, 0) item.textLines = self.textLines[:] item.addSpace = self.addSpace item.siblingPrefix = self.siblingPrefix item.siblingSuffix = self.siblingSuffix item.uId = self.uId item.level = self.level item.height = self.height item.pageNum = self.pageNum item.columnNum = self.columnNum item.pagePos = self.pagePos item.doc = None item.parentItem = self.parentItem item.lastChildItem = self.lastChildItem return item def addIndent(self, prevLevel, nextLevel): """Add
    tags to define indent levels in the output. Arguments: prevLevel -- the level of the previous item in the list nextLevel -- the level of the next item in the list """ for num in range(self.level - prevLevel): self.textLines[0] = '
    ' + self.textLines[0] for num in range(self.level - nextLevel): self.textLines[-1] += '
    ' def addAbsoluteIndent(self, pixels): """Add tags for an individual indentation. Removes the
    tag from the last line to avoid excess space, since
    starts a new line. The Qt output view does not fully support nested
    tags. Arguments: pixels -- the amount to indent """ self.textLines[0] = ('
    {1}'. format(pixels * self.level, self.textLines[0])) if not self.siblingPrefix and self.textLines[-1].endswith('
    '): self.textLines[-1] = self.textLines[-1][:-6] self.textLines[-1] += '
    ' def addSiblingPrefix(self): """Add the sibling prefix before this output. """ if self.siblingPrefix: self.textLines[0] = self.siblingPrefix + self.textLines[0] def addSiblingSuffix(self): """Add the sibling suffix after this output. """ if self.siblingSuffix: self.textLines[-1] += self.siblingSuffix def addAnchor(self): """Add a link anchor to this item. """ self.textLines[0] = '{1}'.format(self.uId, self.textLines[0]) def intLinkIds(self): """Return a set of uIDs from any internal links in this item. """ linkIds = set() for line in self.textLines: startPos = 0 while True: match = _linkRe.search(line, startPos) if not match: break uId = match.group(1) if uId: linkIds.add(uId) startPos = match.start(1) return linkIds def numLines(self): """Return the number of text lines in the item. """ return len(self.textLines) def equalPrefix(self, otherItem): """Return True if sibling prefixes and suffixes are equal. Arguments: otherItem -- the item to compare """ return (self.siblingPrefix == otherItem.siblingPrefix and self.siblingSuffix == otherItem.siblingSuffix) def setDocHeight(self, paintDevice, width, printFont, replaceDoc=False): """Set the height of this item for use in printer output. Creates an output document if not already created. Arguments: paintDevice -- the printer or other device for settings width -- the width available for the output text printFont -- the default font for the document replaceDoc -- if true, re-create the text document """ if not self.doc or replaceDoc: self.doc = QTextDocument() lines = '\n'.join(self.textLines) if lines.endswith('
    '): # remove trailing
    tag to avoid excess space lines = lines[:-6] self.doc.setHtml(lines) self.doc.setDefaultFont(printFont) frameFormat = self.doc.rootFrame().frameFormat() frameFormat.setBorder(0) frameFormat.setMargin(0) frameFormat.setPadding(0) self.doc.rootFrame().setFrameFormat(frameFormat) layout = self.doc.documentLayout() layout.setPaintDevice(paintDevice) self.doc.setTextWidth(width) self.height = layout.documentSize().height() def splitDocHeight(self, initHeight, maxHeight, paintDevice, width, printFont): """Split this item into two items and return them. The first item will fit into initHeight if practical. Splits at line endings if posible. Arguments: initHeight -- the preferred height of the first page maxheight -- the max height of any pages paintDevice -- the printer or other device for settings width -- the width available for the output text printFont -- the default font for the document """ newItem = self.duplicate() fullHeight = self.height lines = '\n'.join(self.textLines) allLines = [line + '
    ' for line in lines.split('
    ')] self.textLines = [] prevHeight = 0 for line in allLines: self.textLines.append(line) self.setDocHeight(paintDevice, width, printFont, True) if ((prevHeight and self.height > initHeight and fullHeight - prevHeight > maxHeight) or (prevHeight and self.height > maxHeight)): self.textLines = self.textLines[:-1] self.setDocHeight(paintDevice, width, printFont, True) newItem.textLines = allLines[len(self.textLines):] newItem.setDocHeight(paintDevice, width, printFont, True) return (self, newItem) if self.height > maxHeight: break prevHeight = self.height # no line ending breaks found text = ' \n'.join(allLines) allWords = [word + ' ' for word in text.split(' ')] newWords = [] prevHeight = 0 for word in allWords: if word.strip() == ' initHeight and fullHeight - prevHeight < maxHeight) or (prevHeight and self.height > maxHeight)): self.textLines = [''.join(newWords[:-1])] self.setDocHeight(paintDevice, width, printFont, True) newItem.textLines = [''.join(allWords[len(newWords):])] newItem.setDocHeight(paintDevice, width, printFont, True) return (self, newItem) if self.height > maxHeight: break prevHeight = self.height newItem.setDocHeight(paintDevice, width, printFont, True) return (newItem, None) # fail to split class OutputGroup(list): """A list of OutputItems that takes TreeNodes as input. Modifies the output text for use in views, html and printing. """ def __init__(self, spotList, includeRoot=True, includeDescend=False, openOnly=False): """Convert the node iter list into a list of output items. Arguments: spotList -- a list of spots to convert to output includeRoot -- if True, include the nodes in nodeList includeDescend -- if True, include children, grandchildren, etc. openOnly -- if true, ignore collapsed children in the main treeView """ super().__init__() for spot in spotList: level = -1 if includeRoot: level = 0 self.append(OutputItem(spot, level)) if includeDescend: self.addChildren(spot, level, openOnly) def addChildren(self, spot, level, openOnly=False): """Recursively add OutputItems for descendants of the given spot. Arguments: spot -- the parent tree spot level -- the parent node's original indent level """ treeView = globalref.mainControl.activeControl.activeWindow.treeView if not openOnly or treeView.isSpotExpanded(spot): for child in spot.childSpots(): self.append(OutputItem(child, level + 1)) self.addChildren(child, level + 1, openOnly) def addIndents(self): """Add nested
    elements to define indentations in the output. """ prevLevel = 0 for item, nextItem in itertools.zip_longest(self, self[1:]): try: nextLevel = nextItem.level except AttributeError: nextLevel = 0 item.addIndent(prevLevel, nextLevel) prevLevel = item.level def addAbsoluteIndents(self, pixels=20): """Add tags for individual indentation on each node. The Qt output view does not fully support nested
    tags. Arguments: pixels -- the amount to indent """ for item in self: item.addAbsoluteIndent(pixels) def addBlanksBetween(self): """Add blank lines between nodes based on node format's spaceBetween. """ for item, nextItem in zip(self, self[1:]): if item.addSpace or nextItem.addSpace: item.textLines[-1] += '
    ' def addAnchors(self, extraLevels=0): """Add anchors to items that are targets and to low level items. Arguments: extraLevels -- force adding anchors if level < this """ linkIds = set() for item in self: linkIds.update(item.intLinkIds()) for item in self: if item.uId in linkIds or item.level < extraLevels: item.addAnchor() def hasPrefixes(self): """Return True if sibling prefixes or suffixes are found. """ return bool([item for item in self if item.siblingPrefix or item.siblingSuffix]) def addSiblingPrefixes(self): """Add sibling prefixes and suffixes for each node. """ if not self.hasPrefixes(): return addPrefix = True for item, nextItem in itertools.zip_longest(self, self[1:]): if addPrefix: item.addSiblingPrefix() if (not nextItem or item.level != nextItem.level or not item.equalPrefix(nextItem)): item.addSiblingSuffix() addPrefix = True else: addPrefix = False def combineAllSiblings(self): """Group all sibling items with the same prefix into single items. Also add sibling prefixes and suffixes and spaces in between. """ newItems = [] prevItem = None for item in self: if prevItem: if item.level == prevItem.level and item.equalPrefix(prevItem): if item.addSpace or prevItem.addSpace: prevItem.textLines[-1] += '
    ' prevItem.textLines.extend(item.textLines) else: prevItem.addSiblingSuffix() newItems.append(prevItem) item.addSiblingPrefix() prevItem = item else: item.addSiblingPrefix() prevItem = item prevItem.addSiblingSuffix() newItems.append(prevItem) self[:] = newItems def combineLines(self, addSpacing=True, addPrefixes=True): """Return an OutputItem including all of the text from all items. Arguments: addPrefixes -- if True, add sibling prefix and suffix to result addSpacing -- if True, add spacing between items with addSpace True """ comboItem = self[0].duplicate() for item in self[1:]: if item.addSpace: comboItem.textLines[-1] += '
    ' comboItem.textLines.extend(item.textLines) if addPrefixes: comboItem.addSiblingPrefix() comboItem.addSiblingSuffix() return comboItem def splitColumns(self, numColumns): """Split output into even length columns using number of lines. Return a list with a group for each column. Arguments: numColumns - the number of columns to split """ if numColumns < 2: return [self] groupList = [] if len(self) <= numColumns: for item in self: groupList.append(OutputGroup([])) groupList[-1].append(item) return groupList numEach = len(self) // numColumns for colNum in range(numColumns - 1): groupList.append(OutputGroup([])) groupList[-1].extend(self[colNum * numEach : (colNum + 1) * numEach]) groupList.append(OutputGroup([])) groupList[-1].extend(self[(numColumns - 1) * numEach : ]) numChanges = 1 while numChanges: numChanges = 0 for colNum in range(numColumns - 1): if (groupList[colNum].totalNumLines() > groupList[colNum + 1]. totalNumLines() + groupList[colNum][-1].numLines()): groupList[colNum + 1].insert(0, groupList[colNum][-1]) del groupList[colNum][-1] numChanges += 1 if (groupList[colNum].totalNumLines() + groupList[colNum + 1][0].numLines() <= groupList[colNum + 1].totalNumLines()): groupList[colNum].append(groupList[colNum + 1][0]) del groupList[colNum + 1][0] numChanges += 1 return groupList def getLines(self): """Return the full list of text lines from this group. """ if not self: return [] lines = [] for item in self: lines.extend(item.textLines) return lines def totalNumLines(self): """Return the total number of lines of all items in this container. """ return sum([item.numLines() for item in self]) def loadFamilyRefs(self): """Set parentItem and lastChildItem for all items. Used by the printdata class. """ recentParents = [None] for item in self: if item.level > 0: item.parentItem = recentParents[item.level - 1] item.parentItem.lastChildItem = item try: recentParents[item.level] = item except IndexError: recentParents.append(item) TreeLine-3.2.1/source/treeselection.py000066400000000000000000000231111506556630100177500ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treeselection.py, provides a class for the tree view's selection model # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import collections import json from PyQt6.QtCore import QItemSelectionModel, QMimeData from PyQt6.QtGui import QClipboard from PyQt6.QtWidgets import QApplication import treestructure import treespotlist import globalref _maxHistoryLength = 10 class TreeSelection(QItemSelectionModel): """Class override for the tree view's selection model. Provides methods for easier access to selected nodes. """ def __init__(self, model, parent=None): """Initialize the selection model. Arguments: model -- the model for view data parent -- the parent tree view """ super().__init__(model, parent) self.modelRef = model self.tempExpandedSpots = [] self.prevSpots = [] self.nextSpots = [] self.restoreFlag = False self.selectionChanged.connect(self.updateSelectLists) def selectedCount(self): """Return the number of selected spots. """ return len(self.selectedIndexes()) def selectedSpots(self): """Return a SpotList of selected spots, sorted in tree order. """ return treespotlist.TreeSpotList([index.internalPointer() for index in self.selectedIndexes()]) def selectedBranchSpots(self): """Return a SpotList of spots at the top of selected branches. Remvoves any duplicate spots that are already covered by the branches. """ spots = self.selectedSpots() spotSet = set(spots) return treespotlist.TreeSpotList([spot for spot in spots if spot.parentSpotSet(). isdisjoint(spotSet)]) def selectedNodes(self): """Return a list of the currently selected tree nodes. Removes any duplicate (cloned) nodes. """ tmpDict = collections.OrderedDict() for spot in self.selectedSpots(): node = spot.nodeRef tmpDict[node.uId] = node return list(tmpDict.values()) def selectedBranches(self): """Return a list of nodes at the top of selected branches. Remvoves any duplicates that are already covered by the branches. """ tmpDict = collections.OrderedDict() for spot in self.selectedBranchSpots(): node = spot.nodeRef tmpDict[node.uId] = node return list(tmpDict.values()) def currentSpot(self): """Return the current tree spot. Can raise AttributeError if no spot is current. """ return self.currentIndex().internalPointer() def currentNode(self): """Return the current tree node. Can raise AttributeError if no node is current. """ return self.currentSpot().nodeRef def selectSpots(self, spotList, signalUpdate=True, expandParents=False): """Clear the current selection and select the given spots. Arguments: spotList -- the spots to select signalUpdate -- if False, block normal select update signals expandParents -- open parent spots to make selection visible """ if expandParents: treeView = (globalref.mainControl.activeControl.activeWindow. treeView) for spot in self.tempExpandedSpots: treeView.collapseSpot(spot) self.tempExpandedSpots = [] for spot in spotList: parent = spot.parentSpot while parent.parentSpot: if not treeView.isSpotExpanded(parent): treeView.expandSpot(parent) self.tempExpandedSpots.append(parent) parent = parent.parentSpot if not signalUpdate: self.blockSignals(True) self.addToHistory(spotList) self.clear() if spotList: for spot in spotList: self.select(spot.index(self.modelRef), QItemSelectionModel.SelectionFlag.Select) self.setCurrentIndex(spotList[0].index(self.modelRef), QItemSelectionModel.SelectionFlag.Current) self.blockSignals(False) def selectNodeById(self, nodeId): """Select the first spot from the given node ID. Return True on success. Arguments: nodeId -- the ID of the node to select """ try: node = self.modelRef.treeStructure.nodeDict[nodeId] self.selectSpots([node.spotByNumber(0)], True, True) except KeyError: return False return True def setCurrentSpot(self, spot): """Set the current spot. Arguments: spot -- the spot to make current """ self.blockSignals(True) self.setCurrentIndex(spot.index(self.modelRef), QItemSelectionModel.SelectionFlag.Current) self.blockSignals(False) def copySelectedNodes(self): """Copy these node branches to the clipboard. """ nodes = self.selectedBranches() if not nodes: return clip = QApplication.clipboard() if clip.supportsSelection(): titleList = [] for node in nodes: titleList.extend(node.exportTitleText()) clip.setText('\n'.join(titleList), QClipboard.Mode.Selection) struct = treestructure.TreeStructure(topNodes=nodes, addSpots=False) generics = {formatRef.genericType for formatRef in struct.treeFormats.values() if formatRef.genericType} for generic in generics: genericRef = self.modelRef.treeStructure.treeFormats[generic] struct.treeFormats.addTypeIfMissing(genericRef) for formatRef in genericRef.derivedTypes: struct.treeFormats.addTypeIfMissing(formatRef) data = struct.fileData() dataStr = json.dumps(data, indent=0, sort_keys=True) mime = QMimeData() mime.setData('application/json', bytes(dataStr, encoding='utf-8')) clip.setMimeData(mime) def restorePrevSelect(self): """Go back to the most recent saved selection. """ self.validateHistory() if len(self.prevSpots) > 1: del self.prevSpots[-1] oldSelect = self.selectedSpots() if oldSelect and (not self.nextSpots or oldSelect != self.nextSpots[-1]): self.nextSpots.append(oldSelect) self.restoreFlag = True self.selectSpots(self.prevSpots[-1], expandParents=True) self.restoreFlag = False def restoreNextSelect(self): """Go forward to the most recent saved selection. """ self.validateHistory() if self.nextSpots: select = self.nextSpots.pop(-1) if select and (not self.prevSpots or select != self.prevSpots[-1]): self.prevSpots.append(select) self.restoreFlag = True self.selectSpots(select, expandParents=True) self.restoreFlag = False def addToHistory(self, spots): """Add given spots to previous select list. Arguments: spots -- a list of spots to be added """ if spots and not self.restoreFlag and (not self.prevSpots or spots != self.prevSpots[-1]): self.prevSpots.append(spots) if len(self.prevSpots) > _maxHistoryLength: del self.prevSpots[:2] self.nextSpots = [] def validateHistory(self): """Clear invalid items from history lists. """ for histList in (self.prevSpots, self.nextSpots): for spots in histList: spots[:] = [spot for spot in spots if spot.isValid()] histList[:] = [spots for spots in histList if spots] def updateSelectLists(self): """Update history after a selection change. """ self.addToHistory(self.selectedSpots()) def selectTitleMatch(self, searchText, forward=True, includeCurrent=False): """Select a node with a title matching the search text. Returns True if found, otherwise False. Arguments: searchText -- the text to look for forward -- next if True, previous if False includeCurrent -- look in current node if True """ searchText = searchText.lower() currentSpot = self.currentSpot() spot = currentSpot while True: if not includeCurrent: if forward: spot = spot.nextTreeSpot(True) else: spot = spot.prevTreeSpot(True) if spot is currentSpot: return False includeCurrent = False if searchText in spot.nodeRef.title().lower(): self.selectSpots([spot], True, True) return True TreeLine-3.2.1/source/treespot.py000066400000000000000000000204151506556630100167540ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treespot.py, provides a class to store locations of tree node instances # # TreeLine, an information storage program # Copyright (C) 2018, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import sys import operator class TreeSpot: """Class to store location info for tree node instances. Used to generate breadcrumb navigation and interface with tree views. A spot without a parent spot is an imaginary root spot, wihout a real node. """ def __init__(self, nodeRef, parentSpot): """Initialize a tree spot. Arguments: nodeRef -- reference to the associated tree node parentSpot -- the parent TreeSpot object """ self.nodeRef = nodeRef self.parentSpot = parentSpot def index(self, modelRef): """Returns the index of this spot in the tree model. Arguments: modelRef -- a ref to the tree model """ return modelRef.createIndex(self.row(), 0, self) def row(self): """Return the rank of this spot in its parent's child list. Should never be called from the imaginary root spot. """ try: return self.parentSpot.nodeRef.childList.index(self.nodeRef) except ValueError: return 0 # avoid error message from interim view updates def instanceNumber(self): """Return this spot's rank in the node's spot list. """ spotList = sorted(list(self.nodeRef.spotRefs), key=operator.methodcaller('sortKey')) return spotList.index(self) def spotId(self): """Return a spot ID string, in the form "nodeID:spotInstance". """ return '{0}:{1:d}'.format(self.nodeRef.uId, self.instanceNumber()) def isValid(self): """Return True if spot references and all parents are valid. """ spot = self while spot.parentSpot: if not (spot in spot.nodeRef.spotRefs and spot.nodeRef in spot.parentSpot.nodeRef.childList): return False spot = spot.parentSpot if not spot in spot.nodeRef.spotRefs: return False return True def spotDescendantGen(self): """Return a generator to step through all spots in this branch. Includes self. """ yield self for childSpot in self.childSpots(): for spot in childSpot.spotDescendantGen(): yield spot def spotDescendantOnlyGen(self): """Return a generator to step through the spots in this branch. Does not include self. """ for childSpot in self.childSpots(): yield childSpot for spot in childSpot.spotDescendantGen(): yield spot def expandedSpotDescendantGen(self, treeView): """Return a generator to step through expanded spots in this branch. Does not include root spot. Arguments: treeView -- a ref to the treeview """ for childSpot in self.childSpots(): if treeView.isSpotExpanded(childSpot): yield childSpot for spot in childSpot.expandedSpotDescendantGen(treeView): yield spot def levelSpotDescendantGen(self, treeView, includeRoot=True, maxLevel=None, openOnly=False, initLevel=0): """Return generator with (spot, level) tuples for this branch. Arguments: treeView -- a ref to the treeview, requiired to check if open includeRoot -- if True, the root spot is included maxLevel -- the max number of levels to return (no limit if none) openOnly -- if True, only include children open in the given view initLevel -- the level number to start with """ if maxLevel == None: maxLevel = sys.maxsize if includeRoot: yield (self, initLevel) initLevel += 1 if initLevel < maxLevel and (not openOnly or treeView.isSpotExpanded(self)): for childSpot in self.childSpots(): for spot, level in childSpot.levelSpotDescendantGen(treeView, True, maxLevel, openOnly, initLevel): yield (spot, level) def childSpots(self): """Return a list of immediate child spots. """ return [childNode.matchedSpot(self) for childNode in self.nodeRef.childList] def prevSiblingSpot(self): """Return the nearest previous sibling spot or None. """ if self.parentSpot: pos = self.row() if pos > 0: node = self.parentSpot.nodeRef.childList[pos - 1] return node.matchedSpot(self.parentSpot) return None def nextSiblingSpot(self): """Return the nearest next sibling spot or None. """ if self.parentSpot: childList = self.parentSpot.nodeRef.childList pos = self.row() + 1 if pos < len(childList): return childList[pos].matchedSpot(self.parentSpot) return None def prevTreeSpot(self, loop=False): """Return the previous node in the tree order. Return None at the start of the tree unless loop is true. Arguments: loop -- return the last node of the tree after the first if true """ sibling = self.prevSiblingSpot() if sibling: return sibling.lastDescendantSpot() if self.parentSpot.parentSpot: return self.parentSpot elif loop: return self.rootSpot().lastDescendantSpot() return None def nextTreeSpot(self, loop=False): """Return the next node in the tree order. Return None at the end of the tree unless loop is true. Arguments: loop -- return the root node at the end of the tree if true """ if self.nodeRef.childList: return self.nodeRef.childList[0].matchedSpot(self) ancestor = self while ancestor.parentSpot: sibling = ancestor.nextSiblingSpot() if sibling: return sibling ancestor = ancestor.parentSpot if loop: return ancestor.nodeRef.childList[0].matchedSpot(ancestor) return None def lastDescendantSpot(self): """Return the last spot of this spots's branch (last in tree order). """ spot = self while spot.nodeRef.childList: spot = spot.nodeRef.childList[-1].matchedSpot(spot) return spot def spotChain(self): """Return a list of parent spots, including self. """ chain = [] spot = self while spot.parentSpot: chain.insert(0, spot) spot = spot.parentSpot return chain def parentSpotSet(self): """Return a set of ancestor spots, not including self. """ result = set() spot = self.parentSpot while spot.parentSpot: result.add(spot) spot = spot.parentSpot return result def rootSpot(self): """Return the root spot that references the tree structure. """ spot = self while spot.parentSpot: spot = spot.parentSpot return spot def sortKey(self): """Return a tuple of parent row positions for sorting in tree order. """ positions = [] spot = self while spot.parentSpot: positions.insert(0, spot.row()) spot = spot.parentSpot return tuple(positions) TreeLine-3.2.1/source/treespotlist.py000066400000000000000000000301531506556630100176500ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treespotlist.py, provides a class to do operations on groups of spots # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import collections import operator from PyQt6.QtWidgets import QApplication import treestructure import undo class TreeSpotList(list): """Class to do operations on groups of spots. Stores a list of nodes. """ def __init__(self, spotList=None, sortSpots=True): """Initialize a tree spot group. Arguments: spotList -- the initial list of spots sortSpots -- if True sort the spots in tree order """ super().__init__() if spotList: self[:] = spotList if sortSpots: self.sort(key=operator.methodcaller('sortKey')) def relatedNodes(self): """Return a list of nodes related to these spots. Removes any duplicate (cloned) nodes. """ tmpDict = collections.OrderedDict() for spot in self: node = spot.nodeRef tmpDict[node.uId] = node return list(tmpDict.values()) def pasteChild(self, treeStruct, treeView): """Paste child nodes from the clipbaord. Return True on success. Arguments: treeStruct -- a ref to the existing tree structure treeView -- a ref to the tree view for expanding nodes """ mimeData = QApplication.clipboard().mimeData() parentNodes = self.relatedNodes() if not parentNodes: parentNodes = [treeStruct] undoObj = undo.ChildListUndo(treeStruct.undoList, parentNodes, treeFormats=treeStruct.treeFormats) for parent in parentNodes: newStruct = treestructure.structFromMimeData(mimeData) if not newStruct: treeStruct.undoList.removeLastUndo(undoObj) return False newStruct.replaceDuplicateIds(treeStruct.nodeDict) treeStruct.addNodesFromStruct(newStruct, parent) for spot in self: treeView.expandSpot(spot) return True def pasteSibling(self, treeStruct, insertBefore=True): """Paste a sibling at the these spots. Return True on success. Arguments: treeStruct -- a ref to the existing tree structure insertBefore -- if True, insert before these nodes, o/w after """ mimeData = QApplication.clipboard().mimeData() parentNodes = [spot.parentSpot.nodeRef for spot in self] undoObj = undo.ChildListUndo(treeStruct.undoList, parentNodes, treeFormats=treeStruct.treeFormats) for spot in self: newStruct = treestructure.structFromMimeData(mimeData) if not newStruct: treeStruct.undoList.removeLastUndo(undoObj) return False newStruct.replaceDuplicateIds(treeStruct.nodeDict) parent = spot.parentSpot.nodeRef pos = parent.childList.index(spot.nodeRef) if not insertBefore: pos += 1 treeStruct.addNodesFromStruct(newStruct, parent, pos) return True def pasteCloneChild(self, treeStruct, treeView): """Paste child clones from the clipbaord. Return True on success. Arguments: treeStruct -- a ref to the existing tree structure treeView -- a ref to the tree view for expanding nodes """ mimeData = QApplication.clipboard().mimeData() newStruct = treestructure.structFromMimeData(mimeData) if not newStruct: return False try: existNodes = [treeStruct.nodeDict[node.uId] for node in newStruct.childList] except KeyError: return False # nodes copied from other file parentNodes = self.relatedNodes() if not parentNodes: parentNodes = [treeStruct] for parent in parentNodes: if not parent.ancestors().isdisjoint(set(existNodes)): return False # circular ref for node in existNodes: if parent in node.parents(): return False # identical siblings undoObj = undo.ChildListUndo(treeStruct.undoList, parentNodes, treeFormats=treeStruct.treeFormats) for parent in parentNodes: for node in existNodes: parent.childList.append(node) node.addSpotRef(parent) for spot in self: treeView.expandSpot(spot) return True def pasteCloneSibling(self, treeStruct, insertBefore=True): """Paste sibling clones at the these spots. Return True on success. Arguments: treeStruct -- a ref to the existing tree structure insertBefore -- if True, insert before these nodes, o/w after """ mimeData = QApplication.clipboard().mimeData() newStruct = treestructure.structFromMimeData(mimeData) if not newStruct: return False try: existNodes = [treeStruct.nodeDict[node.uId] for node in newStruct.childList] except KeyError: return False # nodes copied from other file parentNodes = [spot.parentSpot.nodeRef for spot in self] for parent in parentNodes: if not parent.ancestors().isdisjoint(set(existNodes)): return False # circular ref for node in existNodes: if parent in node.parents(): return False # identical siblings undoObj = undo.ChildListUndo(treeStruct.undoList, parentNodes, treeFormats=treeStruct.treeFormats) for spot in self: parent = spot.parentSpot.nodeRef pos = parent.childList.index(spot.nodeRef) if not insertBefore: pos += 1 for node in existNodes: parent.childList.insert(pos, node) node.addSpotRef(parent) return True def addChild(self, treeStruct, treeView): """Add new child to these spots. Return the new spots. Arguments: treeStruct -- a ref to the existing tree structure treeView -- a ref to the tree view for expanding nodes """ selSpots = self if not selSpots: selSpots = list(treeStruct.spotRefs) undo.ChildListUndo(treeStruct.undoList, [spot.nodeRef for spot in selSpots]) newSpots = [] for spot in selSpots: newNode = spot.nodeRef.addNewChild(treeStruct) newSpots.append(newNode.matchedSpot(spot)) if spot.parentSpot: # can't expand root struct spot treeView.expandSpot(spot) return newSpots def insertSibling(self, treeStruct, insertBefore=True): """Insert a new sibling node at these nodes. Return the new spots. Arguments: treeStruct -- a ref to the existing tree structure insertBefore -- if True, insert before these nodes, o/w after """ undo.ChildListUndo(treeStruct.undoList, [spot.parentSpot.nodeRef for spot in self]) newSpots = [] for spot in self: newNode = spot.parentSpot.nodeRef.addNewChild(treeStruct, spot.nodeRef, insertBefore) newSpots.append(newNode.matchedSpot(spot.parentSpot)) return newSpots def delete(self, treeStruct): """Delete these spots, return a new spot to select. Arguments: treeStruct -- a ref to the existing tree structure """ # gather next selected node in decreasing order of desirability nextSel = [spot.nextSiblingSpot() for spot in self] nextSel.extend([spot.prevSiblingSpot() for spot in self]) nextSel.extend([spot.parentSpot for spot in self]) while (not nextSel[0] or not nextSel[0].parentSpot or nextSel[0] in self): del nextSel[0] spotSet = set(self) branchSpots = [spot for spot in self if spot.parentSpotSet().isdisjoint(spotSet)] undoParents = {spot.parentSpot.nodeRef for spot in branchSpots} undo.ChildListUndo(treeStruct.undoList, list(undoParents)) for spot in branchSpots: treeStruct.deleteNodeSpot(spot) return nextSel[0] def indent(self, treeStruct): """Indent these spots. Makes them children of their previous siblings. Return the new spots. Arguments: treeStruct -- a ref to the existing tree structure """ undoSpots = ([spot.parentSpot for spot in self] + [spot.prevSiblingSpot() for spot in self]) undo.ChildListUndo(treeStruct.undoList, [spot.nodeRef for spot in undoSpots]) newSpots = [] for spot in self: node = spot.nodeRef newParentSpot = spot.prevSiblingSpot() node.changeParent(spot.parentSpot, newParentSpot) newSpots.append(node.matchedSpot(newParentSpot)) return newSpots def unindent(self, treeStruct): """Unindent these spots. Makes them their parent's next sibling. Return the new spots. Arguments: treeStruct -- a ref to the existing tree structure """ undoSpots = [spot.parentSpot for spot in self] undoSpots.extend([spot.parentSpot for spot in undoSpots]) undo.ChildListUndo(treeStruct.undoList, [spot.nodeRef for spot in undoSpots]) newSpots = [] for spot in reversed(self): node = spot.nodeRef oldParentSpot = spot.parentSpot newParentSpot = oldParentSpot.parentSpot pos = (newParentSpot.nodeRef.childList.index(oldParentSpot.nodeRef) + 1) node.changeParent(oldParentSpot, newParentSpot, pos) newSpots.append(node.matchedSpot(newParentSpot)) return newSpots def move(self, treeStruct, up=True): """Move these spots up or down by one item. Arguments: treeStruct -- a ref to the existing tree structure up -- if True move up, o/w down """ undo.ChildListUndo(treeStruct.undoList, [spot.parentSpot.nodeRef for spot in self]) if not up: self.reverse() for spot in self: parent = spot.parentSpot.nodeRef pos = parent.childList.index(spot.nodeRef) del parent.childList[pos] pos = pos - 1 if up else pos + 1 parent.childList.insert(pos, spot.nodeRef) def moveToEnd(self, treeStruct, first=True): """Move these spots to the first or last position. Arguments: treeStruct -- a ref to the existing tree structure first -- if True move to first position, o/w last """ undo.ChildListUndo(treeStruct.undoList, [spot.parentSpot.nodeRef for spot in self]) if first: self.reverse() for spot in self: parent = spot.parentSpot.nodeRef parent.childList.remove(spot.nodeRef) if first: parent.childList.insert(0, spot.nodeRef) else: parent.childList.append(spot.nodeRef) TreeLine-3.2.1/source/treestructure.py000066400000000000000000000314751506556630100200370ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treestructure.py, provides a class to store the tree's data # # TreeLine, an information storage program # Copyright (C) 2018, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import operator import copy import json import uuid import treenode import treeformats import undo try: from __main__ import __version__ except ImportError: __version__ = '' defaultRootTitle = _('Main') class TreeStructure(treenode.TreeNode): """Class to store all tree data. Inherits TreeNode to get childList (holds top nodes) and other methods. """ def __init__(self, fileData=None, topNodes=None, addDefaults=False, addSpots=True): """Create and store a tree structure from file data. If no file data is given, create an empty or a default new structure. Arguments: fileData -- a dict in JSON file format of a structure topNodes -- existing top-level nodes to add to a structure addDefaults -- if True, adds default new structure addSpots -- if True, adds parent spot references """ super().__init__(None) # init TreeNode, with no formatRef self.nodeDict = {} self.undoList = None self.redoList = None self.configDialogFormats = None self.mathZeroBlanks = True self.childRefErrorNodes = [] if fileData: self.treeFormats = treeformats.TreeFormats(fileData['formats']) self.treeFormats.loadGlobalSavedConditions(fileData['properties']) for nodeInfo in fileData['nodes']: formatRef = self.treeFormats[nodeInfo['format']] node = treenode.TreeNode(formatRef, nodeInfo) self.nodeDict[node.uId] = node for node in self.nodeDict.values(): node.assignRefs(self.nodeDict) if node.tmpChildRefs: self.childRefErrorNodes.append(node) node.tmpChildRefs = [] for uId in fileData['properties']['topnodes']: node = self.nodeDict[uId] self.childList.append(node) if 'zeroblanks' in fileData['properties']: self.mathZeroBlanks = fileData['properties']['zeroblanks'] if addSpots: self.generateSpots(None) elif topNodes: self.childList = topNodes self.treeFormats = treeformats.TreeFormats() for topNode in topNodes: for node in topNode.descendantGen(): self.nodeDict[node.uId] = node self.treeFormats.addTypeIfMissing(node.formatRef) if addSpots: self.generateSpots(None) elif addDefaults: self.treeFormats = treeformats.TreeFormats(setDefault=True) node = treenode.TreeNode(self.treeFormats[treeformats. defaultTypeName]) node.setTitle(defaultRootTitle) self.nodeDict[node.uId] = node self.childList.append(node) if addSpots: self.generateSpots(None) else: self.treeFormats = treeformats.TreeFormats() self.fileInfoNode = treenode.TreeNode(self.treeFormats.fileInfoFormat) def fileData(self): """Return a fileData dict in JSON file format. """ formats = self.treeFormats.storeFormats() nodeList = sorted([node.fileData() for node in self.nodeDict.values()], key=operator.itemgetter('uid')) topNodeIds = [node.uId for node in self.childList] properties = {'tlversion': __version__, 'topnodes': topNodeIds} self.treeFormats.storeGlobalSavedConditions(properties) if not self.mathZeroBlanks: properties['zeroblanks'] = False fileData = {'formats': formats, 'nodes': nodeList, 'properties': properties} return fileData def purgeOldFieldData(self): """Remove data from obsolete fields from all nodes. """ fieldSets = self.treeFormats.fieldNameDict() for node in self.nodeDict.values(): oldKeys = set(node.data.keys()) - fieldSets[node.formatRef.name] for key in oldKeys: del node.data[key] def addNodeDictRef(self, node): """Add the given node to the node dictionary. Arguments: node -- the node to add """ self.nodeDict[node.uId] = node def removeNodeDictRef(self, node): """Remove the given node from the node dictionary. Arguments: node -- the node to remove """ try: del self.nodeDict[node.uId] except KeyError: pass def rebuildNodeDict(self): """Remove and re-create the entire node dictionary. """ self.nodeDict = {} for node in self.descendantGen(): self.nodeDict[node.uId] = node def replaceAllSpots(self, removeUnusedNodes=True): """Remove and regenerate all spot refs for the tree. Arguments: removeUnusedNodes -- if True, delete refs to nodes without spots """ self.spotRefs = set() for node in self.nodeDict.values(): node.spotRefs = set() self.generateSpots(None) if removeUnusedNodes: self.nodeDict = {uId:node for (uId, node) in self.nodeDict.items() if node.spotRefs} def deleteNodeSpot(self, spot): """Remove the given spot, removing the entire node if no spots remain. Arguments: spot -- the spot to remove """ spot.parentSpot.nodeRef.childList.remove(spot.nodeRef) for node in spot.nodeRef.descendantGen(): if len(node.spotRefs) <= 1: self.removeNodeDictRef(node) node.spotRefs = set() else: node.removeInvalidSpotRefs(False) def structSpot(self): """Return the top spot (not tied to a node). """ (topSpot, ) = self.spotRefs return topSpot def rootSpots(self): """Return a list of spots from root nodes. """ (topSpot, ) = self.spotRefs return topSpot.childSpots() def spotById(self, spotId): """Return a spot based on a spot ID string. Raises KeyError on invalid node ID, an IndexError on invalid spot num. Arguments: spotId -- a spot ID string, in the form "nodeID:spotInstance" """ nodeId, spotNum = spotId.split(':', 1) return self.nodeDict[nodeId].spotByNumber(int(spotNum)) def descendantGen(self): """Return a generator to step through all nodes in tree order. Override from TreeNode to exclude self. """ for child in self.childList: for node in child.descendantGen(): yield node def getConfigDialogFormats(self, forceReset=False): """Return duplicate formats for use in the config dialog. Arguments: forceReset -- if True, sets duplicate formats back to original """ if not self.configDialogFormats or forceReset: self.configDialogFormats = copy.deepcopy(self.treeFormats) return self.configDialogFormats def applyConfigDialogFormats(self, addUndo=True): """Replace the formats with the duplicates and signal for view update. Also updates all nodes for changed type and field names. """ if addUndo: undo.FormatUndo(self.undoList, self.treeFormats, self.configDialogFormats) self.treeFormats.copySettings(self.configDialogFormats) self.treeFormats.updateDerivedRefs() self.treeFormats.updateMathFieldRefs() if self.configDialogFormats.fieldRenameDict: for node in self.nodeDict.values(): fieldRenameDict = (self.configDialogFormats.fieldRenameDict. get(node.formatRef.name, {})) tmpDataDict = {} for oldName, newName in fieldRenameDict.items(): if oldName in node.data: tmpDataDict[newName] = node.data[oldName] del node.data[oldName] node.data.update(tmpDataDict) self.configDialogFormats.fieldRenameDict = {} if self.treeFormats.emptiedMathDict: for node in self.nodeDict.values(): for fieldName in self.treeFormats.emptiedMathDict.get(node. formatRef. name, set()): node.data.pop(fieldName, None) self.formats.emptiedMathDict = {} def usesType(self, typeName): """Return true if any nodes use the give node format type. Arguments: typeName -- the format name to search for """ for node in self.nodeDict.values(): if node.formatRef.name == typeName: return True return False def replaceDuplicateIds(self, duplicateDict): """Generate new unique IDs for any nodes found in newNodeDict. Arguments: newNodeDict -- a dict to search for duplicates """ for node in list(self.nodeDict.values()): if node.uId in duplicateDict: del self.nodeDict[node.uId] node.uId = uuid.uuid1().hex self.nodeDict[node.uId] = node def addNodesFromStruct(self, treeStruct, parent, position=-1): """Add nodes from the given structure under the given parent. Arguments: treeStruct -- the structure to insert parent -- the parent of the new nodes position -- the location to insert (-1 is appended) """ for nodeFormat in treeStruct.treeFormats.values(): self.treeFormats.addTypeIfMissing(nodeFormat) for node in treeStruct.nodeDict.values(): self.nodeDict[node.uId] = node node.formatRef = self.treeFormats[node.formatRef.name] for node in treeStruct.childList: if position >= 0: parent.childList.insert(position, node) position += 1 else: parent.childList.append(node) node.addSpotRef(parent) def debugCheck(self): """Run debugging checks on structure nodeDict, nodes and spots. Reports results to std output. Not to be run in production releases. """ print('\nChecking nodes in nodeDict:') nodeIds = set() errorCount = 0 for node in self.descendantGen(): nodeIds.add(node.uId) if node.uId not in self.nodeDict: print(' Node not in nodeDict, ID: {}, Title: {}'. format(node.uId, node.title())) errorCount += 1 for uId in set(self.nodeDict.keys()) - nodeIds: node = self.nodeDict[uId] print(' Node not in structure, ID: {}, Title: {}'. format(node.uId, node.title())) errorCount += 1 print(' {} errors found in nodeDict'.format(errorCount)) print('\nChecking spots:') errorCount = 0 for topNode in self.childList: for node in topNode.descendantGen(): for spot in node.spotRefs: if node not in spot.parentSpot.nodeRef.childList: print(' Invalid spot in node, ID: {}, Title: {}'. format(node.uId, node.title())) errorCount += 1 for child in node.childList: if len(child.spotRefs) < len(node.spotRefs): print(' Missing spot in node, ID: {}, Title: {}'. format(child.uId, child.title())) errorCount += 1 print(' {} errors found in spots'.format(errorCount)) #### Utility Functions #### def structFromMimeData(mimeData): """Return a tree structure based on mime data. Arguments: mimeData -- data to be used """ try: data = json.loads(str(mimeData.data('application/json'), 'utf-8')) return TreeStructure(data, addSpots=False) except (ValueError, KeyError, TypeError): return None TreeLine-3.2.1/source/treeview.py000066400000000000000000001000351506556630100167360ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treeview.py, provides a class for the indented tree view # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import unicodedata from PyQt6.QtCore import QEvent, QPoint, QPointF, Qt, pyqtSignal from PyQt6.QtGui import (QContextMenuEvent, QKeySequence, QMouseEvent, QTextDocument) from PyQt6.QtWidgets import (QAbstractItemView, QApplication, QHeaderView, QLabel, QListWidget, QListWidgetItem, QMenu, QStyledItemDelegate, QTreeView) import treeselection import treenode import miscdialogs import globalref class TreeView(QTreeView): """Class override for the indented tree view. Sets view defaults and links with document for content. """ skippedMouseSelect = pyqtSignal(treenode.TreeNode) shortcutEntered = pyqtSignal(QKeySequence) def __init__(self, model, allActions, parent=None): """Initialize the tree view. Arguments: model -- the initial model for view data allActions -- a dictionary of control actions for popup menus parent -- the parent main window """ super().__init__(parent) self.resetModel(model) self.allActions = allActions self.incremSearchMode = False self.incremSearchString = '' self.noMouseSelectMode = False self.mouseFocusNoEditMode = False self.prevSelSpot = None # temp, to check for edit at mouse release self.setSelectionMode(QAbstractItemView.SelectionMode. ExtendedSelection) self.header().setSectionResizeMode(0, QHeaderView.ResizeMode. ResizeToContents) self.header().setStretchLastSection(False) self.setHeaderHidden(True) self.setItemDelegate(TreeEditDelegate(self)) # use mouse event for editing to avoid with multiple select self.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.updateTreeGenOptions() self.setDragDropMode(QAbstractItemView.DragDropMode.DragDrop) self.setDefaultDropAction(Qt.DropAction.MoveAction) self.setDropIndicatorShown(True) self.setUniformRowHeights(True) def resetModel(self, model): """Change the model assigned to this view. Also assigns a new selection model. Arguments: model -- the new model to assign """ self.setModel(model) self.setSelectionModel(treeselection.TreeSelection(model, self)) def updateTreeGenOptions(self): """Set the tree to match the current general options. """ dragAvail = globalref.genOptions['DragTree'] self.setDragEnabled(dragAvail) self.setAcceptDrops(dragAvail) self.setIndentation(globalref.genOptions['IndentOffset'] * self.fontInfo().pixelSize()) def isSpotExpanded(self, spot): """Return True if the given spot is expanded (showing children). Arguments: spot -- the spot to check """ return self.isExpanded(spot.index(self.model())) def expandSpot(self, spot): """Expand a spot in this view. Arguments: spot -- the spot to expand """ self.expand(spot.index(self.model())) def collapseSpot(self, spot): """Collapse a spot in this view. Arguments: spot -- the spot to collapse """ self.collapse(spot.index(self.model())) def expandBranch(self, parentSpot): """Expand all spots in the given branch. Collapses parentSpot first to avoid extreme slowness. Arguments: parentSpot -- the top spot in the branch """ self.collapse(parentSpot.index(self.model())) for spot in parentSpot.spotDescendantOnlyGen(): if spot.nodeRef.childList: self.expand(spot.index(self.model())) self.expand(parentSpot.index(self.model())) def collapseBranch(self, parentSpot): """Collapse all spots in the given branch. Arguments: parentSpot -- the top spot in the branch """ for spot in parentSpot.spotDescendantGen(): if spot.nodeRef.childList: self.collapse(spot.index(self.model())) def savedExpandState(self, spots): """Return a list of tuples of spots and expanded state (True/False). Arguments: spots -- an iterable of spots to save """ return [(spot, self.isSpotExpanded(spot)) for spot in spots] def restoreExpandState(self, expandState): """Expand or collapse based on saved tuples. Arguments: expandState -- a list of tuples of spots and expanded state """ for spot, expanded in expandState: try: if expanded: self.expandSpot(spot) else: self.collapseSpot(spot) except ValueError: pass def spotAtTop(self): """If view is scrolled, return the spot at the top of the view. If not scrolled, return None. """ if self.verticalScrollBar().value() > 0: return self.indexAt(QPoint(0, 0)).internalPointer() return None def scrollToSpot(self, spot): """Scroll the view to move the spot to the top position. Arguments: spot -- the spot to move to the top """ self.scrollTo(spot.index(self.model()), QAbstractItemView.ScrollHint.PositionAtTop) def scrollTo(self, index, hint=QAbstractItemView.ScrollHint.EnsureVisible): """Scroll the view to make node at index visible. Overriden to stop autoScroll from horizontally jumping when selecting nodes. Arguments: index -- the node to be made visible hint -- where the visible item should be """ horizPos = self.horizontalScrollBar().value() super().scrollTo(index, hint) self.horizontalScrollBar().setValue(horizPos) def endEditing(self): """Stop the editing of any item being renamed. """ delegate = self.itemDelegate() if delegate.editor: delegate.commitData.emit(delegate.editor) self.closePersistentEditor(self.selectionModel().currentIndex()) def incremSearchStart(self): """Start an incremental title search. """ self.incremSearchMode = True self.incremSearchString = '' globalref.mainControl.currentStatusBar().showMessage(_('Search for:')) def incremSearchRun(self): """Perform an incremental title search. """ msg = _('Search for: {0}').format(self.incremSearchString) globalref.mainControl.currentStatusBar().showMessage(msg) if (self.incremSearchString and not self.selectionModel().selectTitleMatch(self.incremSearchString, True, True)): msg = _('Search for: {0} (not found)').format(self. incremSearchString) globalref.mainControl.currentStatusBar().showMessage(msg) def incremSearchNext(self): """Go to the next match in an incremental title search. """ if self.incremSearchString: if self.selectionModel().selectTitleMatch(self.incremSearchString): msg = _('Next: {0}').format(self.incremSearchString) else: msg = _('Next: {0} (not found)').format(self. incremSearchString) globalref.mainControl.currentStatusBar().showMessage(msg) def incremSearchPrev(self): """Go to the previous match in an incremental title search. """ if self.incremSearchString: if self.selectionModel().selectTitleMatch(self.incremSearchString, False): msg = _('Next: {0}').format(self.incremSearchString) else: msg = _('Next: {0} (not found)').format(self. incremSearchString) globalref.mainControl.currentStatusBar().showMessage(msg) def incremSearchStop(self): """End an incremental title search. """ self.incremSearchMode = False self.incremSearchString = '' globalref.mainControl.currentStatusBar().clearMessage() def showTypeMenu(self, menu): """Show a popup menu for setting the item type. """ index = self.selectionModel().currentIndex() self.scrollTo(index) rect = self.visualRect(index) pt = self.mapToGlobal(QPoint(rect.center().x(), rect.bottom())) menu.popup(pt) def contextMenu(self): """Return the context menu, creating it if necessary. """ menu = QMenu(self) menu.addAction(self.allActions['EditCut']) menu.addAction(self.allActions['EditCopy']) menu.addAction(self.allActions['EditPaste']) menu.addAction(self.allActions['NodeRename']) menu.addSeparator() menu.addAction(self.allActions['NodeInsertBefore']) menu.addAction(self.allActions['NodeInsertAfter']) menu.addAction(self.allActions['NodeAddChild']) menu.addSeparator() menu.addAction(self.allActions['NodeDelete']) menu.addAction(self.allActions['NodeIndent']) menu.addAction(self.allActions['NodeUnindent']) menu.addSeparator() menu.addAction(self.allActions['NodeMoveUp']) menu.addAction(self.allActions['NodeMoveDown']) menu.addSeparator() menu.addMenu(self.allActions['DataNodeType'].parent()) menu.addSeparator() menu.addAction(self.allActions['ViewExpandBranch']) menu.addAction(self.allActions['ViewCollapseBranch']) return menu def contextMenuEvent(self, event): """Show popup context menu on mouse click or menu key. Arguments: event -- the context menu event """ if event.reason() == QContextMenuEvent.Reason.Mouse: clickedSpot = self.indexAt(event.pos()).internalPointer() if not clickedSpot: event.ignore() return if clickedSpot not in self.selectionModel().selectedSpots(): self.selectionModel().selectSpots([clickedSpot]) pos = event.globalPos() else: # shown for menu key or other reason selectList = self.selectionModel().selectedSpots() if not selectList: event.ignore() return currentSpot = self.selectionModel().currentSpot() if currentSpot in selectList: selectList.insert(0, currentSpot) position = None for spot in selectList: rect = self.visualRect(spot.index(self.model())) pt = QPoint(rect.center().x(), rect.bottom()) if self.rect().contains(pt): position = pt break if not position: self.scrollTo(selectList[0].index(self.model())) rect = self.visualRect(selectList[0].index(self.model())) position = QPoint(rect.center().x(), rect.bottom()) pos = self.mapToGlobal(position) self.contextMenu().popup(pos) event.accept() def dropEvent(self, event): """Event handler for view drop actions. Selects parent node at destination. Arguments: event -- the drop event """ clickedSpot = self.indexAt(event.position().toPoint()).internalPointer() # clear selection to avoid invalid multiple selection bug self.selectionModel().selectSpots([], False) if clickedSpot: super().dropEvent(event) self.selectionModel().selectSpots([clickedSpot], False) self.scheduleDelayedItemsLayout() # reqd before expand self.expandSpot(clickedSpot) else: super().dropEvent(event) self.selectionModel().selectSpots([]) self.scheduleDelayedItemsLayout() if event.isAccepted(): self.model().treeModified.emit(True, True) def toggleNoMouseSelectMode(self, active=True): """Set noMouseSelectMode to active or inactive. noMouseSelectMode will not change selection on mouse click, it will just signal the clicked node for use in links, etc. Arguments: active -- if True, activate noMouseSelectMode """ self.noMouseSelectMode = active def clearHover(self): """Post a mouse move event to clear the mouse hover indication. Needed to avoid crash when deleting nodes with hovered child nodes. """ event = QMouseEvent(QEvent.Type.MouseMove, QPointF(0.0, self.viewport().width()), Qt.MouseButton.NoButton, Qt.MouseButton.NoButton, Qt.KeyboardModifier.NoModifier) QApplication.postEvent(self.viewport(), event) QApplication.processEvents() def mousePressEvent(self, event): """Skip unselecting click if in noMouseSelectMode. If in noMouseSelectMode, signal which node is under the mouse. Arguments: event -- the mouse click event """ if self.incremSearchMode: self.incremSearchStop() self.prevSelSpot = None clickedIndex = self.indexAt(event.position().toPoint()) clickedSpot = clickedIndex.internalPointer() selectModel = self.selectionModel() if self.noMouseSelectMode: if clickedSpot and event.button() == Qt.MouseButton.LeftButton: self.skippedMouseSelect.emit(clickedSpot.nodeRef) event.ignore() return if (event.button() == Qt.MouseButton.LeftButton and not self.mouseFocusNoEditMode and selectModel.selectedCount() == 1 and selectModel.currentSpot() == selectModel.selectedSpots()[0] and event.position().x() > self.visualRect(clickedIndex).left() and globalref.genOptions['ClickRename']): # set for edit if single select and not an expand/collapse click self.prevSelSpot = selectModel.selectedSpots()[0] self.mouseFocusNoEditMode = False super().mousePressEvent(event) def mouseReleaseEvent(self, event): """Initiate editing if clicking on a single selected node. Arguments: event -- the mouse click event """ clickedIndex = self.indexAt(event.position().toPoint()) clickedSpot = clickedIndex.internalPointer() if (event.button() == Qt.MouseButton.LeftButton and self.prevSelSpot and clickedSpot == self.prevSelSpot): self.edit(clickedIndex) event.ignore() return self.prevSelSpot = None super().mouseReleaseEvent(event) def keyPressEvent(self, event): """Record characters if in incremental search mode. Arguments: event -- the key event """ if self.incremSearchMode: if event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter, Qt.Key.Key_Escape): self.incremSearchStop() elif event.key() == Qt.Key.Key_Backspace and self.incremSearchString: self.incremSearchString = self.incremSearchString[:-1] self.incremSearchRun() elif event.text() and unicodedata.category(event.text()) != 'Cc': # unicode category excludes control characters self.incremSearchString += event.text() self.incremSearchRun() event.accept() elif (event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter) and not self.itemDelegate().editor): # enter key selects current item if not selected selectModel = self.selectionModel() if selectModel.currentSpot() not in selectModel.selectedSpots(): selectModel.selectSpots([selectModel.currentSpot()]) event.accept() else: super().keyPressEvent(event) else: super().keyPressEvent(event) def focusInEvent(self, event): """Avoid editing a tree item with a get-focus click. Arguments: event -- the focus in event """ if event.reason() == Qt.FocusReason.MouseFocusReason: self.mouseFocusNoEditMode = True super().focusInEvent(event) def focusOutEvent(self, event): """Stop incremental search on focus loss. Arguments: event -- the focus out event """ if self.incremSearchMode: self.incremSearchStop() super().focusOutEvent(event) class TreeEditDelegate(QStyledItemDelegate): """Class override for editing tree items to capture shortcut keys. """ def __init__(self, parent=None): """Initialize the delegate class. Arguments: parent -- the parent view """ super().__init__(parent) self.editor = None def createEditor(self, parent, styleOption, modelIndex): """Return a new text editor for an item. Arguments: parent -- the parent widget for the editor styleOption -- the data for styles and geometry modelIndex -- the index of the item to be edited """ self.editor = super().createEditor(parent, styleOption, modelIndex) return self.editor def destroyEditor(self, editor, index): """Reset editor storage after editing ends. Arguments: editor -- the editor that is ending index -- the index of the edited item """ self.editor = None super().destroyEditor(editor, index) def eventFilter(self, editor, event): """Override to handle shortcut control keys. Arguments: editor -- the editor that Qt installed a filter on event -- the key press event """ if (event.type() == QEvent.Type.KeyPress and event.modifiers() == Qt.KeyboardModifier.ControlModifier and Qt.Key.Key_A <= event.key() <= Qt.Key.Key_Z): key = QKeySequence(event.keyCombination()) self.parent().shortcutEntered.emit(key) return True return super().eventFilter(editor, event) class TreeFilterViewItem(QListWidgetItem): """Item container for the flat list of filtered nodes. """ def __init__(self, spot, viewParent=None): """Initialize the list view item. Arguments: spot -- the spot to reference for content viewParent -- the parent list view """ super().__init__(viewParent) self.spot = spot self.setFlags(Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsEnabled) self.update() def update(self): """Update title and icon from the stored node. """ node = self.spot.nodeRef self.setText(node.title()) if globalref.genOptions['ShowTreeIcons']: icon = globalref.treeIcons.getIcon(node.formatRef.iconName, True) if icon: self.setIcon(icon) class TreeFilterView(QListWidget): """View to show flat list of filtered nodes. """ skippedMouseSelect = pyqtSignal(treenode.TreeNode) shortcutEntered = pyqtSignal(QKeySequence) def __init__(self, treeViewRef, allActions, parent=None): """Initialize the list view. Arguments: treeViewRef -- a ref to the tree view for data allActions -- a dictionary of control actions for popup menus parent -- the parent main window """ super().__init__(parent) self.structure = treeViewRef.model().treeStructure self.selectionModel = treeViewRef.selectionModel() self.treeModel = treeViewRef.model() self.allActions = allActions self.menu = None self.noMouseSelectMode = False self.mouseFocusNoEditMode = False self.prevSelSpot = None # temp, to check for edit at mouse release self.drivingSelectionChange = False self.conditionalFilter = None self.messageLabel = None self.filterWhat = miscdialogs.FindScope.fullData self.filterHow = miscdialogs.FindType.keyWords self.filterStr = '' self.setSelectionMode(QAbstractItemView.SelectionMode. ExtendedSelection) self.setItemDelegate(TreeEditDelegate(self)) # use mouse event for editing to avoid with multiple select self.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.itemSelectionChanged.connect(self.updateSelectionModel) self.itemChanged.connect(self.changeTitle) treeFont = QTextDocument().defaultFont() treeFontName = globalref.miscOptions['TreeFont'] if treeFontName: treeFont.fromString(treeFontName) self.setFont(treeFont) def updateItem(self, node): """Update the item corresponding to the given node. Arguments: node -- the node to be updated """ for row in range(self.count()): if self.item(row).spot.nodeRef == node: self.blockSignals(True) self.item(row).update() self.blockSignals(False) return def updateContents(self): """Update filtered contents from current structure and filter criteria. """ if self.conditionalFilter: self.conditionalUpdate() return QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) if self.filterHow == miscdialogs.FindType.regExp: criteria = [re.compile(self.filterStr)] useRegExpFilter = True elif self.filterHow == miscdialogs.FindType.fullWords: criteria = [] for word in self.filterStr.lower().split(): criteria.append(re.compile(r'(?i)\b{}\b'. format(re.escape(word)))) useRegExpFilter = True elif self.filterHow == miscdialogs.FindType.keyWords: criteria = self.filterStr.lower().split() useRegExpFilter = False else: # full phrase criteria = [self.filterStr.lower().strip()] useRegExpFilter = False titlesOnly = self.filterWhat == miscdialogs.FindScope.titlesOnly self.blockSignals(True) self.clear() if useRegExpFilter: for rootSpot in self.structure.rootSpots(): for spot in rootSpot.spotDescendantGen(): if spot.nodeRef.regExpSearch(criteria, titlesOnly): item = TreeFilterViewItem(spot, self) else: for rootSpot in self.structure.rootSpots(): for spot in rootSpot.spotDescendantGen(): if spot.nodeRef.wordSearch(criteria, titlesOnly): item = TreeFilterViewItem(spot, self) self.blockSignals(False) self.selectItems(self.selectionModel.selectedSpots(), True) if self.count() and not self.selectedItems(): self.item(0).setSelected(True) if not self.messageLabel: self.messageLabel = QLabel() globalref.mainControl.currentStatusBar().addWidget(self. messageLabel) message = _('Filtering by "{0}", found {1} nodes').format(self. filterStr, self.count()) self.messageLabel.setText(message) QApplication.restoreOverrideCursor() def conditionalUpdate(self): """Update filtered contents from structure and conditional criteria. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) self.blockSignals(True) self.clear() for rootSpot in self.structure.rootSpots(): for spot in rootSpot.spotDescendantGen(): if self.conditionalFilter.evaluate(spot.nodeRef): item = TreeFilterViewItem(spot, self) self.blockSignals(False) self.selectItems(self.selectionModel.selectedSpots(), True) if self.count() and not self.selectedItems(): self.item(0).setSelected(True) if not self.messageLabel: self.messageLabel = QLabel() globalref.mainControl.currentStatusBar().addWidget(self. messageLabel) message = _('Conditional filtering, found {0} nodes').format(self. count()) self.messageLabel.setText(message) QApplication.restoreOverrideCursor() def selectItems(self, spots, signalModel=False): """Select items matching given nodes if in filtered view. Arguments: spots -- the spot list to select signalModel -- signal to update the tree selection model if True """ selectSpots = set(spots) if not signalModel: self.blockSignals(True) for item in self.selectedItems(): item.setSelected(False) for row in range(self.count()): if self.item(row).spot in selectSpots: self.item(row).setSelected(True) self.setCurrentItem(self.item(row)) self.blockSignals(False) def updateFromSelectionModel(self): """Select items selected in the tree selection model. Called from a signal that the tree selection model is changing. """ if self.count() and not self.drivingSelectionChange: self.selectItems(self.selectionModel.selectedSpots()) def updateSelectionModel(self): """Change the selection model based on a filter list selection signal. """ self.drivingSelectionChange = True self.selectionModel.selectSpots([item.spot for item in self.selectedItems()]) self.drivingSelectionChange = False def changeTitle(self, item): """Update the node title in the model based on an edit signal. Reset to the node text if invalid. Arguments: item -- the filter view item that changed """ if not self.treeModel.setData(item.spot.index(self.treeModel), item.text()): self.blockSignals(True) item.setText(item.node.title()) self.blockSignals(False) def nextPrevSpot(self, spot, forward=True): """Return the next or previous spot in this filter list view. Wraps around ends. Return None if view doesn't have spot. Arguments: spot -- the starting spot forward -- next if True, previous if False """ for row in range(self.count()): if self.item(row).spot == spot: if forward: row += 1 if row >= self.count(): row = 0 else: row -= 1 if row < 0: row = self.count() - 1 return self.item(row).spot return None def contextMenu(self): """Return the context menu, creating it if necessary. """ if not self.menu: self.menu = QMenu(self) self.menu.addAction(self.allActions['EditCut']) self.menu.addAction(self.allActions['EditCopy']) self.menu.addAction(self.allActions['NodeRename']) self.menu.addSeparator() self.menu.addAction(self.allActions['NodeDelete']) self.menu.addSeparator() self.menu.addMenu(self.allActions['DataNodeType'].parent()) return self.menu def contextMenuEvent(self, event): """Show popup context menu on mouse click or menu key. Arguments: event -- the context menu event """ if event.reason() == QContextMenuEvent.Reason.Mouse: clickedItem = self.itemAt(event.pos()) if not clickedItem: event.ignore() return if clickedItem.spot not in self.selectionModel.selectedSpots(): self.selectionModel.selectSpots([clickedItem.spot]) pos = event.globalPos() else: # shown for menu key or other reason selectList = self.selectedItems() if not selectList: event.ignore() return currentItem = self.currentItem() if currentItem in selectList: selectList.insert(0, currentItem) posList = [] for item in selectList: rect = self.visualItemRect(item) pt = QPoint(rect.center().x(), rect.bottom()) if self.rect().contains(pt): posList.append(pt) if not posList: self.scrollTo(self.indexFromItem(selectList[0])) rect = self.visualItemRect(selectList[0]) posList = [QPoint(rect.center().x(), rect.bottom())] pos = self.mapToGlobal(posList[0]) self.contextMenu().popup(pos) event.accept() def toggleNoMouseSelectMode(self, active=True): """Set noMouseSelectMode to active or inactive. noMouseSelectMode will not change selection on mouse click, it will just signal the clicked node for use in links, etc. Arguments: active -- if True, activate noMouseSelectMode """ self.noMouseSelectMode = active def mousePressEvent(self, event): """Skip unselecting click on blank spaces. Arguments: event -- the mouse click event """ self.prevSelSpot = None clickedItem = self.itemAt(event.position().toPoint()) if not clickedItem: event.ignore() return if self.noMouseSelectMode: if event.button() == Qt.MouseButton.LeftButton: self.skippedMouseSelect.emit(clickedItem.spot.nodeRef) event.ignore() return if (event.button() == Qt.MouseButton.LeftButton and not self.mouseFocusNoEditMode and self.selectionModel.selectedCount() == 1 and globalref.genOptions['ClickRename']): self.prevSelSpot = self.selectionModel.selectedSpots()[0] self.mouseFocusNoEditMode = False super().mousePressEvent(event) def mouseReleaseEvent(self, event): """Initiate editing if clicking on a single selected node. Arguments: event -- the mouse click event """ clickedItem = self.itemAt(event.position().toPoint()) if (event.button() == Qt.MouseButton.LeftButton and clickedItem and self.prevSelSpot and clickedItem.spot == self.prevSelSpot): self.editItem(clickedItem) event.ignore() return self.prevSelSpot = None super().mouseReleaseEvent(event) def focusInEvent(self, event): """Avoid editing a tree item with a get-focus click. Arguments: event -- the focus in event """ if event.reason() == Qt.FocusReason.MouseFocusReason: self.mouseFocusNoEditMode = True super().focusInEvent(event) TreeLine-3.2.1/source/treewindow.py000066400000000000000000001213521506556630100173000ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # treewindow.py, provides a class for the main window and controls # # TreeLine, an information storage program # Copyright (C) 2025, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import pathlib import base64 from PyQt6.QtCore import QEvent, QRect, QSize, Qt, pyqtSignal from PyQt6.QtGui import QAction, QActionGroup, QGuiApplication, QTextDocument from PyQt6.QtWidgets import (QApplication, QMainWindow, QSplitter, QStackedWidget, QStatusBar, QTabWidget) import treeview import breadcrumbview import outputview import dataeditview import titlelistview import treenode import globalref class TreeWindow(QMainWindow): """Class override for the main window. Contains main window views and controls. """ selectChanged = pyqtSignal() nodeModified = pyqtSignal(treenode.TreeNode) treeModified = pyqtSignal() winActivated = pyqtSignal(QMainWindow) winMinimized = pyqtSignal() winClosing = pyqtSignal(QMainWindow) def __init__(self, model, allActions, parent=None): """Initialize the main window. Arguments: model -- the initial data model allActions -- a dict containing the upper level actions parent -- the parent window, usually None """ super().__init__(parent) self.allActions = allActions.copy() self.allowCloseFlag = True self.winActions = {} self.toolbars = [] self.rightTabActList = [] self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose) self.setAcceptDrops(True) self.setStatusBar(QStatusBar()) self.setCaption() self.setupActions() self.setupMenus() self.setupToolbars() self.restoreToolbarPosition() self.treeView = treeview.TreeView(model, self.allActions) self.breadcrumbSplitter = QSplitter(Qt.Orientation.Vertical) self.setCentralWidget(self.breadcrumbSplitter) self.breadcrumbView = breadcrumbview.BreadcrumbView(self.treeView) self.breadcrumbSplitter.addWidget(self.breadcrumbView) self.breadcrumbView.setVisible(globalref. genOptions['InitShowBreadcrumb']) self.treeSplitter = QSplitter() self.breadcrumbSplitter.addWidget(self.treeSplitter) self.treeStack = QStackedWidget() self.treeSplitter.addWidget(self.treeStack) self.treeStack.addWidget(self.treeView) self.treeView.shortcutEntered.connect(self.execShortcut) self.treeView.selectionModel().selectionChanged.connect(self. updateRightViews) self.treeFilterView = None self.rightTabs = QTabWidget() self.treeSplitter.addWidget(self.rightTabs) self.rightTabs.setTabPosition(QTabWidget.TabPosition.South) self.rightTabs.tabBar().setFocusPolicy(Qt.FocusPolicy.NoFocus) self.outputSplitter = QSplitter(Qt.Orientation.Vertical) self.rightTabs.addTab(self.outputSplitter, _('Data Output')) parentOutputView = outputview.OutputView(self.treeView, False) parentOutputView.highlighted.connect(self.setStatusFromUrl) self.outputSplitter.addWidget(parentOutputView) childOutputView = outputview.OutputView(self.treeView, True) childOutputView.highlighted.connect(self.setStatusFromUrl) self.outputSplitter.addWidget(childOutputView) self.editorSplitter = QSplitter(Qt.Orientation.Vertical) self.rightTabs.addTab(self.editorSplitter, _('Data Edit')) parentEditView = dataeditview.DataEditView(self.treeView, self.allActions, False) parentEditView.shortcutEntered.connect(self.execShortcut) parentEditView.focusOtherView.connect(self.focusNextView) parentEditView.inLinkSelectMode.connect(self.treeView. toggleNoMouseSelectMode) self.treeView.skippedMouseSelect.connect(parentEditView. internalLinkSelected) self.editorSplitter.addWidget(parentEditView) childEditView = dataeditview.DataEditView(self.treeView, self.allActions, True) childEditView.shortcutEntered.connect(self.execShortcut) childEditView.focusOtherView.connect(self.focusNextView) childEditView.inLinkSelectMode.connect(self.treeView. toggleNoMouseSelectMode) self.treeView.skippedMouseSelect.connect(childEditView. internalLinkSelected) parentEditView.hoverFocusActive.connect(childEditView.endEditor) childEditView.hoverFocusActive.connect(parentEditView.endEditor) parentEditView.inLinkSelectMode.connect(childEditView. updateInLinkSelectMode) childEditView.inLinkSelectMode.connect(parentEditView. updateInLinkSelectMode) self.editorSplitter.addWidget(childEditView) self.titleSplitter = QSplitter(Qt.Orientation.Vertical) self.rightTabs.addTab(self.titleSplitter, _('Title List')) parentTitleView = titlelistview.TitleListView(self.treeView, False) parentTitleView.shortcutEntered.connect(self.execShortcut) self.titleSplitter.addWidget(parentTitleView) childTitleView = titlelistview.TitleListView(self.treeView, True) childTitleView.shortcutEntered.connect(self.execShortcut) self.titleSplitter.addWidget(childTitleView) self.rightTabs.currentChanged.connect(self.updateRightViews) self.updateFonts() def setExternalSignals(self): """Connect widow object signals to signals in this object. In a separate method to refresh after local control change. """ self.treeView.selectionModel().selectionChanged.connect(self. selectChanged) for i in range(2): self.editorSplitter.widget(i).nodeModified.connect(self. nodeModified) self.titleSplitter.widget(i).nodeModified.connect(self. nodeModified) self.titleSplitter.widget(i).treeModified.connect(self. treeModified) def updateActions(self, allActions): """Use new actions for menus, etc. when the local control changes. Arguments: allActions -- a dict containing the upper level actions """ # remove submenu actions that are children of the window self.removeAction(self.allActions['DataNodeType']) self.removeAction(self.allActions['FormatFontSize']) self.allActions = allActions.copy() self.allActions.update(self.winActions) self.menuBar().clear() self.setupMenus() self.addToolbarCommands() self.treeView.allActions = self.allActions for i in range(2): self.editorSplitter.widget(i).allActions = self.allActions def updateTreeNode(self, node): """Update all spots for the given node in the tree view. Arguments: node -- the node to be updated """ for spot in node.spotRefs: self.treeView.update(spot.index(self.treeView.model())) self.treeView.resizeColumnToContents(0) self.breadcrumbView.updateContents() def updateTree(self): """Update the full tree view. """ self.treeView.scheduleDelayedItemsLayout() self.breadcrumbView.updateContents() def updateRightViews(self, *args, outputOnly=False): """Update all right-hand views and breadcrumb view. Arguments: *args -- dummy arguments to collect args from signals outputOnly -- only update output views (not edit views) """ if globalref.mainControl.activeControl: self.rightTabActList[self.rightTabs. currentIndex()].setChecked(True) self.breadcrumbView.updateContents() splitter = self.rightTabs.currentWidget() if not outputOnly or isinstance(splitter.widget(0), outputview.OutputView): for i in range(2): splitter.widget(i).updateContents() def refreshDataEditViews(self): """Refresh the data in non-selected cells in curreent data edit views. """ splitter = self.rightTabs.currentWidget() if isinstance(splitter.widget(0), dataeditview.DataEditView): for i in range(2): splitter.widget(i).updateUnselectedCells() def updateCommandsAvail(self): """Set window commands available based on node selections. """ self.allActions['ViewPrevSelect'].setEnabled(len(self.treeView. selectionModel(). prevSpots) > 1) self.allActions['ViewNextSelect'].setEnabled(len(self.treeView. selectionModel(). nextSpots) > 0) def updateWinGenOptions(self): """Update tree and data edit windows based on general option changes. """ self.treeView.updateTreeGenOptions() for i in range(2): self.editorSplitter.widget(i).setMouseTracking(globalref. genOptions['EditorOnHover']) def updateFonts(self): """Update custom fonts in views. """ treeFont = QTextDocument().defaultFont() treeFontName = globalref.miscOptions['TreeFont'] if treeFontName: treeFont.fromString(treeFontName) self.treeView.setFont(treeFont) self.treeView.updateTreeGenOptions() if self.treeFilterView: self.treeFilterView.setFont(treeFont) ouputFont = QTextDocument().defaultFont() ouputFontName = globalref.miscOptions['OutputFont'] if ouputFontName: ouputFont.fromString(ouputFontName) editorFont = QTextDocument().defaultFont() editorFontName = globalref.miscOptions['EditorFont'] if editorFontName: editorFont.fromString(editorFontName) for i in range(2): self.outputSplitter.widget(i).setFont(ouputFont) self.editorSplitter.widget(i).setFont(editorFont) self.titleSplitter.widget(i).setFont(editorFont) def resetTreeModel(self, model): """Change the model assigned to the tree view. Arguments: model -- the new model to assign """ self.treeView.resetModel(model) self.treeView.selectionModel().selectionChanged.connect(self. updateRightViews) def activateAndRaise(self): """Activate this window and raise it to the front. """ self.activateWindow() self.raise_() def setCaption(self, pathObj=None, modified=False): """Change the window caption title based on the file name and path. Arguments: pathObj - a path object for the current file """ modFlag = '*' if modified else '' if pathObj: caption = '{0}{1} [{2}] - TreeLine'.format(str(pathObj.name), modFlag, str(pathObj.parent)) else: caption = '- TreeLine' self.setWindowTitle(caption) def setStatusFromUrl(self, url): """Set the status bar message to the text from a hovered-over URL. Arguments: url - the QUrl to show """ self.statusBar().showMessage(url.toString()) def filterView(self): """Create, show and return a filter view. """ self.removeFilterView() self.treeFilterView = treeview.TreeFilterView(self.treeView, self.allActions) self.treeFilterView.shortcutEntered.connect(self.execShortcut) self.treeView.selectionModel().selectionChanged.connect(self. treeFilterView. updateFromSelectionModel) for i in range(2): editView = self.editorSplitter.widget(i) editView.inLinkSelectMode.connect(self.treeFilterView. toggleNoMouseSelectMode) self.treeFilterView.skippedMouseSelect.connect(editView. internalLinkSelected) self.treeStack.addWidget(self.treeFilterView) self.treeStack.setCurrentWidget(self.treeFilterView) return self.treeFilterView def removeFilterView(self): """Hide and delete the current filter view. """ if self.treeFilterView != None: # check for None since False if empty self.treeStack.removeWidget(self.treeFilterView) globalref.mainControl.currentStatusBar().removeWidget(self. treeFilterView. messageLabel) self.treeFilterView.messageLabel.deleteLater() self.treeFilterView = None def rightParentView(self): """Return the current right-hand parent view if visible (or None). """ view = self.rightTabs.currentWidget().widget(0) if not view.isVisible() or view.height() == 0 or view.width() == 0: return None return view def rightChildView(self): """Return the current right-hand parent view if visible (or None). """ view = self.rightTabs.currentWidget().widget(1) if not view.isVisible() or view.height() == 0 or view.width() == 0: return None return view def focusNextView(self, forward=True): """Focus the next pane in the tab focus series. Called by a signal from the data edit views. Tab sequences tend to skip views without this. Arguments: forward -- forward in tab series if True """ reason = (Qt.FocusReason.TabFocusReason if forward else Qt.FocusReason.BacktabFocusReason) rightParent = self.rightParentView() rightChild = self.rightChildView() if (self.sender().isChildView == forward or (forward and rightChild == None) or (not forward and rightParent == None)): self.treeView.setFocus(reason) elif forward: rightChild.setFocus(reason) else: rightParent.setFocus(reason) def execShortcut(self, key): """Execute an action based on a shortcut key signal from a view. Arguments: key -- the QKeySequence shortcut """ keyDict = {action.shortcut().toString(): action for action in self.allActions.values()} try: action = keyDict[key.toString()] except KeyError: return if action.isEnabled(): action.trigger() def setupActions(self): """Add the actions for contols at the window level. These actions only affect an individual window, they're independent in multiple windows of the same file. """ viewExpandBranchAct = QAction(_('&Expand Full Branch'), self, statusTip=_('Expand all children of the selected nodes')) viewExpandBranchAct.triggered.connect(self.viewExpandBranch) self.winActions['ViewExpandBranch'] = viewExpandBranchAct viewCollapseBranchAct = QAction(_('&Collapse Full Branch'), self, statusTip=_('Collapse all children of the selected nodes')) viewCollapseBranchAct.triggered.connect(self.viewCollapseBranch) self.winActions['ViewCollapseBranch'] = viewCollapseBranchAct viewPrevSelectAct = QAction(_('&Previous Selection'), self, statusTip=_('Return to the previous tree selection')) viewPrevSelectAct.triggered.connect(self.viewPrevSelect) self.winActions['ViewPrevSelect'] = viewPrevSelectAct viewNextSelectAct = QAction(_('&Next Selection'), self, statusTip=_('Go to the next tree selection in history')) viewNextSelectAct.triggered.connect(self.viewNextSelect) self.winActions['ViewNextSelect'] = viewNextSelectAct viewRightTabGrp = QActionGroup(self) viewOutputAct = QAction(_('Show Data &Output'), viewRightTabGrp, statusTip=_('Show data output in right view'), checkable=True) self.winActions['ViewDataOutput'] = viewOutputAct viewEditAct = QAction(_('Show Data &Editor'), viewRightTabGrp, statusTip=_('Show data editor in right view'), checkable=True) self.winActions['ViewDataEditor'] = viewEditAct viewTitleAct = QAction(_('Show &Title List'), viewRightTabGrp, statusTip=_('Show title list in right view'), checkable=True) self.winActions['ViewTitleList'] = viewTitleAct self.rightTabActList = [viewOutputAct, viewEditAct, viewTitleAct] viewRightTabGrp.triggered.connect(self.viewRightTab) viewBreadcrumbAct = QAction(_('Show &Breadcrumb View'), self, statusTip=_('Toggle showing breadcrumb ancestor view'), checkable=True) viewBreadcrumbAct.setChecked(globalref. genOptions['InitShowBreadcrumb']) viewBreadcrumbAct.triggered.connect(self.viewBreadcrumb) self.winActions['ViewBreadcrumb'] = viewBreadcrumbAct viewChildPaneAct = QAction(_('&Show Child Pane'), self, statusTip=_('Toggle showing right-hand child views'), checkable=True) viewChildPaneAct.setChecked(globalref.genOptions['InitShowChildPane']) viewChildPaneAct.triggered.connect(self.viewShowChildPane) self.winActions['ViewShowChildPane'] = viewChildPaneAct viewDescendAct = QAction(_('Show Output &Descendants'), self, statusTip=_('Toggle showing output view indented descendants'), checkable=True) viewDescendAct.setChecked(globalref.genOptions['InitShowDescendants']) viewDescendAct.triggered.connect(self.viewDescendants) self.winActions['ViewShowDescend'] = viewDescendAct winCloseAct = QAction(_('&Close Window'), self, statusTip=_('Close this window')) winCloseAct.triggered.connect(self.close) self.winActions['WinCloseWindow'] = winCloseAct incremSearchStartAct = QAction(_('Start Incremental Search'), self) incremSearchStartAct.triggered.connect(self.incremSearchStart) self.addAction(incremSearchStartAct) self.winActions['IncremSearchStart'] = incremSearchStartAct incremSearchNextAct = QAction(_('Next Incremental Search'), self) incremSearchNextAct.triggered.connect(self.incremSearchNext) self.addAction(incremSearchNextAct) self.winActions['IncremSearchNext'] = incremSearchNextAct incremSearchPrevAct = QAction(_('Previous Incremental Search'), self) incremSearchPrevAct.triggered.connect(self.incremSearchPrev) self.addAction(incremSearchPrevAct) self.winActions['IncremSearchPrev'] = incremSearchPrevAct for name, action in self.winActions.items(): icon = globalref.toolIcons.getIcon(name.lower()) if icon: action.setIcon(icon) key = globalref.keyboardOptions[name] if not key.isEmpty(): action.setShortcut(key) self.allActions.update(self.winActions) def setupToolbars(self): """Add toolbars based on option settings. """ for toolbar in self.toolbars: self.removeToolBar(toolbar) self.toolbars = [] numToolbars = globalref.toolbarOptions['ToolbarQuantity'] iconSize = globalref.toolbarOptions['ToolbarSize'] for num in range(numToolbars): name = 'Toolbar{:d}'.format(num) toolbar = self.addToolBar(name) toolbar.setObjectName(name) toolbar.setIconSize(QSize(iconSize, iconSize)) self.toolbars.append(toolbar) self.addToolbarCommands() def addToolbarCommands(self): """Add toolbar commands for current actions. """ for toolbar, commandList in zip(self.toolbars, globalref. toolbarOptions['ToolbarCommands']): toolbar.clear() for command in commandList.split(','): if command: try: toolbar.addAction(self.allActions[command]) except KeyError: pass else: toolbar.addSeparator() def setupMenus(self): """Add menu items for actions. """ self.fileMenu = self.menuBar().addMenu(_('&File')) self.fileMenu.aboutToShow.connect(self.loadRecentMenu) self.fileMenu.addAction(self.allActions['FileNew']) self.fileMenu.addAction(self.allActions['FileOpen']) self.fileMenu.addAction(self.allActions['FileOpenSample']) self.fileMenu.addAction(self.allActions['FileImport']) self.fileMenu.addSeparator() self.fileMenu.addAction(self.allActions['FileSave']) self.fileMenu.addAction(self.allActions['FileSaveAs']) self.fileMenu.addAction(self.allActions['FileExport']) self.fileMenu.addAction(self.allActions['FileProperties']) self.fileMenu.addSeparator() self.fileMenu.addAction(self.allActions['FilePrintSetup']) self.fileMenu.addAction(self.allActions['FilePrintPreview']) self.fileMenu.addAction(self.allActions['FilePrint']) self.fileMenu.addAction(self.allActions['FilePrintPdf']) self.fileMenu.addSeparator() self.recentFileSep = self.fileMenu.addSeparator() self.fileMenu.addAction(self.allActions['FileQuit']) editMenu = self.menuBar().addMenu(_('&Edit')) editMenu.addAction(self.allActions['EditUndo']) editMenu.addAction(self.allActions['EditRedo']) editMenu.addSeparator() editMenu.addAction(self.allActions['EditCut']) editMenu.addAction(self.allActions['EditCopy']) editMenu.addSeparator() editMenu.addAction(self.allActions['EditPaste']) editMenu.addAction(self.allActions['EditPastePlain']) editMenu.addSeparator() editMenu.addAction(self.allActions['EditPasteChild']) editMenu.addAction(self.allActions['EditPasteBefore']) editMenu.addAction(self.allActions['EditPasteAfter']) editMenu.addSeparator() editMenu.addAction(self.allActions['EditPasteCloneChild']) editMenu.addAction(self.allActions['EditPasteCloneBefore']) editMenu.addAction(self.allActions['EditPasteCloneAfter']) nodeMenu = self.menuBar().addMenu(_('&Node')) nodeMenu.addAction(self.allActions['NodeRename']) nodeMenu.addSeparator() nodeMenu.addAction(self.allActions['NodeAddChild']) nodeMenu.addAction(self.allActions['NodeInsertBefore']) nodeMenu.addAction(self.allActions['NodeInsertAfter']) nodeMenu.addSeparator() nodeMenu.addAction(self.allActions['NodeDelete']) nodeMenu.addAction(self.allActions['NodeIndent']) nodeMenu.addAction(self.allActions['NodeUnindent']) nodeMenu.addSeparator() nodeMenu.addAction(self.allActions['NodeMoveUp']) nodeMenu.addAction(self.allActions['NodeMoveDown']) nodeMenu.addAction(self.allActions['NodeMoveFirst']) nodeMenu.addAction(self.allActions['NodeMoveLast']) dataMenu = self.menuBar().addMenu(_('&Data')) # add action's parent to get the sub-menu dataMenu.addMenu(self.allActions['DataNodeType'].parent()) # add the action to activate the shortcut key self.addAction(self.allActions['DataNodeType']) dataMenu.addAction(self.allActions['DataConfigType']) dataMenu.addAction(self.allActions['DataCopyType']) dataMenu.addAction(self.allActions['DataVisualConfig']) dataMenu.addSeparator() dataMenu.addAction(self.allActions['DataSortNodes']) dataMenu.addAction(self.allActions['DataNumbering']) dataMenu.addAction(self.allActions['DataRegenRefs']) dataMenu.addSeparator() dataMenu.addAction(self.allActions['DataCloneMatches']) dataMenu.addAction(self.allActions['DataDetachClones']) dataMenu.addSeparator() dataMenu.addAction(self.allActions['DataFlatCategory']) dataMenu.addAction(self.allActions['DataAddCategory']) dataMenu.addAction(self.allActions['DataSwapCategory']) toolsMenu = self.menuBar().addMenu(_('&Tools')) toolsMenu.addAction(self.allActions['ToolsFindText']) toolsMenu.addAction(self.allActions['ToolsFindCondition']) toolsMenu.addAction(self.allActions['ToolsFindReplace']) toolsMenu.addSeparator() toolsMenu.addAction(self.allActions['ToolsFilterText']) toolsMenu.addAction(self.allActions['ToolsFilterCondition']) toolsMenu.addSeparator() toolsMenu.addAction(self.allActions['ToolsSpellCheck']) toolsMenu.addSeparator() toolsMenu.addAction(self.allActions['ToolsGenOptions']) toolsMenu.addSeparator() toolsMenu.addAction(self.allActions['ToolsShortcuts']) toolsMenu.addAction(self.allActions['ToolsToolbars']) toolsMenu.addAction(self.allActions['ToolsFonts']) toolsMenu.addAction(self.allActions['ToolsColors']) formatMenu = self.menuBar().addMenu(_('Fo&rmat')) formatMenu.addAction(self.allActions['FormatBoldFont']) formatMenu.addAction(self.allActions['FormatItalicFont']) formatMenu.addAction(self.allActions['FormatUnderlineFont']) formatMenu.addAction(self.allActions['FormatStrikethroughFont']) formatMenu.addSeparator() # add action's parent to get the sub-menu formatMenu.addMenu(self.allActions['FormatFontSize'].parent()) # add the action to activate the shortcut key self.addAction(self.allActions['FormatFontSize']) formatMenu.addAction(self.allActions['FormatFontColor']) formatMenu.addSeparator() formatMenu.addAction(self.allActions['FormatExtLink']) formatMenu.addAction(self.allActions['FormatIntLink']) formatMenu.addAction(self.allActions['FormatInsertDate']) formatMenu.addSeparator() formatMenu.addAction(self.allActions['FormatSelectAll']) formatMenu.addAction(self.allActions['FormatClearFormat']) viewMenu = self.menuBar().addMenu(_('&View')) viewMenu.addAction(self.allActions['ViewExpandBranch']) viewMenu.addAction(self.allActions['ViewCollapseBranch']) viewMenu.addSeparator() viewMenu.addAction(self.allActions['ViewPrevSelect']) viewMenu.addAction(self.allActions['ViewNextSelect']) viewMenu.addSeparator() viewMenu.addAction(self.allActions['ViewDataOutput']) viewMenu.addAction(self.allActions['ViewDataEditor']) viewMenu.addAction(self.allActions['ViewTitleList']) viewMenu.addSeparator() viewMenu.addAction(self.allActions['ViewBreadcrumb']) viewMenu.addAction(self.allActions['ViewShowChildPane']) viewMenu.addAction(self.allActions['ViewShowDescend']) self.windowMenu = self.menuBar().addMenu(_('&Window')) self.windowMenu.aboutToShow.connect(self.loadWindowMenu) self.windowMenu.addAction(self.allActions['WinNewWindow']) self.windowMenu.addAction(self.allActions['WinCloseWindow']) self.windowMenu.addSeparator() helpMenu = self.menuBar().addMenu(_('&Help')) helpMenu.addAction(self.allActions['HelpBasic']) helpMenu.addAction(self.allActions['HelpFull']) helpMenu.addSeparator() helpMenu.addAction(self.allActions['HelpAbout']) def viewExpandBranch(self): """Expand all children of the selected spots. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) selectedSpots = self.treeView.selectionModel().selectedSpots() if not selectedSpots: selectedSpots = self.treeView.model().treeStructure.rootSpots() for spot in selectedSpots: self.treeView.expandBranch(spot) QApplication.restoreOverrideCursor() def viewCollapseBranch(self): """Collapse all children of the selected spots. """ QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor) selectedSpots = self.treeView.selectionModel().selectedSpots() if not selectedSpots: selectedSpots = self.treeView.model().treeStructure.rootSpots() for spot in selectedSpots: self.treeView.collapseBranch(spot) QApplication.restoreOverrideCursor() def viewPrevSelect(self): """Return to the previous tree selection. """ self.treeView.selectionModel().restorePrevSelect() def viewNextSelect(self): """Go to the next tree selection in history. """ self.treeView.selectionModel().restoreNextSelect() def viewRightTab(self, action): """Show the tab in the right-hand view given by action. Arguments: action -- the action triggered in the action group """ if action == self.allActions['ViewDataOutput']: self.rightTabs.setCurrentWidget(self.outputSplitter) elif action == self.allActions['ViewDataEditor']: self.rightTabs.setCurrentWidget(self.editorSplitter) else: self.rightTabs.setCurrentWidget(self.titleSplitter) def viewBreadcrumb(self, checked): """Enable or disable the display of the breadcrumb view. Arguments: checked -- True if to be shown, False if to be hidden """ self.breadcrumbView.setVisible(checked) if checked: self.updateRightViews() def viewShowChildPane(self, checked): """Enable or disable the display of children in a split pane. Arguments: checked -- True if to be shown, False if to be hidden """ for tabNum in range(3): for splitNum in range(2): view = self.rightTabs.widget(tabNum).widget(splitNum) view.hideChildView = not checked self.updateRightViews() def viewDescendants(self, checked): """Set the output view to show indented descendants if checked. Arguments: checked -- True if to be shown, False if to be hidden """ self.outputSplitter.widget(1).showDescendants = checked self.updateRightViews() def incremSearchStart(self): """Start an incremental title search. """ if not self.treeFilterView: self.treeView.setFocus() self.treeView.incremSearchStart() def incremSearchNext(self): """Go to the next match in an incremental title search. """ if not self.treeFilterView: self.treeView.incremSearchNext() def incremSearchPrev(self): """Go to the previous match in an incremental title search. """ if not self.treeFilterView: self.treeView.incremSearchPrev() def loadRecentMenu(self): """Load recent file items to file menu before showing. """ for action in self.fileMenu.actions(): text = action.text() if len(text) > 1 and text[0] == '&' and '0' <= text[1] <= '9': self.fileMenu.removeAction(action) self.fileMenu.insertActions(self.recentFileSep, globalref.mainControl.recentFiles. getActions()) def loadWindowMenu(self): """Load window list items to window menu before showing. """ for action in self.windowMenu.actions(): text = action.text() if len(text) > 1 and text[0] == '&' and '0' <= text[1] <= '9': self.windowMenu.removeAction(action) self.windowMenu.addActions(globalref.mainControl.windowActions()) def saveWindowGeom(self): """Save window geometry parameters to history options. """ contentsRect = self.geometry() frameRect = self.frameGeometry() globalref.histOptions.changeValue('WindowXSize', contentsRect.width()) globalref.histOptions.changeValue('WindowYSize', contentsRect.height()) globalref.histOptions.changeValue('WindowXPos', contentsRect.x()) globalref.histOptions.changeValue('WindowYPos', contentsRect.y()) globalref.histOptions.changeValue('WindowTopMargin', contentsRect.y() - frameRect.y()) globalref.histOptions.changeValue('WindowOtherMargin', contentsRect.x() - frameRect.x()) try: upperWidth, lowerWidth = self.breadcrumbSplitter.sizes() crumbPercent = int(100 * upperWidth / (upperWidth + lowerWidth)) globalref.histOptions.changeValue('CrumbSplitPercent', crumbPercent) leftWidth, rightWidth = self.treeSplitter.sizes() treePercent = int(100 * leftWidth / (leftWidth + rightWidth)) globalref.histOptions.changeValue('TreeSplitPercent', treePercent) upperWidth, lowerWidth = self.outputSplitter.sizes() outputPercent = int(100 * upperWidth / (upperWidth + lowerWidth)) globalref.histOptions.changeValue('OutputSplitPercent', outputPercent) upperWidth, lowerWidth = self.editorSplitter.sizes() editorPercent = int(100 * upperWidth / (upperWidth + lowerWidth)) globalref.histOptions.changeValue('EditorSplitPercent', editorPercent) upperWidth, lowerWidth = self.titleSplitter.sizes() titlePercent = int(100 * upperWidth / (upperWidth + lowerWidth)) globalref.histOptions.changeValue('TitleSplitPercent', titlePercent) except ZeroDivisionError: pass # skip if splitter sizes were never set tabNum = self.rightTabs.currentIndex() globalref.histOptions.changeValue('ActiveRightView', tabNum) def restoreWindowGeom(self, offset=0): """Restore window geometry from history options. Arguments: offset -- number of pixels to offset window, down and to right """ rect = QRect(globalref.histOptions['WindowXPos'], globalref.histOptions['WindowYPos'], globalref.histOptions['WindowXSize'], globalref.histOptions['WindowYSize']) if rect.x() == -1000 and rect.y() == -1000: # let OS position window the first time self.resize(rect.size()) else: if offset: rect.adjust(offset, offset, offset, offset) availRect = QApplication.primaryScreen().availableVirtualGeometry() topMargin = globalref.histOptions['WindowTopMargin'] otherMargin = globalref.histOptions['WindowOtherMargin'] # remove frame space from available rect availRect.adjust(otherMargin, topMargin, -otherMargin, -otherMargin) finalRect = rect.intersected(availRect) if finalRect.isEmpty(): rect.moveTo(0, 0) finalRect = rect.intersected(availRect) if finalRect.isValid(): self.setGeometry(finalRect) crumbWidth = int(self.breadcrumbSplitter.width() / 100 * globalref.histOptions['CrumbSplitPercent']) self.breadcrumbSplitter.setSizes([crumbWidth, self.breadcrumbSplitter.width() - crumbWidth]) treeWidth = int(self.treeSplitter.width() / 100 * globalref.histOptions['TreeSplitPercent']) self.treeSplitter.setSizes([treeWidth, self.treeSplitter.width() - treeWidth]) outHeight = int(self.outputSplitter.height() / 100.0 * globalref.histOptions['OutputSplitPercent']) self.outputSplitter.setSizes([outHeight, self.outputSplitter.height() - outHeight]) editHeight = int(self.editorSplitter.height() / 100.0 * globalref.histOptions['EditorSplitPercent']) self.editorSplitter.setSizes([editHeight, self.editorSplitter.height() - editHeight]) titleHeight = int(self.titleSplitter.height() / 100.0 * globalref.histOptions['TitleSplitPercent']) self.titleSplitter.setSizes([titleHeight, self.titleSplitter.height() - titleHeight]) self.rightTabs.setCurrentIndex(globalref. histOptions['ActiveRightView']) def resetWindowGeom(self): """Set all stored window geometry values back to default settings. """ globalref.histOptions.resetToDefaults(['WindowXPos', 'WindowYPos', 'WindowXSize', 'WindowYSize', 'CrumbSplitPercent', 'TreeSplitPercent', 'OutputSplitPercent', 'EditorSplitPercent', 'TitleSplitPercent', 'ActiveRightView']) def saveToolbarPosition(self): """Save the toolbar position to the toolbar options. """ toolbarPos = base64.b64encode(self.saveState().data()).decode('ascii') globalref.toolbarOptions.changeValue('ToolbarPosition', toolbarPos) globalref.toolbarOptions.writeFile() def restoreToolbarPosition(self): """Restore the toolbar position from the toolbar options. """ toolbarPos = globalref.toolbarOptions['ToolbarPosition'] if toolbarPos: self.restoreState(base64.b64decode(bytes(toolbarPos, 'ascii'))) def dragEnterEvent(self, event): """Accept drags of files to this window. Arguments: event -- the drag event object """ if event.mimeData().hasUrls(): event.accept() def dropEvent(self, event): """Open a file dropped onto this window. Arguments: event -- the drop event object """ fileList = event.mimeData().urls() if fileList: path = pathlib.Path(fileList[0].toLocalFile()) globalref.mainControl.openFile(path, checkModified=True) def changeEvent(self, event): """Detect an activation of the main window and emit a signal. Arguments: event -- the change event object """ super().changeEvent(event) if (event.type() == QEvent.Type.ActivationChange and QApplication.activeWindow() == self): self.winActivated.emit(self) elif (event.type() == QEvent.Type.WindowStateChange and globalref.genOptions['MinToSysTray'] and self.isMinimized()): self.winMinimized.emit() def closeEvent(self, event): """Signal that the view is closing and close if the flag allows it. Also save window status if necessary. Arguments: event -- the close event object """ self.winClosing.emit(self) if self.allowCloseFlag: event.accept() else: event.ignore() TreeLine-3.2.1/source/undo.py000066400000000000000000000426301506556630100160570ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # undo.py, provides a classes to store and execute undo & redo operations # # TreeLine, an information storage program # Copyright (C) 2018, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import copy import treenode import globalref class UndoRedoList(list): """Stores undo or redo objects. """ def __init__(self, action, localControlRef): """Initialize the undo or redo storage. Set the number of stored levels based on the user option. Arguments: action -- the Qt action for undo/redo menus localControlRef -- ref control class for selections, modified, etc. """ super().__init__() self.action = action self.action.setEnabled(False) self.localControlRef = localControlRef self.levels = globalref.genOptions['UndoLevels'] self.altListRef = None # holds a ref to redo or undo list def addUndoObj(self, undoObject, clearRedo=True): """Add the given undo or redo object to the list. Arguments: undoObject -- the object to be added clearRedo -- if true, clear redo list (can't redo after changes) """ self.append(undoObject) del self[:-self.levels] if self.levels == 0: del self[:] self.action.setEnabled(len(self) > 0) if clearRedo and self.altListRef: self.altListRef.clearList() def clearList(self): """Empty the undo/redo list, primarily for no redo after a change. """ del self[:] self.action.setEnabled(False) def setNumLevels(self): """Change number of stored undo levels to the stored option. """ self.levels = globalref.genOptions['UndoLevels'] del self[:-self.levels] if self.levels == 0: del self[:] self.action.setEnabled(len(self) > 0) def removeLastUndo(self, undoObject): """Remove the last undo object if it matches the given object. Arguments: undoObject -- the object to be removed """ if self[-1] is undoObject: del self[-1] self.action.setEnabled(len(self) > 0) def undo(self): """Save current state to altListRef and restore the last saved state. Remove the last undo item from the list. Restore the previous selection and saved doc modified state. """ # # clear selection to avoid crash due to invalid selection: # self.localControlRef.currentSelectionModel().selectSpots([], False) item = self.pop() item.undo(self.altListRef) selectSpots = [node.spotByNumber(num) for (node, num) in item.selectedTuples] self.localControlRef.currentSelectionModel().selectSpots(selectSpots, False) self.localControlRef.setModified(item.modified) self.action.setEnabled(len(self) > 0) class UndoBase: """Abstract base class for undo objects. """ def __init__(self, localControlRef): """Initialize data storage, selected nodes and doc modified status. Arguments: localControlRef -- ref control class for selections, modified, etc. """ self.dataList = [] self.treeStructRef = localControlRef.structure self.selectedTuples = [(spot.nodeRef, spot.instanceNumber()) for spot in localControlRef.currentSelectionModel(). selectedSpots()] self.modified = localControlRef.modified class DataUndo(UndoBase): """Info for undo/redo of tree node data changes. """ def __init__(self, listRef, nodes, addChildren=False, addBranch=False, skipSame=False, fieldRef='', notRedo=True): """Create the data undo class and add it to the undoStore. Can't use skipSame if addChildren or addBranch are True. Arguments: listRef -- a ref to the undo/redo list this gets added to nodes -- a node or a list of nodes to back up addChildren -- if True, include child nodes addBranch -- if True, include all branch nodes (ignores addChildren skipSame -- if true, don't add an undo that is similar to the last fieldRef -- optional field name ref to check for similar changes notRedo -- if True, clear redo list (after changes) """ super().__init__(listRef.localControlRef) if not isinstance(nodes, list): nodes = [nodes] if (skipSame and listRef and isinstance(listRef[-1], DataUndo) and len(listRef[-1].dataList) == 1 and len(nodes) == 1 and nodes[0] == listRef[-1].dataList[0][0] and fieldRef == listRef[-1].dataList[0][2]): return for node in nodes: if addBranch: for child in node.descendantGen(): self.dataList.append((child, child.data.copy(), '')) else: self.dataList.append((node, node.data.copy(), fieldRef)) if addChildren: for child in node.childList: self.dataList.append((child, child.data.copy(), '')) listRef.addUndoObj(self, notRedo) def undo(self, redoRef): """Save current state to redoRef and restore saved state. Arguments: redoRef -- the redo list where the current state is saved """ if redoRef != None: DataUndo(redoRef, [data[0] for data in self.dataList], False, False, False, '', False) for node, data, fieldRef in self.dataList: node.data = data class ChildListUndo(UndoBase): """Info for undo/redo of tree node child lists. """ def __init__(self, listRef, nodes, addBranch=False, treeFormats=None, skipSame=False, notRedo=True): """Create the child list undo class and add it to the undoStore. Also stores data formats if given. Can't use skipSame if addBranch is True. Arguments: listRef -- a ref to the undo/redo list this gets added to nodes -- a parent node or a list of parents to save children addBranch -- if True, include all branch nodes treeFormats -- the format data to store skipSame -- if true, don't add an undo that is similar to the last notRedo -- if True, clear redo list (after changes) """ super().__init__(listRef.localControlRef) if not isinstance(nodes, list): nodes = [nodes] if (skipSame and listRef and isinstance(listRef[-1], ChildListUndo) and len(listRef[-1].dataList) == 1 and len(nodes) == 1 and nodes[0] == listRef[-1].dataList[0][0]): return self.addBranch = addBranch self.treeFormats = None if treeFormats: self.treeFormats = copy.deepcopy(treeFormats) for node in nodes: if addBranch: for child in node.descendantGen(): self.dataList.append((child, child.childList[:])) else: self.dataList.append((node, node.childList[:])) listRef.addUndoObj(self, notRedo) def undo(self, redoRef): """Save current state to redoRef and restore saved state. Arguments: redoRef -- the redo list where the current state is saved """ if redoRef != None: formats = None if self.treeFormats: formats = self.treeStructRef.treeFormats ChildListUndo(redoRef, [data[0] for data in self.dataList], False, formats, False, False) if self.treeFormats: self.treeStructRef.configDialogFormats = self.treeFormats self.treeStructRef.applyConfigDialogFormats(False) globalref.mainControl.updateConfigDialog() newNodes = set() oldNodes = set() for node, childList in self.dataList: origChildren = set(node.childList) children = set(childList) newNodes = newNodes | (children - origChildren) oldNodes = oldNodes | (origChildren - children) for node, childList in self.dataList: node.childList = childList self.treeStructRef.rebuildNodeDict() # slow but reliable for oldNode in oldNodes: oldNode.removeInvalidSpotRefs() for node, childList in self.dataList: for child in childList: if child in newNodes: child.addSpotRef(node) class ChildDataUndo(UndoBase): """Info for undo/redo of tree node child data and lists. """ def __init__(self, listRef, nodes, addBranch=False, treeFormats=None, notRedo=True): """Create the child data undo class and add it to the undoStore. Arguments: listRef -- a ref to the undo/redo list this gets added to nodes -- a parent node or a list of parents to save children addBranch -- if True, include all branch nodes treeFormats -- the format data to store notRedo -- if True, clear redo list (after changes) """ super().__init__(listRef.localControlRef) if not isinstance(nodes, list): nodes = [nodes] self.addBranch = addBranch self.treeFormats = None if treeFormats: self.treeFormats = copy.deepcopy(treeFormats) for parent in nodes: if addBranch: for node in parent.descendantGen(): self.dataList.append((node, node.data.copy(), node.childList[:])) else: self.dataList.append((parent, parent.data.copy(), parent.childList[:])) for node in parent.childList: self.dataList.append((node, node.data.copy(), node.childList[:])) listRef.addUndoObj(self, notRedo) def undo(self, redoRef): """Save current state to redoRef and restore saved state. Arguments: redoRef -- the redo list where the current state is saved """ if redoRef != None: formats = None if self.treeFormats: formats = self.treeStructRef.treeFormats ChildDataUndo(redoRef, [data[0] for data in self.dataList], False, formats, False) if self.treeFormats: self.treeStructRef.configDialogFormats = self.treeFormats self.treeStructRef.applyConfigDialogFormats(False) globalref.mainControl.updateConfigDialog() newNodes = set() oldNodes = set() for node, data, childList in self.dataList: origChildren = set(node.childList) children = set(childList) newNodes = newNodes | (children - origChildren) oldNodes = oldNodes | (origChildren - children) for node, data, childList in self.dataList: node.childList = childList node.data = data self.treeStructRef.rebuildNodeDict() # slow but reliable for newNode in newNodes.copy(): for child in newNode.descendantGen(): newNodes.add(child) for oldNode in oldNodes: oldNode.removeInvalidSpotRefs() for node, data, childList in self.dataList: for child in childList: if child in newNodes: child.addSpotRef(node, not self.addBranch) class TypeUndo(UndoBase): """Info for undo/redo of tree node type name changes. Also saves node data to cover blank node title replacement and initial data settings. """ def __init__(self, listRef, nodes, notRedo=True): """Create the data undo class and add it to the undoStore. Arguments: listRef -- a ref to the undo/redo list this gets added to nodes -- a node or a list of nodes to back up notRedo -- if True, add clones and clear redo list (after changes) """ super().__init__(listRef.localControlRef) if not isinstance(nodes, list): nodes = [nodes] for node in nodes: self.dataList.append((node, node.formatRef.name, node.data.copy())) listRef.addUndoObj(self, notRedo) def undo(self, redoRef): """Save current state to redoRef and restore saved state. Arguments: redoRef -- the redo list where the current state is saved """ if redoRef != None: TypeUndo(redoRef, [data[0] for data in self.dataList], False) for node, formatName, data in self.dataList: node.formatRef = self.treeStructRef.treeFormats[formatName] node.data = data class FormatUndo(UndoBase): """Info for undo/redo of tree node type format changes. """ def __init__(self, listRef, origTreeFormats, newTreeFormats, notRedo=True): """Create the data undo class and add it to the undoStore. Arguments: listRef -- a ref to the undo/redo list this gets added to origTreeFormats -- the format data to store newTreeFormats -- the replacement format, contains rename dicts notRedo -- if True, clear redo list (after changes) """ super().__init__(listRef.localControlRef) self.treeFormats = copy.deepcopy(origTreeFormats) self.treeFormats.fieldRenameDict = {} for typeName, fieldDict in newTreeFormats.fieldRenameDict.items(): self.treeFormats.fieldRenameDict[typeName] = {} for oldName, newName in fieldDict.items(): self.treeFormats.fieldRenameDict[typeName][newName] = oldName self.treeFormats.typeRenameDict = {} for oldName, newName in newTreeFormats.typeRenameDict.items(): self.treeFormats.typeRenameDict[newName] = oldName if newName in self.treeFormats.fieldRenameDict: self.treeFormats.fieldRenameDict[oldName] = (self.treeFormats. fieldRenameDict[newName]) del self.treeFormats.fieldRenameDict[newName] listRef.addUndoObj(self, notRedo) def undo(self, redoRef): """Save current state to redoRef and restore saved state. Arguments: redoRef -- the redo list where the current state is saved """ if redoRef != None: FormatUndo(redoRef, self.treeStructRef.treeFormats, self.treeFormats, False) self.treeStructRef.configDialogFormats = self.treeFormats self.treeStructRef.applyConfigDialogFormats(False) globalref.mainControl.updateConfigDialog() class ParamUndo(UndoBase): """Info for undo/redo of any variable parameter. """ def __init__(self, listRef, varList, notRedo=True): """Create the data undo class and add it to the undoStore. Arguments: listRef -- a ref to the undo/redo list this gets added to varList - list of tuples, variable's owner and variable's name notRedo -- if True, clear redo list (after changes) """ super().__init__(listRef.localControlRef) for varOwner, varName in varList: value = varOwner.__dict__[varName] self.dataList.append((varOwner, varName, value)) listRef.addUndoObj(self, notRedo) def undo(self, redoRef): """Save current state to redoRef and restore saved state. Arguments: redoRef -- the redo list where the current state is saved """ if redoRef != None: ParamUndo(redoRef, [item[:2] for item in self.dataList], False) for varOwner, varName, value in self.dataList: varOwner.__dict__[varName] = value class StateSettingUndo(UndoBase): """Info for undo/redo of objects with get/set functions for attributes. """ def __init__(self, listRef, getFunction, setFunction, notRedo=True): """Create the data undo class and add it to the undoStore. Arguments: listRef -- a ref to the undo/redo list this gets added to getFunction -- a function ref that returns a state variable setFunction -- a function ref that restores from the state varible notRedo -- if True, clear redo list (after changes) """ super().__init__(listRef.localControlRef) self.getFunction = getFunction self.setFunction = setFunction self.data = getFunction() listRef.addUndoObj(self, notRedo) def undo(self, redoRef): """Save current state to redoRef and restore saved state. Arguments: redoRef -- the redo list where the current state is saved """ if redoRef != None: StateSettingUndo(redoRef, self.getFunction, self.setFunction, False) self.setFunction(self.data) TreeLine-3.2.1/source/urltools.py000066400000000000000000000112411506556630100167670ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # urltools.py, provides functions for parsing and modifying URLs. # # TreeLine, an information storage program # Copyright (C) 2018, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import re import sys import os.path _urlRegExp = re.compile(r'([a-z]{2,}://)?(?:/?([a-z]:))?(.*)', re.IGNORECASE) def splitUrl(url): """Return a tuple of scheme, drive letter and address. If any are not present, return empty strings. Arguments: url -- a string with the original URL """ if os.sep == '\\': url = url.replace('\\', '/') scheme, drive, address = _urlRegExp.match(url).groups('') scheme = scheme[:-3] if not scheme and url.startswith('mailto:'): scheme = 'mailto' drive = '' address = url[7:] return (scheme, drive, address) def extractScheme(url): """Return the scheme from this URL, or an empty string if none is given. Arguments: url -- a string with the original URL """ scheme, drive, address = splitUrl(url) return scheme def extractAddress(url): """Remove the scheme from this URL and return the address. Includes the drive letter if present. Arguments: url -- a string with the original URL """ scheme, drive, address = splitUrl(url) return drive + address def replaceScheme(scheme, url): """Replace any scheme in url with the given scheme and return. The scheme is not included with a relative file path. Arguments: scheme -- the new scheme to add url -- the address be modified """ oldScheme, drive, address = splitUrl(url) if drive: drive = '/' + drive elif scheme == 'file' and not address.startswith('/'): return address elif scheme == 'mailto': return '{0}:{1}'.format(scheme, address) return '{0}://{1}{2}'.format(scheme, drive, address) def shortName(url): """Return a default short name using the base portion of the URL filename. Arguments: url -- a string with the original URL """ scheme, drive, address = splitUrl(url) name = os.path.basename(address) if not name: # remove trailing separator if there is no basename name = os.path.basename(address[:-1]) if scheme == 'mailto' or '@' in name: name = name.split('@', 1)[0] return name def isRelative(url): """Return true if this URL is a relative path. Any scheme or drive letter is considered absolute and returns false. Arguments: url -- a string with the original URL """ scheme, drive, address = splitUrl(url) if scheme or drive or address.startswith('/'): return False return True def toAbsolute(url, refPath, addScheme=True): """Convert a relative file URL to an absolute URL and return it. Arguments: url -- a string with the original URL refPath -- the path that the URL is relative to addScheme -- add the 'file' scheme to result if true """ scheme, drive, address = splitUrl(url) url = os.path.normpath(os.path.join(refPath, drive + address)) if addScheme: return replaceScheme('file', url) if os.sep == '\\': url = url.replace('\\', '/') return url def toRelative(url, refPath): """Convert an absolute file URL to a relative URL and return it. Arguments: url -- a string with the original URL refPath -- the path that the URL is relative to """ scheme, drive, address = splitUrl(url) if drive or address.startswith('/'): try: url = os.path.relpath(drive + address, refPath) except ValueError: pass if os.sep == '\\': url = url.replace('\\', '/') return url def which(fileName): """Return the full path if the fileName is found somewhere in the PATH. If not found, return an empty string. Similar to the Linux which command. Arguments: fileName -- the name to search for """ extList = [''] if sys.platform.startswith('win'): extList.extend(os.getenv('PATHEXT', '').split(os.pathsep)) for path in os.get_exec_path(): for ext in extList: fullPath = os.path.join(path, fileName + ext) if os.access(fullPath, os.X_OK): return fullPath return '' TreeLine-3.2.1/templates/000077500000000000000000000000001506556630100152315ustar00rootroot00000000000000TreeLine-3.2.1/templates/110en_Long_Text.trln000066400000000000000000000021041506556630100207360ustar00rootroot00000000000000{ "formats": [ { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Text", "fieldtype": "Text", "lines": 8 } ], "formatname": "LONG_TEXT", "outputlines": [ "{*Name*}", "{*Text*}" ], "titleline": "{*Name*}" } ], "nodes": [ { "children": [ "d8ef9244959111e7a8357054d2175f18" ], "data": { "Name": "Parent", "Text": "Parent text" }, "format": "LONG_TEXT", "uid": "d8ef8eb6959111e7a8357054d2175f18" }, { "children": [], "data": { "Name": "Child", "Text": "Child text" }, "format": "LONG_TEXT", "uid": "d8ef9244959111e7a8357054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "d8ef8eb6959111e7a8357054d2175f18" ] } }TreeLine-3.2.1/templates/210en_Contact_List.trln000066400000000000000000000073601506556630100214330ustar00rootroot00000000000000{ "formats": [ { "childtype": "PERSON", "fields": [ { "fieldname": "Type", "fieldtype": "Text" } ], "formatname": "CATEGORY", "outputlines": [ "{*Type*}" ], "titleline": "{*Type*}" }, { "fields": [ { "fieldname": "FirstName", "fieldtype": "Text", "sortkeynum": 2 }, { "fieldname": "LastName", "fieldtype": "Text", "sortkeynum": 1 }, { "fieldname": "Street", "fieldtype": "Text" }, { "fieldname": "City", "fieldtype": "Text" }, { "fieldname": "State", "fieldtype": "Text" }, { "fieldname": "Zip", "fieldtype": "Text" }, { "fieldname": "HomePhone", "fieldtype": "Text" }, { "fieldname": "WorkPhone", "fieldtype": "Text" }, { "fieldname": "MobilePhone", "fieldtype": "Text" }, { "fieldname": "Birthday", "fieldtype": "Date", "format": "%B %-d, %Y" }, { "fieldname": "Email", "fieldtype": "Text" } ], "formatname": "PERSON", "outputlines": [ "{*FirstName*} {*LastName*}", "{*Street*}", "{*City*}, {*State*} {*Zip*}", "{*HomePhone*} (H)", "{*WorkPhone*} (W)", "{*MobilePhone*} (M)", "DoB: {*Birthday*}", "{*Email*}" ], "titleline": "{*FirstName*} {*LastName*}" } ], "nodes": [ { "children": [ "f402b796959111e7a8357054d2175f18", "f402c33a959111e7a8357054d2175f18" ], "data": { "Type": "Main" }, "format": "CATEGORY", "uid": "f402b5ac959111e7a8357054d2175f18" }, { "children": [ "f402be26959111e7a8357054d2175f18" ], "data": { "Type": "Friends" }, "format": "CATEGORY", "uid": "f402b796959111e7a8357054d2175f18" }, { "children": [], "data": { "City": "Atlantis", "Email": "john.doe@nowhere.com", "FirstName": "John", "HomePhone": "(123) 555-4567", "LastName": "Doe", "State": "CA", "Street": "1492 Columbus Lane", "WorkPhone": "(123) 555-9876", "Zip": "98765" }, "format": "PERSON", "uid": "f402be26959111e7a8357054d2175f18" }, { "children": [ "f402c448959111e7a8357054d2175f18" ], "data": { "Type": "Family" }, "format": "CATEGORY", "uid": "f402c33a959111e7a8357054d2175f18" }, { "children": [], "data": { "Birthday": "1955-02-08", "City": "Britania", "FirstName": "Jane", "HomePhone": "(123) 490-4909", "LastName": "Roe", "State": "NM", "Street": "1812 War Lane", "Zip": "87560" }, "format": "PERSON", "uid": "f402c448959111e7a8357054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "f402b5ac959111e7a8357054d2175f18" ] } }TreeLine-3.2.1/templates/220en_Book_List.trln000066400000000000000000000064731506556630100207370ustar00rootroot00000000000000{ "formats": [ { "childtype": "BOOK", "fields": [ { "fieldname": "AuthorFirstName", "fieldtype": "Text", "sortkeynum": 2 }, { "fieldname": "AuthorLastName", "fieldtype": "Text", "sortkeynum": 1 } ], "formatname": "AUTHOR", "icon": "book_3", "outputlines": [ "{*AuthorFirstName*} {*AuthorLastName*}" ], "titleline": "{*AuthorFirstName*} {*AuthorLastName*}" }, { "fields": [ { "fieldname": "Title", "fieldtype": "Text", "sortkeynum": 2 }, { "fieldname": "Copyright", "fieldtype": "Number", "format": "0000", "sortkeynum": 1 }, { "fieldname": "ReadDate", "fieldtype": "Date", "format": "%B, %Y" }, { "fieldname": "Plot", "fieldtype": "Text" } ], "formatname": "BOOK", "icon": "book_1", "outputlines": [ "\"{*Title*}\"", "(c) {*Copyright*}", "Last Read: {*ReadDate*}", "{*Plot*}" ], "titleline": "\"{*Title*}\"" }, { "childtype": "AUTHOR", "fields": [ { "fieldname": "NAME", "fieldtype": "Text" } ], "formatname": "CATEGORY", "outputlines": [ "{*NAME*}" ], "titleline": "{*NAME*}" } ], "nodes": [ { "children": [ "0b7bffe0959211e7a8357054d2175f18", "0b7c0850959211e7a8357054d2175f18" ], "data": { "NAME": "SF Books" }, "format": "CATEGORY", "uid": "0b7bfb76959211e7a8357054d2175f18" }, { "children": [ "0b7c0530959211e7a8357054d2175f18" ], "data": { "AuthorFirstName": "Orson Scott", "AuthorLastName": "Card" }, "format": "AUTHOR", "uid": "0b7bffe0959211e7a8357054d2175f18" }, { "children": [], "data": { "Copyright": "1985", "Plot": "Young boy is taught fighting and leadership", "ReadDate": "2007-04-30", "Title": "Ender's Game" }, "format": "BOOK", "uid": "0b7c0530959211e7a8357054d2175f18" }, { "children": [ "0b7c0968959211e7a8357054d2175f18" ], "data": { "AuthorFirstName": "Isaac", "AuthorLastName": "Asimov" }, "format": "AUTHOR", "uid": "0b7c0850959211e7a8357054d2175f18" }, { "children": [], "data": { "Copyright": "1951", "Plot": "Psychohistory predicts the fall of empire", "Title": "Foundation" }, "format": "BOOK", "uid": "0b7c0968959211e7a8357054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "0b7bfb76959211e7a8357054d2175f18" ] } }TreeLine-3.2.1/templates/230en_ToDo_List.trln000066400000000000000000000077111506556630100207070ustar00rootroot00000000000000{ "formats": [ { "childtype": "TASK_UNDONE", "fields": [ { "fieldname": "Name", "fieldtype": "Text" } ], "formathtml": true, "formatname": "CATEGORY", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "condition": "Done == \"true\"", "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Done", "fieldtype": "Boolean", "format": "yes/no", "init": "false" }, { "fieldname": "Urgent", "fieldtype": "Boolean", "format": "yes/no", "init": "false" } ], "formathtml": true, "formatname": "TASK_DONE", "icon": "smiley_4", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Done", "fieldtype": "Boolean", "format": "yes/no", "init": "false" }, { "fieldname": "Urgent", "fieldtype": "Boolean", "format": "yes/no", "init": "false" } ], "formathtml": true, "formatname": "TASK_UNDONE", "generic": "TASK_DONE", "icon": "smiley_2", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}" }, { "condition": "Done == \"false\" and Urgent == \"true\"", "fields": [ { "fieldname": "Name", "fieldtype": "Text" }, { "fieldname": "Done", "fieldtype": "Boolean", "format": "yes/no", "init": "false" }, { "fieldname": "Urgent", "fieldtype": "Boolean", "format": "yes/no", "init": "true" } ], "formathtml": true, "formatname": "TASK_UNDONE_URGENT", "generic": "TASK_DONE", "icon": "smiley_5", "outputlines": [ "{*Name*}" ], "titleline": "{*Name*}!!!" } ], "nodes": [ { "children": [ "1d1b7e56959211e7a8357054d2175f18", "1d1b857c959211e7a8357054d2175f18" ], "data": { "Name": "Conditional Task List" }, "format": "CATEGORY", "uid": "1d1b7c9e959211e7a8357054d2175f18" }, { "children": [ "1d1b81b2959211e7a8357054d2175f18" ], "data": { "Name": "Home Tasks" }, "format": "CATEGORY", "uid": "1d1b7e56959211e7a8357054d2175f18" }, { "children": [], "data": { "Done": "false", "Name": "Mow lawn", "Urgent": "false" }, "format": "TASK_UNDONE", "uid": "1d1b81b2959211e7a8357054d2175f18" }, { "children": [ "1d1b868a959211e7a8357054d2175f18" ], "data": { "Name": "Work Tasks" }, "format": "CATEGORY", "uid": "1d1b857c959211e7a8357054d2175f18" }, { "children": [], "data": { "Done": "false", "Name": "Write documents", "Urgent": "false" }, "format": "TASK_UNDONE", "uid": "1d1b868a959211e7a8357054d2175f18" } ], "properties": { "tlversion": "2.9.0", "topnodes": [ "1d1b7c9e959211e7a8357054d2175f18" ] } }TreeLine-3.2.1/templates/exports/000077500000000000000000000000001506556630100167355ustar00rootroot00000000000000TreeLine-3.2.1/templates/exports/live_tree_export.css000066400000000000000000000011271506556630100230270ustar00rootroot00000000000000/* live_tree_export.css, provides css for a read-only TreeLine view */ body { background-color: white; color: black; } #tree { width: 40%; height: 100%; top: 0; left: 0; position: fixed; overflow: scroll; } #tree ul { cursor: default; list-style-type: none; } #tree li { text-indent: -1.3em; } .marker { font-size: 0.8em; display: inline-block; width: 1.3em; text-align: center; vertical-align: middle; color: blue; } .selected { color: red; } #output { margin-left: 41%; } #output div { padding-left: 2em; } TreeLine-3.2.1/templates/exports/live_tree_export.html000066400000000000000000000010441506556630100232010ustar00rootroot00000000000000 TreeLine Export
      TreeLine-3.2.1/templates/exports/live_tree_export.js000066400000000000000000001153371506556630100226640ustar00rootroot00000000000000// live_tree_export.js, provides javascript code for a read-only tree view // Works with TreeLine, an information storage program // Copyright (C) 2023, Douglas W. Bell // This is free software; you can redistribute it and/or modify it under the // terms of the GNU General Public License, either Version 2 or any later // version. This program is distributed in the hope that it will be useful, // but WITTHOUT ANY WARRANTY. See the included LICENSE file for details. "use strict"; var spotDict = {}; var rootSpots = []; var treeFormats = {}; var selectedSpot = null; var openMarker = "\u2296"; var closedMarker = "\u2295"; var leafMarker = "\u25CB"; function main() { if (dataFileName) { if (dataFilePath) { dataFileName = dataFilePath + "/" + dataFileName; } loadFile(dataFileName); } else { loadData(document.getElementById("json").innerHTML); } } function loadFile(filePath) { // initial load from file link var xhttp = new XMLHttpRequest(); xhttp.overrideMimeType("application/json"); xhttp.open("GET", filePath, true); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { loadData(this.responseText); } } xhttp.send(null); } function loadData(textData) { // initial load from file data var fileData = JSON.parse(textData); fileData.formats.forEach(function(formatData) { var formatName = formatData.formatname; treeFormats[formatName] = new NodeFormat(formatData); }); var node, spot; fileData.nodes.forEach(function(nodeData) { node = new TreeNode(treeFormats[nodeData.format], nodeData); spot = new TreeSpot(node, nodeData.uid); }); rootSpots = fileData.properties.topnodes.map(function(id) { return spotDict[id]; }); rootSpots.forEach(function(rootSpot) { rootSpot.nodeRef.assignRefs(null); }); var rootElement = document.getElementById("rootlist"); rootSpots.forEach(function(rootSpot) { if (rootSpot.nodeRef.childList.length > 0) rootSpot.open = true; rootSpot.outputElement(rootElement); }); } function TreeSpot(nodeRef, uId) { // class to store node positions (unique even for cloned nodes) this.nodeRef = nodeRef; this.uId = uId; this.parentSpot; this.open = false; spotDict[uId] = this; nodeRef.spotRefs.push(this); } TreeSpot.prototype.childSpots = function() { // return an array of child spots return this.nodeRef.childList.map(function(node) { return node.matchedSpot(this); }, this); } TreeSpot.prototype.outputElement = function(parentElement) { // recursively output html tree elements var node = this.nodeRef; var element = document.createElement("li"); var markerSpan = document.createElement("span"); var markerText = leafMarker; if (node.childList.length > 0) { markerText = this.open ? openMarker : closedMarker; } markerSpan.appendChild(document.createTextNode(markerText)); markerSpan.className = "marker"; element.appendChild(markerSpan); var textSpan = document.createElement("span"); textSpan.appendChild(document.createTextNode(node.formatRef. formatTitle(this))); textSpan.className = "nodetext"; element.appendChild(textSpan); element.setAttribute("id", this.uId); parentElement.appendChild(element); if (this.open && node.childList.length > 0) this.openChildren(element); } TreeSpot.prototype.openChildren = function(parentElement) { // output children of this node var listElement = document.createElement("ul"); parentElement.appendChild(listElement); this.childSpots().forEach(function(childSpot) { childSpot.outputElement(listElement); }); } TreeSpot.prototype.toggleOpen = function() { // toggle this spot's opened/closed state if (this.nodeRef.childList.length == 0) return; this.open = !this.open; var element = document.getElementById(this.uId); if (this.open) { element.childNodes[0].innerHTML = openMarker; this.openChildren(element); } else { element.childNodes[0].innerHTML = closedMarker; var elementList = element.childNodes; for (var i = 0; i < elementList.length; i++) { if (elementList[i].tagName == "UL") { element.removeChild(elementList[i]); } } } } TreeSpot.prototype.openParents = function() { // open all parent spots of this spot var ancestors = []; var spot = this.parentSpot; var element; while (spot) { ancestors.unshift(spot); spot = spot.parentSpot; } ancestors.forEach(function(ancestor) { if (!ancestor.open) { ancestor.open = true; element = document.getElementById(ancestor.uId); element.childNodes[0].innerHTML = openMarker; ancestor.openChildren(element); } }); } TreeSpot.prototype.select = function() { // change selection to this var prevSpot = selectedSpot; selectedSpot = this; if (prevSpot) { var prevElem = document.getElementById(prevSpot.uId); if (prevElem) prevElem.childNodes[1].classList.remove("selected"); } var element = document.getElementById(this.uId); element.childNodes[1].classList.add("selected"); var outputGroup = new OutputGroup(); document.getElementById("output").innerHTML = outputGroup.getText(); } TreeSpot.prototype.prevTreeSpot = function() { // return the previous open spot in tree order var pos, node, sibling; if (this.parentSpot) { pos = this.parentSpot.nodeRef.childList.indexOf(this.nodeRef); if (pos <= 0) return this.parentSpot; node = this.parentSpot.nodeRef.childList[pos - 1]; sibling = node.matchedSpot(this.parentSpot); } else { pos = rootSpots.indexOf(this); if (pos <= 0) return null; sibling = rootSpots[pos - 1]; } while (sibling.open) { node = sibling.nodeRef.childList[sibling.nodeRef.childList. length - 1]; sibling = node.matchedSpot(sibling); } return sibling; } TreeSpot.prototype.nextTreeSpot = function() { // return the next open spot in tree order if (this.open) { return this.nodeRef.childList[0].matchedSpot(this); } var pos, sibling; var ancestor = this; while (ancestor.parentSpot) { pos = ancestor.parentSpot.nodeRef.childList.indexOf(ancestor.nodeRef); sibling = ancestor.parentSpot.nodeRef.childList[pos + 1]; if (sibling) { return sibling.matchedSpot(ancestor.parentSpot); } ancestor = ancestor.parentSpot; } pos = rootSpots.indexOf(ancestor); sibling = rootSpots[pos + 1]; if (sibling) return sibling; return null; } function TreeNode(formatRef, fileData) { // class to store nodes this.formatRef = formatRef; this.data = fileData.data; this.tmpChildRefs = fileData.children; this.spotRefs = []; this.childList = []; } TreeNode.prototype.assignRefs = function(parentSpot) { // recursively add actual refs to child nodes and parent spots var spot = this.spotRefs[0]; if (spot.parentSpot !== undefined) { // cloned node var id = spot.uId; var num = 1; do { id = id + "_" + num; num += 1; } while (id in spotDict); spot = new TreeSpot(this, id); } spot.parentSpot = parentSpot; this.childList.forEach(function(child) { // for clones (2nd time thru) child.assignRefs(spot); }); var childNode; this.tmpChildRefs.forEach(function(childId) { // for first time thru childNode = spotDict[childId].nodeRef; this.childList.push(childNode); childNode.assignRefs(spot); }, this); this.tmpChildRefs = []; } TreeNode.prototype.matchedSpot = function(parentSpot) { // return the spot for this node that matches the given parent spot for (var i = 0; i < this.spotRefs.length; i++) { if (this.spotRefs[i].parentSpot === parentSpot) { return this.spotRefs[i]; } } return null; } function NodeFormat(formatData) { // class to store node format data and format output this.fieldDict = {}; formatData.fields.forEach(function(fieldData) { this.fieldDict[fieldData.fieldname] = new FieldFormat(fieldData); }, this); this.spaceBetween = valueOrDefault(formatData, "spacebetween", true); this.formatHtml = valueOrDefault(formatData, "formathtml", false); this.outputSeparator = valueOrDefault(formatData, "outputsep", ", "); this.siblingPrefix = ""; this.siblingSuffix = ""; this.titleLine = this.parseLine(formatData.titleline); var lines = formatData.outputlines; this.useBullets = valueOrDefault(formatData, "bullets", false); if (this.useBullets) { this.siblingPrefix = "
        "; this.siblingSuffix = "
      "; if (lines != [""]) { lines[0] = "
    • " + lines[0]; lines[lines.length - 1] += "
    • "; } } this.useTables = valueOrDefault(formatData, "tables", false); if (this.useTables) { lines = lines.filter(String); var newLines = []; var headings = []; var head, firstPart, parts; lines.forEach(function(line) { head = ""; firstPart = this.parseLine(line)[0]; if (typeof firstPart == "string" && firstPart.indexOf(":") >= 0) { parts = line.split(":"); head = parts.shift(); line = parts.join(""); } newLines.push(line.trim()); headings.push(head.trim()); }, this); this.siblingPrefix = ''; if (headings.filter(String).length > 0) { this.siblingPrefix += ""; headings.forEach(function(hd) { this.siblingPrefix += ""; }, this); this.siblingPrefix += ""; } this.siblingSuffix = "
      " + hd + "
      "; lines = newLines.map(function(line) { return "" + line + ""; }); lines[0] = "" + lines[0]; lines[lines.length - 1] += ""; } this.outputLines = lines.map(this.parseLine, this); } NodeFormat.prototype.parseLine = function(text) { // parse text with embedded fields, return list of fields and text var segments = text.split(/({\*(?:\**|\?|!|&|#)[\w_\-.]+\*})/g); return segments.map(this.parseField, this).filter(String); } NodeFormat.prototype.parseField = function(text) { // parse text field, return field type or plain text if not a field var field; var match = /{\*(\**|\?|!|&|#)([\w_\-.]+)\*}/g.exec(text); if (match) { var modifier = match[1]; var fieldName = match[2]; if (modifier == "" && fieldName in this.fieldDict) { return this.fieldDict[fieldName]; } else if (modifier.match(/^\*+$/)) { field = new FieldFormat({"fieldname": fieldName, "fieldtype": "AncestorLevel"}); field.ancestorLevel = modifier.length; field.placeholder = true; return field; } else if (modifier == "?") { field = new FieldFormat({"fieldname": fieldName, "fieldtype": "AnyAncestor"}); field.placeholder = true; return field; } else if (modifier == "&") { field = new FieldFormat({"fieldname": fieldName, "fieldtype": "ChildList"}); field.placeholder = true; return field; } else if (modifier == "#") { match = /[^0-9]+([0-9]+)$/.exec(fieldName); if (match && match[1] != "0") { field = new FieldFormat({"fieldname": fieldName, "fieldtype": "DescendantCount"}); field.descendantLevel = Number(match[1]); field.placeholder = true; return field; } } else if (modifier == "!") { field = new FieldFormat({"fieldname": fieldName, "fieldtype": "StaticFileInfo"}); if (fieldName == "File_Name") { field.staticInfo = dataFileName; } else if (fieldName == "File_Path") { field.staticInfo = dataFilePath; } field.placeholder = true; return field; } } return text; } NodeFormat.prototype.formatTitle = function(spot) { // return a string with formatted title data var result = this.titleLine.map(function(part) { if (typeof part.outputText === "function") { return part.outputText(spot, true, this.formatHtml); } return part; }, this); return result.join("").trim().split("\n", 1)[0]; } NodeFormat.prototype.formatOutput = function(spot, keepBlanks) { // return a list of formatted text output lines var line, numEmptyFields, numFullFields, text, match; var result = []; this.outputLines.forEach(function(lineData) { line = ""; numEmptyFields = 0; numFullFields = 0; lineData.forEach(function(part) { if (typeof part.outputText === "function") { text = part.outputText(spot, false, this.formatHtml); if (text) { numFullFields += 1; } else { numEmptyFields += 1; } line += text; } else { if (!this.formatHtml) { part = escapeHtml(part); } line += part; } }, this); if (keepBlanks || numFullFields > 0 || numEmptyFields == 0) { result.push(line); } else if (this.formatHtml && result.length > 0) { match = /.*(|)$/gi.exec(line); if (match) { result[result.length - 1] += match[1]; } } }, this); return result; } function FieldFormat(fieldData) { // class to store field format data and format field output this.name = fieldData.fieldname; this.fieldType = fieldData.fieldtype; this.format = valueOrDefault(fieldData, "format", ""); this.prefix = valueOrDefault(fieldData, "prefix", ""); this.suffix = valueOrDefault(fieldData, "suffix", ""); this.mathResultType = valueOrDefault(fieldData, "resulttype", "number"); this.placeholder = false; this.ancestorLevel = 0; this.descendantLevel = 0; this.staticInfo = ""; if (this.fieldType == "Numbering") { this.numberingFormats = initNumbering(this.format); } if (this.fieldType == "Choice" || this.fieldType == "Combination") { var formatText = this.format.replace(/\/\//g, "\0"); if (valueOrDefault(fieldData, "evalhtml", false)) { formatText = escapeHtml(formatText); } this.choiceList = formatText.split("/").map(function(text) { return text.replace(/\0/g, "/"); }); } } FieldFormat.prototype.outputText = function(spot, titleMode, formatHtml) { // return formatted output text for this field in this node var splitValue, outputSep, selections, result, match, i, field; var newNodes, prevNodes; var value = valueOrDefault(spot.nodeRef.data, this.name, ""); if (!value && !this.placeholder) return ""; switch (this.fieldType) { case "OneLineText": value = value.split("
      ", 1)[0]; break; case "SpacedText": value = "
      " + value + "
      "; break; case "Number": var num = Number(value); value = formatNumber(num, this.format); break; case "Math": if (this.mathResultType == "number") { var num = Number(value); value = formatNumber(num, this.format); } else if (this.mathResultType == "date") { value = formatDate(value, this.format); } else if (this.mathResultType == "time") { value = formatTime(value, this.format); } else if (this.mathResultType == "boolean") { value = formatBoolean(value, this.format); } break; case "Numbering": value = formatNumbering(value, this.numberingFormats); break; case "Date": value = formatDate(value, this.format); break; case "Time": value = formatTime(value, this.format); break; case "DateTime": splitValue = value.split(" "); value = formatDate(splitValue[0], this.format); value = formatTime(splitValue[1], value); break; case "Choice": if (this.choiceList.indexOf(value) < 0) value = "#####"; break; case "Combination": outputSep = spot.nodeRef.formatRef.outputSeparator; value = value.replace(/\/\//g, "\0"); selections = value.split("/").map(function(text) { return text.replace(/\0/g, "/"); }); result = this.choiceList.filter(function(text) { return selections.indexOf(text) >= 0; }); if (result.length == selections.length) { value = result.join(outputSep); } else { value = "#####"; } break; case "AutoCombination": outputSep = spot.nodeRef.formatRef.outputSeparator; value = value.replace(/\/\//g, "\0"); selections = value.split("/").map(function(text) { return text.replace(/\0/g, "/"); }); value = selections.join(outputSep); break; case "Boolean": value = formatBoolean(value, this.format); break; case "ExternalLink": case "InternalLink": if (titleMode) { match = /
      ]*href="([^"]+)"[^>]*>([\S\s]*?)<\/a>/i. exec(value); if (match) { value = match[2].trim(); if (!value) { value = match[1]; if (value.startsWith("#")) value = value.substr(1); } } } break; case "Picture": if (titleMode) { match = /]*src="([^"]+)"[^>]*>/i.exec(value); if (match) value = match(1).trim(); } break; case "RegularExpression": match = new RegExp(this.format).exec(unescapeHtml(value)); if (!match || match[0] != unescapeHtml(value)) { value = "#####"; } break; case "AncestorLevel": value = ""; for (i = 0; i < this.ancestorLevel; i++) { spot = spot.parentSpot; } if (spot) { field = spot.nodeRef.formatRef.fieldDict[this.name]; if (field) { value = field.outputText(spot, titleMode, formatHtml); } } break; case "AnyAncestor": value = ""; while (spot.parentSpot) { spot = spot.parentSpot; field = spot.nodeRef.formatRef.fieldDict[this.name]; if (field) { value = field.outputText(spot, titleMode, formatHtml); break; } } break; case "ChildList": result = []; spot.childSpots().forEach(function(childSpot) { field = childSpot.nodeRef.formatRef.fieldDict[this.name]; if (field) { result.push(field.outputText(childSpot, titleMode, formatHtml)); } }, this); outputSep = spot.nodeRef.formatRef.outputSeparator; value = result.join(outputSep); break; case "DescendantCount": newNodes = [spot.nodeRef]; for (i = 0; i < this.descendantLevel; i++) { prevNodes = newNodes; newNodes = []; prevNodes.forEach(function(child) { newNodes = newNodes.concat(child.childList); }); } value = newNodes.length.toString(); break; case "StaticFileInfo": value = this.staticInfo; break; } var prefix = this.prefix; var suffix = this.suffix; if (titleMode) { value = removeMarkup(value); if (formatHtml) { prefix = removeMarkup(prefix); suffix = removeMarkup(suffix); } } else if (!formatHtml) { prefix = escapeHtml(prefix); suffix = escapeHtml(suffix); } return prefix + value + suffix; } function OutputItem(spot, level) { // class to store output for a single node var format = spot.nodeRef.formatRef; if (format.useTables) { this.textLines = format.formatOutput(spot, true); } else { this.textLines = format.formatOutput(spot, false). map(function(line) { return line + "
      "; }); } this.level = level; this.uId = spot.uId; this.addSpace = format.spaceBetween; this.siblingPrefix = format.siblingPrefix; this.siblingSuffix = format.siblingSuffix; if (format.useBullets && this.textLines.length > 0) { this.textLines[this.textLines.length - 1] = this.textLines[this.textLines.length - 1].slice(0, -6); } } OutputItem.prototype.addIndent = function(prevLevel, nextLevel) { // add
      tags to define indent levels in the output var i; for (i = 0; i < this.level - prevLevel; i++) { this.textLines[0] = "
      " + this.textLines[0]; } for (i = 0; i < this.level - nextLevel; i++) { this.textLines[this.textLines.length - 1] += "
      "; } } OutputItem.prototype.addSiblingPrefix = function() { // add the sibling prefix before this output if (this.siblingPrefix) { this.textLines[0] = this.siblingPrefix + this.textLines[0]; } } OutputItem.prototype.addSiblingSuffix = function() { // add the sibling suffix after this output if (this.siblingSuffix) { this.textLines[this.textLines.length - 1] += this.siblingSuffix; } } OutputItem.prototype.equalPrefix = function(otherItem) { // return true if sibling prefixes and suffixes are equal return (this.siblingPrefix == otherItem.siblingPrefix && this.siblingSuffix == otherItem.siblingSuffix); } function OutputGroup() { // class to store and modify output lines this.itemList = []; if (selectedSpot) { this.itemList.push(new OutputItem(selectedSpot, 0)); this.addChildren(selectedSpot, 0); if (this.hasPrefixes()) this.combineAllSiblings(); this.addBlanksBetween(); this.addIndents(); } } OutputGroup.prototype.addChildren = function(spot, level) { // recursively add output items for descendants spot.childSpots().forEach(function(childSpot) { this.itemList.push(new OutputItem(childSpot, level + 1)); this.addChildren(childSpot, level + 1); }, this); } OutputGroup.prototype.addBlanksBetween = function() { // add blank lines between items based on node format for (var i = 0; i < this.itemList.length - 1; i++) { if (this.itemList[i].addSpace || this.itemList[i + 1].addSpace) { var lines = this.itemList[i].textLines; lines[lines.length - 1] += "
      " } } } OutputGroup.prototype.addIndents = function() { // add nested
      elements to define indentations in the output var prevLevel = 0; var nextLevel; for (var i = 0; i < this.itemList.length; i++) { if (i + 1 < this.itemList.length) { nextLevel = this.itemList[i + 1].level; } else { nextLevel = 0; } this.itemList[i].addIndent(prevLevel, nextLevel); prevLevel = this.itemList[i].level; } } OutputGroup.prototype.hasPrefixes = function() { // return true if sibling prefixes or suffixes are found var items = this.itemList.filter(function(item) { return item.siblingPrefix || item.siblingSuffix; }); return items.length > 0; } OutputGroup.prototype.combineAllSiblings = function() { // group all sibling items with the same prefix into single items // also add sibling prefixes and suffixes and spaces in between var newItems = []; var prevItem = null; this.itemList.forEach(function(item) { if (prevItem) { if (item.level == prevItem.level && item.equalPrefix(prevItem)) { if (item.addSpace || prevItem.addSpace) { prevItem.textLines[prevItem.textLines.length - 1] += "
      "; } prevItem.textLines = prevItem.textLines.concat(item.textLines); } else { prevItem.addSiblingSuffix(); newItems.push(prevItem); item.addSiblingPrefix(); prevItem = item; } } else { item.addSiblingPrefix(); prevItem = item; } }); prevItem.addSiblingSuffix(); newItems.push(prevItem); this.itemList = newItems; } OutputGroup.prototype.getText = function() { // return a text string for all output if (this.itemList.length == 0) return ""; var lines = []; this.itemList.forEach(function(item) { lines = lines.concat(item.textLines); }); return lines.join("\n"); } window.onclick = function(event) { // handle mouse clicks for open/close and selection var spot; if (event.target.tagName == "SPAN") { var elemId = event.target.parentElement.getAttribute("id"); spot = spotDict[elemId]; if (spot) { if (event.target.classList.contains("marker")) { spot.toggleOpen(); } else if (event.target.classList.contains("nodetext")) { spot.select(); } } } else if (event.target.tagName == "A") { var addr = event.target.getAttribute("href"); if (addr.startsWith("#")) { event.preventDefault(); spot = spotDict[addr.substr(1)]; if (spot) { spot.openParents(); spot.select(); } } } } window.onkeydown = function(event) { // handle arrow keys for selection management var spot; switch (event.which) { case 38: // up arrow if (selectedSpot) { spot = selectedSpot.prevTreeSpot(); } else { spot = rootSpots[0]; } if (spot) spot.select(); event.preventDefault(); break; case 40: // down arrow if (selectedSpot) { spot = selectedSpot.nextTreeSpot(); } else { spot = rootSpots[0]; } if (spot) spot.select(); event.preventDefault(); break; case 37: // left arrow if (selectedSpot && selectedSpot.open) selectedSpot.toggleOpen(); event.preventDefault(); break; case 39: // right arrow if (selectedSpot && !selectedSpot.open) selectedSpot.toggleOpen(); event.preventDefault(); break; } } function valueOrDefault(object, name, dflt) { // return the value of the named property or the default value var value = object[name]; if (value !== undefined) return value; return dflt; } function escapeHtml(text) { // return the given string with &, <, > escaped return text.replace(/&/g, '&').replace(//g, '>'); } function unescapeHtml(text) { // return the given string with &, <, > unescaped return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); } function removeMarkup(text) { // return text with all HTML Markup removed and entities unescaped return text.replace(/<.*?>/g, "").replace(/&/g, "&"). replace(/</g, "<").replace(/>/g, ">"); } function formatNumber(num, format) { // return a formttted string for the given number var formatParts = format.split(/e/i); if (formatParts.length < 2) return formatBasicNumber(num, format); var formatMain = formatParts[0]; var formatExp = formatParts[1]; var exp = Math.floor(Math.log(Math.abs(num)) / Math.LN10); num = num / Math.pow(10, exp); var totalPlcs = (formatMain.match(/[#0]/g) || []).length; if (totalPlcs < 1) totalPlcs = 1; num = Number(num.toFixed(totalPlcs - 1)); var radix = "."; if (format.indexOf("\\,") < 0 && (format.indexOf("\\.") >= 0 || (format.indexOf(",") >= 0 && format.indexOf(".") < 0))) { radix = ","; } var formatWhole = formatMain.split(radix)[0]; var wholePlcs = (formatWhole.match(/[#0]/g) || []).length; var expChg = wholePlcs - Math.floor(Math.log(Math.abs(num)) / Math.LN10) - 1; num = num * Math.pow(10, expChg); exp -= expChg; var c = format.indexOf("e") >= 0 ? "e" : "E"; return formatBasicNumber(num, formatMain) + c + formatBasicNumber(exp, formatExp) } function formatBasicNumber(num, format) { // return a formatted string for the given number without an exponent var radix; if (format.indexOf("\\,") < 0 && (format.indexOf("\\.") >= 0 || (format.indexOf(",") >= 0 && format.indexOf(".") < 0))) { radix = ","; format.replace(/\\./g, "."); } else { radix = "."; format.replace(/\\,/g, ","); } var formatParts = format.split(radix); var formatWhole = formatParts[0].split(""); var formatFract = formatParts.length > 1 ? formatParts[1] : ""; var decPlcs = (formatFract.match(/[#0]/g) || []).length; formatFract = formatFract.split(""); var numParts = num.toFixed(decPlcs).split("."); var numWhole = numParts[0].split(""); var numFract = numParts.length > 1 ? numParts[1] : ""; numFract = numFract.replace(/0+$/g, "").split(""); var sign = "+"; if (numWhole[0] == "-") sign = numWhole.shift(); var c; var result = []; while (numWhole.length || formatWhole.length) { c = formatWhole.length ? formatWhole.pop() : ""; if (c && "#0 +-".indexOf(c) < 0) { if (numWhole.length || formatWhole.indexOf("0") >= 0) { result.unshift(c); } } else if (numWhole.length && c != " ") { result.unshift(numWhole.pop()); if (c && "+-".indexOf(c) >= 0) { formatWhole.push(c); } } else if ("0 ".indexOf(c) >= 0) { result.unshift(c); } else if ("+-".indexOf(c) >= 0) { if (sign == "-" || c == "+") { result.unshift(sign); } sign = ""; } } if (sign == "-") { if (result[0] == " ") { result = [result.join("").replace(/\s(?!\s)/, "-")]; } else { result.unshift("-"); } } if (formatFract.length || (format.length && format.charAt(format.length - 1) == radix)) { result.push(radix); } while (formatFract.length) { c = formatFract.shift(); if ("#0 ".indexOf(c) < 0) { if (numFract.length || formatFract.indexOf("0") >= 0) { result.push(c); } } else if (numFract.length) { result.push(numFract.shift()); } else if ("0 ".indexOf(c) >= 0) { result.push("0"); } } return result.join(""); } function initNumbering(format) { // return an array of basic numbering formats var sectionStyle = false; var tmpFormat = format.replace(/\.\./g, ".").replace(/\/\//g, "\0"); var delim = "/"; var formats = tmpFormat.split(delim); if (formats.length < 2) { tmpFormat = format.replace(/\/\//g, "/").replace(/\.\./g, "\0"); delim = "."; formats = tmpFormat.split(delim); if (formats.length > 1) sectionStyle = true; } formats = formats.map(function(text) { return new NumberingFormat(text.replace(/\0/g, delim), sectionStyle); }); return formats; } function NumberingFormat(formatStr, sectionStyle) { // class to store basic formatting for an element of numbering fields this.romanDict = {0: "", 1: "I", 2: "II", 3: "III", 4: "IV", 5: "V", 6: "VI", 7: "VII", 8: "VIII", 9: "IX", 10: "X", 20: "XX", 30: "XXX", 40: "XL", 50: "L", 60: "LX", 70: "LXX", 80: "LXXX", 90: "XC", 100: "C", 200: "CC", 300: "CCC", 400: "CD", 500: "D", 600: "DC", 700: "DCC", 800: "DCCC", 900: "CM", 1000: "M", 2000: "MM", 3000: "MMM"}; this.sectionStyle = sectionStyle; var match = /(.*)([1AaIi])(.*)/.exec(formatStr); if (match) { this.prefix = match[1]; this.format = match[2]; this.suffix = match[3]; } else { this.prefix = formatStr; this.format = "1"; this.suffix = ""; } } NumberingFormat.prototype.numString = function(num) { var result = ""; var digit; var factor = 1000; if (num > 0) { if (this.format == "1") { result = num.toString(); } else if (this.format == "A" || this.format == "a") { while (num) { digit = (num - 1) % 26; result = String.fromCharCode(digit + "A".charCodeAt(0)) + result; num = Math.floor((num - digit - 1) / 26); } if (this.format == "a") result = result.toLowerCase(); } else if (num < 4000) { while (num) { digit = num - (num % factor); result += this.romanDict[digit]; factor = Math.floor(factor / 10); num -= digit; } if (this.format == "i") result = result.toLowerCase(); } } return this.prefix + result + this.suffix; } function formatNumbering(value, numFormats) { // return a formatted string for a numbering field var inputNums = value.split(".").map(function(num) { return Number(num); }); if (numFormats[0].sectionStyle) { numFormats = numFormats.slice(); while (numFormats.length < inputNums.length) { numFormats.push(numFormats[numFormats.length - 1]); } var results = inputNums.map(function(num, i) { return numFormats[i].numString(num); }); return results.join("."); } else { var numFormat = numFormats[inputNums.length - 1]; if (!numFormat) numFormat = numFormats[numFormats.length - 1]; return numFormat.numString(inputNums[inputNums.length - 1]); } } function formatDate(storedText, format) { // return a formatted date string var monthNames = ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; var dateArray = storedText.split("-"); var year = dateArray[0]; var month = dateArray[1]; var day = dateArray[2]; var yearNum = Number(year); var monthNum = Number(month); var dayNum = Number(day); format = format.replace(/%-d/g, dayNum).replace(/%d/g, day); format = format.replace(/%a/g, weekday(yearNum, monthNum, dayNum).substr(0, 3)); format = format.replace(/%A/g, weekday(yearNum, monthNum, dayNum)); format = format.replace(/%-m/g, monthNum).replace(/%m/g, month); format = format.replace(/%b/g, monthNames[monthNum].substr(0, 3)); format = format.replace(/%B/g, monthNames[monthNum]); format = format.replace(/%y/g, year.slice(-2)).replace(/%Y/g, year); format = format.replace(/%-U/g, weekNumber(yearNum, monthNum, dayNum)); format = format.replace(/%-j/g, dayOfYear(yearNum, monthNum, dayNum)); return format; } function dayOfYear(year, month, day) { // return the day of year (1 to 366) var daysInMonths = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; var day = daysInMonths[month - 1] + day; if (month > 2 && year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) { day += 1; } return day; } function firstWeekday(year) { // return a number for the weekday of Jan. 1st (0=Sun., 6=Sat.) var y = year - 1; return (y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) + 1) % 7; } function weekday(year, month, day) { // return the weekday name for the given date var weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; var day = (firstWeekday(year) + dayOfYear(year, month, day) - 1) % 7; return weekdays[day]; } function weekNumber(year, month, day) { // return the week number for the given date return Math.floor((dayOfYear(year, month, day) + firstWeekday(year) - 1) / 7); } function formatTime(storedText, format) { // return a formatted time string var timeArray = storedText.split(":"); var hour = timeArray[0]; var minute = timeArray[1]; var second = timeArray[2].split(".")[0]; var microSecond = timeArray[2].split(".")[1]; var hourNum = Number(hour); var minuteNum = Number(minute); var secondNum = Number(second); format = format.replace(/%-H/g, hourNum).replace(/%H/g, hour); var ampm = "AM"; if (hourNum == 0) { hourNum = 12; hour = "12"; } else if (hourNum > 11) { ampm = "PM"; if (hourNum > 12) { hourNum -= 12; hour = hourNum.toString(); if (hourNum < 10) hour = "0" + hour; } } format = format.replace(/%-I/g, hourNum).replace(/%I/g, hour); format = format.replace(/%-M/g, minuteNum).replace(/%M/g, minute); format = format.replace(/%-S/g, secondNum).replace(/%S/g, second); format = format.replace(/%f/g, microSecond).replace(/%p/g, ampm); return format; } function formatBoolean(storedText, format) { // return a formatted boolean string var boolDict = {"true": 0, "false": 1, "t": 0, "f": 1, "yes": 0, "no": 1, "y": 0, "n": 1}; var valueNum = boolDict[storedText.toLowerCase()]; var value = format.split("/")[valueNum]; if (value == undefined) value = "#####"; return value; } main(); TreeLine-3.2.1/translations/000077500000000000000000000000001506556630100157545ustar00rootroot00000000000000TreeLine-3.2.1/translations/qt_de.qm000066400000000000000000000656031506556630100174210ustar00rootroot00000000000000<¸dÊÍ!¿`¡½ÝB *+]@;h;�;º;à;M8O`Àˆ}°mد+;#+ONH4€H�§J¼ÎLD÷L“ PSGZrr[`™\ÝÇ_Ãò1º¿ÃS‡›‚‡›²˜,à§Ô §ÔH«Œ‡¶Þ±ÏßÐ%Ð%<Ókì0�ì0Ðì0þö5*ö5R D|+Ԟʴ5>4 Ac>} K!?>ç b�b?( b¾`?¹ laô@ laô@8 lfñ@n ŒtÓ@“ Ží@Ø Ÿ¥ÞA ˰BU ÝÕB“ ñ%'C- ÷»¼CÊ )µžD */åD9 =äDr BÇéDÅ Tþ^EU c(åEˆ eœÇE° ¨JÉEã ¬%pF ¬,…Fa °ÌÕF˜ Ë”FÕ è¼:G ëf GO ý‡sGœ ˜ÄGá 0†NH EÔ9HÄ Mc\I* f)Ir ‰ÄIÅ Œ5TKa ŒHK¢ ‘$þKß ’.@L — iLO £Ü L· £Ü Lý ¯ÙJMF ̺óMˆ Ô-DM½ âkÔN õ0ËNZ öNª .ÉãNý RVŽOC RV®O| SÀ�O¶ YåOá [•›P j7oP“ p¡ÃQ\ ‘ñQ¿ –‚™R ©‰R� ÍÜ%S( ÝÂSi +>ºS‘ ;ɾSÙ PtµT ^+dTK fèeT· g­Tõ iFCU„ iØÄU½ u®Uò w®V1 w}¤Vƒ —Ã^VÕ ªôRW ðt5Wƒ ø¾WÁpSX XRuXGa.ÅXᆚYÊæÂY>Ý–þY®ò[yZ  íÒZ`%º4Z½-v›Zè0i)[[0’À[—2wT[ÉaØÎ\c5\¦{~a\ç•`é]5¯·]†¾N]¿Ðky^ÜâJ_0éPé_øt2_Ði`J**QWidget++ QShortcutAMAM QDateTimeEditOKOK QColorDialogOKOKQDialogButtonBoxOKOK QMessageBoxOKOK QPrintDialogOKOKQPrintPropertiesDialogPMPM QDateTimeEditNeinNo QShortcutHochUp QShortcutamam QDateTimeEditpmpm QDateTimeEditÿÿÿÿto QPrintDialog&OK&OK QErrorMessage N&ein&NoQDialogButtonBoxAltAlt QShortcutF%1F%1 QShortcutEntfDel QShortcutEndeEnd QShortcutEscEsc QShortcut EinfgIns QShortcutTabTab QShortcut AnfangTop QScrollBarXIMXIM QInputContextJaYes QShortcutFehler: Fatal Error: QErrorMessage&Ja&YesQDialogButtonBox ZurückBack QFileDialog ZurückBack QShortcut AnrufCall QShortcut&AusschneidenCu&t QLineEdit&AusschneidenCu&t QTextControlStrgCtrl QShortcut RunterDown QShortcutBeendenExitQMenuBar DateiFile QFileDialog DateiFile QPrintDialogUmdrehenFlip QShortcut HilfeHelpQDialogButtonBox HilfeHelp QMessageBox HilfeHelp QShortcutPos1HomeQObjectPos1Home QShortcutÿÿÿÿKind QDirModel LinksLeft QShortcutMenüMenu QShortcutMetaMeta QShortcutNameNamePPDOptionsModelNameName QDirModel ÖffnenOpenQDialogButtonBox ÖffnenOpen QFileDialogBild aufwärtsPgUp QShortcut WiederherstellenRedo QUndoGroup WiederherstellenRedo QUndoStackBeendenQuitQMenuBarSpeichernSaveQDialogButtonBoxSpeichernSaveQPrintPropertiesDialog GrößeSize QDirModelSortierenSort QFileDialogAbbrechenStop QShortcutWahrTrueQObjectRückgängigUndo QUndoGroupRückgängigUndo QUndoStack"A6 (105 x 148 mm)A6 (105 x 148 mm) QPrintDialog&Kopieren&Copy QLineEdit&Kopieren&Copy QTextControl&Schriftart&Font QFontDialogVer&schieben&Move QWorkspace&Öffnen&Open QFileDialog &Rot:&Red: QColorDialog"Wieder&herstellen&Redo QLineEdit"Wieder&herstellen&Redo QTextControl &Sat:&Sat: QColorDialogS&peichern&Save QFileDialog &Größe&Size QFontDialog&Größe ändern&Size QWorkspace&Rückgängig&Undo QLineEdit&Rückgängig&Undo QTextControl &Val:&Val: QColorDialogFLegal (8,5 x 14 Zoll, 216 x 356 mm)%Legal (8.5 x 14 inches, 216 x 356 mm) QPrintDialogAbbrechenAbortQDialogButtonBoxÜberAboutQMenuBarAnwendenApplyQDialogButtonBoxSchließenCloseQDialogButtonBoxSchließenClose QWorkspaceLaufwerkDrive QFileDialog EnterEnter QShortcut FalschFalseQObjectFarb&ton:Hu&e: QColorDialogMinimierenMinimize QWorkspaceAlles drucken Print all QPrintDialog ÖffnenOpen  QFileDialog PausePause QShortcutSonstigesOther QPrintDialog DruckPrint QPrintDialog DruckPrint QShortcutÿÿÿÿResetQDialogButtonBoxWiederholenRetryQDialogButtonBox RechtsRight QShortcutEinrichtenSetupQMenuBarUmschaltShift QShortcutÿÿÿÿSize: QPrintDialogLeertasteSpace QShortcutÿÿÿÿValuePPDOptionsModelDirekthilfe What's This?QDialogDirekthilfe What's This?QWhatsThisActionÿÿÿÿ–

      About Qt

      %1

      Qt is a C++ toolkit for cross-platform application development.

      Qt provides single-source portability across MS Windows, Mac OS X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qtopia Core.

      Qt is a Trolltech product. See www.trolltech.com/qt/ for more information.

       QMessageBoxÿÿÿÿRestore DefaultsQDialogButtonBoxAufzeichnen Media Record QShortcut"B6 (125 x 176 mm)B6 (125 x 176 mm) QPrintDialog$Bildschirm drucken Print Screen QShortcut8Eigene Farben &definieren >>&Define Custom Colors >> QColorDialogPapierquelle: Paper source: QPrintDialogB8 (62 x 88 mm)B8 (62 x 88 mm) QPrintDialogA8 (52 x 74 mm)A8 (52 x 74 mm) QPrintDialogB9 (44 x 62 mm)B9 (44 x 62 mm) QPrintDialogA9 (37 x 52 mm)A9 (37 x 52 mm) QPrintDialog*Nach &Größe sortieren Sort by &Size QFileDialog&B0 (1000 x 1414 mm)B0 (1000 x 1414 mm) QPrintDialog*Nach &Datum sortieren Sort by &Date QFileDialog(Nach &Name sortieren Sort by &Name QFileDialogÿÿÿÿ9'%1' is write protected. Do you want to delete it anyway? QFileDialogDAktiviert das Programmhauptfenster#Activates the program's main window QApplicationÿÿÿÿShow Details... QMessageBox"A5 (148 x 210 mm)A5 (148 x 210 mm) QPrintDialog,Tabloid (279 x 432 mm)Tabloid (279 x 432 mm) QPrintDialogHRLE Start of right-to-left embedding$RLE Start of right-to-left embeddingQUnicodeControlCharacterMenu.Im &Vordergrund bleiben Stay on &Top QWorkspaceJDiese Meldungen noch einmal an&zeigen&Show this message again QErrorMessage B10 (31 x 44 mm)B10 (31 x 44 mm) QPrintDialog,Windows-EingabemethodeWindows input method QInputContext&Dekrementieren Step &downQAbstractSpinBoxHöhen - Treble Down QShortcut$XIM-EingabemethodeXIM input method QInputContext"B2 (500 x 707 mm)B2 (500 x 707 mm) QPrintDialogSchl&ießen&Close QWorkspaceÿÿÿÿPPD PropertiesQPrintPropertiesDialogEinf&ügen&Paste QLineEditEinf&ügen&Paste QTextControlÿÿÿÿ Selection QPrintDialog*Rollen-Feststelltaste Scroll Lock QShortcut&Nach unten scrollen Scroll down QScrollBarHier scrollen Scroll here QScrollBar&Nach links scrollen Scroll left QScrollBarÿÿÿÿ QUndoModel"A3 (297 x 420 mm)A3 (297 x 420 mm) QPrintDialog*Die Selektion DruckenPrint selection QPrintDialog%1 - [%2] %1 - [%2] QWorkspace*ZWSP Zero width spaceZWSP Zero width spaceQUnicodeControlCharacterMenuLautstärke - Volume Down QShortcutTon aus Volume Mute QShortcut"B4 (250 x 353 mm)B4 (250 x 353 mm) QPrintDialogVorherigerMedia Previous QShortcutÿÿÿÿ Home Page QShortcutPapierformat Paper format QPrintDialogLautstärke + Volume Up QShortcutÿÿÿÿ Print dialog QPrintDialogÿÿÿÿ/%1 already exists. Do you want to overwrite it? QPrintDialog"A1 (594 x 841 mm)A1 (594 x 841 mm) QPrintDialogFarbauswahl Select color QColorDialogÿÿÿÿ Printer info: QPrintDialogRZu benutzerdefinierten Farben &hinzufügen&Add to Custom Colors QColorDialog Bla&u:Bl&ue: QColorDialogLTRQT_LAYOUT_DIRECTION QApplicationEndeBottom QScrollBarAbbrechenCancel QColorDialogAbbrechenCancelQDialogButtonBoxAbbrechenCancel QPrintDialogAbbrechenCancelQProgressDialogÿÿÿÿBrowse QPrintDialogStart (6) Launch (6) QShortcutStart (7) Launch (7) QShortcutStart (8) Launch (8) QShortcutStart (9) Launch (9) QShortcutStart (2) Launch (2) QShortcutStart (3) Launch (3) QShortcutStart (4) Launch (4) QShortcutStart (5) Launch (5) QShortcutStart (0) Launch (0) QShortcutStart (1) Launch (1) QShortcutStart (F) Launch (F) QShortcutStart (B) Launch (B) QShortcutStart (C) Launch (C) QShortcutStart (D) Launch (D) QShortcutStart (E) Launch (E) QShortcutStart (A) Launch (A) QShortcutKonfigurationConfigQMenuBarÿÿÿÿCopies QPrintDialogLöschenDelete QLineEditLöschenDelete QShortcutLöschenDelete QTextControlQuerformat Landscape QPrintDialog EscapeEscape QShortcutAuflegenHangup QShortcut"ElternverzeichnisParent Directory QFileDialog$B1 (707 x 1000 mm)B1 (707 x 1000 mm) QPrintDialogÿÿÿÿ> File not found. Please verify the correct file name was given QFileDialogIgnorierenIgnoreQDialogButtonBoxEinfügenInsert QShortcut(Folio (210 x 330 mm)Folio (210 x 330 mm) QPrintDialogBass Boost Bass Boost QShortcutBild abwärtsPgDown QShortcut$DLE (110 x 220 mm)DLE (110 x 220 mm) QPrintDialog ReturnReturn QShortcutBeispielSample QFontDialog&AufrollenSh&ade QWorkspace SuchenSearch QShortcutAuswählenSelect QShortcut&Unsortiert &Unsorted QFileDialog$C5E (163 x 229 mm)C5E (163 x 229 mm) QPrintDialog"B5 (176 x 250 mm)%B5 (176 x 250 mm, 6.93 x 9.84 inches) QPrintDialog SysReqSysReq QShortcut*Zahlen-FeststelltasteNumLock QShortcutMein Computer My Computer QFileDialogBereich drucken Print range QPrintDialog*Rollen-Feststelltaste ScrollLock QShortcutÿÿÿÿClose without SavingQDialogButtonBoxKontext1Context1 QShortcutKontext2Context2 QShortcutKontext3Context3 QShortcutKontext4Context4 QShortcutSuchen in:Look in: QFileDialog$Anzahl der Kopien:Number of copies: QPrintDialogOptionenOptionsQMenuBarBild aufwärtsPage Up QShortcut(Eine Seite nach obenPage up QScrollBarÿÿÿÿ File exists QPrintDialog.Mac OS X-EingabemethodeMac OS X input method QInputContextHochformatPortrait QPrintDialogÖffne URLOpen URL QShortcutÿÿÿÿ Properties QPrintDialogDebug Ausgabe:Debug Message: QErrorMessageFeststelltaste Caps Lock QShortcutDateiname: File name: QFileDialogSeitengröße: Page size: QPrintDialog,Eine Seite nach rechts Page right QScrollBarDruckerPrinter QPrintDialogN&ein zu allem N&o to AllQDialogButtonBoxÿÿÿÿDouble side printing QPrintDialog$A0 (841 x 1189 mm)A0 (841 x 1189 mm) QPrintDialogSchrifts&til Font st&yle QFontDialog8Farbig drucken falls möglichPrint in color if available QPrintDialog direkt verbundenlocally connected QPrintDialog*Ledger (432 x 279 mm)Ledger (432 x 279 mm) QPrintDialog"Dateien des Typs:Files of type: QFileDialogSystem RequestSystem Request QShortcutFeststelltasteCapsLock QShortcutRück-TabBacktab QShortcut Bass +Bass Up QShortcutWarnung:Warning: QErrorMessage&SchriftsystemWr&iting System QFontDialogAktualisierenRefresh QShortcutÿÿÿÿQuit %1QMenuBarÿÿÿÿSave AllQDialogButtonBox"Wieder&herstellen&Restore QWorkspace8&Versteckte Dateien anzeigenShow &hidden files QFileDialogÿÿÿÿ!Are sure you want to delete '%1'? QFileDialog@Unicode-Kontrollzeichen einfügen Insert Unicode control characterQUnicodeControlCharacterMenu$Nach oben scrollen Scroll up QScrollBarÜber QtAbout QtQMenuBarÜber QtAbout Qt QMessageBoxÿÿÿÿAbout %1QMenuBarSpeichern unterSave As QFileDialogAlias: %1 Aliases: %1 QPrintDialogÔ%1 Das Verzeichnis konnte nicht gefunden werden. Stellen Sie sicher, dass der Verzeichnisname richtig ist.K%1 Directory not found. Please verify the correct directory name was given. QFileDialogEinstellungenSettingQMenuBarFLRO Start of left-to-right override#LRO Start of left-to-right overrideQUnicodeControlCharacterMenuHLRE Start of left-to-right embedding$LRE Start of left-to-right embeddingQUnicodeControlCharacterMenuStart Mail Launch Mail QShortcutÿÿÿÿPrint To File ... QPrintDialogRücktaste Backspace QShortcut(Schriftart auswählen Select Font QFontDialogJUS Common #10 Envelope (105 x 241 mm)%US Common #10 Envelope (105 x 241 mm) QPrintDialog Bass - Bass Down QShortcutÿÿÿÿCollate QPrintDialog Liste List View QFileDialogStandbyStandby QShortcut&Inkrementieren&Step upQAbstractSpinBox&Löschen&Delete QFileDialogAktivierenActivate QApplication&Unterstrichen &Underline QFontDialog &Grün:&Green: QColorDialog Alle Dateien (*) All Files (*) QFileDialogVerzeichnisse Directories QFileDialogÿÿÿÿDiscardQDialogButtonBoxjApplikation '%1' benötigt Qt %2, aber Qt %3 gefunden.,Executable '%1' requires Qt %2, found Qt %3. QApplication4Wählen Sie ein VerzeichnisSelect a Directory QFileDialogJa zu &allem Yes to &AllQDialogButtonBox$Alle Dateien (*.*)All Files (*.*) QFileDialogÿÿÿÿ|

      This program uses Qt Open Source Edition version %1.

      Qt Open Source Edition is intended for the development of Open Source applications. You need a commercial Qt license for development of proprietary (closed source) applications.

      Please see www.trolltech.com/company/model/ for an overview of Qt licensing.

       QMessageBoxErne&ut laden&Reload QFileDialog&Umbenennen&Rename QFileDialogÿÿÿÿCould not delete directory. QFileDialogHöhen + Treble Up QShortcut"A4 (210 x 297 mm)%A4 (210 x 297 mm, 8.26 x 11.7 inches) QPrintDialogAlles auswählen Select All QLineEditAlles auswählen Select All QTextControlVerzeichnis: Directory: QFileDialogEffekteEffects QFontDialog Durch&gestrichen Stri&keout QFontDialog(Nach rechts scrollen Scroll right QScrollBar*Zahlen-FeststelltasteNum Lock QShortcut*Zahlen-Feststelltaste Number Lock QShortcutGrundfar&ben &Basic colors QColorDialogUnbekanntUnknown QFileDialogunbekanntunknown QPrintDialogÿÿÿÿ Pages from QPrintDialog&Herabrollen&Unshade QWorkspace,RLM Right-to-left markRLM Right-to-left markQUnicodeControlCharacterMenu|Die Datei %1 existiert bereits. Soll sie überschreiben werden?-%1 already exists. Do you want to replace it? QFileDialog4&Benutzerdefinierte Farben&Custom colors QColorDialogÿÿÿÿ%Do you want to overwrite it? QPrintDialogNExecutive (7,5 x 10 Zoll, 191 x 254 mm))Executive (7.5 x 10 inches, 191 x 254 mm) QPrintDialog<PDF Pop directional formattingPDF Pop directional formattingQUnicodeControlCharacterMenuEinstellungen PreferenceQMenuBarÿÿÿÿ PreferencesQMenuBarA&lphakanal:A&lpha channel: QColorDialogÿÿÿÿCopy &Link Location QTextControlM&inimieren Mi&nimize QWorkspace6Letzte Seite zuerst druckenPrint last page first QPrintDialogLinke Seite Left edge QScrollBarHLetter (8,5 x 11 Zoll, 216 x 279 mm)&Letter (8.5 x 11 inches, 216 x 279 mm) QPrintDialogFavoriten Favorites QShortcutVorwärtsForward QShortcutBild abwärts Page Down QShortcut*Eine Seite nach unten Page down QScrollBar*Eine Seite nach links Page left QScrollBarÿÿÿÿHide Details... QMessageBox4ZWNJ Zero width non-joinerZWNJ Zero width non-joinerQUnicodeControlCharacterMenuMa&ximieren Ma&ximize QWorkspace Wiederherstellen Restore Down QWorkspaceTypAll other platformsType QDirModelFRLO Start of right-to-left override#RLO Start of right-to-left overrideQUnicodeControlCharacterMenuÿÿÿÿ Don't SaveQDialogButtonBoxÿÿÿÿ Print to file QPrintDialog*ZWJ Zero width joinerZWJ Zero width joinerQUnicodeControlCharacterMenuÿÿÿÿ=File %1 is not writable. Please choose a different file name. QPrintDialog"B3 (353 x 500 mm)B3 (353 x 500 mm) QPrintDialog,Neuen Ordner erstellenCreate New Folder QFileDialogÿÿÿÿ Date Modified QDirModel,LRM Left-to-right markLRM Left-to-right markQUnicodeControlCharacterMenuWiedergabe Media Play QShortcut Stopp Media Stop QShortcutNächster Media Next QShortcut^<p>Dieses Programm verwendet Qt Version %1.</p>'

      This program uses Qt version %1.

       QMessageBoxRechte Seite Right edge QScrollBar$Start Media Player Launch Media QShortcut A7 (74 x 105 mm)A7 (74 x 105 mm) QPrintDialogDetails Detail View QFileDialog¼%1 Die Datei konnte nicht gefunden werden. Stellen Sie sicher, dass der Dateiname richtig ist.A%1 File not found. Please verify the correct file name was given. QFileDialog"A2 (420 x 594 mm)A2 (420 x 594 mm) QPrintDialog"Druckausrichtung: Orientation: QPrintDialog B7 (88 x 125 mm)B7 (88 x 125 mm) QPrintDialog<Qt Bibliothek ist inkompatibelIncompatible Qt Library Error QApplicationˆTreeLine-3.2.1/translations/qt_es.qm000066400000000000000000001024551506556630100174350ustar00rootroot00000000000000<¸dÊÍ!¿`¡½ÝBè*+];;>;`;…;®;Ò;÷M OO-À7}ImS¯](5c+;o+;–+O¬+OÉH4ÕH�áJ¼íKûLDL“PSZr+[`7\ÝO_Ã[_Ãs1º}¿Ã›¿Ã¸‡›Ä‡›‡›-˜,C§ÔU§Ôx§Ôš¨¥®«Œ¾¶ÞÌÐ%ÜÐ%Ð%%Ó9ì0Mì0mì0’ì0²ö5 DÔ+ÔÚ,£òYïÔ RZŠ ^Zg• d\]4 x\ƒµ ¼|^ „v�„v�@…éÃ`‹fÀ’ß®˜IA¥[³„¨œаI´ªº«yÈɵnðɵnɵnɵn3ɵnJɵn`ɵnyËÔËÔÁÐ BïãŽÞ1è YêMº£qùËHÊï<äõpùo×5“#Qé™%UT½*ä4ý2ÀéCÅ'CÅdC„É�CÎe¼CÎe÷D"õ!D"õ^DÓ1ŠM—âaR?4fPá:l‡‡^oR‡dw¶^º|{yÀ•ìéè¡ÏW¨2jµ´.¦·Ùèà d0ÄyØòº„þói6óur< ¸äB"l®H)¬-À¤Â/=Nà1Ø$5~ < Äd?»N”NkyT]Ýé|`êœ`ê±—ú·™�úߥ²) ª6•s¬Ñó‡´^¡�¶Š¥Ç¶Š¥è¶Š¥º=º÷ž ¾‚´&¾œû,¿¾f¿Eå–À‚´ÄÄ{ŽÊ8AÛA ß[ynâL´–󂤜󂤱ó‚¤Èó‚¤Ýó‚¤óó‚¤ õðMöE”*öE”_w�‹w�°!ÏeÄ)Õô*/e5”Œ2;„8B‹yÐO«øZõfþ`à BcÖƒ Hu(µ j‡lÉ p“” v¯É$ |¯É$ ̰‚µ!¾ÿÄ!’Ã( !ºÎ^!àÖˆ7"nã n"tä,Ô"zëÕÿ"€ñ;y"†öŠÂ"®º"Þ&H„"ä/¥Ä"êIxS"ðYMá#>YMá#yh�^#«iïÓ#½ssc$=wÞ$C€»Ñ$IŒ‡$ŸŽÛŠ$¥–´N$·–»]$ØI¼$Ó˜I¼$ú˜I¼%%˜I¼%K˜I¼%r˜I¼%�˜I¼%ØI¼%ê˜I¼&™n•&*ŸI&0ŸY&JŸi&dŸy&~Ÿ‰&˜Ÿ™&²Ÿ©&ÌŸ¹&æŸé'Ÿù'ŸI'4Ÿ‰'NŸ™'hŸ©'‚Ÿ¹'œŸù'¶¡uD'СuD( ¦oÃ(A¬,¥(G¬,¥(i¬,¥(‰¬,¥(©¬,¥(ĹÊå(Öɘe(ìÌ5$(þÑfR)èNÀ)6é•)Nõ¬c)zöû*ù^þ*,ûPq*2þV…*~œ”*’œ”*¸œ”*Ü ×ä*ò©*ø¼‚+&%CÉ+,?"£+LKN+RMî+XR¿ò+†]¿ž+Œ]¿ž+£k¶Þ+©yô^+»€{y+ÁŒ¼Ž+ë˜G%+ÿšÇ¥,›ˆ˜,+œ+¤,A¦±t,]¦±t,Œ§{y,ª¯rÉ,Ô°ˆÁ-(°ª½-:µÞ%-@½C--FÂ5Ë-ˆƨ¥-žƨ¥-È˾ä-âÒ�z-èÕ§?.çf•.6~b.toÓ.–!ë¿.ä+ï3.ê/ô….ð6Ï /G¾ñ/4LAU/~Uô/„Uô/¸ZËÑ/ÞZËÒ/öZËÓ0ZËÔ0&]k*0>^ãn0Xe‘0ºižä0àižä1rgŠ19y;Ç1a}u�1g}w�1�}w�1ÒŠê‚2�Õä2@—ßt2z›ƒt2€ «.2– «.2«¥Pè2±µD„3 ·Ýt3‰·Ýt3Ç·Ýt3ûÀ_ 4%ÉF±4=Ê¢ä4CÊ¢ä4XÊçd4^Êçd4sÊçd4ŠÊçd4ŸÌ594¥ÌÖ£4«ä‡4±ì»U4ïþ¯B5w®5E …‘5K2ì5Q6’Ñ5ƒDØ5ÓKÕ6U|6/arÅ6_p³ª6et‰6�}wZ6­}š$6Õ}š$7�Z’7L´K<7RÅ7lÆü÷7ÊÎû 7ÐÕ/7úë»E8,î@58du8¨›T8ài~9É9h5kE9˜XU 9ÈbD9ðgŸA:iê$:nx1 :tz*2:Ž‚¨d:¾ŠU€:ÄŽ÷5:ê•z:ð©Ò‰;ºm;¼ìn;8½ŒÈ;\ÄO~;vÇC¼;|Ê´5;‚ÚÔ„;œÝD„<âÜd<–ðF5="ò»Y=(üùI=.ýAs=b äÑ=z }$=€ qe=† Ú¤=Æ íE>. íE>E Ac>K Ac>œ 3š5>Ü K!?? b�b? b¾`?l iä3?ž laô@ ‚|Å@6 ŒtÓ@„ ŒtÓ@³ Ží@Ñ Ÿ¥Þ@é ¢³ÄA‹ §²A³ ­>óAÑ ­‚µA× ¸æÉAó ¸æÉB ÜKçB ÝÕB ñ%'Bb ö ®B° ÷»¼C> ü®C^ )µžCd */åCj 7uóC| =äCª BÇéCè Tþ^D2 ]‘žDX `±D– `±D­ c(åD³ dÐÍD¹ eœÇDÑ eœÇE fŽ1E& g½ÔEj gînE¨ kŸ,F rD"F( xšÄFp ~ó”Fv …éÓF| ‡Î9FÚ ˜IœFü ˜IœG! šÉ;G9 œ¬Ge œ¬G| ¨JÉG‚ ¬%pG” ¬,…G¬ ¬,…GÑ °ÌÕGå Ë”Gù ÐP¸H ÔàÄH+ ÔàÄHd Þ68H” è¼:HÞ ëf Hò ëf I5 ÷4�Ig ý‡sIm ý‡sIš AAI¶ ˜ÄJ m,J #-tJX 0†NJ´ EÔ9K& EÔ9Ko LöK§ Mc\KÅ SÐKß V×Kå ]â$L/ f)L5 f)L| io>L² mû`M wÇM Œ5TM< ŒHMT ŒHM ‘$þM™ ’.@MŸ “þ’MÅ — iN £Ü Na £Ü N– £Ü NÊ ¯ÙJNð ¯ÙJO ¿t.O9 ÂkÔO? ÃÓ‡OE ÈÇOK ̺óOw Ô-DO‹ âkÔO¡ èU)OÛ ðË<P õ0ËP  „P-  „Pd öP’ xHP¸ .ÉãPú 7F´Q >ÏòQP >ÏòQ� >ÏòQ· >ÏòQò >ÏòR$ >ÏòRZ D€TR‚ IëËRÐ RVŽRÖ RV®Rò S.ŸS SÀ�SN YåST [•›Sv j7oS¨ p¡ÃT ŒÁ.T< ŒÑBTB ŽèTH �½TT€ �½TT• �½TT¬ �½TT ’›¢TÈ “èÄTÎ –‚™TÔ �)dU0 ©‰U� ¬Á.UÒ ¬Á.Uç ¬Á.Uþ ¬Á.V ¸aV » yVW ë¬åV] úùVc tVŸ :bVÝ ÊœW+ DW1  rW7 +>ºWÝ 0ÒEWû ;ɾXÅ PtµXË ^+dXå fèeY- g­YQ iFCY¥ iØÄY½ u®YÕ w®Y÷ w®Z8 w}¤Zj w}¤Z± ƒÈôZé ƒÈô[ —Ã^[> ªôR[D ¾o²[~ ÜX[„ êD�[¼ ðt5\ ø¾\( ø)¤\L ú¾\��T\–gT\œpS\Ô*‡«\â/ÇE\þIÌ_]$XRu]�[Ÿ ]Üa.Å^PvÉ…^Vy$^p€~¹^’†š^ò´÷S^øÇB¤_VÊæÂ_¦Î_ÖÝ–þ`ò[y`  íÒ`H íÒ`�"#`Á$ÚU`Ç%º4a-v›a 0i)a?0’Àak1�ca‘2wTaÃD¢ÃaçHúùbqJdb·L$.béaØÎc“c5cûyƒCd{~ad‹•`éd©¯·dϯ·e¾Ne(ÐkyeÂâJeêéPéføt2f.û¾fvû¾f�û¾f¦if¬*+AMAceptar Q3TabDialogAceptar QAxSelectAceptar QColorDialogAceptarQDialogButtonBoxAceptar QMessageBoxAceptar QPrintDialogAceptarPMNo QShortcutNo Arribaampmÿÿÿÿ%1%&Aceptar Q3FileDialog&Aceptar&No Q3FileDialog&NoAltF%1SuprDirFinEscInsTabPrincipioXIMSí QShortcutSíError fatal:&Sí Q3FileDialog&Sí,Precedente (histórico) Q3FileDialogAnterior QFileDialogAnterior LlamarCor&tar Q3TextEditCor&tar QLineEditCor&tar FechaCtrl AbajoFichero Q3FileDialogFichero QFileDialogFicheroVoltear Ayuda Q3TabDialog AyudaQDialogButtonBox Ayuda QMessageBox Ayuda InicioÿÿÿÿIzquierdaÿÿÿÿMenúMetaÿÿÿÿ NombrePPDOptionsModel Nombre Q3FileDialog Nombre Abrir Q3FileDialog Abrir QComboBox AbrirQDialogButtonBox Abrir QFileDialog AbrirQMenu Abrir QPushButton Abrir Re Págÿÿÿÿ QUndoGroupÿÿÿÿGuardarQDialogButtonBoxGuardar QFileDialogGuardar Tamaño Q3FileDialog TamañoOrdenar Q3FileDialogOrdenarDetenerVerdadero Q3DataTableVerdaderoTipoÿÿÿÿ QUndoGroupÿÿÿÿ"A6 (105 x 148 mm)&Copiar Q3TextEdit&Copiar QLineEdit&Copiar&Tipo de letra &Ayuda &Mover &Abrir Q3FileDialog &Abrir &Rojo:&Rehacer Q3TextEdit&Rehacer QLineEdit&Rehacer&Saturación:&Guardar Q3FileDialog&Guardar&Tamaño QFontDialog&Tamaño&Deshacer Q3TextEdit&Deshacer QLineEdit&Deshacer&Brillo:NLegal (8,5 x 14 pulgadas, 216 x 356 mm)InterrumpirAplicar Q3TabDialogAplicarÿÿÿÿ QCheckBoxÿÿÿÿLimpiar Cerrar Q3TitleBar CerrarQDialogButtonBox CerrarQMenu Cerrar Unidad Intro Falso Q3DataTable Falso Error &Tono:Minimizar Q3TitleBarMinimizar0No se ha podido abrir %1Imprimir todo Abrir  Q3FileDialog Abrir  PausaÿÿÿÿÿÿÿÿImpr Pant QPrintDialogImpr PantÿÿÿÿReintentarDerechaMayÿÿÿÿEspacio>La operación de red ha expiradoÿÿÿÿLEl equpo remoto ha cerrado la conexión¿Qué es esto?QDialog¿Qué es esto?ZEl protocolo «%1» no permite recibir ficherosPEl listado del directorio ha fallado: %1ÿÿÿÿbNo se ha podido borrar el fichero o directorio %1ÿÿÿÿEscritura: %1Grabar medio"B6 (125 x 176 mm)ÿÿÿÿ QDB2Driverÿÿÿÿ QIBaseDriverÿÿÿÿ QIBaseResultÿÿÿÿ QMYSQLDriverÿÿÿÿ QODBCDriverÿÿÿÿQSQLite2Driverÿÿÿÿ(Equipo no encontradoQAbstractSocket(Equipo no encontrado<Descriptor de socket no válido"Imprimir pantallaD&Definir colores personalizados >>"Fuente del papel:B8 (62 x 88 mm)ÿÿÿÿtreferencia a entidad no analizada en un contexto no válidoA8 (52 x 74 mm)ÿÿÿÿB9 (44 x 62 mm):Tipo de protocolo no admitidoÿÿÿÿA9 (37 x 52 mm)&Ordenar por &tamaño Q3FileDialog&Ordenar por &tamaño&B0 (1000 x 1414 mm)$Ordenar por &fecha Q3FileDialog$Ordenar por &fecha&Ordenar por &nombre Q3FileDialog&Ordenar por &nombreRFallo de la creación de un directorio: %1LNo se ha podido crear el directorio %1ÿÿÿÿNueva carpeta 1ÿÿÿÿPActiva la ventana principal del programaÿÿÿÿ"A5 (148 x 210 mm).Tabloide (279 x 432 mm)HRLE Start of right-to-left embedding6Permanecer en &primer plano<Mo&strar este mensaje de nuevoBsintaxis no válida para lookahead¢no se permiten referencias a entidades externas generales ya analizadas en la DTD B10 (31 x 44 mm)2Método de entrada Windowsÿÿÿÿÿÿÿÿÿÿÿÿ^valor erróneo para la declaración independienteRe&ducirNo conectado Bajar los agudosÿÿÿÿRConexión para conexión de datos rechazada*Método de entrada XIMºse esperaba una declaración de codificación o declaración autónoma al leer la declaración XML"B2 (500 x 707 mm)el directorioÿÿÿÿ QDB2Resultÿÿÿÿ"&Tipo de fichero:&&Nombre de fichero:bNo hay ningún fichero o directorio con ese nombre&Cerrarÿÿÿÿ4Identificación fallida: %1 &Pegar Q3TextEdit &Pegar QLineEdit &Pegarÿÿÿÿÿÿÿÿÿÿÿÿ4Bloqueo del desplazamiento*Desplazar hacia abajo(Desplazar hasta aquí8Desplazar hacia la izquierdaÿÿÿÿBorrar %1HFallo de la descarga del fichero: %1"A3 (297 x 420 mm)ÿÿÿÿÿÿÿÿ QDB2Resultÿÿÿÿ QMYSQLResultÿÿÿÿ QOCIResultÿÿÿÿ QODBCResultÿÿÿÿQSQLite2Resultÿÿÿÿ%1 - [%2]&Conectado al equipoQFtp&Conectado al equipoAlinear Q3MainWindowAlinear*ZWSP Zero width space Bajar el volumenSilenciarÿÿÿÿ’Intento de usar un socket IPv6 sobre una plataforma que no contempla IPv6"B4 (250 x 353 mm)ÿÿÿÿ>La plataforma no contempla IPv6ÿÿÿÿMedio anteriorÿÿÿÿÿÿÿÿÿÿÿÿ>no se ha producido ningún errorQRegExp>no se ha producido ningún error|se ha producido un error durante el análisis de una referencia"Formato del papel Subir el volumenˆse esperaba una declaración independiente al leer la declaración XMLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"A1 (594 x 841 mm)*Selección de un colorÿÿÿÿÿÿÿÿÿÿÿÿH&Añadir a los colores personalizados,Conectado al equipo %1QFtp,Conectado al equipo %1 Más...zEl protocolo «%1» no permite renombrar ficheros o directoriosÿÿÿÿÿÿÿÿPLa conexión con el equipo ha fallado: %1ÿÿÿÿ Az&ul:LTR FinalCancelar Q3FileDialogCancelarQ3ProgressDialogCancelar Q3TabDialogCancelar QColorDialogCancelarQDialogButtonBoxCancelar QFileDialogCancelar QPrintDialogCancelarQProgressDialogCancelarÿÿÿÿLanzar (6)Lanzar (7)Lanzar (8)Lanzar (9)Lanzar (2)Lanzar (3)Lanzar (4)Lanzar (5)Lanzar (0)Lanzar (1)Lanzar (F)Lanzar (B)Lanzar (C)Lanzar (D)Lanzar (E)Lanzar (A).Equipo %1 no encontradoQFtp.Equipo %1 no encontradoÿÿÿÿ Borrar Q3DataTable Borrar QLineEdit Borrar QShortcut BorrarQSql BorrarApaisado EscapeR&ecargarNueva carpetaDescolgar&Directorio superior‚El protocolo «%1» no permite listar los ficheros de un directorio$B1 (707 x 1000 mm)ÿÿÿÿFEl envío del fichero ha fallado: %1IgnorarInsertar Q3DataTableInsertar QShortcutInsertarÿÿÿÿ(Folio (210 x 330 mm)ÿÿÿÿ(desconocido)ÿÿÿÿÿÿÿÿ(Potenciar los gravesÿÿÿÿÿÿÿÿ QIBaseDriverÿÿÿÿ Av Págÿÿÿÿ$DLE (110 x 220 mm)RetornoMuestraSombre&arBúsquedaSeleccionar&Sin ordenar Q3FileDialog&Sin ordenar$C5E (163 x 229 mm)NB5 (176 x 250 mm, 6,93 x 9,84 pulgadas) PetSisÿÿÿÿÿÿÿÿ<falta el delimitador izquierdoBloq NumActualizar Q3DataTableActualizarÿÿÿÿBuscar &en:,¿Borrar este registro?8Imposible recibir un mensajeMi computadoraHContenido del fichero previsualizadoÿÿÿÿÿÿÿÿ$Imprimir intervaloBloq DesplDFallo del cambio de directorio: %1ÿÿÿÿ Permiso denegado QIODevice Permiso denegadoContexto1Contexto2Contexto3Contexto4Buscar en:\nombre de instrucción de tratamiento no válido Nueva carpeta %1"Equipo encontradoQFtp"Equipo encontrado"Número de copias:ÿÿÿÿ"Retroceder página.Una página hacia arriba QScrollBar.Una página hacia arriba4error debido al consumidor4Método de entrada Mac OS XÿÿÿÿVerticalÿÿÿÿ QScrollBarÿÿÿÿVsintaxis no válida para clase de caracteresvse ha producido un error durante el análisis de un elemento$Conexión rechazadaQAbstractSocket$Conexión rechazadaQHttp$Conexión rechazadaAbrir URLÿÿÿÿÿÿÿÿ QDB2Resultÿÿÿÿÿÿÿÿ QDB2Resultÿÿÿÿ QMYSQLResultÿÿÿÿ QOCIResultÿÿÿÿÿÿÿÿÿÿÿÿ8¿Guardar las modificaciones?$Imposible escribir&carácter inesperadoÿÿÿÿÿÿÿÿ,Mensaje de depuración:JEliminación de directorio fallida: %1.etiqueta desequilibrada"Lectura-escritura*Bloqueo de mayúsculasÿÿÿÿ$Nombre de fichero:Sólo lectura"Tamaño de página:.Una página a la derecha QScrollBar.Una página a la derechaÿÿÿÿN&o a todoXse ha usado una característica no habilitadaÿÿÿÿ$A0 (841 x 1189 mm),Solicitud HTTP fallida2&Estilo del tipo de letra>Imprimir en color si es posible2Copiar o mover un fichero(conectado localmenteT<qt>¿Seguro que desea borrar %1 «%2»?</qt>*Ledger (432 x 279 mm)*valor octal no válido"Ficheros de tipo:(Petición del sistemaJNo se ha podido leer el directorio %1ÿÿÿÿBloq Mayús*Tabulador hacia atrásÿÿÿÿ Subir los gravesÿÿÿÿ Aviso:ÿÿÿÿ*Sistema de escr&ituraPersonalizar...Actualizarÿÿÿÿÿÿÿÿ&Restaurartse ha producido un error durante el análisis del contenidozse ha producido un error durante el análisis de un comentario†no se permiten referencias a entidades internas generales en la DTDÿÿÿÿÿÿÿÿ.Buscar en el directorioAtributosÿÿÿÿÿÿÿÿ:Dirección de tipo desconocidobYa hay otro socket escuchando por el mismo puertoÿÿÿÿ QMYSQLResultÿÿÿÿ:Mostrar los ficheros &ocultos Q3FileDialog:Mostrar los ficheros &ocultos6Imposible enviar un mensajeÿÿÿÿHInsertar carácter de control Unicode,Desplazar hacia arribatEl protocolo «%1» no permite borrar ficheros o directoriosAcerca de QtHLa dirección enlazada ya está en usoGuardar como Q3FileDialogGuardar comoAlias: %1œ%1 Directorio no encontrado. Verique que el nombre del directorio es correcto."Conexión expiradaError de redÿÿÿÿInaccesibleÿÿÿÿ QIBaseResultÿÿÿÿÿÿÿÿFLRO Start of left-to-right overrideHLRE Start of left-to-right embeddingˆ%1 Fichero no encontrado. Compruebe la ruta y el nombre del fichero.Lanzar correoÿÿÿÿÿÿÿÿ Borrar(entidades recursivas8Seleccionar un tipo de letraDSobre US Common #10 (105 x 241 mm) Bajar los graves8Operación socker no admitidaÿÿÿÿ QIBaseDriverÿÿÿÿÿÿÿÿConfirmarVista de lista Q3FileDialogVista de lista>Conexión rechazada al equipo %18Operación socket no admitidaTmás de una definición de tipo de documento Fichero especialBOperación detenida por el usuarioÿÿÿÿÿÿÿÿXEl protocolo «%1» no permite enviar ficherosSólo escritura&CancelarQ3Wizard&Cancelar&el enlace simbólicoÿÿÿÿ QMYSQLResultÿÿÿÿ Reposo&Aumentar&Borrar Q3FileDialog&BorrarActivarS&ubrayado&Terminar*Conexión a %1 cerradaQFtp*Conexión a %1 cerradaDsintaxis no válida para repetición&Verde:,Todos los ficheros (*) Q3FileDialog,Todos los ficheros (*)ÿÿÿÿDirectorios Q3FileDialogDirectoriosDEliminación de fichero fallida: %1ÿÿÿÿLEnlace simbólico a un fichero especialVImposible inicializar el socket de difusiónlEl ejecutable «%1» requiere Qt %2 (se encontró Qt %3).2Seleccionar un directorio Q3FileDialog2Seleccionar un directorioSiguie&nte >Sí a &todoÿÿÿÿDNo queda espacio en el dispositivoÿÿÿÿ0Todos los ficheros (*.*) Q3FileDialog0Todos los ficheros (*.*)bse esperaba la versión al leer la declaración XMLÿÿÿÿLectura: %1&Recargar&Renombrar Q3FileDialog&Renombrarÿÿÿÿ Subir los agudosBNo se ha podido renombrar %1 a %2NA4 (210 x 297 mm, 8,26 x 11,7 pulgadas) Seleccionar todo Q3TextEdit Seleccionar todo QLineEdit Seleccionar todoDirectorio: Q3FileDialogDirectorio:ÿÿÿÿÿÿÿÿÿÿÿÿ&Valores por omisiónEfectos&Tachado4Desplazar hacia la derecha0Fragmento HTTP no válidoÿÿÿÿBloq num(Equipo %1 encontradoQFtp(Equipo %1 encontrado Bloqueo numérico<Longitud del contenido errónea Colores &básicos*se esperaba una letra"Error desconocidoQFtp"Error desconocido QHostInfo"Error desconocidoQHostInfoAgent"Error desconocidoQHttp"Error desconocido QIODevice"Error desconocidoHLa secuencia %1, %2 no está definidaÿÿÿÿDesconocidodesconocido:¿Cancelar sus modificaciones?ÿÿÿÿQ&uitar sombra,RLM Right-to-left markZEl fichero %1 ya existe. ¿Desea reemplazarlo?.Colores &personalizadosÿÿÿÿÿÿÿÿ2fin de fichero inesperadoÿÿÿÿ QDB2Driverÿÿÿÿ QMYSQLDriverÿÿÿÿ QODBCDriverÿÿÿÿÿÿÿÿÿÿÿÿVEjecutivo (7,5 x 10 pulgadas, 191 x 254 mm)ZImposible inicializar el socket no bloqueante<PDF Pop directional formattingÿÿÿÿ QDB2Driverÿÿÿÿ QIBaseDriverÿÿÿÿ QMYSQLDriverÿÿÿÿ6La dirección está protegidaÿÿÿÿÿÿÿÿ6No se ha podido escribir %18se alcanzó el límite internoHCabecera de respuesta HTTP no válidaÿÿÿÿÿÿÿÿ Error de expiracioD socks5 mientras se establecía una conexión al servidor socksCanal a&lfa:Äno se permiten referencias a entidades externas generales ya analizadas en el valor de un atributoÿÿÿÿMi&nimizarBImprimir primero la última páginaBorde izquierdoNCarta (8,5 x 11 pulgadas, 216 x 279 mm)FavoritosSiguienteAvanzar página,Una página hacia abajo QScrollBar,Una página hacia abajo2Una página a la izquierda QScrollBar2Una página a la izquierda Conexión cerradaQFtp Conexión cerradaÿÿÿÿ4ZWNJ Zero width non-joinerÿÿÿÿ2Ir al directorio superiorLInformación del fichero previsualizadoMa&ximizarRestaurar abajo>Secuencia ambigua %1 no tratadaÿÿÿÿÿÿÿÿ2Operación socket expiradaTipo< &Anterior Red inalcanzablefNo se ha indicado ningún servidor al que conectarseFRLO Start of right-to-left overridenerror en la declaración de texto de una entidad externaÿÿÿÿel ficherofin inesperadoZEl servidor cerró la conexión inesperadamenteÿÿÿÿXDemasiados ficheros abiertos simultáneamenteJEl protocolo «%1» no está contemplado*ZWJ Zero width joiner>La dirección no está disponibleÿÿÿÿ"B3 (353 x 500 mm).Crear una nueva carpeta Q3FileDialog.Crear una nueva carpetaÿÿÿÿ:Enlace simbólico a un ficheroÿÿÿÿ,LRM Left-to-right mark&Reproducir el medio Detener el medio,Insuficientes recursosSiguiente medio„El protocolo «%1» no permite copiar o mover ficheros o directorios@Enlace simbólico a un directorio,Solicitud interrumpida¤se ha producido un error durante el análisis de la definición de tipo de documentob<p>Este programa utiliza la versión %1 de Qt.</p>Borde derechojEl protocolo «%1» no permite crear nuevos directoriosLanzar medio A7 (74 x 105 mm)Vista detallada Q3FileDialogVista detallada”%1 Fichero no encontrado. Verifique que el nombre del fichero es correcto."A2 (420 x 594 mm)Orientación: B7 (88 x 125 mm)BError: biblioteca Qt incompatibleÿÿÿÿ QMYSQLDriverÿÿÿÿQSQLite2Driverÿÿÿÿ/z÷ "(/8=CFKR\ahu{‚ˆŽ”›ª±·ÇÌÓàæòøÿ $,9AHORenw�…Œ•œ«³¸ÄÕÝáèîôû '-39@ QProgressBarQDialog QDB2Driver QCheckBox QUndoStackQXml Q3TitleBar QMYSQLResultQDialogButtonBoxQ3Accel Q3TextEditQFtpQLibrary QFontDialogQMultiInputContextQRegExp QODBCResultQMultiInputContextPlugin QDB2Result QODBCDriver QDirModel QTcpServer QTDSDriver Q3FileDialog QSQLiteResultQSQLite2Result QToolButton QScrollBarQNativeSocketEngine Q3LocalFsQSlider QTextControl QPSQLDriver QColorDialog QIODevice QMYSQLDriver QAxSelect QWorkspace QApplication QOCIResult QShortcutQAbstractSpinBox QErrorMessage QSQLiteDriverQHostInfoAgent QUdpSocket QRadioButton QDateTimeEdit QMessageBox Q3TabDialogQSqlQTabBar QFileDialogQ3ProgressDialogQProgressDialogPPDOptionsModelQ3NetworkProtocolQMenu Q3MainWindowQWhatsThisAction QPrintDialogQUnicodeControlCharacterMenuQSQLite2DriverQObjectQPrintPropertiesDialog QComboBoxQ3Wizard Q3UrlOperator QInputContextQHttp QIBaseDriver Q3ToolBar QHostInfo QIBaseResultQWidget QLineEdit Q3DataTableQAbstractSocket QPSQLResultQSocks5SocketEngine QUndoModel QOCIDriver QUndoGroup QPushButtonQSpinBoxTreeLine-3.2.1/translations/qt_pt.qm000066400000000000000000002112641506556630100174500ustar00rootroot00000000000000<¸dÊÍ!¿`¡½ÝB(*ê9+Áe]6Ê;Û;-¤;;`;};;«M6òOÎ OØwÀÓç}7m7B¯°ò+;Û+;8S+;>ÿ+O¯+O8#H4Á†H�ÅÔJ¼Ä K „LDÅ)L“Å}PSÇlZrÓB[`Á;[`éŠ\ÝkU_ÃÔÌ_ÃÙ1º?ú¿Ãí¿Ã8¹‡›­‡›E³‡›Á­˜,Âù§Ôþ§Ôp˜§ÔÜ0¨¥Ñ«ŒÄv¶ÞÄýÐ% OÐ%G˜ÓÆ4ì0­ì0:§ì0yøì0|°ì0ÆÏì0ëXö5™ö5Æû D=À DKn+ÔÌL,£>Ÿ,£Ö½ÐF…ÖèH5 4H5=êH5KïH5™«f¾ pf¾1Þf¾;‹f¾I¾f¾|Hf¾±•f¾ÜálÀÏû‹¯ÝÊ‹¯Þb˜Å<§¡½¡>¡L ¦”ð«`Òž«`é_¹µA¹µ2 ÀegÀe>DÀeLWįÝûįޓ «y¡,*¦y*¦yoÏ*¦yÚë*ÖTLˆ*ì0'¿*ì0ê�+FÅy+FÅëï+f¾+f¾C+‹z0+‹¯d+‹¯p0+‹¯ÛR+˜z0U+˜Åu+˜Å8�+˜ÅCt+¡LÉ+¡yŽ+¡ìZ+į˜+įpc+įۈ+Çú0‘F0i©ëG–”8êHw9Hw99"Ië›.4Ië›±ÃJ+‚ÎJ6•xJ6•1‚J6•9•J6•>nJ6•yÅJ6•{ìJ6•®VJ6•ìÍK�ÅGeLZÂÅPLƒ•ÞLƒ•1±L™b !O|Š1RPFEPFE{PFEíuTæÑQV1¼«ÛV1¼°Vl ŸVŒ•ÏžWŒ£ÝW�T«?W�TÐ%XÉÄ;¾XÉÄçeXË™<]XýôÐûYïÔÒ Zg•Ò8\]4ƒø\]4ÖH\ƒµ™Ü|^‡è„v�7j„v�éî…éÃ"å‹fSјIA)¥[³;ú¨œÛ°I´ÍHº«y¥Yɵn2@ɵn^ØÉµneÝɵnqÆÉµn‘�ɵn¶Uɵn¹âËÔ) ËÔWÐ Bƒ.ãŽÞÐRêMº�òEòlPqù¥þHÊ-`<äùžpù¡Ñ×5‚Î#Qé¦L%UT…â*ä4”2Àé¢CÅÇC„É¢ÅCÎe#D"õuDÓ1QòM—ÔaR?C§fPá èl‡‡¼oR‡+Xw¶^}a|{y Ø•ìé¬Í¡ÏWáΨ2{˜¨2î*µ´.?*·Ù²là dóÄy£vòº„jíóurgR ¸ä�”"l®úè)*Ø-À¤T�/=NÓi1Ø$‚<5~Pµ< Äk€?»Nî{Nky£Ç]Ýé`ê4`ê–õ—ú Ô™�ú „™�úGÌ¥²)i ª6•7êª6•xçª6•ë¼´^¡TB¶Š¥3¶Š¥p¶Š¥Ûº=}¶º÷ž°°¾‚´ÚF¾œûÑ,¿¾¿¬¿¾çÚ¿Eå¿ü¿Eåè(À‚´À@À‚´èjÄ{ŽÞ.Ê8AþÛARbß[yŸîâL´�…ì‚n¬só‚¤4•ó‚¤u„ó‚¤�󂤗ˆ󂤷k󂤻—õðMxªõðMë‚öE”ORöE”X&w�w�½É!ÏeäÉ)ÕÔ*/eÔN5”Œ^;„€�B‹y¤oO«šZõfÝH`àxcÖƒÍu(µÇ%“” ’h¯É$´Ù¯É$÷*°‚µò.Ã( Ô�Î^÷Õã n›ä,ÔaëÕÿ�Ùñ;yŸF&H„`m/¥Ä_êIxS.ÐYMáO YMáXuh�^ »iïÓ%çssc~­wÞ½‰€»ÑO÷Œ‡ŽŽÛŠ1–´NVz–»]½–»]åM˜I¼Þ˜I¼Ç˜I¼5˜I¼9Z˜I¼±[˜I¼×˜I¼ë&ŸIÉIŸYɉŸiÉÉŸyÊ Ÿ‰ÈIŸ™È‰Ÿ©ÈÉŸ¹É ŸéÇÉŸùÈ ŸIˉŸ‰Ê‰Ÿ™ÊÉŸ©Ë Ÿ¹ËIŸùÊI¡uDS*¡uDZc¦oïJ¬,¥ª¬,¥pȬ,¥Äͬ,¥×ˬ,¥Üc¹Êåœx¹Êå®�ɘeŤÌ5$­ÑfR aÑfRI€èNÀÆ›é•Iìõ¬c#›öû£ûPqUþþV…:ÚþV…åzœ” œ”Ç™œ”ØJ ×ä‹©©.¼‚h*$ã‰%CÉ î?"£sàKNÙ;MîÂKR¿ò~]¿ž]á]¿žd×k¶ÞÏËyô^f€{y¦ñŒ¼ŽÐ˘G%MƙصŒÅšÇ¥í÷›ˆ˜Ñ§œ+¤ÑÛ¦±t©§{y¦š¯rɤðˆÁÒʰª½ ˆµÞ%.e½C-´qÂ5ËÎ|ƨ¥yƨ¥Øæ˾äe]Ò�z úÕ§?×öçf•‰ä~bI5~bKŸoÓ Ñ!ë¿c++ï3·ó/ô…¬!/ô…°V6Ï ÑkG¾ñNâLAUÙ¿Pѧ9ËUôi}Uô…‰ZËÑÖZËÒÃÎZËÓÄZËÔÄ>^ãnõ®e‘  ižäSˆižäZÂy;ÇrÏ{¯…}u�Ïk}w�¾î}w�ÕÓ}w�ç!„èàŠê‚ò£�Õäj‚›ƒt�M›ƒt®Ð «.¿4 «.Ö¥Pè±÷µD„ñ¿·Ýt([·ÝtY·Ýt�†À_ ÎðÉF±v Ê¢ä5oʢ䘄Êçd6bÊçdvwÊçd�ýÊçd˜úÌ59b)ä‡ؘì»UŠùþ¯Bøèw®�0–½mu …‘b¢2ì?¤6’ÑTÕCU]å«DØø‘KÕ1U|Ã'arŸut‰ë}wZœ¶}š$¾Ÿ}š$Õ‡}š$æÔ�Z’±´K<;ų-Îû žïÕ/Y»ë»EMqu›T­Âi~É©‹5kE³¼XU HbDÒúbG·lËgŸA²iê$�ax1 Ã`z*2‚¨d“sŠU€ÂÂŽ÷5µ^•z@>ºmN�¼ìn½½ŒÈДÀbÑ*ÇC¼<ÜÊ´5yPÊ´5ìÚÔ„ðœÝD„ð)âÜdôïðF5áðF5zgò»YœüùI $üùIHmýAsp äÑ5ä }$wƒ qeWc Ú¤× íEtƒ íEŽØ AcP AcJk 3š5Šq K!?E@ b�bÞÆ b¾`Àï b¾`é iä3% laô|p lfñ ‚|ŇU ŒtÓµ ŒtÓJ. Ží¢m Ÿ¥Þ@t ¢³Ä(± ¢³Ä�à §²ƒ« ­>óºþ ­‚µ o ¸æÉfØ ¸æÉu ÜKçô ÝÕà� ñ%'ß_ ö ®³ ÷»¼ËÉ ü®š• )µž«u */åÁß 7uó÷‚ =äMú BÇé­2 Tþ^‡ ]‘ž‹¹ `±^g `±¸é c(å¯ dÐÍ×™ eœÇ ² eœÇHî fŽ1Q& gînö— kŸ, rD": xšÄ„Ê ~ó”dQ …éÓ$Q ‡Î9” ˜Iœ'S ˜Iœ-) ˜Iœ7¬ šÉ;– œ¬vý œ¬¼� ¨JÉÒe ¬%p*“ ¬,…y ¬,…BÍ °ÌÕ+! Ë”Lþ ÐP¸'‰ ÐP¸êX ÔàÄQš ÔàÄYb Þ68²Î è¼:/å ëf ¶ ëf Dˆ ÷4�a› ý‡s ² ý‡sFø AAUE ˜Ä:& m, #-tˆw 0†N+æ EÔ9õ Lö'í Löêº Mc\=! SÐc¸ V×hŸ ]â$3¢ f) f)Dá io>úO mû` A wÇ~ ŒH7 ŒHC3 ‘$þEã ’.@Óª “þ’Ì — i B £Ü / £Ü pø £Ü Ü– ¯ÙJ ê ¯ÙJG/ ¿t.•4 ÂkÔÚ™ ÃÓ‡¨ ÈÇk ̺óM< Ô-DNU âkÔÀ– âkÔè¾ èU)[ ðË<¿ õ0ËÎF  „RØ  „Z öα xH] ®ÞÙ .Éã/F 7F´öD >ÏòU¶ >ÏòV· >ÏòWÔ >Ïò]6 >Ïòj5 >Ïòoƒ >Ïò‹b >Ïò�ˆ D€Tú IëË.— RVŽJ× RVŽé² RV®® S.Ÿ×@ SÀ�¯Á YåìŽ [•›ây j7oB@ p¡Ã/� ŒÁ.¶â ŒÑBfh Žèù; �½T2Ç �½TrQ �½T’ �½T›¥ ‘ñži ’›¢gÀ “èÄ4ù “èĘ –‚™§H œüSp �)d‰, ©‰áC ¬Á.3 ¬Á._c ¬Á.sY ¬Á.”® ¸a†ã » yS ë¬å| úùU t´ :b[u Êœ-È +>º0Å 0ÒEóí ;ɾÛÀ PtµzÑ Ptµí9 fèe½E fèeåü g­ª� iFCÅû iØÄH· iØÄÆf u®Ï2 w®¾ w®Ôó w®æ> w}¤¾O w}¤Õ: w}¤æ† ƒÈôPm ƒÈôXÍ —Ã^|Þ ¢}ÒnS ªôRä6 ÜX - êD�? ðt5z( ðt5ìý ø¾{L ø¾í® ø)¤J ú¾ö�T)¼gT**‡«(%*‡«êñ/ÇE)c/ÇE„m=êBkÜIÌ_[ñXRuâþ[Ÿ ï‰a.Å:dvÉ…Yy$µ€~¹\¡´÷SiÌÇB¤&ÏÊæÂã²Î†cÝ–þ§êò[y¤úrÁE íÒ íÒF^"#ºn$ÚU°%º4=o%º4K-v›à 0i)ÌÂ0’ÀÍŽ1�c…92wTÌ~D¢Ã!5HúùWJd\ZL$.ñc5¿ic5ç™iC¼±yƒC" {~aÌ•`é¡€¯· :¯·F¯¾NAYÐkyŸšéP饭øt2,—û¾q@û¾ŒAû¾µÍû¾¹[iûkSobre o %1About %1MAC_APPLICATION_MENUOcultar %1Hide %1MAC_APPLICATION_MENUOcultar Outros Hide OthersMAC_APPLICATION_MENUPreferências &Preferences...MAC_APPLICATION_MENUEncerrar %1Quit %1MAC_APPLICATION_MENUServiçosServicesMAC_APPLICATION_MENUMostrar TudoShow AllMAC_APPLICATION_MENU"%1, %2 indefinido%1, %2 not definedQ3Accel,%1 ambíguo não tratadoAmbiguous %1 not handledQ3AccelRemoverDelete Q3DataTable FalsoFalse Q3DataTableInserirInsert Q3DataTableVerdadeiroTrue Q3DataTableActualizarUpdate Q3DataTablez%1 Ficheiro não encontrado. Verifique a localização e o nome.+%1 File not found. Check path and filename. Q3FileDialog&Apagar&Delete Q3FileDialog&Não&No Q3FileDialog&OK&OK Q3FileDialog &Abrir&Open Q3FileDialog&Mudar Nome&Rename Q3FileDialog&Gravar&Save Q3FileDialogNão &Ordenado &Unsorted Q3FileDialog&Sim&Yes Q3FileDialogJ<qt>Deseja mesmo apagar %1 "%2"?</qt>1Are you sure you wish to delete %1 "%2"? Q3FileDialog,Todos os Ficheiros (*) All Files (*) Q3FileDialog0Todos os Ficheiros (*.*)All Files (*.*) Q3FileDialogAtributos Attributes Q3FileDialog RecuarBack Q3FileDialogCancelarCancel Q3FileDialog6Copiar ou Mover um FicheiroCopy or Move a File Q3FileDialog Criar Nova PastaCreate New Folder Q3FileDialogDataDate Q3FileDialogApagar %1 Delete %1 Q3FileDialogVista Detalhada Detail View Q3FileDialog PastaDir Q3FileDialog Pastas Directories Q3FileDialog Pasta: Directory: Q3FileDialogErroError Q3FileDialogFicheiroFile Q3FileDialog$&Nome do Ficheiro: File &name: Q3FileDialog$&Tipo de Ficheiro: File &type: Q3FileDialogProcurar PastaFind Directory Q3FileDialogInacessível Inaccessible Q3FileDialogVista Abreviada List View Q3FileDialogVer &em: Look &in: Q3FileDialogNomeName Q3FileDialogNova Pasta New Folder Q3FileDialogNova Pasta %1 New Folder %1 Q3FileDialogNova Pasta 1 New Folder 1 Q3FileDialogPasta MãeOne directory up Q3FileDialog AbrirOpen Q3FileDialog Abrir Open  Q3FileDialog8Antever Conteúdo do FicheiroPreview File Contents Q3FileDialog<Antever Informação do FicheiroPreview File Info Q3FileDialog&RecarregarR&eload Q3FileDialogApenas Leitura Read-only Q3FileDialog"Leitura e escrita Read-write Q3FileDialogLer: %1Read: %1 Q3FileDialogGuardar ComoSave As Q3FileDialog(Seleccione uma PastaSelect a Directory Q3FileDialog:Mostrar ficheiros &escondidosShow &hidden files Q3FileDialogTamanhoSize Q3FileDialogOrdenarSort Q3FileDialog$Ordenar pela &Data Sort by &Date Q3FileDialog$Ordenar pelo &Nome Sort by &Name Q3FileDialog*Ordenar pelo &Tamanho Sort by &Size Q3FileDialogEspecialSpecial Q3FileDialog$Ligação para PastaSymlink to Directory Q3FileDialog*Ligação para FicheiroSymlink to File Q3FileDialog*Ligação para EspecialSymlink to Special Q3FileDialogTipoType Q3FileDialogApenas Escrita Write-only Q3FileDialogEscrever: %1 Write: %1 Q3FileDialoga pasta the directory Q3FileDialogo ficheirothe file Q3FileDialoga ligação the symlink Q3FileDialogBNão foi possível criar a pasta %1Could not create directory %1 Q3LocalFs2Não foi possível abrir %1Could not open %1 Q3LocalFs>Não foi possível ler a pasta %1Could not read directory %1 Q3LocalFs`Não foi possível apagar o ficheiro ou a pasta %1%Could not remove file or directory %1 Q3LocalFsRNão foi possível mudar o nome %1 para %2Could not rename %1 to %2 Q3LocalFs8Nao foi possível escrever %1Could not write %1 Q3LocalFsConfigurar... Customize... Q3MainWindowAlinharLine up Q3MainWindowJOperação interrompida pelo utilizadorOperation stopped by the userQ3NetworkProtocolCancelarCancelQ3ProgressDialogAplicarApply Q3TabDialogCancelarCancel Q3TabDialogPredefiniçõesDefaults Q3TabDialog AjudaHelp Q3TabDialogOKOK Q3TabDialog&Copiar&Copy Q3TextEdit Co&lar&Paste Q3TextEdit&Refazer&Redo Q3TextEdit&Desfazer&Undo Q3TextEdit LimparClear Q3TextEditCor&tarCu&t Q3TextEdit Seleccionar Tudo Select All Q3TextEdit FecharClose Q3TitleBarFecha a janelaCloses the window Q3TitleBarNContém comandos para manipular a janela*Contains commands to manipulate the window Q3TitleBarvMostra o nome da janela e contém controlos para a manipularFDisplays the name of the window and contains controls to manipulate it Q3TitleBar@Coloca a janela em ecrã completoMakes the window full screen Q3TitleBarMaximizarMaximize Q3TitleBarMinimizarMinimize Q3TitleBar.Tira a janela da frenteMoves the window out of the way Q3TitleBarZColoca uma janela maximizada no estado normal&Puts a maximized window back to normal Q3TitleBarZColoca uma janela minimizada no estado normalPuts a minimized back to normal Q3TitleBar Restaurar abaixo Restore down Q3TitleBarRestaurar acima Restore up Q3TitleBarSistemaSystem Q3TitleBarMais...More... Q3ToolBar(desconhecido) (unknown) Q3UrlOperator€O protocolo '%1' não suporta copiar ou mover ficheiros ou pastasIThe protocol `%1' does not support copying or moving files or directories Q3UrlOperatorhO protocolo '%1' não suporta criação de novas pastas;The protocol `%1' does not support creating new directories Q3UrlOperatordO protocolo '%1' não suporta obtenção de ficheiros0The protocol `%1' does not support getting files Q3UrlOperator^O protocolo '%1' não suporta listagem de pastas6The protocol `%1' does not support listing directories Q3UrlOperatorfO protocolo '%1' não suporta colocação de ficheiros0The protocol `%1' does not support putting files Q3UrlOperator|O protocolo '%1' não suporta eliminação de ficheiros ou pastas@The protocol `%1' does not support removing files or directories Q3UrlOperator†O protocolo '%1' não suporta mudança de nome de ficheiros ou pastas@The protocol `%1' does not support renaming files or directories Q3UrlOperator@O protocolo '%1' não é suportado"The protocol `%1' is not supported Q3UrlOperator&Cancelar&CancelQ3Wizard&Terminar&FinishQ3Wizard &Ajuda&HelpQ3Wizard&Avançar >&Next >Q3Wizard< &Recuar< &BackQ3Wizard Ligação recusadaConnection refusedQAbstractSocket Ligação expiradaConnection timed outQAbstractSocket(Máquina desconhecidaHost not foundQAbstractSocket"Rede inalcançávelNetwork unreachableQAbstractSocket$'Socket' desligadoSocket is not connectedQAbstractSocket:Operação de 'socket' expiradaSocket operation timed outQAbstractSocket&Passo acima&Step upQAbstractSpinBoxPasso &abaixo Step &downQAbstractSpinBoxActivarActivate QApplicationJActiva a janela principal do programa#Activates the program's main window QApplicationdO executável '%1' requere Qt %2, Qt %3 encontrado.,Executable '%1' requires Qt %2, found Qt %3. QApplicationTErro de Incompatibilidade da Biblioteca QtIncompatible Qt Library Error QApplication&Cancelar&Cancel QAxSelect&Objecto COM: COM &Object: QAxSelectOKOK QAxSelect8Seleccionar Controlo ActiveXSelect ActiveX Control QAxSelectActivarCheck QCheckBoxComutarToggle QCheckBoxDesactivarUncheck QCheckBox@&Adicionar às Cores Customizadas&Add to Custom Colors QColorDialogCores &básicas &Basic colors QColorDialog&Cores c&ustomizadas&Custom colors QColorDialogV&erde:&Green: QColorDialog&Vermelho:&Red: QColorDialog&Saturação:&Sat: QColorDialog&Valor:&Val: QColorDialog*Canal &transparência:A&lpha channel: QColorDialog &Azul:Bl&ue: QColorDialog C&or:Hu&e: QColorDialog FecharClose QComboBox FalsoFalse QComboBox AbrirOpen QComboBoxVerdadeiroTrue QComboBoxLFinalização de transacção não possívelUnable to commit transaction QDB2Driver(Ligação não possívelUnable to connect QDB2DriverFAnulação de transacção não possívelUnable to rollback transaction QDB2DriverFFinalização automática não possívelUnable to set autocommit QDB2Driver@Ligação de variável não possívelUnable to bind variable QDB2Result*Execução não possívelUnable to execute statement QDB2ResultBObtenção do primeiro não possívelUnable to fetch first QDB2ResultBObtenção do seguinte não possívelUnable to fetch next QDB2ResultFObtenção do registo %1 não possívelUnable to fetch record %1 QDB2Result.Preparação não possívelUnable to prepare statement QDB2ResultAMAM QDateTimeEditPMPM QDateTimeEditamam QDateTimeEditpmpm QDateTimeEditO Que é Isto? What's This?QDialog&Cancelar&CancelQDialogButtonBox&Fechar&CloseQDialogButtonBox&Não&NoQDialogButtonBox&OK&OKQDialogButtonBox&Gravar&SaveQDialogButtonBox&Sim&YesQDialogButtonBoxAbortarAbortQDialogButtonBoxAplicarApplyQDialogButtonBoxCancelarCancelQDialogButtonBox FecharCloseQDialogButtonBox"Fechar sem GravarClose without SavingQDialogButtonBoxDescartarDiscardQDialogButtonBoxNão Gravar Don't SaveQDialogButtonBox AjudaHelpQDialogButtonBoxIgnorarIgnoreQDialogButtonBoxN&ão para Todos N&o to AllQDialogButtonBoxOKOKQDialogButtonBox AbrirOpenQDialogButtonBoxRestaurarResetQDialogButtonBox.Restaurar PredefiniçõesRestore DefaultsQDialogButtonBox Tentar NovamenteRetryQDialogButtonBox GravarSaveQDialogButtonBoxGravar TodosSave AllQDialogButtonBoxSim para &Todos Yes to &AllQDialogButtonBox&Data de Modificação Date Modified QDirModelTipoKind QDirModelNomeName QDirModelTamanhoSize QDirModelTipoType QDirModel FecharClose QDockWidget MenosLessQDoubleSpinBoxMaisMoreQDoubleSpinBox&OK&OK QErrorMessage@&Mostrar esta mensagem novamente&Show this message again QErrorMessage&Mensagem Depuração:Debug Message: QErrorMessageErro Fatal: Fatal Error: QErrorMessage Aviso:Warning: QErrorMessagez%1 Pasta não encontrada. Por favor verifique o nome da pasta.K%1 Directory not found. Please verify the correct directory name was given. QFileDialog†%1 Ficheiro não encontrado. Por favor verifique o nome do ficheiro.A%1 File not found. Please verify the correct file name was given. QFileDialog@%1 já existe. Deseja substituir?-%1 already exists. Do you want to replace it? QFileDialog&Apagar&Delete QFileDialog &Abrir&Open QFileDialog&Mudar o Nome&Rename QFileDialog&Gravar&Save QFileDialogˆ'%1' está protegido contra escrita. Deseja apagar de qualquer forma?9'%1' is write protected. Do you want to delete it anyway? QFileDialog,Todos os Ficheiros (*) All Files (*) QFileDialog0Todos os Ficheiros (*.*)All Files (*.*) QFileDialog2Deseja mesmo apagar '%1'?!Are sure you want to delete '%1'? QFileDialog RecuarBack QFileDialog@Não foi possível apagar a pasta.Could not delete directory. QFileDialog Criar Nova PastaCreate New Folder QFileDialogVista Detalhada Detail View QFileDialog Pastas Directories QFileDialog Pasta: Directory: QFileDialogUnidadeDrive QFileDialogFicheiroFile QFileDialog$&Nome do Ficheiro: File &name: QFileDialog$FIcheiros do tipo:Files of type: QFileDialogProcurar PastaFind Directory QFileDialogSeguinteForward QFileDialogVista Abreviada List View QFileDialog O Meu Computador My Computer QFileDialogNova Pasta New Folder QFileDialog AbrirOpen QFileDialogPasta MãeParent Directory QFileDialogGravar ComoSave As QFileDialog:Mostrar ficheiros &escondidosShow &hidden files QFileDialogDesconhecidoUnknown QFileDialog&Data de Modificação Date ModifiedQFileSystemModelTipoKindQFileSystemModel O Meu Computador My ComputerQFileSystemModelNomeNameQFileSystemModelTamanhoSizeQFileSystemModelTipoTypeQFileSystemModel&Tipo de Letra&Font QFontDialog&Tamanho&Size QFontDialog&Sublinhar &Underline QFontDialogEfeitosEffects QFontDialog*&Estilo Tipo de Letra Font st&yle QFontDialogAmostraSample QFontDialog0Seleccione Tipo de Letra Select Font QFontDialog&Riscar Stri&keout QFontDialog&&Sistema de EscritaWr&iting System QFontDialog:A mudança de pasta falhou: %1Changing directory failed: %1QFtp$Ligado ao servidorConnected to hostQFtp*Ligado ao servidor %1Connected to host %1QFtp@A ligação ao servidor falhou: %1Connecting to host failed: %1QFtpLigação fechadaConnection closedQFtp2Ligação de dados recusada&Connection refused for data connectionQFtp>Ligação ao servidor %1 recusadaConnection refused to host %1QFtp(Ligação a %1 fechadaConnection to %1 closedQFtp:A criação da pasta falhou: %1Creating directory failed: %1QFtpBA descarga do ficheiro falhou: %1Downloading file failed: %1QFtp,Servidor %1 encontrado Host %1 foundQFtp4Servidor %1 não encontradoHost %1 not foundQFtp&Servidor encontrado Host foundQFtp<A listagem da pasta falhou: %1Listing directory failed: %1QFtp2A autenticação falhou: %1Login failed: %1QFtpDesligado Not connectedQFtp:A remoção da pasta falhou: %1Removing directory failed: %1QFtp@A remoção do ficheiro falhou: %1Removing file failed: %1QFtp"Erro desconhecido Unknown errorQFtpJO carregamento do ficheiro falhou: %1Uploading file failed: %1QFtpLTRQT_LAYOUT_DIRECTIONQGuiApplication"Erro desconhecido Unknown error QHostInfo.Servidor Não encontradoHost not foundQHostInfoAgent:Tipo de endereço desconhecidoUnknown address typeQHostInfoAgent"Erro desconhecido Unknown errorQHostInfoAgent$Ligado ao servidorConnected to hostQHttp*Ligado ao servidor %1Connected to host %1QHttpLigação fechadaConnection closedQHttp Ligação recusadaConnection refusedQHttp(Ligação a %1 fechadaConnection to %1 closedQHttp(O pedido HTTP falhouHTTP request failedQHttp,Servidor %1 encontrado Host %1 foundQHttp4Servidor %1 não encontradoHost %1 not foundQHttp&Servidor encontrado Host foundQHttp6Corpo parcial HTTP inválidoInvalid HTTP chunked bodyQHttpFCabeçalho de resposta HTTP inválidoInvalid HTTP response headerQHttp4Nenhum servidor para ligarNo server set to connect toQHttpPedido abortadoRequest abortedQHttpVO servidor fechou a ligação inesperadamente%Server closed connection unexpectedlyQHttp"Erro desconhecido Unknown errorQHttp4Tamanho de conteúdo erradoWrong content lengthQHttpJNão foi possível iniciar a transacçãoCould not start transaction QIBaseDriver:Erro ao abrir a base de dadosError opening database QIBaseDriverNNão foi possível finalizar a transacçãoUnable to commit transaction QIBaseDriverHNão foi possível anular a transacçãoUnable to rollback transaction QIBaseDriverFNão foi possível alocar a expressãoCould not allocate statement QIBaseResultbNão foi possível descrever a expressão de entrada"Could not describe input statement QIBaseResultLNão foi possível descrever a expressãoCould not describe statement QIBaseResultTNão foi possível obter o elemento seguinteCould not fetch next item QIBaseResultDNão foi possível encontrar o arrayCould not find array QIBaseResultPNão foi possível obter os dados do arrayCould not get array data QIBaseResultTNão foi possível obter informação da queryCould not get query info QIBaseResult\Não foi possível obter informação da expressãoCould not get statement info QIBaseResultJNão foi possível preparar a expressãoCould not prepare statement QIBaseResultJNão foi possível iniciar a transacçãoCould not start transaction QIBaseResultFNão foi possível fechar a expressãoUnable to close statement QIBaseResultNNão foi possível finalizar a transacçãoUnable to commit transaction QIBaseResult:Não foi possível criar o BLOBUnable to create BLOB QIBaseResultBNão foi possível executar a queryUnable to execute query QIBaseResult:Não foi possível abrir o BLOBUnable to open BLOB QIBaseResult6Não foi possível ler o BLOBUnable to read BLOB QIBaseResult@Não foi possível escrever o BLOBUnable to write BLOB QIBaseResult8Dispositivo sem espaço livreNo space left on device QIODevice:Ficheiro ou pasta inexistenteNo such file or directory QIODevice Permissão negadaPermission denied QIODevice8Demasiados ficheiros abertosToo many open files QIODevice"Erro desconhecido Unknown error QIODevice4Método de entrada Max OS XMac OS X input method QInputContext2Método de entrada WindowsWindows input method QInputContextXIMXIM QInputContext*Método de entrada XIMXIM input method QInputContext@Não foi possivel mapear '%1': %2Could not mmap '%1': %2QLibraryFNão foi possível desmapear '%1': %2Could not unmap '%1': %2QLibrarydDados de verificação do plugin incorrectos em '%1')Plugin verification data mismatch in '%1'QLibrary„O plugin '%1' usa uma biblioteca Qt incompatível. (%2.%3.%4) [%5]=The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]QLibraryÄO plugin '%1' usa uma biblioteca Qt incompatível. A chave de compilação esperada "%2", ficou "%3"OThe plugin '%1' uses incompatible Qt library. Expected build key "%2", got "%3"QLibrary"Erro desconhecido Unknown errorQLibrary&Copiar&Copy QLineEdit Co&lar&Paste QLineEdit&Refazer&Redo QLineEdit&Desfazer&Undo QLineEditCor&tarCu&t QLineEdit ApagarDelete QLineEdit Seleccionar Tudo Select All QLineEditJNão foi possível iniciar a transacçãoUnable to begin transaction QMYSQLDriverNNão foi possível finalizar a transacçãoUnable to commit transaction QMYSQLDriverLNão foi possível estabelecer a ligaçãoUnable to connect QMYSQLDriverPNão foi possível abrir a base de dados 'Unable to open database ' QMYSQLDriverHNão foi possível anular a transacçãoUnable to rollback transaction QMYSQLDriverjNão foi possível fazer a ligação dos valores externosUnable to bind outvalues QMYSQLResultRNão foi possível fazer a ligação do valorUnable to bind value QMYSQLResultBNão foi possível executar a queryUnable to execute query QMYSQLResultJNão foi possível executar a expressãoUnable to execute statement QMYSQLResult8Não foi possível obter dadosUnable to fetch data QMYSQLResultJNão foi possível preparar a expressãoUnable to prepare statement QMYSQLResultLNão foi possível restaurar a expressãoUnable to reset statement QMYSQLResultHNão foi possível guardar o resultadoUnable to store result QMYSQLResultfNão foi possível guardar os resultados da expressão!Unable to store statement results QMYSQLResult%1 - [%2] %1 - [%2] QMdiSubWindow&Fechar&Close QMdiSubWindow &Mover&Move QMdiSubWindow&Restaurar&Restore QMdiSubWindow&Tamanho&Size QMdiSubWindow FecharClose QMdiSubWindow AjudaHelp QMdiSubWindowMa&ximizar Ma&ximize QMdiSubWindowMaximizarMaximize QMdiSubWindowMenuMenu QMdiSubWindowMi&nimizar Mi&nimize QMdiSubWindowMinimizarMinimize QMdiSubWindowRestaurar Baixo Restore Down QMdiSubWindow&Permanecer no &Topo Stay on &Top QMdiSubWindow FecharCloseQMenuExecutarExecuteQMenu AbrirOpenQMenuAcerca do QtAbout Qt QMessageBox AjudaHelp QMessageBox.Não Mostrar Detalhes...Hide Details... QMessageBoxOKOK QMessageBox&Mostrar Detalhes...Show Details... QMessageBox8Seleccione Método de Entrada Select IMQMultiInputContextDSeleccionador de método de entradaMultiple input method switcherQMultiInputContextPlugin°Seleccionador de método de entrada que utiliza o menu de contexto dos elementos de textoMMultiple input method switcher that uses the context menu of the text widgetsQMultiInputContextPlugin\Outro 'socket' já está à escuta no mesmo porto4Another socket is already listening on the same portQNativeSocketEngine’Tentativa de utilização de 'socket' IPv6 numa plataforma sem suporte IPv6=Attempt to use IPv6 socket on a platform with no IPv6 supportQNativeSocketEngine Ligação recusadaConnection refusedQNativeSocketEngine Ligação expiradaConnection timed outQNativeSocketEngineLDatagrama demasiado grande para enviarDatagram was too large to sendQNativeSocketEngine(Máquina inalcançávelHost unreachableQNativeSocketEngine<Descritor de 'socket' inválidoInvalid socket descriptorQNativeSocketEngineErro de rede Network errorQNativeSocketEngine2Operação de rede expiradaNetwork operation timed outQNativeSocketEngine"Rede inalcançávelNetwork unreachableQNativeSocketEngine0Operação em não 'socket'Operation on non-socketQNativeSocketEngineSem recursosOut of resourcesQNativeSocketEngine Permissão negadaPermission deniedQNativeSocketEngine>Tipo de protocolo não suportadoProtocol type not supportedQNativeSocketEngine<O endereço não está disponívelThe address is not availableQNativeSocketEngine2O endereço está protegidoThe address is protectedQNativeSocketEngineHO endereço de ligação já está em uso#The bound address is already in useQNativeSocketEngineBA máquina remota fechou a ligação%The remote host closed the connectionQNativeSocketEnginehNão foi possível inicializar 'socket' de transmissão%Unable to initialize broadcast socketQNativeSocketEnginehNão foi possível inicializar 'socket' não bloqueante(Unable to initialize non-blocking socketQNativeSocketEngineJNão foi possível receber uma mensagemUnable to receive a messageQNativeSocketEngineHNão foi possível enviar uma mensagemUnable to send a messageQNativeSocketEngine2Não foi possível escreverUnable to writeQNativeSocketEngine"Erro desconhecido Unknown errorQNativeSocketEngineDOperação de 'socket' não suportadaUnsupported socket operationQNativeSocketEngineJNão foi possível iniciar a transacçãoUnable to begin transaction QOCIDriver8Não foi possível inicializarUnable to initialize QOCIDriver6Não foi possível autenticarUnable to logon QOCIDriverFNão foi possível alocar a expressãoUnable to alloc statement QOCIResult€Não foi possível fazer a licação da coluna para execução 'batch''Unable to bind column for batch execute QOCIResultVNão foi possível fazer o ligamento do valorUnable to bind value QOCIResult`Não foi possível executar a expressão de 'batch'!Unable to execute batch statement QOCIResultJNão foi possível executar a expressãoUnable to execute statement QOCIResultFNão foi possível passar ao seguinteUnable to goto next QOCIResultJNão foi possível preparar a expressãoUnable to prepare statement QOCIResultNNão foi possível finalizar a transacçãoUnable to commit transaction QODBCDriver,Não foi possível ligarUnable to connect QODBCDriver¨Não foi possível ligar - O 'driver' não suporta todas as funcionalidades necessáriasCUnable to connect - Driver doesn't support all needed functionality QODBCDriverfNão foi possível desactivar finalização automáticaUnable to disable autocommit QODBCDriver^Não foi possível activar finalização automáticaUnable to enable autocommit QODBCDriverHNão foi possível anular a transacçãoUnable to rollback transaction QODBCDriver(QODBCResult::reset: Não foi possível definir 'SQL_CURSOR_STATIC' como atributo da expressão. Por favor verifique a configuração do seu 'driver' ODBCyQODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration QODBCResult\Não foi possível fazer o ligamento da variávelUnable to bind variable QODBCResultJNão foi possível executar a expressãoUnable to execute statement QODBCResultBObtenção do primeiro não possívelUnable to fetch first QODBCResultBNão foi possível obter o seguinteUnable to fetch next QODBCResultJNão foi possível preparar a expressãoUnable to prepare statement QODBCResult InícioHomeQObjectNomeNameQPPDOptionsModel ValorValueQPPDOptionsModelJNão foi possível iniciar a transacçãoCould not begin transaction QPSQLDriverNNão foi possível finalizar a transacçãoCould not commit transaction QPSQLDriverHNão foi possível anular a transacçãoCould not rollback transaction QPSQLDriver,Não foi possível ligarUnable to connect QPSQLDriver@Não foi possível criar a 'query'Unable to create query QPSQLResultPaisagem LandscapeQPageSetupWidgetTamanho página: Page size:QPageSetupWidgetFonte papel: Paper source:QPageSetupWidgetRetratoPortraitQPageSetupWidget"Erro desconhecido Unknown error QPluginLoader@%1 já existe. Deseja substituir?/%1 already exists. Do you want to overwrite it? QPrintDialog@<qt>Deseja gravar por cima?</qt>%Do you want to overwrite it? QPrintDialog$A0 (841 x 1189 mm)A0 (841 x 1189 mm) QPrintDialog"A1 (594 x 841 mm)A1 (594 x 841 mm) QPrintDialog"A2 (420 x 594 mm)A2 (420 x 594 mm) QPrintDialog"A3 (297 x 420 mm)A3 (297 x 420 mm) QPrintDialogPA4 (210 x 297 mm, 8.26 x 11.7 polegadas)%A4 (210 x 297 mm, 8.26 x 11.7 inches) QPrintDialog"A5 (148 x 210 mm)A5 (148 x 210 mm) QPrintDialog"A6 (105 x 148 mm)A6 (105 x 148 mm) QPrintDialog A7 (74 x 105 mm)A7 (74 x 105 mm) QPrintDialogA8 (52 x 74 mm)A8 (52 x 74 mm) QPrintDialogA9 (37 x 52 mm)A9 (37 x 52 mm) QPrintDialog,Nomes Alternativos: %1 Aliases: %1 QPrintDialog&B0 (1000 x 1414 mm)B0 (1000 x 1414 mm) QPrintDialog$B1 (707 x 1000 mm)B1 (707 x 1000 mm) QPrintDialog B10 (31 x 44 mm)B10 (31 x 44 mm) QPrintDialog"B2 (500 x 707 mm)B2 (500 x 707 mm) QPrintDialog"B3 (353 x 500 mm)B3 (353 x 500 mm) QPrintDialog"B4 (250 x 353 mm)B4 (250 x 353 mm) QPrintDialogPB5 (176 x 250 mm, 6.93 x 9.84 polegadas)%B5 (176 x 250 mm, 6.93 x 9.84 inches) QPrintDialog"B6 (125 x 176 mm)B6 (125 x 176 mm) QPrintDialog B7 (88 x 125 mm)B7 (88 x 125 mm) QPrintDialogB8 (62 x 88 mm)B8 (62 x 88 mm) QPrintDialogB9 (44 x 62 mm)B9 (44 x 62 mm) QPrintDialog$C5E (163 x 229 mm)C5E (163 x 229 mm) QPrintDialog$DLE (110 x 220 mm)DLE (110 x 220 mm) QPrintDialogXExecutivo (7.5 x 10 polegadas, 191 x 254 mm))Executive (7.5 x 10 inches, 191 x 254 mm) QPrintDialog˜Não é possível escrever no ficheiro %1. Por favor escolha um nome diferente.=File %1 is not writable. Please choose a different file name. QPrintDialog"O ficheiro existe File exists QPrintDialog(Folio (210 x 330 mm)Folio (210 x 330 mm) QPrintDialog*Ledger (432 x 279 mm)Ledger (432 x 279 mm) QPrintDialogPLegal (8.5 x 14 polegadas, 216 x 356 mm)%Legal (8.5 x 14 inches, 216 x 356 mm) QPrintDialogPCarta (8.5 x 11 polegadas, 216 x 279 mm)&Letter (8.5 x 11 inches, 216 x 279 mm) QPrintDialogOKOK QPrintDialogImprimirPrint QPrintDialog4Imprimir Para Ficheiro ...Print To File ... QPrintDialogImprimir todas Print all QPrintDialog&Selecção de páginas Print range QPrintDialog*Selecção de ImpressãoPrint selection QPrintDialog.Tablóide (279 x 432 mm)Tabloid (279 x 432 mm) QPrintDialogJEnvelope #10 Comum EUA (105 x 241 mm)%US Common #10 Envelope (105 x 241 mm) QPrintDialog"ligado localmentelocally connected QPrintDialogdesconhecidounknown QPrintDialog FecharCloseQPrintPreviewDialogPaisagem LandscapeQPrintPreviewDialogRetratoPortraitQPrintPreviewDialog JuntarCollateQPrintSettingsOutput CópiasCopiesQPrintSettingsOutput OpçõesOptionsQPrintSettingsOutputPáginas de Pages fromQPrintSettingsOutputImprimir todas Print allQPrintSettingsOutput&Selecção de páginas Print rangeQPrintSettingsOutputSelecção SelectionQPrintSettingsOutputatoQPrintSettingsOutputImpressoraPrinter QPrintWidgetCancelarCancelQProgressDialog AbrirOpen QPushButtonActivarCheck QRadioButtonDmá sintaxe de classe de caracteresbad char class syntaxQRegExp2má sintaxe de antecipaçãobad lookahead syntaxQRegExp.má sintaxe de repetiçãobad repetition syntaxQRegExp^funcionalidade desactivada está a ser utilizadadisabled feature usedQRegExp(valor octal inválidoinvalid octal valueQRegExp0limite interno alcançadomet internal limitQRegExp:delimitador esquerdo em faltamissing left delimQRegExpsem errosno error occurredQRegExpfim inesperadounexpected endQRegExp6Erro ao abrir base de dadosError to open databaseQSQLite2DriverJNão foi possível iniciar a transacçãoUnable to begin transactionQSQLite2DriverNNão foi possível finalizar a transacçãoUnable to commit transactionQSQLite2DriverHNão foi possível anular a transacçãoUnable to rollback TransactionQSQLite2DriverJNão foi possível executar a expressãoUnable to execute statementQSQLite2ResultHNão foi possível obter os resultadosUnable to fetch resultsQSQLite2Result<Erro ao fechar a base de dadosError closing database QSQLiteDriver:Erro ao abrir a base de dadosError opening database QSQLiteDriverJNão foi possível iniciar a transacçãoUnable to begin transaction QSQLiteDriverNNão foi possível finalizar a transacçãoUnable to commit transaction QSQLiteDriverVIncorrespondência de contagem de parâmetrosParameter count mismatch QSQLiteResult^Não foi possível fazer a ligação dos parametrosUnable to bind parameters QSQLiteResultJNão foi possível executar a expressãoUnable to execute statement QSQLiteResult<Não foi possível obter a linhaUnable to fetch row QSQLiteResultLNão foi possível restaurar a expressãoUnable to reset statement QSQLiteResult FundoBottom QScrollBarBorda esquerda Left edge QScrollBarLinha abaixo Line down QScrollBarLinha acimaLine up QScrollBar"Página para baixo Page down QScrollBar(Página para esquerda Page left QScrollBar&Página para direita Page right QScrollBar Página para cimaPage up QScrollBarPosiçãoPosition QScrollBarBorda direita Right edge QScrollBar&Deslizar para baixo Scroll down QScrollBarDeslizar aqui Scroll here QScrollBar,Deslizar para esquerda Scroll left QScrollBar.Deslizar para a direita Scroll right QScrollBar$Deslizar para cima Scroll up QScrollBarTopoTop QScrollBar++ QShortcutAltAlt QShortcutAnteriorBack QShortcutBackspace Backspace QShortcutBacktabBacktab QShortcutBass Boost Bass Boost QShortcutBass Baixo Bass Down QShortcutBass CimaBass Up QShortcut ChamarCall QShortcutCaps Lock Caps Lock QShortcutCapsLockCapsLock QShortcutContexto1Context1 QShortcutContexto2Context2 QShortcutContexto3Context3 QShortcutContexto4Context4 QShortcutCtrlCtrl QShortcut DeleteDel QShortcut DeleteDelete QShortcut BaixoDown QShortcutEndEnd QShortcut EnterEnter QShortcutEscEsc QShortcut EscapeEscape QShortcutF%1F%1 QShortcutFavoritos Favorites QShortcutInverterFlip QShortcutSeguinteForward QShortcutDesligarHangup QShortcut AjudaHelp QShortcutHomeHome QShortcut Página Principal Home Page QShortcut InsertIns QShortcut InsertInsert QShortcutExecutar (0) Launch (0) QShortcutExecutar (1) Launch (1) QShortcutExecutar (2) Launch (2) QShortcutExecutar (3) Launch (3) QShortcutExecutar (4) Launch (4) QShortcutExecutar (5) Launch (5) QShortcutExecutar (6) Launch (6) QShortcutExecutar (7) Launch (7) QShortcutExecutar (8) Launch (8) QShortcutExecutar (9) Launch (9) QShortcutExecutar (A) Launch (A) QShortcutExecutar (B) Launch (B) QShortcutExecutar (C) Launch (C) QShortcutExecutar (D) Launch (D) QShortcutExecutar (E) Launch (E) QShortcutExecutar (F) Launch (F) QShortcut&Correio Electrónico Launch Mail QShortcut Média Launch Media QShortcutEsquerdaLeft QShortcutMédia Seguinte Media Next QShortcutTocar Média Media Play QShortcutMédia AnteriorMedia Previous QShortcutGravação Média Media Record QShortcutParar Média Media Stop QShortcutMenuMenu QShortcutMetaMeta QShortcutNãoNo QShortcutNum LockNum Lock QShortcutNum LockNumLock QShortcutNumber Lock Number Lock QShortcutAbrir EndereçoOpen URL QShortcutPage Down Page Down QShortcutPage UpPage Up QShortcut PausePause QShortcut PgDownPgDown QShortcutPgUpPgUp QShortcut PrintPrint QShortcutPrint Screen Print Screen QShortcutRefrescarRefresh QShortcut ReturnReturn QShortcutDireitaRight QShortcutScroll Lock Scroll Lock QShortcutScrollLock ScrollLock QShortcutProcurarSearch QShortcut SelectSelect QShortcut ShiftShift QShortcut SpaceSpace QShortcutHibernaçãoStandby QShortcut PararStop QShortcut SysReqSysReq QShortcutSystem RequestSystem Request QShortcutTabTab QShortcutTreble Baixo Treble Down QShortcutTreble Cima Treble Up QShortcutCimaUp QShortcutVolume Cima Volume Down QShortcutVolume Mute Volume Mute QShortcutVolume Baixo Volume Up QShortcutSimYes QShortcut"Página para baixo Page downQSlider(Página para esquerda Page leftQSlider&Página para direita Page rightQSlider Página para cimaPage upQSliderPosiçãoPositionQSlider2Operação de rede expiradaNetwork operation timed outQSocks5SocketEngine MenosLessQSpinBoxMaisMoreQSpinBoxCancelarCancelQSql.Cancelar as alterações?Cancel your edits?QSqlConfirmarConfirmQSql ApagarDeleteQSql(Apagar este registo?Delete this record?QSqlInserirInsertQSqlNãoNoQSql*Gravar as alterações? Save edits?QSqlActualizarUpdateQSqlSimYesQSqlLNão foi possível estabelecer a ligaçãoUnable to open connection QTDSDriverRNão foi possível utilizar a base de dadosUnable to use database QTDSDriver,Deslizar para Esquerda Scroll LeftQTabBar*Deslizar para Direita Scroll RightQTabBar&Copiar&Copy QTextControl Co&lar&Paste QTextControl&Refazer&Redo QTextControl&Desfazer&Undo QTextControl<Copiar &Localização da LigaçãoCopy &Link Location QTextControlCor&tarCu&t QTextControl ApagarDelete QTextControl Seleccionar Tudo Select All QTextControl AbrirOpen QToolButtonPressionarPress QToolButton@Esta plataforma não suporta IPv6#This platform does not support IPv6 QUdpSocketRefazerRedo QUndoGroupDesfazerUndo QUndoGroup<vazio> QUndoModelRefazerRedo QUndoStackDesfazerUndo QUndoStackHInserir carácter de controlo Unicode Insert Unicode control characterQUnicodeControlCharacterMenuVLRE Início de encaixe esquerda-para-direita$LRE Start of left-to-right embeddingQUnicodeControlCharacterMenu>LRM Marca esquerda-para-direitaLRM Left-to-right markQUnicodeControlCharacterMenu`LRO Início de sobreposição esquerda-para-direita#LRO Start of left-to-right overrideQUnicodeControlCharacterMenu<PDF Formatação pop direccionalPDF Pop directional formattingQUnicodeControlCharacterMenuVRLE Início de encaixe direita-para-esquerda$RLE Start of right-to-left embeddingQUnicodeControlCharacterMenu>RLM Marca direita-para-esquerdaRLM Right-to-left markQUnicodeControlCharacterMenu`RLO Início de sobreposição direita-para-esquerda#RLO Start of right-to-left overrideQUnicodeControlCharacterMenu>ZWJ Ligador de comprimento zeroZWJ Zero width joinerQUnicodeControlCharacterMenuHZWNJ Não-ligador de comprimento zeroZWNJ Zero width non-joinerQUnicodeControlCharacterMenu>ZWSP Espaço de comprimento zeroZWSP Zero width spaceQUnicodeControlCharacterMenu FundoBottomQWebPageIgnorarIgnoreQWebPageIgnorar Ignore Grammar context menu itemIgnoreQWebPageBorda esquerda Left edgeQWebPage"Página para baixo Page downQWebPage(Página para esquerda Page leftQWebPage&Página para direita Page rightQWebPage Página para cimaPage upQWebPageRestaurarResetQWebPageBorda direita Right edgeQWebPage&Deslizar para baixo Scroll downQWebPageDeslizar aqui Scroll hereQWebPage,Deslizar para esquerda Scroll leftQWebPage.Deslizar para a direita Scroll rightQWebPage$Deslizar para cima Scroll upQWebPage PararStopQWebPageTopoTopQWebPageDesconhecidoUnknownQWebPageO Que é Isto? What's This?QWhatsThisAction**QWidget&Terminar&FinishQWizard &Ajuda&HelpQWizard&Avançar >&Next >QWizard< &Recuar< &BackQWizardCancelarCancelQWizard AjudaHelpQWizard%1 - [%2] %1 - [%2] QWorkspace&Fechar&Close QWorkspace &Mover&Move QWorkspace&Restaurar&Restore QWorkspace&Tamanho&Size QWorkspace&Sair Sombra&Unshade QWorkspace FecharClose QWorkspaceMa&ximizar Ma&ximize QWorkspaceMi&nimizar Mi&nimize QWorkspaceMinimizarMinimize QWorkspaceRestaurar Baixo Restore Down QWorkspaceSombr&aSh&ade QWorkspace&Permanecer no &Topo Stay on &Top QWorkspaceœdeclaração de codificação ou declaração única esperada ao ler a declaração XMLYencoding declaration or standalone declaration expected while reading the XML declarationQXmlTerro na declaração de uma entidade externa3error in the text declaration of an external entityQXml6erro ao analisar comentário$error occurred while parsing commentQXml6erro ao analisar o conteúdo$error occurred while parsing contentQXmlberro ao analisar a definição de tipo de documento5error occurred while parsing document type definitionQXml2erro ao analisar elemento$error occurred while parsing elementQXml6erro ao analisar referência&error occurred while parsing referenceQXml<erro disparado pelo consumidorerror triggered by consumerQXml†referência de entidade geral analisada externa não permitida na DTD;external parsed general entity reference not allowed in DTDQXml¢referência de entidade geral analisada externa não permitida no valor do atributoGexternal parsed general entity reference not allowed in attribute valueQXmlrreferência de entidade geral interna não permitida na DTD4internal general entity reference not allowed in DTDQXmlVnome inválido de instrução de processamento'invalid name for processing instructionQXml(uma letra é esperadaletter is expectedQXmlTmais de uma definição de tipo de documento&more than one document type definitionQXml.não ocorreu nenhum errono error occurredQXml(entidades recursivasrecursive entitiesQXmlbdeclaração única esperada ao ler a declaração XMLAstandalone declaration expected while reading the XML declarationQXml2má combinação de etiqueta tag mismatchQXml&carácter inesperadounexpected characterQXml4fim de ficheiro inesperadounexpected end of fileQXmlnreferência de entidade não analisada em contexto errado*unparsed entity reference in wrong contextQXmlNversão esperada ao ler a declaração XML2version expected while reading the XML declarationQXmlDvalor errado para declaração única&wrong value for standalone declarationQXmlˆTreeLine-3.2.1/translations/qt_ru.qm000066400000000000000000004552511506556630100174610ustar00rootroot00000000000000<¸dÊÍ!¿`¡½ÝB-À*À+�ˆ@ó„Aó¨BóóCôDôqEõ4FõŽGõ²HõÖIõúP÷éQø RøXSø|Tø UøÄVùWùBXùfYùŠ]%èsë't‡„ëÏߎŸ;&À;ºò;z;ú;4ŽM&O }O À¯U}&8þñõ=òdm&`tò�¯,þ(5 d+;4µ+;dó+OM1-hD@óÌE@ø1H4‚LHYQ¾H��WIC‹J¼‹)JÄ “JÄŠÑLDŒIL“Œ�PS‘QRýRV+TÇŸ¢U½ 'X´¥ Zr«í[`yó\ǰÃ]xð‰_à ú_ò%ygÉ&1º5ÊÔE7µ¿Ã{‡›C ‡›„p�‰„F“µ†1–$RÓ–[†š˜,‡e¦y X¦yŠq§Ô“B§Ôn«ŒЧ¬9SA¶E å¶Þ‹îÄz‚Ï ÉÏ�+Ð%F^ÐD�êÓŽÖ�ì;Ö�&©Ö�)4Ö�-’Ø5Žuì0¥›ì0ºgì0Áì0�[ì0>ö5�íö5êáÏ�æ W> D'2 DP²+Ô˜´ƒŠ--¶Š¥’|¶Š¥!·Ržòº·�Tðº÷ž,M¼~.!¾‚´òö¾œû§K¿¾x„¿EåxÌÀ‚´yÄ{Žû+Ç=±ÈrÛAaÛô7âL´Þ'ä¤ÎúæjVBó‚¤#•󂤠Fó‚¤Ý0ó‚¤ä|ó‚¤nšó‚¤sÑõØm¥2õðM¤6e™ï…c^¼ÚáçÀžá·£ü±¥q´:èTeÉ ê‚|z!Ïe&¸ž#\(¸9ïÉ)Õ°*(Lÿê*(”ü]*(•üœ*(–üÛ*( ý*(¡ýY*(¢ý˜*(£ý×*(¤þ*(¥þU*(¦þ”*(§ÿ*/e°K*ASf‰+‹ %+žÖÜ,N´Ö*;„¼)=¤-¨?†4×@ÍN9FoDKi„†bO«çÂ\c· `à£cÖƒš¦dåõ|ûfãÄ$~jCN mtÕ§p/TB qÑtßu¶u(µ�Z}kaº€Þ^.ã�½õX‚ˆàí,‹î[‹QÞ_ù�Ó~,‘¿— ¾0—øÑ_‡žèÔø[¦ ß©ßÒ”G¯É$„2¯É$9t¯É$;°‚µÑ´àäSu¹îg†Á¼°›ò¼ÿ§�SÀ0ŠÃ( °�ÊôrÎèÎ^Ú֊²×ñUìã nè¯ãõÉŸQä,Ôs�ëÕÿùAÑŽ <3žº. nÒ=à‘ù&H„rô+› ”.Ž–/¥ÄrS=BõZÃ?5)ã@`…gÊCr€£IxSÑLÙŠ6Rå>)³YMá]ÚYÚuþ,_oµMubUC+c{Cöc{DöNc{Eö~dÔnì_esƒôËkD>+n«Ø v'œ4O€»Ñ^IƒpÀBˆxóQ팇ÛgŽÛŠE–´N·–»]v¡—ÌÅ)¹˜I¼˜I¼3¿˜I¼ˆ-˜I¼ G™(²FËŸI•ŸY•SŸi••Ÿy•ן‰” Ÿ™”KŸ©”�Ÿ¹”ÏŸé“…Ÿù“ÇŸI—cŸ‰–[Ÿ™–�Ÿ©–ߟ¹—!Ÿù–¡uDa}¡uDid¢?’‚Ȣݾ ¦D u¦L÷ ¦oÃ'ö¨½•,¬,¥EC¬,¥“v¬,¥‹P¬,¥«¬«]똬«]ù®®åœl4´é„6f¹Êåìì¹Êå!ź ä~2º äÓÁ•ÎÖɘeŒÄÑfRJ#Ö*ÂGÑánòåÍ9ƒ‹èNÀ�-é•J•ë˜ÇTáîTP îTQ >îTR ¡îTS ÑîTT îTU 1îTV aîTW ‘îTX ÁîTY ñðë‰\ÁøSÒW ûPqdþV…öÿfR?ކBƒ·œ”‘C°±ç+ ‚óU¬å�ÅôhîQô˜¼‚yÙúÔp¤µá=¶“?e …l“7$ãÖ&‹~Uñ)È2‹@.§yX­5åÆ˜8‘Ä™ 8¼Ñõ>1¥Î?"£žQFÏÃë(KNò LÿÁô;Mî…JN¾©2'O{@‰V“|Wj]4Š,]¿žp|]¿žvÞe4û e6; Cg°^¡|k¶Þ¢ŒnMŒèƒrHÚ¡wy}Åí~›´í÷†1Z‹‰¯ ëŒ5t¥¶ŒFÅK>Œ¼Ž¦'“åW ˜G%\d™ØµÙµ›ˆ˜§Ô›¨Äœ+¤¨žä ¤`€Ñ¤ÎYˆªª‰zg¬;åYά>äÀ’¬Jå—M­­¤cz®xAZ°9\Y°ˆÁ«q°�sYYµÞ% r¶ˆÕân¸Œ¼® ½C-9 Â5Ë ”ÆC^i±˾äwRÔiÒþÚZ>'ÏÛi}±%Ûz‹9zߺºñtãÄ6Ûä�¥ µçf•Æ7ê—tÓ’ë¡¥Úþø˜EFÊü3g±õþ!ží³-dö/ Éøú$¢~bIÞ~bPáMŠ*�éQ¸!ë¿uT%?å­Î)òɯ+›yÊ+²&Q+ï3o,$å`ˆ/ô…+«0jIKh4~Ò¡6Ï §˜8-Ç v<…ãh<nˆTA£•'­Dç^G¾ñ]hGÎbOÄLô|°LAUò{LÿÁô•O�r³—PѧeUR“ iŠRÌC�£SfgLéSÅnYUô{*UôÁ;UÞToqV(c!YÄ»ƒZ4lôþ[ ­]k*I¢^o2ÍF^~°Í�^ãné_PÔ²µ_pÔ&`7õ4½fgÙëúkQ¾)Mn$4Ì£oÛN"p4Ä(¯pñå»×qè"�{ ú{*B}u�¡ë}w�wó}¶¨!‚†Ò&Œˆô¢Ê>Šê‚:�r°{ �çõ —B˜\ƒ½ ›v£.O›ƒtðN›ƒt#^¡®38(¥Pè5¦<>¾|¨¼™wª�ô µ¬šb¿Ó¯ƒWÀWµD„fµY´–·ÝtA·ÝthÄ·Ýt½ ºç�”À_ ¡@Âa±25ÂÝÎÓuÉF± ¾Ê™Ê¢ä$�Ê¢äæIÊÆ´åÍÊçd%nÊçd¡'ÊçdÞ£ÊçdçGÊçdê¬Ì59tzÐ2ÂÁÑ�ç/)ÖjÂÁ[Ø+kÉØÿ鉫ÚNSæÅÝWD`}ãµ¾;žå1ÄêræB>Îëk˜²íëtþÈ—ìaþé°ìy®Õì»UÇ0ììRÉ^îd�ÈÕþ¯BÕþáhäópÈËAw®Ú’$K×–½�µÄBD,%¤½Âº …‘tÝ0½bËŒ2ì5p6’Ñbù:3©û>Ñ*îK?;ÞóC˜U­DØ�J0žò LÿÁõXLÿÑøèU|ˆ]\¬"²arÅoŠlòd‰ün8åÞ\sFY_Vu®[7|¬#}wZî›}š$w¦„”^?䌂GŒÏ—.��Z’.Å�Z’¤ÙŸ±Djø¢úÂʆ£ø$‡Z°Gí[°` e°zdZk±< ¯´K<3´¼| +·ƒz²·ƒðÅ6aÆ×³*„Ë8‡QKТ~©HÕCļ�ÕfC‡™×}ÆrØž Úe“�ûã“t©ÿãûµ³ë»E\#ïú„b9%5PQ©Š­’Αw>Ñ-ìbDê`…F#²Ê%’¾"�'ÕÌŒ+›i+¸)[.÷Ž%4Ð>P5kE7Œ=ƒâ� =ƒâñž>1.‡ ?ƒâ”ú?ƒâšû@J‰…CtIS´EfÄäZFú…)NºPž~V%îeµV%îgXU GC^MÿT^MÿŸ_Ž“Rå`åå|bD«¡bG·‹Åb^ÃþhI•UGiê$Ü¢m5�©x1 ˆ z*2…~þèÇO‚¨dàãŠU€…Ç‹¬Ù…þ•z6•c.j›¯4ßô¦µ„N3ª�Fª�±¬bô¸ªžÀÓºm]»Ñúl»Ñû¦¼%BƒE¼­Ô/C½ŒÈ¥�ÀbÑsÄØiRaÇC¼ÎÉU�…Ê´5¤¹ʶզóÌÉÅ+ýÏ¡$à½Ó^ mÃÚÔ„[Û”#$òÝD„êâÜd6ãAŽÕ†ðF5¦ò»YêDópÉleù¥1èêú&D‚süùIG‰ý=©W‘ äÑ$ü }$¢£ qeg[ Ú¤» Ú¥)k ôd¹( íEžâ íEÜ AcL Úôµt "knv. 3š5Æ´ ™ëR bÅ,¥ b�büä b¾`y« gUò˜‚ h¾iF laô ì laôº7 lfñG qzŒ¯Ô s-”3› tíN×™ xqƒ ‚|ÅÃ Š·J-Á ŒtÓKr ŒÖôØÒ Ž .!‡ •y`î –é‚†Æ š„9D­ Ÿ¥ÞórŸ ¸æÉx£ ¸æÉŸØ ºn™� º°.Ê Ä$é|1 ŰeëÒ ÊY+€ ˰! Õ Â Õ  ÝÕÿY æ¡Ä:� 팤Ô` 팤Ծ îEÄ„œ ñ%'ý{ ÷»¼—¥ ú¸ÒL| ûC’y ÿÄɇ½ èqXÞ  D1z ü®è5 }´ñ ü9MÌ o´7K Ðô»• í1 !¸øE… '(à '(Ûb )fê )µží */å„Þ *ÅŽóH .>¤š 2§å*÷ 7uó‰ ;�Ù�ï =ä\– H åð J‰"Ì Qí RÛ®h Ty í` Tþ^…Ž Uj4”ž YHY ¿ \tž¨ ]‘žÇæ ^&Ęà `±pð `±l» `±oø bÕ–ô c(å'! c·E ä dht,Ä eœÇI e¨{€° fŽ1_ fü*(/ g5U" gy½ÅX gîn¶ t xšÄÀp ~ó”vb „­$& ‘[Ä…ž ˜Iœdˆ ›m4� œœO œ¬¡£ œ¬t³ Ÿfµ? ŸjñÔù  =)U| ¨JɪN ©3TÓ ª$¡ ª${Ë ¬%pü ¬,…?W ¹>r[— ¹E!„‹ ¿`j” Ä㋵ Äãê4 ÆB‡' ÆÄT ÆÄ‡ ÇvĪû Ê+ éò Êl«2 Ë”[ª ÐP¸ L ÒWÔ,E Þ685î ä“çíX å«Ií è¼:ö ëF AÅ ëf A~ ï±åu ÷4�sö øÊ.Zh ùû"ú ý‡sE¼ AAck —9ð ˜Ä… ÷9£À !i¢ rÉ‹‚ %j #-tÄÜ '‚Ìô +«i6 0†N u =@!ìº @±åÇ A›ùÏ¥ CóU[ F)3ù L‹Nc Lö á Mc\ SÐu× V×z> ZƒŸj ]qt0ê ]â$"� cÂ3® f=¦ • io>4 l#¦† sàk: sàpk· wq=Î yC™B ‹¤]€ ŒH@ �Ü ² ‘$þD. ’.@®} ›…ªÅ �ˆ½¼ £Ü Ü £Ü “¨ £Ü æ ¥zd‰; ¨¼5~ ©~ÌJç ®áéb¨ ¯ÙJE÷ ´Ž? ¿t.⊠ÂkÔó= ÂÂËÝ ÇÉ:® ÊN>Œq Ë/˜†a Ì·êîê ̺ó[î Ô-D\Ù ÖØ.�; Ú%³o ÛG‘ì Û·å#œ Ü6Çä âkÔy^ æÅº¥ ê)yY� óŸã}o óŸãðÓ ôÄ9» õ0Ë N $r§ §éì¨ 5ùúš ÷ úø I©ùÞ µ™ú< ŒITk ¨©ûV º™û´ ‚%Z£ ßL ö Ç (G› ƒòš� ¸c e ô� ®Þ$ ! 5ÈA "N%Ç‘ .ÉãM 5Î! 7F´m :†9J >ÏòcÒ >Ïòf >Ïòg¾ >Ïò{â >Ïò}à >Ïò� >Ïò�¿ >ÏòÇ� >Ïòà >Ïòè3 >ÏòïÌ @ÓŠ¶ Aà£� Efž  KÑúï KÑü) K’½ Mbâ©g OœÅÄ‘ RVŽL¿ RV®Îg SGùͶ SÀ�+, Wo²Ŧ Yçõ¨ [•›£ ^ÄUT' hÛ®Sô j7o>… p¡Ã™ „’>r ˆ¾¢¾¹ ŒÑBx? �_S Žè& �½T!» �½Tœõ �½Tß— �½Té) ’›¢ys “èÄ$ “èÄåV ”ܬT ”Å T§ –�ît ›c™¹ œüS» �)dÅ� Ÿ§T˜ô ©‰ÿÿ ¬Á." ¬Á.qØ ¬Á.�Ö ¬Á.Ú~ ¬Á.â ¬Á.n ¬Á.qW ¬â¢ô °†Ô¹¯ ¸aÂÄ ¹eu( »s¨h Ìôe�© ÍÜ%n Ò‚î µ áÙK ã>•ÜÜ èY”ò ë¬åŒô ó|ô} t8œ aÒ¦ „Õ�· ˆÚ9 8ô<å ˜£é? Ê$a ñ”z ${v #=—/Ø (I$³ +>ºû 0ÒEZ 4~¾�; 64~4 8¦”ü :³n¼! ;ɾ FgÉ: K×9Êù Ptµ¦| Sì,¬ fèevÎ iFC�~ iØÄH iØÄŽD jÓ®} m9äHe n¤î%¨ u®¡ª uÊ *Ü uüÁÒ$ v&¥ðµ w®w w}¤w\ |[®, �u�°ê ƒÈô^à ƒÈôhu „ÿ<76 ŽJ©m —Ã^º™ šKäÃI £¼Y�ÿ ªôRh ¯%7î% ¶²Ë¤ Ä"¦£É ÇÒU–� Ûùž& ßb¨v àÄYH› ä&Þ+¨ çxÔ×� ë¼óJí ìÕ+E ðt5¥Ï ø¾§4 øÊÒ˜HÕŽ/w¤2­�TB‡Û‡ÛH4Ì=j›gT¡Fñ ™#ãŒà*‡« *¦ò\+.†t… /ÇE]/ÇEÀ3~þû7ñÒ2ý8þ9Ì8ºþåNÞµ�mOO”˜V5ãlXRu0[Ÿ V[°d~±`ïÉ´a.Å�gc´ãnyG*�y$9Åy?.Ó �%+_�%f¥ˆn““ª4Ïs”vˆ;’šÑô™;Ÿjâ !ŸÚ•¸¯(>Â곈dù6´÷S{w·°'¨¸Â²@C»Nžž»®^´¿ß:ìnÂ�¥(,ÊæÂÖÎÂ`ØÓ$'ØÜrµ“èÝ–þ ãrœêåTcåE næ´÷6ñR¼zúrÁ”ûFCN7:5 ÞþØQ ¶Ù�º íÒDŸlD1ÑK2 –þ"ì"#r!%º4&ë%º4P,-¤áÀ-v›þÌ0i)šR0’À›–1�cÀÙ1µ¥hw2wT™™=|s=²…üe>k7ÿF74ÔMK¡ò¸²L$.È[m4 jb4rõ—c5x;g3"]iC¼øi¯TK³l?ÅÌpþÅéåz3žˆÖ{`åf{~a—Ø�&òÊ}�&òÍ?�DÉh†Ã“Hˆ$t‚Ã�¸ôßÜ¡[ôªÏ$0O«Í££«Í£ë‘®þ#ÿ¯·Ew´�Üy¾N=mÁ 8SzÃÙt-7Ä›45ÅßôUÆÈŒ´)íȬ´)mÉÉg ÉrÔ²ÉrÔó‡ÉÜ´¦Ì-1æ®ÖíUCÂè$ƒéB÷(ÖðÙ~»MõÓîå÷6q� øt2 ,ùMÙOžû¾œû¾ØÊû¾m*û¾pfýâHÄi,½0:@KBL 2:;04:C Close Tab CloseButton ?@>3@0<<5 %1About %1MAC_APPLICATION_MENU!:@KBL %1Hide %1MAC_APPLICATION_MENU!:@KBL 4@C385 Hide OthersMAC_APPLICATION_MENU0AB@>9:8...Preferences...MAC_APPLICATION_MENU025@H8BL %1Quit %1MAC_APPLICATION_MENU !;C61KServicesMAC_APPLICATION_MENU>:070BL 2AQShow AllMAC_APPLICATION_MENU*B:070=> 2 A>548=5=88Connection refusedQAbstractSocket6@5<O =0 A>548=5=85 8AB5:;>Connection timed outQAbstractSocket#75; =5 =0945=Host not foundQAbstractSocket!5BL =54>ABC?=0Network unreachableQAbstractSocketH?5@0F8O A A>:5B>< =5 ?>445@68205BAO$Operation on socket is not supportedQAbstractSocket$!>:5B =5 ?>4:;NGQ=Socket is not connectedQAbstractSocket,@5<O >?5@0F88 8AB5:;>Socket operation timed outQAbstractSocketR>?KB:0 ?>4:;NG8BLAO 2> 2@5<O ?>4:;NG5=8O1Trying to connect while connection is in progressQAbstractSocket&K45;8BL 2AQ &Select AllQAbstractSpinBox(03 22&5@E&Step upQAbstractSpinBox(03 2=&87 Step &downQAbstractSpinBox#<5=LH8BLDecreaseQAccessibleActionInterface$#<5=LH8BL 7=0G5=85Decrease the valueQAccessibleActionInterface#25;8G8BLIncreaseQAccessibleActionInterface$#25;8G8BL 7=0G5=85Increase the valueQAccessibleActionInterface 060BLPressQAccessibleActionInterface#AB0=>28BL$>:CASetFocusQAccessibleActionInterface #AB0=>28BL D>:CASets the focusQAccessibleActionInterface>:070BL5=NShowMenuQAccessibleActionInterface>:070BL <5=NShows the menuQAccessibleActionInterface!<5=8BLToggleQAccessibleActionInterface"!<5=8BL A>AB>O=85Toggles the stateQAccessibleActionInterface$K?>;=8BL 459AB285Triggers the actionQAccessibleActionInterface5BNoQAndroidPlatformTheme5B 4;O 2A5E No to AllQAndroidPlatformTheme0YesQAndroidPlatformTheme0 4;O 2A5E Yes to AllQAndroidPlatformThemej@>3@0<<5 «%1» B@51C5BAO Qt %2, 0 8A?>;L7C5BAO Qt %3.,Executable '%1' requires Qt %2, found Qt %3. QApplicationDH81:0 A>2<5AB8<>AB8 181;8>B5:8 QtIncompatible Qt Library Error QApplication ?@>3@0<<5AboutQCocoaMenuItem QtAbout QtQCocoaMenuItem>=D83C@ConfigQCocoaMenuItem>?8@>20BLCopyQCocoaMenuItemK@570BLCutQCocoaMenuItem KE>4ExitQCocoaMenuItem0@0<5B@KOptionsQCocoaMenuItemAB028BLPasteQCocoaMenuItem!2>9AB2 PreferenceQCocoaMenuItem 025@HQuitQCocoaMenuItemK45;8BL 2AQ Select AllQCocoaMenuItem0AB@>9:SettingQCocoaMenuItem 0AB@SetupQCocoaMenuItem&5 A>E@0=OBL Don't Save QCocoaThemeF&>1028BL : ?>;L7>20B5;LA:8< F25B0<&Add to Custom Colors QColorDialog&A=>2=K5 F25B0 &Basic colors QColorDialog.&>;L7>20B5;LA:85 F25B0&Custom colors QColorDialog&5;Q=K9:&Green: QColorDialog &HTML:&HTML: QColorDialog&@0A=K9:&Red: QColorDialog &0A:&Sat: QColorDialog &/@::&Val: QColorDialog&;LD0-:0=0;:A&lpha channel: QColorDialog!&8=89:Bl&ue: QColorDialog`C@A>@ 2 %1, %2, F25B: %3 06<8B5 ESC 4;O >B<5=K/Cursor at %1, %2, color: %3 Press ESC to cancel QColorDialog &">=:Hu&e: QColorDialog&7OBL F25B A M:@0=0Pick Screen Color QColorDialogK1>@ F25B0 Select Color QColorDialog5BFalse QComboBox2B:@KBL 2K?040NI89 A?8A>:"Open the combo box selection popup QComboBox0True QComboBox@3C<5=BK: Arguments:QCommandLineParser.B>1@078BL MBC A?@02:C.Displays this help.QCommandLineParser>B>1@078BL 8=D>@<0F8N > 25@A88.Displays version information.QCommandLineParser@BACBAB2C5B 7=0G5=85 ?>A;5 «%1».Missing value after '%1'.QCommandLineParser0@0<5B@K:Options:QCommandLineParser@5>6840==>5 7=0G5=85 ?>A;5 «%1».Unexpected value after '%1'.QCommandLineParser458725AB=K9 ?0@0<5B@ «%1».Unknown option '%1'.QCommandLineParser458725AB=K5 ?0@0<5B@K: %1.Unknown options: %1.QCommandLineParser"A?>;L7>20=85: %1 Usage: %1QCommandLineParser[?0@0<5B@K] [options]QCommandLineParser%1: >H81:0 ftok%1: ftok failedQCoreApplication%1: ?CAB>9 :;NG%1: key is emptyQCoreApplication6%1: =52>7<>6=> A>740BL :;NG%1: unable to make keyQCoreApplicationLTRQT_LAYOUT_DIRECTIONQCoreApplication@8D Banner PagesQCupsJobWidget*;0BQ6=0O 8=D>@<0F8O:Billing information:QCupsJobWidget&3@0=8G5==K9 4>ABC? ClassifiedQCupsJobWidget!5:@5B=> ConfidentialQCupsJobWidget,=Q< (A 6:00 ?> 17:59)Day (06:00 to 17:59)QCupsJobWidget :>=F5:End:QCupsJobWidgetB;>68BLHold IndefinitelyQCupsJobWidget040=85JobQCupsJobWidget#?@02;5=85 Job ControlQCupsJobWidget@8>@8B5B: Job priority:QCupsJobWidget.>GLN (A 18:00 ?> 5:59)Night (18:00 to 05:59)QCupsJobWidget5BNoneQCupsJobWidget"0?5G0B0BL A59G0APrint ImmediatelyQCupsJobWidget$B;>65==0O ?5G0BL:Scheduled printing:QCupsJobWidgetD> 2B>@CN A<5=C (A 16:00 ?> 23:59)Second Shift (16:00 to 23:59)QCupsJobWidget&!>25@H5==> A5:@5B=>SecretQCupsJobWidget( >?@545;Q==>5 2@5<O Specific TimeQCupsJobWidget!B0=40@B=0OStandardQCupsJobWidget =0G0;5:Start:QCupsJobWidget> B@5BLN A<5=C (A 0:00 ?> 7:59)Third Shift (00:00 to 07:59)QCupsJobWidgetA>1>9 206=>AB8 Top SecretQCupsJobWidget&B:@KB0O 8=D>@<0F8O UnclassifiedQCupsJobWidgetD 2KE>4=K5 (AC11>B0 8 2>A:@5A5=L5)Weekend (Saturday to Sunday)QCupsJobWidget>52>7<>6=> 7025@H8BL B@0=70:F8NUnable to commit transaction QDB2Driver,52>7<>6=> A>548=8BLAOUnable to connect QDB2Driver<52>7<>6=> >B:0B8BL B@0=70:F8NUnable to rollback transaction QDB2Driver^52>7<>6=> CAB0=>28BL 02B>7025@H5=85 B@0=70:F89Unable to set autocommit QDB2Driver:52>7<>6=> ?@82O70BL 7=0G5=85Unable to bind variable QDB2Result<52>7<>6=> 2K?>;=8BL 2K@065=85Unable to execute statement QDB2ResultB52>7<>6=> ?>;CG8BL ?5@2CN AB@>:CUnable to fetch first QDB2ResultH52>7<>6=> ?>;CG8BL A;54CNICN AB@>:CUnable to fetch next QDB2Result:52>7<>6=> ?>;CG8BL 70?8AL %1Unable to fetch record %1 QDB2Result@52>7<>6=> ?>43>B>28BL 2K@065=85Unable to prepare statement QDB2ResultAMAM QDateTimeEditPMPM QDateTimeEditamam QDateTimeEditpmpm QDateTimeEdit'B> MB>? What's This?QDialogOKOKQDialogButtonBox0B0 87<5=5=8O Date Modified QDirModel84Kind QDirModel<OName QDirModel  07<5@Size QDirModel"8?Type QDirModel"?5@0F8O >B<5=5=0Operation cancelled QDnsLookup@5 C40;>AL @0725@=CBL 8<O 4><5=0Could not expand domain nameQDnsLookupRunnable^4@5A0 IPv6 A5@25@>2 8<Q= 5IQ =5 ?>445@6820NBAO9IPv6 addresses for nameservers is currently not supportedQDnsLookupRunnable>5:>@@5:B=0O 70?8AL 04@5A0 IPv4Invalid IPv4 address recordQDnsLookupRunnable>5:>@@5:B=0O 70?8AL 04@5A0 IPv6Invalid IPv6 address recordQDnsLookupRunnableF5:>@@5:B=0O 70?8AL cannonical nameInvalid canonical name recordQDnsLookupRunnable.5:>@@5:B=>5 8<O 4><5=0Invalid domain nameQDnsLookupRunnable*5:>@@5:B=>5 8<O C7;0Invalid hostnameQDnsLookupRunnableB5:>@@5:B=0O 70?8AL mail exchangeInvalid mail exchange recordQDnsLookupRunnable>5:>@@5:B=0O 70?8AL name serverInvalid name server recordQDnsLookupRunnable65:>@@5:B=0O 70?8AL pointerInvalid pointer recordQDnsLookupRunnable4>;CG5= =5:>@@5:B=K9 >B25BInvalid reply receivedQDnsLookupRunnable65:>@@5:B=0O 70?8AL serviceInvalid service recordQDnsLookupRunnable05:>@@5:B=0O 70?8AL textInvalid text recordQDnsLookupRunnable&<O C7;0 =5 C:070=>No hostname givenQDnsLookupRunnable&><5= =5 ACI5AB2C5BNon existent domainQDnsLookupRunnableBIQ =5 ?>445@68205BAO ?>4 AndroidNot yet supported on AndroidQDnsLookupRunnableD$C=:F8O @07@5H5=8O 8<Q= =5 =0945=0Resolver functions not foundQDnsLookupRunnableV5 C40;>AL 8=8F80;878@>20BL @07@5H5=85 8<Q=Resolver initialization failedQDnsLookupRunnableÒ5 C40;>AL 703@C78BL 181;8>B5:C 4;O @07@5H5=8O 8<Q=: 703@C7:0 181;8>B5: 2> 2@5<O @01>BK =5 ?>445@68205BAODResolver library can't be loaded: No runtime library loading supportQDnsLookupRunnable@!5@25@ =5 A<>3 >1@01>B0BL 70?@>AServer could not process queryQDnsLookupRunnableH81:0 A5@25@0Server failureQDnsLookupRunnable,!5@25@ >B:;>=8; 70?@>AServer refused to answerQDnsLookupRunnable0:@KBLClose QDockWidget 0:@K205B 28465BCloses the dock widget QDockWidget;020NI55Float QDockWidgetFBA>548=O5B 8 ?5@53@C??8@C5B 28465B'Undocks and re-attaches the dock widget QDockWidget&0:@KBL&OK QErrorMessageL&>:07K20BL MB> A>>1I5=85 2 40;L=59H5<&Show this message again QErrorMessage*B;04>G=>5 A>>1I5=85:Debug Message: QErrorMessage&@8B8G5A:0O >H81:0: Fatal Error: QErrorMessage@54C?@5645=85:Warning: QErrorMessage@52>7<>6=> A>740BL %1 4;O 2K2>40Cannot create %1 for outputQFile>52>7<>6=> >B:@KBL %1 4;O 22>40Cannot open %1 for inputQFile:52>7<>6=> >B:@KBL 4;O 2K2>40Cannot open for outputQFile@52>7<>6=> C40;8BL 8AE>4=K9 D09;Cannot remove source fileQFile$09; ACI5AB2C5BDestination file existsQFileR$09; =07=0G5=8O B0:>9 65, GB> 8 8AE>4=K9."Destination file is the same file.QFileF>7=8:;0 >H81:0 ?@8 ?5@58<5=>20=88.Error while renaming.QFile"!1>9 70?8A8 1;>:0Failure to write blockQFile4AE>4=K9 D09; >BACBAB2C5B.Source file does not exist.QFileB5 C40;>AL 2>AAB0=>28BL 87 %1: %2Unable to restore from %1: %2QFile¦>A;54>20B5;L=K9 D09; =5 1C45B ?5@58<5=>20= A 8A?>;L7>20=85< ?>1;>G=>3> :>?8@>20=8O0Will not rename sequential file using block copyQFilet5B D09;>2>3> 4286:0 8;8 >= =5 ?>445@68205B UnMapExtensionBNo file engine available or engine does not support UnMapExtension QFileDeviceŽ%1 0B0;>3 =5 =0945=. @>25@LB5 ?@028;L=>ABL C:070==>3> 8<5=8 :0B0;>30.K%1 Directory not found. Please verify the correct directory name was given. QFileDialog‚%1 $09; =5 =0945=. @>25@LB5 ?@028;L=>ABL C:070==>3> 8<5=8 D09;0.A%1 File not found. Please verify the correct file name was given. QFileDialog$09; %1%1 File QFileDialogN%1 C65 ACI5AB2C5B. %>B8B5 70<5=8BL 53>?-%1 already exists. Do you want to replace it? QFileDialog&K1@0BL&Choose QFileDialog&#40;8BL&Delete QFileDialog&>20O ?0?:0 &New Folder QFileDialog&B:@KBL&Open QFileDialog&5@58<5=>20BL&Rename QFileDialog&!>E@0=8BL&Save QFileDialogl«%1» 70I8IQ= >B 70?8A8. 59AB28B5;L=> 65;05B5 C40;8BL?9'%1' is write protected. Do you want to delete it anyway? QFileDialogA524>=8<Alias QFileDialogA5 D09;K (*) All Files (*) QFileDialogA5 D09;K (*) All files (*) QFileDialogAlt+LeftAlt+Left QFileDialogAlt+Right Alt+Right QFileDialog Alt+UpAlt+Up QFileDialog*5;05B5 C40;8BL «%1»?%Are you sure you want to delete '%1'? QFileDialog 0704Back QFileDialog:5@5:;NG8BL 2 ?>4@>1=K9 @568<Change to detail view mode QFileDialog45@5:;NG8BL 2 @568< A?8A:0Change to list view mode QFileDialog65 C40;>AL C40;8BL :0B0;>3.Could not delete directory. QFileDialog!>740BL ?0?:CCreate New Folder QFileDialog&!>740BL =>2CN ?0?:CCreate a New Folder QFileDialog#40;8BLDelete QFileDialog>4@>1=K9 284 Detail View QFileDialog0B0;>38 Directories QFileDialog0B0;>3: Directory: QFileDialog8A:Drive QFileDialog$09;File QFileDialog&<O D09;0: File &name: QFileDialog0?:0 A D09;0<8 File Folder QFileDialog $09;KFiles QFileDialog"8?K D09;>2:Files of type: QFileDialog09B8 :0B0;>3Find Directory QFileDialog 0?:0Folder QFileDialog ?5@Q4Forward QFileDialog 0704Go back QFileDialog ?5@Q4 Go forward QFileDialog<5@59B8 2 @>48B5;LA:89 :0B0;>3Go to the parent directory QFileDialog !?8A>: List View QFileDialog 5AB0 8 70:;04:8List of places and bookmarks QFileDialog5@59B8 ::Look in: QFileDialog>9 :><?LNB5@ My Computer QFileDialog>20O ?0?:0 New Folder QFileDialogB:@KBLOpen QFileDialog( >48B5;LA:89 :0B0;>3Parent Directory QFileDialog$5402=85 4>:C<5=BK Recent Places QFileDialog#40;8BLRemove QFileDialog!>E@0=8BL :0:Save As QFileDialog /@;K:Shortcut QFileDialog>:070BL Show  QFileDialog.>:070BL A:&@KBK5 D09;KShow &hidden files QFileDialog>:>20O ?0=5;LSidebar QFileDialog58725AB=K9Unknown QFileDialog %1 1%1 GBQFileSystemModel %1 1%1 KBQFileSystemModel %1 1%1 MBQFileSystemModel %1 "1%1 TBQFileSystemModel%1 109B %1 byte(s)QFileSystemModel%1 109B%1 bytesQFileSystemModelì<b><O «%1» =5 <>65B 1KBL 8A?>;L7>20=>.</b><p>>?@>1C9B5 8A?>;L7>20BL 8<O <5=LH59 4;8=K 8/8;8 157 A8<2>;>2 ?C=:BC0F88.oThe name "%1" can not be used.

      Try using another name, with fewer characters or no punctuations marks.QFileSystemModel><?LNB5@ComputerQFileSystemModel0B0 87<5=5=8O Date ModifiedQFileSystemModel,5:>@@5:B=>5 8<O D09;0Invalid filenameQFileSystemModel84KindQFileSystemModel>9 :><?LNB5@ My ComputerQFileSystemModel<ONameQFileSystemModel  07<5@SizeQFileSystemModel"8?TypeQFileSystemModel N10OAny QFontDatabase@01A:0OArabic QFontDatabase@<O=A:0OArmenian QFontDatabase5=30;LA:0OBengali QFontDatabase 'Q@=K9Black QFontDatabase 8@=K9Bold QFontDatabase8@8;;8F0Cyrillic QFontDatabase!@54=89Demi QFontDatabase>;C68@=K9 Demi Bold QFontDatabase520=038@8 Devanagari QFontDatabase@C78=A:0OGeorgian QFontDatabase@5G5A:0OGreek QFontDatabaseC460@0B8Gujarati QFontDatabaseC@<C:E8Gurmukhi QFontDatabase 2@8BHebrew QFontDatabase C@A82Italic QFontDatabase/?>=A:0OJapanese QFontDatabase0==040Kannada QFontDatabaseE<5@A:0OKhmer QFontDatabase>@59A:0OKorean QFontDatabase0>AA:0OLao QFontDatabase0B8=8F0Latin QFontDatabase!25B;K9Light QFontDatabase0;09O;0< Malayalam QFontDatabase LO=<0Myanmar QFontDatabase:>N'Ko QFontDatabase1KG=K9Normal QFontDatabase0:;>==K9Oblique QFontDatabase30<8G5A:0OOgham QFontDatabase@8OOriya QFontDatabase C=8G5A:0ORunic QFontDatabase(8B09A:0O C?@>IQ==0OSimplified Chinese QFontDatabase!8=30;LA:0OSinhala QFontDatabase!8<2>;L=0OSymbol QFontDatabase!8@89A:0OSyriac QFontDatabase"0<8;LA:0OTamil QFontDatabase "5;C3CTelugu QFontDatabase "00=0Thaana QFontDatabase"09A:0OThai QFontDatabase"815BA:0OTibetan QFontDatabase,8B09A:0O B@048F8>==0OTraditional Chinese QFontDatabaseL5B=0<A:0O Vietnamese QFontDatabase &(@8DB&Font QFontDialog& 07<5@&Size QFontDialog&>4GQ@:=CBK9 &Underline QFontDialog-DD5:BKEffects QFontDialog&0G5@B0=85 Font st&yle QFontDialog @8<5@Sample QFontDialogK1>@ H@8DB0 Select Font QFontDialog0GQ@&:=CBK9 Stri&keout QFontDialog&!8AB5<0 ?8AL<0Wr&iting System QFontDialog<5 C40;>AL A<5=8BL :0B0;>3: %1Changing directory failed: %1QFtpB#AB0=>2;5=> A>548=5=85 A C7;>< %1Connected to host %1QFtpD5 C40;>AL A>548=8BLAO A C7;><: %1Connecting to host failed: %1QFtp$!>548=5=85 70:@KB>Connection closedQFtp@ A>548=5=88 A C7;>< %1 >B:070=>Connection refused to host %1QFtpL@5<O =0 A>548=5=85 A C7;>< %1 8AB5:;>Connection timed out to host %1QFtp<5 C40;>AL A>740BL :0B0;>3: %1Creating directory failed: %1QFtpbB:;>=5=0 ?>?KB:0 ?>4:;NG5=8O 4;O ?5@540G8 40==KEData Connection refusedQFtp:5 C40;>AL 703@C78BL D09;: %1Downloading file failed: %1QFtp"#75; %1 =5 =0945=Host %1 not foundQFtp@5 C40;>AL ?@>G8B0BL :0B0;>3: %1Listing directory failed: %1QFtp:5 C40;>AL 02B>@87>20BLAO: %1Login failed: %1QFtp2!>548=5=85 =5 CAB0=>2;5=> Not connectedQFtp<5 C40;>AL C40;8BL :0B0;>3: %1Removing directory failed: %1QFtp65 C40;>AL C40;8BL D09;: %1Removing file failed: %1QFtp$58725AB=0O >H81:0 Unknown errorQFtp:5 C40;>AL >B3@C78BL D09;: %1Uploading file failed: %1QFtpB&<5=0&Cancel QGnomeTheme&0:@KBL&Close QGnomeTheme&OK&OK QGnomeTheme&!>E@0=8BL&Save QGnomeTheme,0:@KBL 157 A>E@0=5=8OClose without Saving QGnomeTheme$<O C7;0 =5 7040=>No host name given QHostInfo$58725AB=0O >H81:0 Unknown error QHostInfo#75; =5 =0945=Host not foundQHostInfoAgent*5:>@@5:B=>5 8<O C7;0Invalid hostnameQHostInfoAgent$<O C7;0 =5 7040=>No host name givenQHostInfoAgent,58725AB=K9 B8? 04@5A0Unknown address typeQHostInfoAgent$58725AB=0O >H81:0 Unknown errorQHostInfoAgent.58725AB=0O >H81:0 (%1)Unknown error (%1)QHostInfoAgent$!>548=5=85 70:@KB>Connection closedQHttp*B:070=> 2 A>548=5=88Connection refusedQHttp"0==K5 ?>2@5645=KData corruptedQHttp"#75; %1 =5 =0945=Host %1 not foundQHttp0#75; B@51C5B 02B>@870F8NHost requires authenticationQHttpF@5<O =0 >?5@0F8N A A>:5B>< 8AB5:;>Proxy requires authenticationQHttp628B8@>20=85 SSL =5 C40;>ALSSL handshake failedQHttp6#:070= =58725AB=K9 ?@>B>:>;Unknown protocol specifiedQHttp*"@51C5BAO 02B>@870F8OAuthentication requiredQHttpSocketEngineN5 ?>;CG5= HTTP->B25B >B ?@>:A8-A5@25@0(Did not receive HTTP response from proxyQHttpSocketEngineXH81:0 >1<5=0 40==K<8 A ?@>:A8-A5@25@>< HTTP#Error communicating with HTTP proxyQHttpSocketEnginehH81:0 @071>@0 70?@>A0 02B>@870F88 >B ?@>:A8-A5@25@0/Error parsing authentication request from proxyQHttpSocketEngine^!>548=5=85 A ?@>:A8-A5@25@>< =5>6840==> 70:@KB>#Proxy connection closed prematurelyQHttpSocketEngineJ A>548=5=88 ?@>:A8-A5@25@>< >B:070=>Proxy connection refusedQHttpSocketEngineB@>:A8-A5@25@ 70?@5B8; A>548=5=85Proxy denied connectionQHttpSocketEngineZ@5<O =0 A>548=5=85 A ?@>:A8-A5@25@>< 8AB5:;>!Proxy server connection timed outQHttpSocketEngine.@>:A8-A5@25@ =5 =0945=Proxy server not foundQHttpSocketEngine85 C40;>AL =0G0BL B@0=70:F8NCould not start transaction QIBaseDriver6H81:0 >B:@KB8O 107K 40==KEError opening database QIBaseDriver>52>7<>6=> 7025@H8BL B@0=70:F8NUnable to commit transaction QIBaseDriver<52>7<>6=> >B:0B8BL B@0=70:F8NUnable to rollback transaction QIBaseDriverd5 C40;>AL ?>;CG8BL @5AC@AK 4;O A>740=8O 2K@065=8OCould not allocate statement QIBaseResultJ5 C40;>AL >?8A0BL 2E>4OI55 2K@065=85"Could not describe input statement QIBaseResult85 C40;>AL >?8A0BL 2K@065=85Could not describe statement QIBaseResultJ5 C40;>AL ?>;CG8BL A;54CNI89 M;5<5=BCould not fetch next item QIBaseResult.5 C40;>AL =09B8 <0AA82Could not find array QIBaseResult>5 C40;>AL =09B8 40==K5 <0AA820Could not get array data QIBaseResultJ5 C40;>AL =09B8 8=D>@<0F8N > 70?@>A5Could not get query info QIBaseResultN5 C40;>AL =09B8 8=D>@<0F8N > 2K@065=88Could not get statement info QIBaseResult@5 C40;>AL ?>43>B>28BL 2K@065=85Could not prepare statement QIBaseResult85 C40;>AL =0G0BL B@0=70:F8NCould not start transaction QIBaseResult852>7<>6=> 70:@KBL 2K@065=85Unable to close statement QIBaseResult>52>7<>6=> 7025@H8BL B@0=70:F8NUnable to commit transaction QIBaseResult.52>7<>6=> A>740BL BLOBUnable to create BLOB QIBaseResult652>7<>6=> 2K?>;=8BL 70?@>AUnable to execute query QIBaseResult.52>7<>6=> >B:@KBL BLOBUnable to open BLOB QIBaseResult252>7<>6=> ?@>G8B0BL BLOBUnable to read BLOB QIBaseResult052>7<>6=> 70?8A0BL BLOBUnable to write BLOB QIBaseResultD5B A2>1>4=>3> <5AB0 =0 CAB@>9AB25No space left on device QIODevice<$09; 8;8 :0B0;>3 =5 ACI5AB2C5BNo such file or directory QIODevice>ABC? 70?@5IQ=Permission denied QIODevice:!;8H:>< <=>3> >B:@KBKE D09;>2Too many open files QIODevice$58725AB=0O >H81:0 Unknown error QIODeviceF>B:@K205<K9 D09; O2;O5BAO :0B0;>3><file to open is a directory QIODevice$09; =5 =0945=File not found QImageReader.5:>@@5:B=>5 CAB@>9AB2>Invalid device QImageReaderN5 C40;>AL ?@>G8B0BL 40==K5 87>1@065=8OUnable to read image data QImageReader$58725AB=0O >H81:0 Unknown error QImageReaderF5?>445@68205<K9 D>@<0B 87>1@065=8OUnsupported image format QImageReader(#AB@>9AB2> =5 7040=>Device is not set QImageWriterB#AB@>9AB2> =5 ?>445@68205B 70?8ALDevice not writable QImageWriter$58725AB=0O >H81:0 Unknown error QImageWriterF5?>445@68205<K9 D>@<0B 87>1@065=8OUnsupported image format QImageWriter"#:068B5 7=0G5=85:Enter a value: QInputDialog.<CA>@ 2 :>=F5 4>:C<5=B0"garbage at the end of the documentQJsonParseError$=5:>@@5:B=>5 G8A;>illegal numberQJsonParseError*=54>?CAB8<>5 7=0G5=85 illegal valueQJsonParseErrorH=5:>@@5:B=0O ?>A;54>20B5;L=>ABL UTF8invalid UTF8 stringQJsonParseErrorF=5:>@@5:B=0O ESC-?>A;54>20B5;L=>ABLinvalid escape sequenceQJsonParseError<=5:>@@5:B=>5 7025@H5=85 G8A;><invalid termination by numberQJsonParseError8>BACBAB2C5B @0745;8B5;L 8<Q=missing name separatorQJsonParseError@>BACBAB2C5B @0745;8B5;L 7=0G5=89missing value separatorQJsonParseError$>H81:8 >BACBAB2CNBno error occurredQJsonParseError<>BACBAB2C5B >1J5:B ?>A;5 B>G:8object is missing after a commaQJsonParseErrorV4>:C<5=B 8<55B A;8H:>< 3;C1>:CN 2;>65==>ABLtoo deeply nested documentQJsonParseError0A;8H:>< 1>;LH>9 4>:C<5=Btoo large documentQJsonParseError(=57025@HQ==K9 <0AA82unterminated arrayQJsonParseError(57025@HQ==K9 >1J5:Bunterminated objectQJsonParseError(=57025@HQ==0O AB@>:0unterminated stringQJsonParseError%1, ...%1, ...QKeySequenceEdit006<8B5 A>G5B0=85 :;028HPress shortcutQKeySequenceEditX«%1» O2;O5BAO =5:>@@5:B=K< >1J5:B>< ELF (%2)"'%1' is an invalid ELF object (%2)QLibrary"«%1» =5 ?;038= Qt'%1' is not a Qt pluginQLibraryN«%1» =525@=K9 18=0@=K9 D09; Mach-O (%2)&'%1' is not a valid Mach-O binary (%2)QLibrary:«%1» =5 O2;O5BAO >1J5:B>< ELF'%1' is not an ELF objectQLibraryD«%1» =5 O2;O5BAO >1J5:B>< ELF (%2)'%1' is not an ELF object (%2)QLibraryL52>7<>6=> 703@C78BL 181;8>B5:C %1: %2Cannot load library %1: %2QLibraryR52>7<>6=> @07@5H8BL A8<2>; «%1» 2 %2: %3$Cannot resolve symbol "%1" in %2: %3QLibraryL52>7<>6=> 2K3@C78BL 181;8>B5:C %1: %2Cannot unload library %1: %2QLibraryf@>25@>G=0O 8=D>@<0F8O 4;O <>4C;O «%1» =5 A>2?0405B)Plugin verification data mismatch in '%1'QLibrary\$09; «%1»  =5 O2;O5BAO :>@@5:B=K< <>4C;5< Qt.'The file '%1' is not a valid Qt plugin.QLibrary„>4C;L «%1» 8A?>;L7C5B =5A><5AB8<CN 181;8>B5:C Qt. (%2.%3.%4) [%5]=The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]QLibraryØ>4C;L «%1» 8A?>;L7C5B =5A><5AB8<CN 181;8>B5:C Qt. (52>7<>6=> A>2<5AB8BL @5;87=K5 8 >B;04>G=K5 181;8>B5:8.)WThe plugin '%1' uses incompatible Qt library. (Cannot mix debug and release libraries.)QLibraryF8=0<8G5A:0O 181;8>B5:0 =5 =0945=0.!The shared library was not found.QLibrary$58725AB=0O >H81:0 Unknown errorQLibraryD09; ?>2@564Q=file is corruptQLibrary D09; A;8H:>< <0;file too smallQLibrary2=525@=K9 845=B8D8:0B>@ %1invalid magic %1QLibraryD=5B ?>4E>4OI59 0@E8B5:BC@K 2 D09;5&no suitable architecture in fat binaryQLibrary4=5 48=0<8G5A:0O 181;8>B5:0not a dynamic libraryQLibrary(=525@=0O 0@E8B5:BC@0wrong architectureQLibrary&>?8@>20BL&Copy QLineEdit&AB028BL&Paste QLineEdit&&>2B>@8BL 459AB285&Redo QLineEdit$&B<5=8BL 459AB285&Undo QLineEdit&K@570BLCu&t QLineEdit#40;8BLDelete QLineEditK45;8BL 2AQ Select All QLineEdit,%1: 4@5A 8A?>;L7C5BAO%1: Address in use QLocalServer(%1: 5:>@@5:B=>5 8<O%1: Name error QLocalServer&%1: >ABC? 70?@5IQ=%1: Permission denied QLocalServer2%1: 58725AB=0O >H81:0 %2%1: Unknown error %2 QLocalServer&%1: >ABC? 70?@5IQ=%1: Access denied QLocalSocket*%1: H81:0 A>548=5=8O%1: Connection error QLocalSocket2%1: B:070=> 2 A>548=5=88%1: Connection refused QLocalSocket<%1: 0B03@0<<0 A;8H:>< 1>;LH0O%1: Datagram too large QLocalSocket(%1: 5:>@@5:B=>5 8<O%1: Invalid name QLocalSocketn%1: ?5@0F8O =5 @07@5H5=0, :>340 A>:5B 2 MB>< A>AB>O=888%1: Operation not permitted when socket is in this state QLocalSocket<%1: 0:@KB> C40;5==>9 AB>@>=>9%1: Remote closed QLocalSocket:%1: H81:0 >1@0I5=8O : A>:5BC%1: Socket access error QLocalSocketN%1: @5<O =0 >?5@0F8N A A>:5B>< 8AB5:;>%1: Socket operation timed out QLocalSocketH%1: H81:0 2K45;5=8O @5AC@A>2 A>:5B0%1: Socket resource error QLocalSocketP%1: ?5@0F8O A A>:5B>< =5 ?>445@68205BAO)%1: The socket operation is not supported QLocalSocket,%1: 58725AB=0O >H81:0%1: Unknown error QLocalSocket2%1: 58725AB=0O >H81:0 %2%1: Unknown error %2 QLocalSocketR>?KB:0 ?>4:;NG8BLAO 2> 2@5<O ?>4:;NG5=8O1Trying to connect while connection is in progress QLocalSocket852>7<>6=> =0G0BL B@0=70:F8NUnable to begin transaction QMYSQLDriver>52>7<>6=> 7025@H8BL B@0=70:F8NUnable to commit transaction QMYSQLDriver,52>7<>6=> A>548=8BLAOUnable to connect QMYSQLDriverF52>7<>6=> >B:@KBL 107C 40==KE «%1»Unable to open database '%1' QMYSQLDriver<52>7<>6=> >B:0B8BL B@0=70:F8NUnable to rollback transaction QMYSQLDriverX52>7<>6=> ?@82O70BL @57C;LB8@CNI85 7=0G5=8OUnable to bind outvalues QMYSQLResult:52>7<>6=> ?@82O70BL 7=0G5=85Unable to bind value QMYSQLResultJ52>7<>6=> 2K?>;=8BL A;54CNI89 70?@>AUnable to execute next query QMYSQLResult652>7<>6=> 2K?>;=8BL 70?@>AUnable to execute query QMYSQLResult<52>7<>6=> 2K?>;=8BL 2K@065=85Unable to execute statement QMYSQLResult452>7<>6=> ?>;CG8BL 40==K5Unable to fetch data QMYSQLResult@52>7<>6=> ?>43>B>28BL 2K@065=85Unable to prepare statement QMYSQLResult:52>7<>6=> A1@>A8BL 2K@065=85Unable to reset statement QMYSQLResultP52>7<>6=> A>E@0=8BL A;54CNI89 @57C;LB0BUnable to store next result QMYSQLResult<52>7<>6=> A>E@0=8BL @57C;LB0BUnable to store result QMYSQLResulth52>7<>6=> A>E@0=8BL @57C;LB0BK 2K?>;=5=8O 2K@065=8O!Unable to store statement results QMYSQLResult(5>703;02;5=>) (Untitled)QMdiArea%1 - [%2] %1 - [%2] QMdiSubWindow&0:@KBL&Close QMdiSubWindow&5@5<5AB8BL&Move QMdiSubWindow&>AAB0=>28BL&Restore QMdiSubWindow& 07<5@&Size QMdiSubWindow - [%1]- [%1] QMdiSubWindow0:@KBLClose QMdiSubWindow!?@02:0Help QMdiSubWindow &0A?0E=CBL Ma&ximize QMdiSubWindow 0A?0E=CBLMaximize QMdiSubWindow5=NMenu QMdiSubWindow&!25@=CBL Mi&nimize QMdiSubWindow!25@=CBLMinimize QMdiSubWindow>AAB0=>28BLRestore QMdiSubWindow>AAB0=>28BL Restore Down QMdiSubWindow(!25@=CBL 2 703>;>2>:Shade QMdiSubWindow$AB020BLAO &A25@EC Stay on &Top QMdiSubWindow2>AAB0=>28BL 87 703>;>2:0Unshade QMdiSubWindowz<h3> Qt</h3><p>0==0O ?@>3@0<<0 8A?>;L7C5B Qt 25@A88 %1.</p>8

      About Qt

      This program uses Qt version %1.

       QMessageBox l<p>Qt  MB> 8=AB@C<5=B0@89 4;O @07@01>B:8 :@>AA?;0BD>@<5==KE ?@8;>65=89 =0 C++.</p><p>Qt ?@54>AB02;O5B A>2<5AB8<>ABL =0 C@>2=5 8AE>4=KE B5:AB>2 <564C 4;O 2A5E ?>?C;O@=KE =0AB>;L=KE >?5@0F8>==KE A8AB5<. "0:65 Qt 4>ABC?=0 4;O 2AB@08205<>3> Linux 8 4@C38E <>18;L=KE >?5@0F8>==KE A8AB5<.</p><p>Qt 4>ABC?=0 ?>4 B@5<O @07;8G=K<8 ;8F5=78O<8, @07@01>B0==K<8 4;O C4>2;5B2>@5=8O B@51>20=89 @07=KE ?>;L7>20B5;59.</p><p>Qt ?>4 =0H59 :><<5@G5A:>9 ;8F5=7859 ?@54=07=0G5=0 4;O @0728B8O ?@>?@85B0@=>3>/:><<5@G5A:>3> ?@>3@0<<=>3> >15A?5G5=8O, :>340 =5B 65;0=8O/ ?@54>AB02;OBL 8AE>4=K5 B5:ABK B@5BL8< ;8F0< 2 A;CG05 =52>7<>6=>AB8 ?@8=OB8O CA;>289 ;8F5=789 GNU LGPL 25@A88 3 8;8 GNU LGPL 25@A88 2.1.</p><p>Qt ?>4 ;8F5=7859 GNU LGPL 25@A88 3 ?@54=07=0G5=0 4;O @07@01>B:8 ?@>3@0<<=>3> >15A?5G5=8O C4>2;5B2>@ONI53> B@51>20=8O< ;8F5=788 GNU LGPL 25@A88 3.</p><p>Qt ?>4 ;8F5=7859 GNU LGPL 25@A88 2.1 ?@54=07=0G5=0 4;O @07@01>B:8 ?@>3@0<<=>3> >15A?5G5=8O C4>2;5B2>@ONI53> B@51>20=8O< ;8F5=788 GNU LGPL 25@A88 2.1.</p><p>>4@>1=55 A CA;>28O<8 ;8F5=78@>20=8O Qt <>6=> >7=0:><8BLAO =0 A09B5 <a href="http://%2/">%2</a>.</p><p>Copyright (C) %1 Digia Plc 8/8;8 5Q 4>G5@=85 ?>4@0745;5=8O 8 4@C385 CG0AB=8:8.</p><p>Qt, :0: >B:@KBK9 ?@>5:B, @07@010BK205BAO =0 <a href="http://qt-project.org/">qt-project.org</a>.</p><p>Qt  ?@>4C:B :><?0=88 Digia, @07@010BK205<K9 2 :0G5AB25 ?@>5:B0 A >B:@KBK<8 8AE>4=K<8 B5:AB0<8. >;55 ?>4@>1=CN 8=D>@<0F8N <>6=> =09B8 =0 A09B5 <a href="http://%3/">%3</a>.</p>c

      Qt is a C++ toolkit for cross-platform application development.

      Qt provides single-source portability across all major desktop operating systems. It is also available for embedded Linux and other embedded and mobile operating systems.

      Qt is available under three different licensing options designed to accommodate the needs of our various users.

      Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of the GNU LGPL version 3 or GNU LGPL version 2.1.

      Qt licensed under the GNU LGPL version 3 is appropriate for the development of Qt applications provided you can comply with the terms and conditions of the GNU LGPL version 3.

      Qt licensed under the GNU LGPL version 2.1 is appropriate for the development of Qt applications provided you can comply with the terms and conditions of the GNU LGPL version 2.1.

      Please see %2 for an overview of Qt licensing.

      Copyright (C) %1 Digia Plc and/or its subsidiary(-ies) and other contributors.

      Qt and the Qt logo are trademarks of Digia Plc and/or its subsidiary(-ies).

      Qt is a Digia product developed as an open source project. See %3 for more information.

       QMessageBox QtAbout Qt QMessageBox!?@02:0Help QMessageBox*!:@KBL ?>4@>1=>AB8...Hide Details... QMessageBox0:@KBLOK QMessageBox.>:070BL ?>4@>1=>AB8...Show Details... QMessageBoxN@C3>9 A>:5B C65 ?@>A;CH8205B MB>B ?>@B4Another socket is already listening on the same portQNativeSocketEngine|>?KB:0 8A?>;L7>20BL IPv6 =0 ?;0BD>@<5, =5 ?>445@6820NI59 IPv6=Attempt to use IPv6 socket on a platform with no IPv6 supportQNativeSocketEngine*B:070=> 2 A>548=5=88Connection refusedQNativeSocketEngine6@5<O =0 A>548=5=85 8AB5:;>Connection timed outQNativeSocketEngineN0B03@0<<0 A;8H:>< 1>;LH0O 4;O >B?@02:8Datagram was too large to sendQNativeSocketEngine#75; =54>ABC?5=Host unreachableQNativeSocketEngine<5:>@@5:B=K9 45A:@8?B>@ A>:5B0Invalid socket descriptorQNativeSocketEngineH81:0 A5B8 Network errorQNativeSocketEngineB@5<O =0 A5B52CN >?5@0F8N 8AB5:;>Network operation timed outQNativeSocketEngine!5BL =54>ABC?=0Network unreachableQNativeSocketEngine*?5@0F8O A =5-A>:5B><Operation on non-socketQNativeSocketEngine*54>AB0B>G=> @5AC@A>2Out of resourcesQNativeSocketEngine>ABC? 70?@5IQ=Permission deniedQNativeSocketEngine4@>B>:>; =5 ?>445@68205BAOProtocol type not supportedQNativeSocketEngine @5<5==0O >H81:0Temporary errorQNativeSocketEngine 4@5A =54>ABC?5=The address is not availableQNativeSocketEngine4@5A 70I8IQ=The address is protectedQNativeSocketEngine,4@5A C65 8A?>;L7C5BAO#The bound address is already in useQNativeSocketEnginef5:>@@5:B=K9 B8? ?@>:A8-A5@25@0 4;O 40==>9 >?5@0F88,The proxy type is invalid for this operationQNativeSocketEngine@#40;Q==K9 C75; 70:@K; A>548=5=85%The remote host closed the connectionQNativeSocketEnginef52>7<>6=> 8=8F80;878@>20BL H8@>:>25I0B5;L=K9 A>:5B%Unable to initialize broadcast socketQNativeSocketEngineX52>7<>6=> 8=8F80;878@>20BL =5-1;>G=K9 A>:5B(Unable to initialize non-blocking socketQNativeSocketEngine:52>7<>6=> ?>;CG8BL A>>1I5=85Unable to receive a messageQNativeSocketEngine<52>7<>6=> >B?@028BL A>>1I5=85Unable to send a messageQNativeSocketEngine&52>7<>6=> 70?8A0BLUnable to writeQNativeSocketEngine$58725AB=0O >H81:0 Unknown errorQNativeSocketEngineH?5@0F8O A A>:5B>< =5 ?>445@68205BAOUnsupported socket operationQNativeSocketEngine$H81:0 >B:@KB8O %1Error opening %1QNetworkAccessCacheBackend(5:>@@5:B=K9 URI: %1Invalid URI: %1QNetworkAccessDataBackendf#40;Q==K9 C75; =5>6840==> ?@5@20; A>548=5=85 4;O %13Remote host closed the connection prematurely on %1QNetworkAccessDebugPipeBackend.H8:0 A>:5B0 4;O %1: %2Socket error on %1: %2QNetworkAccessDebugPipeBackend,H81:0 70?8A8 2 %1: %2Write error writing to %1: %2QNetworkAccessDebugPipeBackendZ52>7<>6=> >B:@KBL %1: #:070= ?CBL : :0B0;>3C#Cannot open %1: Path is a directoryQNetworkAccessFileBackend,H81:0 >B:@KB8O %1: %2Error opening %1: %2QNetworkAccessFileBackend.H81:0 GB5=8O 87 %1: %2Read error reading from %1: %2QNetworkAccessFileBackend`0?@>A =0 >B:@KB85 D09;0 2=5 D09;>2>9 A8AB5<K %1%Request for opening non-local file %1QNetworkAccessFileBackend,H81:0 70?8A8 2 %1: %2Write error writing to %1: %2QNetworkAccessFileBackendZ52>7<>6=> >B:@KBL %1: #:070= ?CBL : :0B0;>3CCannot open %1: is a directoryQNetworkAccessFtpBackendBH81:0 2 ?@>F5AA5 703@C7:8 %1: %2Error while downloading %1: %2QNetworkAccessFtpBackendBH81:0 2 ?@>F5AA5 >B3@C7:8 %1: %2Error while uploading %1: %2QNetworkAccessFtpBackendb!>548=5=85 A %1 =5 C40;>AL: B@51C5BAO 02B>@870F8O0Logging in to %1 failed: authentication requiredQNetworkAccessFtpBackendD>4E>4OI89 ?@>:A8-A5@25@ =5 =0945=No suitable proxy foundQNetworkAccessFtpBackend.>ABC? 2 A5BL >B:;NGQ=.Network access is disabled.QNetworkAccessManager8$>=>2K5 70?@>AK =54>?CAB8<K.Background request not allowed. QNetworkReplyLH81:0 703@C7:8 %1  >B25B A5@25@0: %2)Error downloading %1 - server replied: %2 QNetworkReply,H81:0 A5B52>9 A5AA88.Network session error. QNetworkReply258725AB=K9 ?@>B>:>; «%1»Protocol "%1" is unknown QNetworkReply,@5<5==0O >H81:0 A5B8.Temporary network failure. QNetworkReply0>H81:0 70?CA:0 4@0925@0.backend start error. QNetworkReplyD>4E>4OI89 ?@>:A8-A5@25@ =5 =0945=No suitable proxy foundQNetworkReplyHttpImpl"?5@0F8O >B<5=5=0Operation canceledQNetworkReplyHttpImpl"?5@0F8O >B<5=5=0Operation canceledQNetworkReplyImpl45:>@@5:B=0O :>=D83C@0F8O.Invalid configuration.QNetworkSession> >C<8=3 ?@5@20= 8;8 =52>7<>65=.'Roaming was aborted or is not possible.QNetworkSessionPrivateImpl\"@51C5<0O >?5@0F8O =5 ?>445@68205BAO A8AB5<>9.7The requested operation is not supported by the system.QNetworkSessionPrivateImpl`!5AA8O 1K;0 ?@5@20=0 ?>;L7>20B5;5< 8;8 A8AB5<>9..The session was aborted by the user or system.QNetworkSessionPrivateImpl^52>7<>6=> 8A?>;L7>20BL C:070==CN :>=D83C@0F8N.+The specified configuration cannot be used.QNetworkSessionPrivateImpl458725AB=0O >H81:0 A5AA88.Unknown session error.QNetworkSessionPrivateImpl852>7<>6=> =0G0BL B@0=70:F8NUnable to begin transaction QOCIDriver>52>7<>6=> 7025@H8BL B@0=70:F8NUnable to commit transaction QOCIDriver652>7<>6=> 8=8F80;878@>20BLUnable to initialize QOCIDriver252>7<>6=> 02B>@87>20BLAOUnable to logon QOCIDriver<52>7<>6=> >B:0B8BL B@0=70:F8NUnable to rollback transaction QOCIDriver852>7<>6=> A>740BL 2K@065=85Unable to alloc statement QOCIResultj52>7<>6=> ?@82O70BL AB>;15F 4;O ?0:5B=>3> 2K?>;=5=8O'Unable to bind column for batch execute QOCIResultX52>7<>6=> ?@82O70BL @57C;LB8@CNI85 7=0G5=8OUnable to bind value QOCIResultN52>7<>6=> 2K?>;=8BL ?0:5B=>5 2K@065=85!Unable to execute batch statement QOCIResult<52>7<>6=> 2K?>;=8BL 2K@065=85Unable to execute statement QOCIResultF52>7<>6=> >?@545;8BL B8? 2K@065=8OUnable to get statement type QOCIResultJ52>7<>6=> ?5@59B8 : A;54CNI59 AB@>:5Unable to goto next QOCIResult@52>7<>6=> ?>43>B>28BL 2K@065=85Unable to prepare statement QOCIResult>52>7<>6=> 7025@H8BL B@0=70:F8NUnable to commit transaction QODBCDriver,52>7<>6=> A>548=8BLAOUnable to connect QODBCDriverŠ52>7<>6=> A>548=8BLAO  @0925@ =5 ?>445@68205B B@51C5<K9 DC=:F8>=0;EUnable to connect - Driver doesn't support all functionality required QODBCDriver\52>7<>6=> >B:;NG8BL 02B>7025@H5=85 B@0=70:F89Unable to disable autocommit QODBCDriverZ52>7<>6=> 2:;NG8BL 02B>7025@H5=85 B@0=70:F89Unable to enable autocommit QODBCDriver<52>7<>6=> >B:0B8BL B@0=70:F8NUnable to rollback transaction QODBCDriverèQODBCResult::reset: 52>7<>6=> CAB0=>28BL «SQL_CURSOR_STATIC» 0B@81CB>< 2K@065=85. @>25@LB5 =0AB@>9:8 4@0925@0 ODBCyQODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration QODBCResult:52>7<>6=> ?@82O70BL 7=0G5=85Unable to bind variable QODBCResult<52>7<>6=> 2K?>;=8BL 2K@065=85Unable to execute statement QODBCResult452>7<>6=> ?>;CG8BL 40==K5Unable to fetch QODBCResultB52>7<>6=> ?>;CG8BL ?5@2CN AB@>:CUnable to fetch first QODBCResultH52>7<>6=> ?>;CG8BL ?>A;54=NN AB@>:CUnable to fetch last QODBCResultH52>7<>6=> ?>;CG8BL A;54CNICN AB@>:CUnable to fetch next QODBCResultJ52>7<>6=> ?>;CG8BL ?@54K4CICN AB@>:CUnable to fetch previous QODBCResult@52>7<>6=> ?>43>B>28BL 2K@065=85Unable to prepare statement QODBCResult85 C40;>AL =0G0BL B@0=70:F8NCould not begin transaction QPSQLDriver>5 C40;>AL 7025@H8BL B@0=70:F8NCould not commit transaction QPSQLDriver<5 C40;>AL >B:0B8BL B@0=70:F8NCould not rollback transaction QPSQLDriver,52>7<>6=> A>548=8BLAOUnable to connect QPSQLDriver,52>7<>6=> ?>4?8A0BLAOUnable to subscribe QPSQLDriver*52>7<>6=> >B?8A0BLAOUnable to unsubscribe QPSQLDriver252>7<>6=> A>740BL 70?@>AUnable to create query QPSQLResult@52>7<>6=> ?>43>B>28BL 2K@065=85Unable to prepare statement QPSQLResultCCCCQPageSetupWidget&8F5@> (CC) Cicero (CC)QPageSetupWidget A>1K9CustomQPageSetupWidgetDDDDQPageSetupWidget84> (DD) Didot (DD)QPageSetupWidget $>@<0FormQPageSetupWidgetKA>B0:Height:QPageSetupWidgetN9<K (4<) Inches (in)QPageSetupWidget;L1><=0O LandscapeQPageSetupWidget>;OMarginsQPageSetupWidget8;;8<5B@K (<<)Millimeters (mm)QPageSetupWidget@85=B0F8O OrientationQPageSetupWidget$ 07<5I5=85 AB@0=8F Page LayoutQPageSetupWidget >@O4>: AB@0=8F: Page order:QPageSetupWidget  07<5@ AB@0=8FK: Page size:QPageSetupWidget"!B@0=8F =0 ;8AB5:Pages per sheet:QPageSetupWidget C<030PaperQPageSetupWidget AB>G=8: 1C<038: Paper source:QPageSetupWidget8:0 (P8) Pica (P̸)QPageSetupWidget">G:8 (?B) Points (pt)QPageSetupWidget=86=0OPortraitQPageSetupWidgetP8P̸QPageSetupWidget,5@52Q@=CB0O 0;L1><=0OReverse landscapeQPageSetupWidget(5@52Q@=CB0O :=86=0OReverse portraitQPageSetupWidget(8@8=0:Width:QPageSetupWidget=86=55 ?>;5 bottom marginQPageSetupWidget4<inQPageSetupWidget;52>5 ?>;5 left marginQPageSetupWidget<<mmQPageSetupWidget?BptQPageSetupWidget?@02>5 ?>;5 right marginQPageSetupWidget25@E=55 ?>;5 top marginQPageSetupWidget%1 x %2 4< %1 x %2 in QPageSizeA0A0 QPageSizeA1A1 QPageSizeA10A10 QPageSizeA2A2 QPageSizeA3A3 QPageSizeA3 ExtraA3 Extra QPageSizeA4A4 QPageSizeA4 ExtraA4 Extra QPageSizeA4 PlusA4 Plus QPageSizeA4 SmallA4 Small QPageSizeA5A5 QPageSizeA5 ExtraA5 Extra QPageSizeA6A6 QPageSizeA7A7 QPageSizeA8A8 QPageSizeA9A9 QPageSize ANSI CANSI C QPageSize ANSI DANSI D QPageSize ANSI EANSI E QPageSizeArchitect A Architect A QPageSizeArchitect B Architect B QPageSizeArchitect C Architect C QPageSizeArchitect D Architect D QPageSizeArchitect E Architect E QPageSizeB0B0 QPageSizeB1B1 QPageSizeB10B10 QPageSizeB2B2 QPageSizeB3B3 QPageSizeB4B4 QPageSizeB5B5 QPageSizeB5 ExtraB5 Extra QPageSizeB6B6 QPageSizeB7B7 QPageSizeB8B8 QPageSizeB9B9 QPageSize A>1K9Custom QPageSize,A>1K9 (%1 CC x %2 CC)Custom (%1CC x %2CC) QPageSize,A>1K9 (%1 DD x %2 DD)Custom (%1DD x %2DD) QPageSize,A>1K9 (%1 4< x %2 4<)Custom (%1in x %2in) QPageSize,A>1K9 (%1 << x %2 <<)Custom (%1mm x %2mm) QPageSize,A>1K9 (%1 P8 x %2 P8)Custom (%1pc x %2pc) QPageSize,A>1K9 (%1 ?B x %2 ?B)Custom (%1pt x %2pt) QPageSizeDouble PostcardDouble Postcard QPageSizeEnvelope B4 Envelope B4 QPageSizeEnvelope B5 Envelope B5 QPageSizeEnvelope B6 Envelope B6 QPageSizeEnvelope C0 Envelope C0 QPageSizeEnvelope C1 Envelope C1 QPageSizeEnvelope C2 Envelope C2 QPageSizeEnvelope C3 Envelope C3 QPageSizeEnvelope C4 Envelope C4 QPageSizeEnvelope C5 Envelope C5 QPageSizeEnvelope C6 Envelope C6 QPageSizeEnvelope C65 Envelope C65 QPageSizeEnvelope C7 Envelope C7 QPageSizeEnvelope Chou 3Envelope Chou 3 QPageSizeEnvelope Chou 4Envelope Chou 4 QPageSizeEnvelope DL Envelope DL QPageSizeEnvelope InviteEnvelope Invite QPageSize Envelope ItalianEnvelope Italian QPageSizeEnvelope Kaku 2Envelope Kaku 2 QPageSizeEnvelope Kaku 3Envelope Kaku 3 QPageSize Envelope MonarchEnvelope Monarch QPageSizeEnvelope PRC 1Envelope PRC 1 QPageSizeEnvelope PRC 10Envelope PRC 10 QPageSizeEnvelope PRC 2Envelope PRC 2 QPageSizeEnvelope PRC 3Envelope PRC 3 QPageSizeEnvelope PRC 4Envelope PRC 4 QPageSizeEnvelope PRC 5Envelope PRC 5 QPageSizeEnvelope PRC 6Envelope PRC 6 QPageSizeEnvelope PRC 7Envelope PRC 7 QPageSizeEnvelope PRC 8Envelope PRC 8 QPageSizeEnvelope PRC 9Envelope PRC 9 QPageSize"Envelope PersonalEnvelope Personal QPageSizeEnvelope US 10Envelope US 10 QPageSizeEnvelope US 11Envelope US 11 QPageSizeEnvelope US 12Envelope US 12 QPageSizeEnvelope US 14Envelope US 14 QPageSizeEnvelope US 9 Envelope US 9 QPageSizeEnvelope You 4Envelope You 4 QPageSize4Executive (7.25 x 10.5 4<)Executive (7.25 x 10.5 in) QPageSize.Executive (7.5 x 10 4<)Executive (7.5 x 10 in) QPageSize:Fan-fold German (8.5 x 12 in)Fan-fold German (8.5 x 12 in) QPageSizeFFan-fold German Legal (8.5 x 13 in)#Fan-fold German Legal (8.5 x 13 in) QPageSize8Fan-fold US (14.875 x 11 in)Fan-fold US (14.875 x 11 in) QPageSize(Folio (8.27 x 13 4<)Folio (8.27 x 13 in) QPageSize JIS B0JIS B0 QPageSize JIS B1JIS B1 QPageSizeJIS B10JIS B10 QPageSize JIS B2JIS B2 QPageSize JIS B3JIS B3 QPageSize JIS B4JIS B4 QPageSize JIS B5JIS B5 QPageSize JIS B6JIS B6 QPageSize JIS B7JIS B7 QPageSize JIS B8JIS B8 QPageSize JIS B9JIS B9 QPageSizeLedger / ANSI BLedger / ANSI B QPageSize LegalLegal QPageSizeLegal Extra Legal Extra QPageSizeLetter / ANSI ALetter / ANSI A QPageSizeLetter Extra Letter Extra QPageSizeLetter Plus Letter Plus QPageSizeLetter Small Letter Small QPageSizeNoteNote QPageSizePRC 16KPRC 16K QPageSizePRC 32KPRC 32K QPageSizePRC 32K Big PRC 32K Big QPageSizePostcardPostcard QPageSize QuartoQuarto QPageSizeStatement Statement QPageSizeSuper ASuper A QPageSizeSuper BSuper B QPageSize Tabloid / ANSI BTabloid / ANSI B QPageSizeTabloid Extra Tabloid Extra QPageSize&5B&NoQPlatformTheme&0&YesQPlatformTheme@5@20BLAbortQPlatformTheme@8<5=8BLApplyQPlatformTheme B<5=0CancelQPlatformTheme0:@KBLCloseQPlatformThemeB:;>=8BLDiscardQPlatformTheme!?@02:0HelpQPlatformTheme@>?CAB8BLIgnoreQPlatformTheme&5B 4;O 2A5E N&o to AllQPlatformThemeOKOKQPlatformThemeB:@KBLOpenQPlatformTheme!1@>A8BLResetQPlatformTheme> C<>;G0=8NRestore DefaultsQPlatformTheme>2B>@8BLRetryQPlatformTheme!>E@0=8BLSaveQPlatformTheme!>E@0=8BL 2A5Save AllQPlatformTheme0 4;O &2A5E Yes to &AllQPlatformTheme.>4C;L =5 1K; 703@C65=.The plugin was not loaded. QPluginLoader$58725AB=0O >H81:0 Unknown error QPluginLoaderN%1 C65 ACI5AB2C5B. %>B8B5 70<5=8BL 53>?/%1 already exists. Do you want to overwrite it? QPrintDialogX%1  MB> :0B0;>3. K15@8B5 4@C3>5 8<O D09;0.7%1 is a directory. Please choose a different file name. QPrintDialog&0@0<5B@K << &Options << QPrintDialog&0@0<5B@K >> &Options >> QPrintDialog&5G0BL&Print QPrintDialog1 (1x1)1 (1x1) QPrintDialog16 (4x4)16 (4x4) QPrintDialog2 (2x1)2 (2x1) QPrintDialog4 (2x2)4 (2x2) QPrintDialog6 (2x3)6 (2x3) QPrintDialog9 (3x3)9 (3x3) QPrintDialogA5 AB@0=8FK All Pages QPrintDialog2B><0B8G5A:8 Automatic QPrintDialog4!=87C 225@E, A;520 =0?@02>Bottom to Top, Left to Right QPrintDialog4!=87C 225@E, A?@020 =0;52>Bottom to Top, Right to Left QPrintDialog 'QB=K5 Even Pages QPrintDialogh%1 =54>ABC?5= 4;O 70?8A8. K15@8B5 4@C3>5 8<O D09;0.=File %1 is not writable. Please choose a different file name. QPrintDialog4!;520 =0?@02>, A=87C 225@ELeft to Right, Bottom to Top QPrintDialog4!;520 =0?@02>, A25@EC 2=87Left to Right, Top to Bottom QPrintDialog>:0;L=K9 D09; Local file QPrintDialogOKOK QPrintDialog5GQB=K5 Odd Pages QPrintDialogØ0@0<5B@K «!B@0=8F =0 ;8AB5» 8 «!?8A>: AB@0=8F» =5 <>3CB 8A?>;L7>20BLAO >4=>2@5<5==>. K:;NG8B5 >48= 87 =8E.gOptions 'Pages Per Sheet' and 'Page Set' cannot be used together. Please turn one of those options off. QPrintDialog 5G0BLPrint QPrintDialog"5G0BL 2 D09; ...Print To File ... QPrintDialog&5G0BL 2 D09; (PDF)Print to File (PDF) QPrintDialog4!?@020 =0;52>, A=87C 225@ERight to Left, Bottom to Top QPrintDialog4!?@020 =0;52>, A25@EC 2=87Right to Left, Top to Bottom QPrintDialog`=0G5=85 «A» =5 <>65B 1KBL 1>;LH5 7=0G5=8O «?>».7The 'From' value cannot be greater than the 'To' value. QPrintDialog4!25@EC 2=87, A;520 =0?@02>Top to Bottom, Left to Right QPrintDialog4!25@EC 2=87, A?@020 =0;52>Top to Bottom, Right to Left QPrintDialog0?8AL D09; PDFWrite PDF file QPrintDialog%1%%1%QPrintPreviewDialog-:A?>@B 2 PDF Export to PDFQPrintPreviewDialog5@20O AB@0=8F0 First pageQPrintPreviewDialog0 2AN AB@0=8FCFit pageQPrintPreviewDialog> H8@8=5 Fit widthQPrintPreviewDialog;L1><=0O LandscapeQPrintPreviewDialog$>A;54=OO AB@0=8F0 Last pageQPrintPreviewDialog$!;54CNI0O AB@0=8F0 Next pageQPrintPreviewDialog$0@0<5B@K AB@0=8FK Page SetupQPrintPreviewDialog$0@0<5B@K AB@0=8FK Page setupQPrintPreviewDialog=86=0OPortraitQPrintPreviewDialog&@54K4CI0O AB@0=8F0 Previous pageQPrintPreviewDialog 5G0BLPrintQPrintPreviewDialog@>A<>B@ ?5G0B8 Print PreviewQPrintPreviewDialog6>:070BL B8BC;L=K5 AB@0=8FKShow facing pagesQPrintPreviewDialog6>:070BL >17>@ 2A5E AB@0=8FShow overview of all pagesQPrintPreviewDialog,>:070BL >4=C AB@0=8FCShow single pageQPrintPreviewDialog#25;8G8BLZoom inQPrintPreviewDialog#<5=LH8BLZoom outQPrintPreviewDialog"0@0<5B@K 7040=8O Job OptionsQPrintPropertiesDialog $>@<0FormQPrintPropertiesWidget!B@0=8F0PageQPrintPropertiesWidget& 07>1@0BL ?> :>?8O<CollateQPrintSettingsOutput&25BColorQPrintSettingsOutput 568< F25B0 Color ModeQPrintSettingsOutput >?88CopiesQPrintSettingsOutput">;8G5AB2> :>?89:Copies:QPrintSettingsOutput "5:CI0O AB@0=8F0 Current PageQPrintSettingsOutput&2CAB>@>==OO ?5G0BLDuplex PrintingQPrintSettingsOutput $>@<0FormQPrintSettingsOutputBB5=:8 A5@>3> GrayscaleQPrintSettingsOutput$> 4;8==>9 AB>@>=5 Long sideQPrintSettingsOutput5BNoneQPrintSettingsOutput0@0<5B@KOptionsQPrintSettingsOutput 0AB@>9:8 2K2>40Output SettingsQPrintSettingsOutput!?8A>: AB@0=8F: Page Set:QPrintSettingsOutput!B@0=8FK A Pages fromQPrintSettingsOutputA5 Print allQPrintSettingsOutput80?07>= ?5G0B8 Print rangeQPrintSettingsOutput 1@0B=K9 ?>@O4>:ReverseQPrintSettingsOutput&K45;5==K9 D@03<5=B SelectionQPrintSettingsOutput&> :>@>B:>9 AB>@>=5 Short sideQPrintSettingsOutput?>toQPrintSettingsOutput&0720=85:&Name: QPrintWidget...... QPrintWidget $>@<0Form QPrintWidget 0A?>;>65=85: Location: QPrintWidgetK2>4 2 &D09;: Output &file: QPrintWidget!&2>9AB20 P&roperties QPrintWidget@>A<>B@Preview QPrintWidget@8=B5@Printer QPrintWidget"8?:Type: QPrintWidgetf5 C40;>AL >B:@KBL ?5@5=0?@02;5=85 22>40 4;O GB5=8O,Could not open input redirection for readingQProcessh5 C40;>AL >B:@KBL ?5@5=0?@02;5=85 2K2>40 4;O 70?8A8-Could not open output redirection for writingQProcessFH81:0 ?>;CG5=8O 40==KE >B ?@>F5AA0Error reading from processQProcess>H81:0 >B?@02:8 40==KE ?@>F5AACError writing to processQProcess(@>3@0<<0 =5 C:070=0No program definedQProcess8@>F5AA 7025@H8;AO A >H81:>9Process crashedQProcess@5 C40;>AL 70?CAB8BL ?@>F5AA: %1Process failed to start: %1QProcessJ@5<O =0 >?5@0F8N A ?@>F5AA>< 8AB5:;>Process operation timed outQProcessRH81:0 2K45;5=8O @5AC@A>2 (A1>9 fork): %1!Resource error (fork failure): %1QProcessB<5=8BLCancelQProgressDialogA5 D09;K (*.*)All files (*.*)QQnxFileDialogHelper"",CANCELQQnxFileDialogHelperOKOKQQnxFileDialogHelperK1>@ D09;0 Pick a fileQQnxFilePickerL=5?@028;L=K9 A8=B0:A8A :;0AA0 A8<2>;>2bad char class syntaxQRegExp@=5?@028;L=K9 A8=B0:A8A lookaheadbad lookahead syntaxQRegExpB=5?@028;L=K9 A8=B0:A8A ?>2B>@5=8Obad repetition syntaxQRegExpL8A?>;L7>20=85 >B:;NGQ==KE 2>7<>6=>AB59disabled feature usedQRegExp,=5:>@@5:B=0O :0B53>@8Oinvalid categoryQRegExp*=5:>@@5:B=K9 8=B5@20;invalid intervalQRegExpD=5:>@@5:B=>5 2>AL<5@8G=>5 7=0G5=85invalid octal valueQRegExpXlookbehind =5 ?>445@68205BAO, A<. QTBUG-2371)lookbehinds not supported, see QTBUG-2371QRegExpB4>AB83=CB> 2=CB@5==55 >3@0=8G5=85met internal limitQRegExp:>BACBAB2C5B ;52K9 @0745;8B5;Lmissing left delimQRegExp$>H81:8 >BACBAB2CNBno error occurredQRegExp"=5>6840==K9 :>=5Funexpected endQRegExp:(*MARK) 4>;65= 8<5BL 0@3C<5=B(*MARK) must have an argumentQRegularExpression$(*VERB) =5 >?>7=0=(*VERB) not recognizedQRegularExpressionR70 (?R 8;8 (?[+-]F8D@K 4>;6=0 A;54>20BL ))(?R or (?[+-]digits must be followed by )QRegularExpressionP3@C??0 DEFINE A>45@68B 1>;55 >4=>9 25B:8*DEFINE group contains more than one branchQRegularExpressionZPCRE =5 ?>445@68205B \L, \l, \N{8<O}, \U 8 \u1PCRE does not support \L, \l, \N{name}, \U, or \uQRegularExpressionXPOSIX-A>@B8@>2:0 M;5<5=B>2 =5 ?>445@68205BAO*POSIX collating elements are not supportedQRegularExpressionˆ:;0AAK 8<5=>20==K5 2 AB8;5 POSIX ?>445@6820NBAO B>;L:> 2=CB@8 :;0AA05POSIX named classes are supported only within a classQRegularExpression"\ 2 :>=F5 H01;>=0\ at end of patternQRegularExpressionJ\C =5 4>?CAB8<0 2 ?@>25@:5 lookbehind&\C not allowed in lookbehind assertionQRegularExpression:\N =5 ?>445@68205BAO 2 :;0AA5\N is not supported in a classQRegularExpression$\c 2 :>=F5 H01;>=0\c at end of patternQRegularExpressionL?>A;5 \c 4>;65= A;54>20BL A8<2>; ASCII)\c must be followed by an ASCII characterQRegularExpressionÂ70 \g 4>;6=> A;54>20BL G8A;> 8;8 =0720=85/G8A;> 70:;NGQ==>5 2 D83C@=K5/C3;>2K5 A:>1:8 8;8 :02KG:8[\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain numberQRegularExpression¢70 \k 4>;6=> A;54>20BL =0720=85 70:;NGQ==>5 2 D83C@=K5/C3;>2K5 A:>1:8 8;8 :02KG:8?\k is not followed by a braced, angle-bracketed, or quoted nameQRegularExpression€] =54>?CAB8<K9 A8<2>; 40==KE 2 @568<5 A>2<5AB8<>AB8 A JavaScript?] is an invalid data character in JavaScript compatibility modeQRegularExpressionP=C<5@>20==0O AAK;:0 =5 4>;6=0 1KBL =C;Q<%a numbered reference must not be zeroQRegularExpressionr4;O (*ACCEPT), (*FAIL) 8 (*COMMIT) 0@3C<5=BK =5 4>?CAB8<K?an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)QRegularExpression8?>A;5 (?( B@51C5BAO ?@>25@:0assertion expected after (?(QRegularExpressiont7=0G5=85 A8<2>;0 2 ?>A;54>20B5;L=>AB8 \u... A;8H:>< 25;8:>/character value in \u.... sequence is too largeQRegularExpressionz7=0G5=85 A8<2>;0 2 ?>A;54>20B5;L=>AB8 \x{...} A;8H:>< 1>;LH>50character value in \x{...} sequence is too largeQRegularExpression>B@51C5BAO 70:@K20NI0O ) 4;O (?Cclosing ) for (?C expectedQRegularExpressionRCA;>2=0O 3@C??0 A>45@68B 1>;55 42CE 25B>:1conditional group contains more than two branchesQRegularExpressionv>B;8G=K5 8<5=0 4;O ?>4H01;>=>2 A >4=8< =><5@>< =5 4>?CAB8<KBdifferent names for subpatterns of the same number are not allowedQRegularExpression2?>A;5 (?+ B@51C5BAO F8D@0digit expected after (?+QRegularExpressionv=54>?CAB8<0O :>4>20O B>G:0 Unicode (>= 0xd800 && <= 0xdfff)6disallowed Unicode code point (>= 0xd800 && <= 0xdfff)QRegularExpressionB2 :0G5AB25 erroffset ?5@540= NULLerroffset passed as NULLQRegularExpression4=5 C40;>AL 2K45;8BL ?0<OBLfailed to get memoryQRegularExpressionL8<O 3@C??K 4>;6=> =0G8=0BLAO A =5F8D@K&group name must start with a non-digitQRegularExpression6=5A>2<5AB8<0O >?F8O NEWLINEinconsistent NEWLINE optionsQRegularExpressionH2=CB@5==OO >H81:0: ?5@5?>;=5=85 :>40internal error: code overflowQRegularExpressionl2=CB@5==OO >H81:0: 2KE>4 70 ?@545;K >1;0AB8 :><?8;OF88+internal error: overran compiling workspaceQRegularExpressionp2=CB@5==OO >H81:0: @0=55 ?@>25@5==K9 ?>4H01;>= =5 =0945=Binternal error: previously-checked referenced subpattern not foundQRegularExpressionJ2=CB@5==OO >H81:0: =5>6840==K9 ?>2B>@!internal error: unexpected repeatQRegularExpressionr2=CB@5==OO >H81:0: =58725AB=K9 >?:>4 2 find_fixedlength()4internal error: unknown opcode in find_fixedlength()QRegularExpression4=5:>@@5:B=0O AB@>:0 UTF-16invalid UTF-16 stringQRegularExpression4=5:>@@5:B=0O AB@>:0 UTF-32invalid UTF-32 stringQRegularExpression2=5:>@@5:B=0O AB@>:0 UTF-8invalid UTF-8 stringQRegularExpression4=5:>@@5:B=>5 CA;>285 (?(0)invalid condition (?(0)QRegularExpressionj=5:>@@5:B=0O ESC-?>A;54>20B5;L=>ABL 2 :;0AA5 A8<2>;>2*invalid escape sequence in character classQRegularExpressionN=54>?CAB8<K9 480?07>= 2 :;0AA5 A8<2>;>2 invalid range in character classQRegularExpression^?@>25@:0 lookbehind 8<55B =5D8:A8@>20==CN 4;8=C(lookbehind assertion is not fixed lengthQRegularExpressionj=5:>@@5:B=> AD>@<8@>20=0 ?>A;54>20B5;L=>ABL \P 8;8 \pmalformed \P or \p sequenceQRegularExpression`=5:>@@5:B=> AD>@<8@>20=> G8A;> 8;8 8<O ?>A;5 (?("malformed number or name after (?(QRegularExpression>BACBAB2C5B ) missing )QRegularExpression>>BACBAB2C5B ) ?>A;5 :><<5=B0@8Omissing ) after commentQRegularExpression`>BACBAB2C5B >B:@K20NI0O D83C@=0O A:>1:0 ?>A;5 \omissing opening brace after \oQRegularExpressionZ>BACBAB2C5B 7025@H0NI0O ] 4;O :;0AA0 A8<2>;>2)missing terminating ] for character classQRegularExpressionxA;8H:>< 4;8==>5 8<O 2 (*MARK), (*PRUNE), (*SKIP) 8;8 (*THEN):name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)QRegularExpression=5B >H81:8no errorQRegularExpressionŠ=5-H5AB=04F0B5@8G=K9 A8<2>; 2 \x {} (>BACBAB2C5B 70:@K20NI0O A:>1:0?)2non-hex character in \x{} (closing brace missing?)QRegularExpression€=5-2>AL<5@8G=K9 A8<2>; 2 \o {} (>BACBAB2C5B 70:@K20NI0O A:>1:0?)4non-octal character in \o{} (closing brace missing?)QRegularExpression =5G53> ?>2B>@OBLnothing to repeatQRegularExpression4G8A;> ?>A;5 (?C 1>;LH5 255number after (?C is > 255QRegularExpression(G8A;> A;8H:>< 25;8:>number is too bigQRegularExpressionNG8A;> A;8H:>< 25;8:> 2 :20;8D8:0B>@5 {}number too big in {} quantifierQRegularExpressionJ=5:>@@5:B=K5 G8A;0 2 :20;8D8:0B>@5 {}%numbers out of order in {} quantifierQRegularExpressiond2>AL<8@8G=>5 G8A;> 1>;LH5 \377 (2 @568<5 =5 UTF-8)4octal value is greater than \377 (not in UTF-8 mode)QRegularExpression>A;8H:>< 1>;LH>5 2;>65=85 A:>1>:!parentheses are too deeply nestedQRegularExpression`A;8H:>< 1>;LH>5 2;>65=85 A:>1>: (:>=B@>;L AB5:0)/parentheses are too deeply nested (stack check)QRegularExpressionN=5:>@@5:B=K9 480?07>= 2 :;0AA5 A8<2>;>2%range out of order in character classQRegularExpressionV@5:C@A82=K9 2K7>2 <>65B 70F8:;8BLAO =025G=>&recursive call could loop indefinitelyQRegularExpressionDAAK;:0 =0 =5ACI5AB2CNI89 ?>4H01;>=$reference to non-existent subpatternQRegularExpressionF 53C;O@=>5 2K@065=85 A;8H:>< 25;8:>regular expression is too largeQRegularExpression@?>2B>@ 3@C??K DEFINE =5 4>?CAB8<'repeating a DEFINE group is not allowedQRegularExpressionF=0AB@>9:0 UTF >B:;NG5=0 ?@8;>65=85<*setting UTF is disabled by the applicationQRegularExpression0B@51C5BAO 8<O ?>4H01;>=0subpattern name expectedQRegularExpressionx=0720=85 ?>4H01;>=0 A;8H:>< 25;8:> (>3@0=8G5=> 2 32 A8<2>;0)3subpattern name is too long (maximum 32 characters)QRegularExpressionN?>445@6:0 \P, \p 8 \X =5 A:><?8;8@>20=00support for \P, \p, and \X has not been compiledQRegularExpression’A8=B0:A8G5A:0O >H81:0 2 8<5=8 ?>4H01;>=0 (>BACBAB2C5B ?@87=0: 7025@H5=8O)4syntax error in subpattern name (missing terminator)QRegularExpression\MB0 25@A8O PCRE A>1@0=0 157 ?>445@6:8 PCRE_UCP:this version of PCRE is not compiled with PCRE_UCP supportQRegularExpression^MB0 25@A8O PCRE A>1@0=0 157 ?>445@6:8 PCRE_UTF8;this version of PCRE is not compiled with PCRE_UTF8 supportQRegularExpression@A;8H:>< <=>3> >?5@560NI8E AAK;>:too many forward referencesQRegularExpressionnA;8H:>< <=>3> 8<5=>20=KE ?>4H01;>=>2 (>3@0=8G5=> 10000)*too many named subpatterns (maximum 10000)QRegularExpression^420 8<5=>20==KE ?>4H01;>=0 8<5NB >48=0:>2>5 8<O(two named subpatterns have the same nameQRegularExpression8=58725AB=>5 8<O POSIX :;0AA0unknown POSIX class nameQRegularExpression\=58725AB=K9 =01>@ D;03>2 @53C;O@=>3> 2K@065=8Ounknown option bit(s) setQRegularExpressionP=58725AB=>5 8<O A2>9AB20 ?>A;5 \P 8;8 \p$unknown property name after \P or \pQRegularExpression::@C3;K5 A:>1:8 =5 A>3;0A>20=Kunmatched parenthesesQRegularExpressionRA8<2>; A;54CNI89 70 (? 8;8 (?- =5 >?>7=0=&unrecognized character after (? or (?-QRegularExpression6A8<2>; ?>A;5 (?< =5 >?>7=0= unrecognized character after (?<QRegularExpression6A8<2>; ?>A;5 (?P =5 >?>7=0= unrecognized character after (?PQRegularExpression@A8<2>; A;54CNI89 70 \ =5 >?>7=0= unrecognized character follows \QRegularExpression6H81:0 >B:@KB8O 107K 40==KEError opening databaseQSQLite2Driver852>7<>6=> =0G0BL B@0=70:F8NUnable to begin transactionQSQLite2Driver>52>7<>6=> 7025@H8BL B@0=70:F8NUnable to commit transactionQSQLite2Driver<52>7<>6=> >B:0B8BL B@0=70:F8NUnable to rollback transactionQSQLite2Driver<52>7<>6=> 2K?>;=8BL 2K@065=85Unable to execute statementQSQLite2Result<52>7<>6=> ?>;CG8BL @57C;LB0BKUnable to fetch resultsQSQLite2Result6H81:0 70:@KB8O 107K 40==KEError closing database QSQLiteDriver6H81:0 >B:@KB8O 107K 40==KEError opening database QSQLiteDriver852>7<>6=> =0G0BL B@0=70:F8NUnable to begin transaction QSQLiteDriver>52>7<>6=> 7025@H8BL B@0=70:F8NUnable to commit transaction QSQLiteDriver<52>7<>6=> >B:0B8BL B@0=70:F8NUnable to rollback transaction QSQLiteDriver$BACBAB2C5B 70?@>ANo query QSQLiteResultD>;8G5AB2> ?0@0<5B@>2 =5 A>2?0405BParameter count mismatch QSQLiteResult:52>7<>6=> ?@82O70BL ?0@0<5B@Unable to bind parameters QSQLiteResultl52>7<>6=> >4=>2@5<5==> 70?CAB8BL =5A:>;L:> >?5@0B>@>2/Unable to execute multiple statements at a time QSQLiteResult<52>7<>6=> 2K?>;=8BL 2K@065=85Unable to execute statement QSQLiteResult452>7<>6=> ?>;CG8BL AB@>:CUnable to fetch row QSQLiteResult:52>7<>6=> A1@>A8BL 2K@065=85Unable to reset statement QSQLiteResultP!CI5AB2CNI89 D09; «%1» 70I8IQ= >B 70?8A8 Existing file %1 is not writable QSaveFile<<O D09;0 AAK;05BAO =0 :0B0;>3Filename refers to a directory QSaveFile60?8AL ?@5@20=0 ?@8;>65=85<Writing canceled by application QSaveFile=87Bottom QScrollBar ;52>9 3@0=8F5 Left edge QScrollBar 0 AB@0=8FC 2=87 Page down QScrollBar"0 AB@0=8FC 2;52> Page left QScrollBar$0 AB@0=8FC 2?@02> Page right QScrollBar"0 AB@0=8FC 225@EPage up QScrollBar  ?@02>9 3@0=8F5 Right edge QScrollBar@>:@CB8BL 2=87 Scroll down QScrollBar@>:@CB8BL AN40 Scroll here QScrollBar @>:@CB8BL 2;52> Scroll left QScrollBar"@>:@CB8BL 2?@02> Scroll right QScrollBar @>:@CB8BL 225@E Scroll up QScrollBar 25@ETop QScrollBarR%1: A?5F8D8G5A:89 :;NG UNIX =5 ACI5AB2C5B%1: UNIX key file doesn't exist QSharedMemory$%1: C65 ACI5AB2C5B%1: already exists QSharedMemory,%1: @07<5@ <5=LH5 =C;O%1: create size is less then 0 QSharedMemory"%1: =5 ACI5AB2C5B%1: doesn't exist QSharedMemory%1: >H81:0 ftok%1: ftok failed QSharedMemory.%1: =54>?CAB8<K9 @07<5@%1: invalid size QSharedMemory %1: >H81:0 :;NG0 %1: key error QSharedMemory%1: ?CAB>9 :;NG%1: key is empty QSharedMemory$%1: =5 ?@8;>65==K9%1: not attached QSharedMemory2%1: =54>AB0B>G=> @5AC@A>2%1: out of resources QSharedMemory&%1: 4>ABC? 70?@5IQ=%1: permission denied QSharedMemory>%1: =5 C40;>AL 70?@>A8BL @07<5@%1: size query failed QSharedMemoryV%1: A8AB5<>9 =0;>65=K >3@0=8G5=8O =0 @07<5@$%1: system-imposed size restrictions QSharedMemory8%1: =52>7<>6=> 701;>:8@>20BL%1: unable to lock QSharedMemory6%1: =52>7<>6=> A>740BL :;NG%1: unable to make key QSharedMemoryR%1: =52>7<>6=> CAB0=>28BL :;NG 1;>:8@>2:8%1: unable to set key on lock QSharedMemory:%1: =52>7<>6=> @071;>:8@>20BL%1: unable to unlock QSharedMemory2%1: =58725AB=0O >H81:0 %2%1: unknown error %2 QSharedMemory++ QShortcut(>1028BL 2 871@0==>5 Add Favorite QShortcut"0AB@>9:0 O@:>AB8Adjust Brightness QShortcutAltAlt QShortcut"520O A>DB-:=>?:0Application Left QShortcut$@020O A>DB-:=>?:0Application Right QShortcutF0F8:;5==>5 2>A?@>872545=85 4>@>6:8Audio Cycle Track QShortcut2!;CG09=>5 2>A?@>872545=85Audio Random Play QShortcut0>A?@>872545=85 ?> :@C3C Audio Repeat QShortcut#HQ;Away QShortcut 0704Back QShortcut0704/2?5@Q4 Back Forward QShortcutBackspace Backspace QShortcutBacktabBacktab QShortcut#A8;5=85 10A>2 Bass Boost QShortcut0AK =865 Bass Down QShortcut0AK 2KH5Bass Up QShortcut0B0@5OBattery QShortcut>;C10OBlue QShortcutBluetooth Bluetooth QShortcut =830Book QShortcut1>7@520B5;LBrowser QShortcutCDCD QShortcut0;L:C;OB>@ Calculator QShortcut>72>=8BLCall QShortcut$$>:CA8@>2:0 :0<5@K Camera Focus QShortcut0B2>@ :0<5@KCamera Shutter QShortcut B<5=0Cancel QShortcut5@=89 @538AB@ Caps Lock QShortcutCapsLockCapsLock QShortcut0=0; 2=87 Channel Down QShortcut0=0; 225@E Channel Up QShortcutG8AB8BLClear QShortcutG8AB8BL 70E20B Clear Grab QShortcut0:@KBLClose QShortcut2>4 :>40 Code input QShortcut!>>1I5AB2> Community QShortcut>?8@>20BLCopy QShortcutCtrlCtrl QShortcutK@570BLCut QShortcutDOSDOS QShortcutDelDel QShortcut#40;8BLDelete QShortcutDisplayDisplay QShortcut>:C<5=BK Documents QShortcut=87Down QShortcut72;5GLEject QShortcutEndEnd QShortcut EnterEnter QShortcutEscEsc QShortcut EscapeEscape QShortcutK?>;=8BLExecute QShortcut KE>4Exit QShortcutF%1F%1 QShortcut71@0==>5 Favorites QShortcut$8=0=AKFinance QShortcut 09B8Find QShortcut @KH:0Flip QShortcut ?5@Q4Forward QShortcut3@0Game QShortcut5@59B8Go QShortcut5;Q=0OGreen QShortcut ><>ILGuide QShortcut B1>9Hangup QShortcutHelpHelp QShortcut#AK?8BL Hibernate QShortcutAB>@8OHistory QShortcutHomeHome QShortcut><0H=89 >D8A Home Office QShortcut"><0H=OO AB@0=8F0 Home Page QShortcut>@OG85 AAK;:8 Hot Links QShortcut=D>@<0F8OInfo QShortcutInsIns QShortcutAB028BLInsert QShortcutL#<5=LH8BL O@:>ABL ?>4A25B:8 :;0280BC@KKeyboard Brightness Down QShortcutL#25;8G8BL O@:>ABL ?>4A25B:8 :;0280BC@KKeyboard Brightness Up QShortcut>:;./>B:;. ?>4A25B:C :;0280BC@KKeyboard Light On/Off QShortcut";0280BC@=>5 <5=N Keyboard Menu QShortcut>2B>@=K9 =01>@Last Number Redial QShortcut0?CAB8BL (0) Launch (0) QShortcut0?CAB8BL (1) Launch (1) QShortcut0?CAB8BL (2) Launch (2) QShortcut0?CAB8BL (3) Launch (3) QShortcut0?CAB8BL (4) Launch (4) QShortcut0?CAB8BL (5) Launch (5) QShortcut0?CAB8BL (6) Launch (6) QShortcut0?CAB8BL (7) Launch (7) QShortcut0?CAB8BL (8) Launch (8) QShortcut0?CAB8BL (9) Launch (9) QShortcut0?CAB8BL (A) Launch (A) QShortcut0?CAB8BL (B) Launch (B) QShortcut0?CAB8BL (C) Launch (C) QShortcut0?CAB8BL (D) Launch (D) QShortcut0?CAB8BL (E) Launch (E) QShortcut0?CAB8BL (F) Launch (F) QShortcut >GB0 Launch Mail QShortcut@>83@K20B5;L Launch Media QShortcut ;52>Left QShortcut0<?>G:0 LightBulb QShortcut K9B8 87 A8AB5<KLogoff QShortcut 5@5A;0BL ?8AL<> Mail Forward QShortcut  K=>:Market QShortcut.#A:>@5==>5 ?@>83@K20=85Media Fast Forward QShortcut.>A?@>8725AB8 A;54CNI55 Media Next QShortcut:@8>AB0=>28BL 2>A?@>872545=85 Media Pause QShortcut,0G0BL 2>A?@>872545=85 Media Play QShortcut0>A?@>8725AB8 ?@54K4CI55Media Previous QShortcut0G0BL 70?8AL Media Record QShortcut&5@5<>B0BL 2 =0G0;> Media Rewind QShortcut4AB0=>28BL 2>A?@>872545=85 Media Stop QShortcutAB@5G0Meeting QShortcutMenuMenu QShortcutJ;85=B >1<5=0 <3=>25==K<8 A>>1I5=8O<8 Messenger QShortcutMetaMeta QShortcut$K:;NG8BL <8:@>D>=Microphone Mute QShortcut:#<5=LH8BL 3@><:>ABL <8:@>D>=0Microphone Volume Down QShortcut:#25;8G8BL 3@><:>ABL <8:@>D>=0Microphone Volume Up QShortcut4#<5=LH8BL O@:>ABL <>=8B>@0Monitor Brightness Down QShortcut4#25;8G8BL O@:>ABL <>=8B>@0Monitor Brightness Up QShortcut&5A:>;L:> 20@80=B>2Multiple Candidate QShortcut C7K:0Music QShortcut>8 A09BKMy Sites QShortcut!>740BLNew QShortcut>2>AB8News QShortcut5BNo QShortcutNumNum QShortcut &8D@>2K5 :;028H8Num Lock QShortcutNumLockNumLock QShortcut &8D@>2K5 :;028H8 Number Lock QShortcutB:@KBLOpen QShortcutB:@KBL URLOpen URL QShortcut ?F8OOption QShortcut!B@0=8F0 2=87 Page Down QShortcut!B@0=8F0 225@EPage Up QShortcutAB028BLPaste QShortcut PausePause QShortcut PgDownPgDown QShortcutPgUpPgUp QShortcut"5;5D>=Phone QShortcut7>1@065=8OPictures QShortcut>A?@>8725AB8Play QShortcutK:;NG8BL Power Down QShortcut$B:;NG5=85 ?8B0=8O Power Off QShortcut$@54K4CI89 20@80=BPrevious Candidate QShortcut PrintPrint QShortcut5G0BL M:@0=0 Print Screen QShortcut@8=B5@Printer QShortcut@0A=0ORed QShortcut$>2B>@8BL 459AB285Redo QShortcut1=>28BLRefresh QShortcut5@5703@C78BLReload QShortcutB25B8BLReply QShortcut ReturnReturn QShortcut ?@02>Right QShortcut>25@=CBL >:=0Rotate Windows QShortcut!>E@0=8BLSave QShortcut %@0=8B5;L M:@0=0 Screensaver QShortcut$$8:A0F8O ?@>:@CB:8 Scroll Lock QShortcutScrollLock ScrollLock QShortcut >8A:Search QShortcutK1@0BLSelect QShortcutB?@028BLSend QShortcut0AB@>9:8Settings QShortcut ShiftShift QShortcut03078=Shop QShortcut!?OI89 @568<Sleep QShortcut @>15;Space QShortcut&@>25@:0 >@D>3@0D88 Spellchecker QShortcut 0745;8BL M:@0= Split Screen QShortcut&-;5:B@>==0O B01;8FK Spreadsheet QShortcut 568< >6840=8OStandby QShortcutAB0=>28BLStop QShortcut!C1B8B@KSubtitle QShortcut>445@6:0Support QShortcut@8>AB0=>28BLSuspend QShortcut SysReqSysReq QShortcut !8AB5<=K9 70?@>ASystem Request QShortcutTabTab QShortcut0=5;L 7040G Task Panel QShortcut"5@<8=0;Terminal QShortcut @5<OTime QShortcut*!=OBL/?>;>68BL B@C1:CToggle Call/Hangup QShortcutP@8>AB0=>28BL/?@>4>;68BL 2>A?@>872545=85Toggle Media Play/Pause QShortcut=AB@C<5=BKTools QShortcut;02=>5 <5=NTop Menu QShortcutCB5H5AB285Travel QShortcut' =865 Treble Down QShortcut' 2KH5 Treble Up QShortcut2!25@EH8@>:>?>;>A=0O A2O7LUltra Wide Band QShortcut"B<5=8BL 459AB285Undo QShortcut 25@EUp QShortcut 845>Video QShortcut84View QShortcut>;>A>2>9 2K7>2 Voice Dial QShortcut"8H5 Volume Down QShortcutK:;NG8BL 72C: Volume Mute QShortcut @><G5 Volume Up QShortcutWWWWWW QShortcut@>1C645=85Wake Up QShortcutM1-:0<5@0WebCam QShortcut"5A?@>2>4=0O A5BLWireless QShortcut$"5:AB>2K9 @540:B>@Word Processor QShortcut Q;B0OYellow QShortcut0Yes QShortcut#25;8G8BLZoom QShortcut#25;8G8BLZoom In QShortcut#<5=LH8BLZoom Out QShortcut iTouchiTouch QShortcut8"8? 04@5A0 =5 ?>445@68205BAOAddress type not supportedQSocks5SocketEngineP!>548=5=85 =5 @07@5H5=> A5@25@>< SOCKSv5(Connection not allowed by SOCKSv5 serverQSocks5SocketEngine^!>548=5=85 A ?@>:A8-A5@25@>< =5>6840==> 70:@KB>&Connection to proxy closed prematurelyQSocks5SocketEngineN A>548=5=88 A ?@>:A8-A5@25@>< >B:070=>Connection to proxy refusedQSocks5SocketEngineZ@5<O =0 A>548=5=85 A ?@>:A8-A5@25@>< 8AB5:;>Connection to proxy timed outQSocks5SocketEngine,H81:0 A5@25@5 SOCKSv5General SOCKSv5 server failureQSocks5SocketEngineB@5<O =0 A5B52CN >?5@0F8N 8AB5:;>Network operation timed outQSocks5SocketEngineV5 C40;>AL 02B>@87>20BLAO =0 ?@>:A8-A5@25@5Proxy authentication failedQSocks5SocketEngine^5 C40;>AL 02B>@87>20BLAO =0 ?@>:A8-A5@25@5: %1Proxy authentication failed: %1QSocks5SocketEngine.@>:A8-A5@25@ =5 =0945=Proxy host not foundQSocks5SocketEngine0H81:0 ?@>B>:>;0 SOCKSv5SOCKS version 5 protocol errorQSocks5SocketEngineB><0=40 SOCKSv5 =5 ?>445@68205BAOSOCKSv5 command not supportedQSocks5SocketEngine!5BL =54>ABC?=0 TTL expiredQSocks5SocketEngineX58725AB=0O >H81:0 SOCKSv5 ?@>:A8 (:>4 0x%1)%Unknown SOCKSv5 proxy error code 0x%1QSocks5SocketEngine0480;>3 A ?@54C?@5645=85< alert messageQSpiAccessibleBridge0=8<0F8O animationQSpiAccessibleBridge?@8;>65=85 applicationQSpiAccessibleBridge?><>I=8: assistantQSpiAccessibleBridge<5=N :=>?:8 button menuQSpiAccessibleBridge0:=>?:0 A 2K?040NI8< <5=Nbutton with drop downQSpiAccessibleBridge8:=>?:0 A 2K?040NI59 B01;8F59button with drop down gridQSpiAccessibleBridge E>;ABcanvasQSpiAccessibleBridge OG59:0cellQSpiAccessibleBridge4803@0<<0chartQSpiAccessibleBridge D;06>: check boxQSpiAccessibleBridgeG0AKclockQSpiAccessibleBridge2K1>@ F25B0 color chooserQSpiAccessibleBridge:>;>=:0columnQSpiAccessibleBridge =0720=85 :>;>=:8 column headerQSpiAccessibleBridge"2K?040NI89 A?8A>: combo boxQSpiAccessibleBridge24>?>;=8B5;L=0O 8=D>@<0F8Ocomplementary contentQSpiAccessibleBridge:C@A>@ <KH8cursorQSpiAccessibleBridge@53C;OB>@dialQSpiAccessibleBridge 480;>3dialogQSpiAccessibleBridge4>:C<5=BdocumentQSpiAccessibleBridgeC@02=5=85equationQSpiAccessibleBridge70?>;=8B5;LfillerQSpiAccessibleBridge"=86=89 :>;>=B8BC;footerQSpiAccessibleBridge D>@<0formQSpiAccessibleBridge @0<:0frameQSpiAccessibleBridge3@0D8:0graphicQSpiAccessibleBridge"@53C;OB>@ @07<5@0gripQSpiAccessibleBridge703>;>2>:headingQSpiAccessibleBridge*2A?;K20NI0O ?>4A:07:0 help balloonQSpiAccessibleBridge<?>;5 4;O 22>40 3>@OG59 :;028H8 hotkey fieldQSpiAccessibleBridge8=48:0B>@ indicatorQSpiAccessibleBridge"=5:>@@5:B=0O @>;L invalid roleQSpiAccessibleBridge=04?8ALlabelQSpiAccessibleBridge :0A:04=0O ?0=5;L layered paneQSpiAccessibleBridge AAK;:0linkQSpiAccessibleBridge A?8A>:listQSpiAccessibleBridgeM;5<5=B A?8A:0 list itemQSpiAccessibleBridgeAB@>:0 <5=Nmenu barQSpiAccessibleBridgeM;5<5=B <5=N menu itemQSpiAccessibleBridge70<5B:0noteQSpiAccessibleBridge 2:;04:0 AB@0=8FKpage tabQSpiAccessibleBridgeA?8A>: 2:;04>: page tab listQSpiAccessibleBridge ?0=5;LpanelQSpiAccessibleBridge?0@03@0D paragraphQSpiAccessibleBridge 2A?;K20NI55 <5=N popup menuQSpiAccessibleBridge(8=48:0B>@ 2K?>;=5=8O progress barQSpiAccessibleBridge AB@0=8F0 A2>9AB2 property pageQSpiAccessibleBridge :=>?:0 push buttonQSpiAccessibleBridge?5@5:;NG0B5;L radio buttonQSpiAccessibleBridge AB@>:0rowQSpiAccessibleBridge=0720=85 AB@>:8 row headerQSpiAccessibleBridge ?>;>A0 ?@>:@CB:8 scroll barQSpiAccessibleBridge A5:F8OsectionQSpiAccessibleBridge@0745;8B5;L separatorQSpiAccessibleBridge?>;7C=>:sliderQSpiAccessibleBridge72C:soundQSpiAccessibleBridge?CAB>5 <5AB>spaceQSpiAccessibleBridgeG8A;>2>5 ?>;5spin boxQSpiAccessibleBridge @0745;8B5;L >:>=splitterQSpiAccessibleBridge AB@>:0 A>AB>O=8O status barQSpiAccessibleBridgeB01;8F0tableQSpiAccessibleBridge B5:ABtextQSpiAccessibleBridge:C@A>@ 2 B5:AB5 text caretQSpiAccessibleBridge AB@>:0 703>;>2:0 title barQSpiAccessibleBridge&?0=5;L 8=AB@C<5=B>2tool barQSpiAccessibleBridge?>4A:07:0tool tipQSpiAccessibleBridge 45@52>treeQSpiAccessibleBridgeM;5<5=B 45@520 tree itemQSpiAccessibleBridge=58725AB=0OunknownQSpiAccessibleBridgeweb-4>:C<5=B web documentQSpiAccessibleBridge`52>7<>6=> ?@54>AB028BL A5@B8D8:0B 157 :;NG0, %1,Cannot provide a certificate with no key, %1 QSslSocketFH81:0 A>740=8O :>=B5:AB0 SSL: (%1)Error creating SSL context (%1) QSslSocket<H81:0 A>740=8O A5AA88 SSL, %1Error creating SSL session, %1 QSslSocket<H81:0 A>740=8O A5AA88 SSL: %1Error creating SSL session: %1 QSslSocket6H81:0 :28B8@>20=8O SSL: %1Error during SSL handshake: %1 QSslSocketTH81:0 703@C7:8 ;>:0;L=>3> A5@B8D8:0B0, %1#Error loading local certificate, %1 QSslSocketFH81:0 703@C7:8 70:@KB>3> :;NG0, %1Error loading private key, %1 QSslSocket"H81:0 GB5=8O: %1Error while reading: %1 QSslSocketT5:>@@5:B=K9 8;8 ?CAB>9 A?8A>: H8D@>2 (%1)!Invalid or empty cipher list (%1) QSslSocket@5 C40;>AL ?@>25@8BL A5@B8D8:0BK!No certificates could be verified QSslSocket5B >H81:8No error QSslSocketh48= 87 A5@B8D8:0B>2 F5=B@0 A5@B8D8:0F88 =5:>@@5:B5=%One of the CA certificates is invalid QSslSocketd0:@KBK9 :;NG =5 A>>B25BAB2C5B >B:@KB><C :;NGC, %1+Private key does not certify public key, %1 QSslSocket>!>548=5=85 TLS/SSL 1K;> 70:@KB>&The TLS/SSL connection has been closed QSslSocket’@52KH5=> 7=0G5=85 ?0@0<5B@0 4;8=K ?CB8 ?>;O basicConstraints A5@B8D8:0B0!@>: 459AB28O A5@B8D8:0B0 8ABQ:The certificate has expired QSslSocketR!@>: 459AB28O A5@B8D8:0B0 5IQ =5 =0ABC?8; The certificate is not yet valid QSslSocketf!5@B8D8:0B A0<>?>4?8A0==K9 8 =5 O2;O5BAO 7025@5==K<-The certificate is self-signed, and untrusted QSslSocketV5 C40;>AL @0AH8D@>20BL ?>4?8AL A5@B8D8:0B00The certificate signature could not be decrypted QSslSocketj>;5 notAfter A5@B8D8:0B0 A>45@68B =5:>@@5:B=>5 2@5<O9The certificate's notAfter field contains an invalid time QSslSocketl>;5 notBefore A5@B8D8:0B0 A>45@68B =5:>@@5:B=>5 2@5<O:The certificate's notBefore field contains an invalid time QSslSocket "5:CI89 A5@B8D8:0B 8740B5;O 1K; >B:;>=Q=, B0: :0: =0720=85 8740B5;O 8 A5@89=K9 =><5@ =5 A>2?040NB A 845=B8D8:0B>@>< :;NG0 A5@B8D8:0B0µThe current candidate issuer certificate was rejected because its issuer name and serial number was present and did not match the authority key identifier of the current certificate QSslSocketÚ"5:CI89 A5@B8D8:0B 8740B5;O 1K; >B:;>=Q=, B0: :0: =0720=85 B5<K =5 A>2?0405B A =0720=85< 8740B5;O A5@B8D8:0B0‡The current candidate issuer certificate was rejected because its subject name did not match the issuer name of the current certificate QSslSocketŠ0720=85 C7;0 =5 A>2?0405B A 4>?CAB8<K<8 =0720=8O<8 C7;>2 A5@B8D8:0B0GThe host name did not match any of the valid hosts for this certificate QSslSocketH5 C40;>AL =09B8 A5@B8D8:0B 8740B5;O)The issuer certificate could not be found QSslSocketv5 C40;>AL =09B8 A5@B8D8:0B 8740B5;O ;>:0;L=>3> A5@B8D8:0B0LThe issuer certificate of a locally looked up certificate could not be found QSslSocket>!5@B8D8:0B C7;0 2 GQ@=>< A?8A:5#The peer certificate is blacklisted QSslSocket<!5@B8D8:0B =5 1K; ?@54>AB02;5=(The peer did not present any certificate QSslSocket\5 C40;>AL ?@>G8B0BL >B:@KBK9 :;NG A5@B8D8:0B03The public key in the certificate could not be read QSslSocketš>@=52>9 A5@B8D8:0B F5=B@0 A5@B8D8:0F88 >B<5G5= =0 >B:;>=5=85 4;O 40==>9 F5;8AThe root CA certificate is marked to reject the specified purpose QSslSocketœ>@=52>9 A5@B8D8:0B F5=B@0 A5@B8D8:0F88 =5 O2;O5BAO 7025@5==K< 4;O 40==>9 F5;87The root CA certificate is not trusted for this purpose QSslSocket¢>@=52>9 A5@B8D8:0B F5?>G:8 A5@B8D8:0B>2 A0<>?>4?8A0==K9 8 =5 O2;O5BAO 7025@5==K<KThe root certificate of the certificate chain is self-signed, and untrusted QSslSocket@5:>@@5:B=0O ?>4?8AL A5@B8D8:0B0+The signature of the certificate is invalid QSslSocketh@54AB02;5==K9 A5@B8D8:0B =5?@83>45= 4;O 40==>9 F5;87The supplied certificate is unsuitable for this purpose QSslSocketD5 C40;>AL @0AH8D@>20BL 40==K5: %1Unable to decrypt data: %1 QSslSocketX5 C40;>AL 8=8F80;878@>20BL :>=B5:AB SSL: %1Unable to init SSL Context: %1 QSslSocket<5 C40;>AL 70?8A0BL 40==K5: %1Unable to write data: %1 QSslSocket$58725AB=0O >H81:0 Unknown error QSslSocket4?@>B>:>; =5 ?>445@68205BAOunsupported protocol QSslSocket"0==K5 ?@8;>65=89Application DataQStandardPaths@8;>65=8O ApplicationsQStandardPathsMHCacheQStandardPaths0AB@>9:8 ConfigurationQStandardPaths 01>G89 AB>;DesktopQStandardPaths>:C<5=BK DocumentsQStandardPaths03@C7:8DownloadQStandardPaths (@8DBKFontsQStandardPaths ><0H=89 :0B0;>3HomeQStandardPaths $8;L<KMoviesQStandardPaths C7K:0MusicQStandardPaths7>1@065=8OPicturesQStandardPaths"A?>;=O5<K5 D09;KRuntimeQStandardPaths1I89 :MH Shared CacheQStandardPaths$1I0O :>=D83C@0F8OShared ConfigurationQStandardPaths1I85 40==K5 Shared DataQStandardPaths"@5<5==K9 :0B0;>3Temporary DirectoryQStandardPaths€BACBAB2C5B A>AB>O=85 ?> C<>;G0=8N 2 8AB>@8G5A:>< A>AB>O=88 «%1»+Missing default state in history state '%1' QStateMachinerBACBAB2C5B 8AE>4=>5 A>AB>O=85 2 A>AB02=>< A>AB>O=88 «%1»,Missing initial state in compound state '%1' QStateMachine~5B >1I53> ?@54:0 C 8AB>G=8:0 8 F5;8 ?5@5E>40 87 A>AB>O=8O «%1»GNo common ancestor for targets and source of transition from state '%1' QStateMachine$58725AB=0O >H81:0 Unknown error QStateMachine$%1: C65 ACI5AB2C5B%1: already existsQSystemSemaphore"%1: =5 ACI5AB2C5B%1: does not existQSystemSemaphore2%1: =54>AB0B>G=> @5AC@A>2%1: out of resourcesQSystemSemaphore&%1: 4>ABC? 70?@5IQ=%1: permission deniedQSystemSemaphore2%1: =58725AB=0O >H81:0 %2%1: unknown error %2QSystemSemaphore:52>7<>6=> >B:@KBL A>548=5=85Unable to open connection QTDSDriverF52>7<>6=> 8A?>;L7>20BL 107C 40==KEUnable to use database QTDSDriver @>:@CB8BL 2;52> Scroll LeftQTabBar"@>:@CB8BL 2?@02> Scroll RightQTabBarH?5@0F8O A A>:5B>< =5 ?>445@68205BAO$Operation on socket is not supported QTcpServerT5 C40;>AL ?@>G8B0BL >:>=G0=85 87>1@065=8OCould not read footerQTgaFileN5 C40;>AL ?@>G8B0BL 40==K5 87>1@065=8OCould not read image dataQTgaFileB5 C40;>AL ?5@5<5AB8BLAO : 40==K<Could not reset to read dataQTgaFileX5 C40;>AL ?5@5<5AB8BLAO : :>=FC 87>1@065=8O#Could not seek to image read footerQTgaFileL54>?CAB8<0O 3;C18=0 F25B0 87>1@065=8OImage depth not validQTgaFileT5 C40;>AL ?@>G8B0BL 703>;>2>: 87>1@065=8OImage header read failedQTgaFilef5?>445@68205<K9 B8? 87>1@065=8O: =5 TrueVision 2.0-Image type (non-TrueVision 2.0) not supportedQTgaFile@5?>445@68205<K9 B8? 87>1@065=8OImage type not supportedQTgaFile˜5 C40;>AL ?@>8725AB8 ?5@5<5I5=85 ?> D09;C/CAB@>9AB2C 4;O GB5=8O 87>1@065=8O&Seek file/device for image read failedQTgaFile˜'B5=85 87 ?>A;54>20B5;L=KE CAB@>9AB2 (=0?@8<5@, 87 A>:5B0) =5 ?>445@68205BAO:Sequential device (eg socket) for image read not supportedQTgaFile$>2B>@8BL 459AB285Redo QUndoGroup>2B>@8BL %1Redo %1 QUndoGroup"B<5=8BL 459AB285Undo QUndoGroupB<5=8BL %1Undo %1 QUndoGroup<?CAB>> QUndoModel$>2B>@8BL 459AB285Redo QUndoStack>2B>@8BL %1Redo %1 QUndoStack"B<5=8BL 459AB285Undo QUndoStackB<5=8BL %1Undo %1 QUndoStack6FSI 5@20O 6QAB:0O 87>;OF8OFSI First strong isolateQUnicodeControlCharacterMenuFAB028BL C?@02;ONI89 A8<2>; Unicode Insert Unicode control characterQUnicodeControlCharacterMenu\LRE 0G0;> 2AB@0820=8O =0?8A0=8O A;520 =0?@02>$LRE Start of left-to-right embeddingQUnicodeControlCharacterMenuVLRI 0G0;> 87>;OF88 =0?8A0=8O A;520 =0?@02>LRI Left-to-right isolateQUnicodeControlCharacterMenuFLRM @87=0: =0?8A0=8O A;520 =0?@02>LRM Left-to-right markQUnicodeControlCharacterMenuRLRO 0G0;> 70<5=K =0?8A0=8O A;520 =0?@02>#LRO Start of left-to-right overrideQUnicodeControlCharacterMenujPDF @87=0: >:>=G0=8O =0?8A0=8O A 4@C38< =0?@02;5=85<PDF Pop directional formattingQUnicodeControlCharacterMenuNPDI >AAB0=>2;5=85 87>;OF88 =0?@02;5=8OPDI Pop directional isolateQUnicodeControlCharacterMenu\LRE 0G0;> 2AB@0820=8O =0?8A0=8O A?@020 =0;52>$RLE Start of right-to-left embeddingQUnicodeControlCharacterMenuVRLI 0G0;> 87>;OF88 =0?8A0=8O A?@020 =0;52>RLI Right-to-left isolateQUnicodeControlCharacterMenuFRLM @87=0: =0?8A0=8O A?@020 =0;52>RLM Right-to-left markQUnicodeControlCharacterMenuRRLO 0G0;> 70<5=K =0?8A0=8O A?@020 =0;52>#RLO Start of right-to-left overrideQUnicodeControlCharacterMenuLZWJ 1J548=ONI89 A8<2>; =C;52>9 H8@8=KZWJ Zero width joinerQUnicodeControlCharacterMenuRZWNJ 5>1J548=ONI89 A8<2>; =C;52>9 H8@8=KZWNJ Zero width non-joinerQUnicodeControlCharacterMenu4ZWSP @>15; =C;52>9 H8@8=KZWSP Zero width spaceQUnicodeControlCharacterMenu'B> MB>? What's This?QWhatsThisAction**QWidget&>?8@>20BL&CopyQWidgetTextControl&AB028BL&PasteQWidgetTextControl&&>2B>@8BL 459AB285&RedoQWidgetTextControl$&B<5=8BL 459AB285&UndoQWidgetTextControl2!:>?8@>20BL &04@5A AAK;:8Copy &Link LocationQWidgetTextControl&K@570BLCu&tQWidgetTextControl#40;8BLDeleteQWidgetTextControlK45;8BL 2AQ Select AllQWidgetTextControl\5 C40;>AL 703@C78BL <>4C;L ?;0BD>@<K direct2d$Cannot load direct2d platform pluginQWindowsDirect2DIntegrationQt =5 <>65B 703@C78BL <>4C;L ?;0BD>@<K direct2d, B0: :0: CAB0=>2;5==0O 25@A8O Direct2D A;8H:>< AB0@0O. 8=8<0;L=K5 B@51>20=8O MB>3> <>4C;O: Windows 7 SP1 A Platform Update. "@51C5BAO Direct2D 25@A88 =5 =865 %1.%2.%3.%4. 5@A8O >1=0@C65==>3> Direct2D: %5.%6.%7.%8.-Qt cannot load the direct2d platform plugin because the Direct2D version on this system is too old. The minimum system requirement for this platform plugin is Windows 7 SP1 with Platform Update. The minimum Direct2D version required is %1.%2.%3.%4. The Direct2D version on this system is %5.%6.%7.%8.QWindowsDirect2DIntegration&025@H8BL&FinishQWizard&!?@02:0&HelpQWizard &0;55&NextQWizard&0;55 >&Next >QWizard< &0704< &BackQWizard B<5=0CancelQWizard>4B25@48BLCommitQWizard@>4>;68BLContinueQWizard >B>2>DoneQWizard 0704Go BackQWizard!?@02:0HelpQWizardx2 >1JO2;5=88 XML B@51CNBAO ?0@0<5B@K encoding 8;8 standaloneYencoding declaration or standalone declaration expected while reading the XML declarationQXmlH>H81:0 2 >1JO2;5=88 2=5H=53> >1J5:B03error in the text declaration of an external entityQXml4>H81:0 @071>@0 :><<5=B0@8O$error occurred while parsing commentQXml0>H81:0 @071>@0 4>:C<5=B0$error occurred while parsing contentQXmlP>H81:0 @071>@0 >1JO2;5=8O B8?0 4>:C<5=B05error occurred while parsing document type definitionQXml.>H81:0 @071>@0 M;5<5=B0$error occurred while parsing elementQXml*>H81:0 @071>@0 AAK;:8&error occurred while parsing referenceQXml8>H81:0 2K720=0 ?>;L7>20B5;5<error triggered by consumerQXml`2=5H=OO AAK;:0 =0 >1I89 >1J5:B =54>?CAB8<0 2 DTD;external parsed general entity reference not allowed in DTDQXml|2=5H=OO AAK;:0 =0 >1I89 >1J5:B =54>?CAB8<0 2 7=0G5=88 0B@81CB0Gexternal parsed general entity reference not allowed in attribute valueQXmlf2=CB@5==OO AAK;:0 =0 >1I89 >1J5:B =54>?CAB8<0 2 DTD4internal general entity reference not allowed in DTDQXmlD=5:>@@5:B=>5 8<O 48@5:B82K @071>@0'invalid name for processing instructionQXmlB@51C5BAO 1C:20letter is expectedQXmlFC:070=> 1>;55 >4=>3> B8?0 4>:C<5=B0&more than one document type definitionQXml$>H81:8 >BACBAB2CNBno error occurredQXml&@5:C@A82=K5 >1J5:BKrecursive entitiesQXml\2 >1JO2;5=88 XML B@51C5BAO ?0@0<5B@ standaloneAstandalone declaration expected while reading the XML declarationQXml BM3 =5 A>2?0405B tag mismatchQXml$=5>6840==K9 A8<2>;unexpected characterQXml.=5>6840==K9 :>=5F D09;0unexpected end of fileQXmln=5@07>1@0==0O AAK;:0 =0 >1J5:B 2 =5?@028;L=>< :>=B5:AB5*unparsed entity reference in wrong contextQXmlV2 >1JO2;5=88 XML B@51C5BAO ?0@0<5B@ version2version expected while reading the XML declarationQXmlT=5:>@@5:B=>5 7=0G5=85 ?0@0<5B@0 standalone&wrong value for standalone declarationQXmlN%1  =5:>@@5:B=K9 845=B8D8:0B>@ PUBLIC.#%1 is an invalid PUBLIC identifier. QXmlStream`%1  =5 O2;O5BAO :>@@5:B=K< =0720=85< :>48@>2:8.%1 is an invalid encoding name. QXmlStream|%1 =5 O2;O5BAO :>@@5:B=K< =0720=85< >1@010BK205<>9 8=AB@C:F88.-%1 is an invalid processing instruction name. QXmlStream, ?>;CG8;8 ' , but got ' QXmlStream6B@81CB «%1» ?5@5>?@545;Q=.Attribute '%1' redefined. QXmlStream<>48@>2:0 %1 =5 ?>445@68205BAOEncoding %1 is unsupported QXmlStreamb1=0@C65=> =5:>@@5:B=> 70:>48@>20==>5 A>45@68<>5.(Encountered incorrectly encoded content. QXmlStream01J5:B «%1» =5 >1JO2;5=.Entity '%1' not declared. QXmlStream"@51C5BAO  Expected  QXmlStream8"@51CNBAO A8<2>;L=K5 40==K5.Expected character data. QXmlStream@8H=85 40==K5 2 :>=F5 4>:C<5=B0.!Extra content at end of document. QXmlStreamT5:>@@5:B=>5 >1JO2;5=85 ?@>AB@0=AB20 8<Q=.Illegal namespace declaration. QXmlStream05:>@@5:B=K9 A8<2>; XML.Invalid XML character. QXmlStream*5:>@@5:B=>5 8<O XML.Invalid XML name. QXmlStream>5:>@@5:B=0O AB@>:0 25@A88 XML.Invalid XML version string. QXmlStreamL5:>@@5:B=K9 0B@81CB 2 >1JO2;5=88 XML.%Invalid attribute in XML declaration. QXmlStream>5:>@@5:B=0O A8<2>;L=0O AAK;:0.Invalid character reference. QXmlStream,5:>@@5:B=K9 4>:C<5=B.Invalid document. QXmlStream<5:>@@5:B=>5 7=0G5=85 >1J5:B0.Invalid entity value. QXmlStream`5:>@@5:B=>5 =0720=85 >1@010BK205<>9 8=AB@C:F88.$Invalid processing instruction name. QXmlStream:NDATA 2 >1JO2;5=88 ?0@0<5B@0.&NDATA in parameter entity declaration. QXmlStreamT@5D8:A ?@>AB@0=AB20 8<Q= «%1» =5 >1JO2;5="Namespace prefix '%1' not declared QXmlStreamVB:@K20NI89 BM3 =5 A>2?0405B A 70:@K20NI8<. Opening and ending tag mismatch. QXmlStream85>6840==K9 :>=5F 4>:C<5=B0.Premature end of document. QXmlStream:1=0@C65= @5:C@A82=K9 >1J5:B.Recursive entity detected. QXmlStreamd!AK;:0 =0 2=5H=89 >1J5:B «%1» 2 7=0G5=88 0B@81CB0.5Reference to external entity '%1' in attribute value. QXmlStreamJ!AK;:0 =0 =5>1@01>B0==K9 >1J5:B «%1»."Reference to unparsed entity '%1'. QXmlStreamd>A;54>20B5;L=>ABL «]]>» =54>?CAB8<0 2 A>45@68<><.&Sequence ']]>' not allowed in content. QXmlStream”A524>0B@81CB «standalone» <>65B ?@8=8<0BL B>;L:> 7=0G5=8O «yes» 8;8 «no»."Standalone accepts only yes or no. QXmlStream4"@51C5BAO >B:@K20NI89 BM3.Start tag expected. QXmlStreamŒA524>0B@81CB «standalone» 4>;65= =0E>48BLAO ?>A;5 C:070=8O :>48@>2:8.?The standalone pseudo attribute must appear after the encoding. QXmlStream5>6840==>5 ' Unexpected ' QXmlStreamx5>6840==K9 A8<2>; «%1» 2 ;8B5@0;5 >B:@KB>3> 845=B8D8:0B>@0./Unexpected character '%1' in public id literal. QXmlStream85?>445@68205<0O 25@A8O XML.Unsupported XML version. QXmlStream^1JO2;5=85 XML =0E>48BAO =5 2 =0G0;5 4>:C<5=B0.)XML declaration not at start of document. QXmlStreamˆ ý) ÿý, TreeLine-3.2.1/translations/qt_zh.qm000066400000000000000000003450541506556630100174530ustar00rootroot00000000000000<¸dÊÍ!¿`¡½ÝB+°*�+ÕÑ@¤ŠA¥B¥ƒC¥þD¦yE§&F§¡G¨H¨”I© P©´Qª5R«.S«©T¬$U¬ŸV­LW­ÇX®?Y®´]4 ;2;,›;{Ð; ƒ;´‡M4HOà¤Oí®Àåó}4pm4˜¯Â(5¸Ó+;f+;7U+;ž+O8+O�Ö1€E@ª³F•¯)H4ÕòHYF)H�ÙÚI¯×J¼Ø®JÄ…K5LDÙ/L“ÙƒPSÛ&Q’RIÚWŒ ÿZrål[`ÐŽ[`—\ÝgŒ_Ãæ¤_Ãî1º8¿Ãj¿Ãžl‡›Ì‡›=Ù‡›Ö–$G–$þ†˜,×7¦y§ÔA§ÔmݧÔõ«¨¥¦«ŒØ„¬9Gnµ›6®¶E5b¶E¶ÞÙÐ%èÐ%?DÓÚ0Ö�™aÖ�½ÞÖ�¿ŽÖ�ªì0 ì0x°ì0{mì0Ÿðì0Ú§ì0bö5“÷ö5ÚÑ D5í DE;+Ôß",£6ÿ,£ìd¹µ0~ÀeÄÀe6_ÀeEüį÷ į÷† «y§È~‘ïN^‘îù‘òoxžQ7–3î–m™Ç¼.(4²B”(4òBÈ(5Bü(5‚C0*¦yX*¦ym *¦yôš*ÖTMÉ*ì0'˜*ì0Ý+FÅwµ+FÅñ+Lô +f¾–+f¾;è+‹z.ˆ+‹¯¹+‹¯m+‹¯ôÿ+˜z.¼+˜Åþ+˜ÅXýôãYYÄóKxYç¥z9YïÔäQYö�AöZg•ä~Zkô´ZƒüLp[;^c\ŠÃÕ\]4€1\]4é®\ƒµ–Û\ú¿åat#�gcºlG¹œú|^ƒa�cÞ„V„v�5†„v�T…éÃ$Œ‹fS2Ž4L£uŽ5®£³Žã.7å�6CG<˜IA¸¥[³¡§ë‹ܨœ°I´ß꺫y­sɵn1xɵn`aɵndɵnrêɵn‹àɵnŽÞɵnɪɵn˧ËÔ(²ËÔUYÐ B¡Ó*Î —Þ'Ž“tãŽÞâ¾å˜Ë–êMº›>òEòiuòÎaÆ÷ËùW,qù®f Á¥o¢>\ºHÊ,]<äpù¨»×5]#Qé®Û%UT�™(ÅŽC™*ä4�.-ctò62Àé©05vXów¶^{öx¹ÉÌ=|{y§M�ÂcÑN…GñIN•ìé¶‹¡ÏWù¯¨2zd¨2Ø©ý±{'ÿKµ´.7†¶RÞ#î·Aiþ ·ÙÇ9¿P`¸à d-ÄyªÝÇtÕf.ìØiUî²Ä^šïy#[Iòº„gBóurdë ¸äŒã Ü~v¯ Yd ö⊙"l®ä)*¡-À¤S´/=Nå“1Ø$5~PØ< Äg·?—2ˆµ?»NM¡ã %Nky«UU¿i™W÷~cÂXŠþcþ]ÝéP`ê2‡`ê‘àj•t5lg˜lyzgõl}µèoiÁvty0êvtyÒP�1ýJ]”"¾#—úO™�ú™�ú?l£),¤¾s9¥4žG˜¥²)eýª6•w�ª6•�¡ª6•À´^¡S{´ƒŠÂK¶Š¥ˆ¶Š¥mO¶Š¥ôÌ·Ržœÿ·�T£ñº=|1º÷žÁ±¼~.$w¾‚´óྜûㆿ¾Ï“¿¾ ?¿EåÏÅ¿Eå oÀ‚´ÏùÀ‚´ ¡Ä{Ž÷1Ç=±†Ê8AÏÛAROÛÃè\ß[y¦%âL´ŽXä¤î:ì‚nµ~òø‘oó‚¤2Éó‚¤u󂤎󂤒#ó‚¤ÊBó‚¤ÌþõØmxQõðMwDõðM†öE”OçöE”VLw�ßw�ÎTâþV^îY’ ÍIµþ ŽžFÚáñ¨žáêLÅþCr ê‚Ò!Ïeû %ŽB4&¸ž%ð)Õæ*/eæH5”Œ"1;„}äB‹y¬KEcš.,F±å4éO«—Zõfö‹\céý`àv¿bœE¥cփ߲fãÄ&ªg&4 jCCdmÑnk8qï£qÕ_ËtßuéZu(µÚû{>‚}kaëí�½õK§ˆàš0�Ó~"‚�³O\“” �_—øÑQ{£y¾ B£–þFu©ßÒnª¯É$Ȭ¯É$ˆ°‚µ�´àäG˜ÀÄÌÁ+³57Ã( æuÊ�þœ�Êôr‰Î^ñÑKõ ûÑKõž*ÖŠÂ/×ã n—–ãõÉt„ä,Ôa‘êˆëÕÿ¢‰ñ;y¥/ùOžŒÔú-îQñùAïôžºÃ’nJ7^já=€4&H„a>.Ž ÷/¥Ä`õ?Þ;ÉIxS-…MþæRå>)ÇYMáPYMáVƒ^Á¾Päh�^#iïÓ&Zssc|Äs¡®+£wÞÎ$€»ÑPZˆxóFR‰/^qÒ‹2‹8Øè‹Œá^æá_~èNÀÚé•A2ë˜ÇHÀõ¬c$øöûª\øSÒJ”ûPqT¡þV… þV…FÿfR;«œ” œ”ÛMœ”í‹ ‚óHð ‚óÜ ×ä ^æ•A©²’ž”¢äŽ ö¼‚esúÔ_ˆ$ãä%CÉ#I&‹~I®&§Þ1ž)È2hÞ)ðž6Å*Ú4L’+­Â²a,ºÂ³ ?"£t?>u5J«î?¡KNóYMîÖ«R¿ò|kV“|JÃ]¿ž_Ô]¿žcŠdIŠŒg¡¾A k¶Þâ7yô^ ã€{y°Œ5t [ŒFÅAŸŒ¼Žã)�:�[‘ΞUv“åJï˜G%Nɘœn:™ØµŒ'šÇ¥§›ˆ˜äœ+¤ä)£6Äئ±t0§{y¯S¨/þ«”G¬;åLŸ®xALϯrɬư9\L°ˆÁäô°�sL@°ª½"ñ±Ï¾˜lµÞ%-0¸{ÎGý½C-ÈpÂ5ËàüÆžÆC^Y¥ƨ¥ dƨ¥íù˾äcÒÍîdtÒ�z-ÔiðâÕ§?íQÚZ>(ÉÛz‹9xߺºœ`ážhsãÄ8¿çf•„‹èq.�óm}¡üä^=þ!žš£ É £ú$v.~b@¡~bEhoÓÈMh0!ë¿b¬)ÑžQ‰+ÖuWð+ï3ÊŒ,8ΗÔ/ô…µJ/ô…ÁA1�õ�Z4~‹ 6Ï ãÅ? 2A£•¾¨Dç!_G¾ñO�GÎbD�LAUó�O�rçìPѧŸNQ…îXƒSÅn¢TµxÙUôfHUô�VUÞT_/ZËÑ×ÌZËÒ×úZËÓØ(ZËÔØV[ï]k*@s]ú®62^ãn¬_pÔ½se‘ÇižäSižäYwkQ¾)…oÛN%'y;Çsm{ÀZ}u�á×}w�Ï }w�çI}w� ¯}¶¨º<„ñ¤†Ò'öŠê‚ç�Õäfõ�r°Ðö“"ŽŽ#—B>™íÞ|ç›v£ÃC›ƒt›´›ƒt»Ž «.Ï9 «.çr¡®399¥PèÆø¦iU¸'¯aD”åµD„;µY´o»·Ýt(2·ÝtVö·Ýt~{¸°Ž0ºç�"Ò½-n�|À_ ánÃ+çùÉF±u_ÊC¾[þÊ¢ä3QÊ¢ä“(ÊÆ´’äÊçd3ÚÊçdu ÊçdŽ˜Êçd“°Êçd˜×Ë0 Ì59b"Ñ�çÄØ+] ÚNS“jä‡íËì»U….îd�”þ¯B þáh’jw®Œd–½jŒ 2þW¯ ×þÒ?†M …‘bc'V|O+ª¤ZÃ,ŒDÁ/ÿî2¼2ì7Ø42Þa£6’ÑSâ7·D‘M:‰rÃ?;Þ�6CU]mDØqIàN9|J0žœÉKÕ®K¯ ÙU|×]V7ÞN>\¬»arÅÊÒt‰€wÛKl|(^ |�ãü|¬»T}wZš×}š$ÎÞ}š$ç}š$ ‚ŒÏ—Ã{�Z’çœVN^fŸ”ÚŸ±D\B L>XS¡’§ãN…ªÜq±´K< Hµf+W·ƒÐ´·ƒññýž2ÅǶÆ×³ÀŽÎû ¤±Õ/XFàŸ,îãûµ´Tä½U�Éë»ENŽïHŽg˜õ�þxVøvþ”u %5Dü›T¸e©h{ e~Oói~™ɲŒúi 9%PÑä”ÿwÿb-Ý#²–%’¾%r'Õ‡|-å.zb.÷Ž' 5kEÇ÷=ƒâÕ‡=ƒâó ?ƒâo/?ƒârYCtIGÉPËîNîV%î”XXU ?©ZŒîh`ååÑÓ`îNvDbDå$bG·iÄfƒîBãf“dýUgŸAmhI•I iê$�Àx1 ×–z*2Öx|QR6‚¨d�âƒJ„w熮žlŠU€× ‹(.•vŽ÷5É•z8J•c.[ª�1-ª�ÔDµÞrµ¶°ãšé¸XÔѺmO^ºå^_»²e ò¼ìn¦½$¾K̽ŒÈãÀbÑa†5nÄØiF¶ÇC¼¡•Ê´5wèÊ´5!ʶÕyÖÌÉÅÁ}Ó^ ^AÚÔ„xÛ”#¼®ÝD„#ß'Nm4âÜd5ðF5!(ðF5yò»Y˜•ópÉ]qõ+>ƒBüùI�üùI?áýAs� äÑ3’ }$v| qeU” Ú¤}h Ú¥¿¿ ôdëO íEtE íE�ƒ î� Ac} AcB! Úôé 3š5„Þ u³ bÅÁç b�b÷­ b¾`Ð^ b¾`  gUòpÊ iä3%Ö laô{= lfñq uáÎu6 xq"% |o¾S‹ ‚|Å‚Ž Š·JÂÓ ŒtÓ ŒtÓAÉ Ž .$É Ží©~ ˜ŠÞ` ™)þM1 šF>,[ Ÿ¥Þ9° ¢³Ä(r ¢³Ä~¿ ¦„„ê§ §²ô ¨B¾— ©Ò‰µ¶ ­>óÌ· ­‚µÄ ²î¾Z{ ¸æÉd§ ¸æÉtÓ ºnqi ¼áNr] ÉËÃÿà ÊY+ÔŒ ÜKç  ÝÕøà 팤‹X îl~= ñ%'ø ö ® Ž ÷»¼Þ½ û/î1( =Ž!™ èqKã ü®—N }´œ# o´9 ¬Ž7V )µž´Ø */åÖ? .>¤q· 5Ýî^Á 7uó¾ ;�Ùk& =äNó BÇé·± BònE4 J‰"‡ J‰"•J K2# RÛ® 5 Ty š` Tþ^ÖÛ Uj4né ]‘ž…¬ `±` `±Ë bÕpI b¿®ˆP c(å¾B c·E¹Ì dÐÍí eœÇû eœÇ@B e¨{Ôá fŽ1Q/ fü*¿ g5Uºª gîn3 kŸ,Ö rD" t>nG è¼:.R ëf  ëf = ÷4�aÚ øÊ.M- øûŽW# ý‡s] ý‡s>º AAT, —9›x ˜ÄŸ� ÷9w ½ m,ƒ #-tƒÄ 0†N+a 5Ε A›ùîŸ CóUM— EÔ9> I߆ L‘¥( Lö'Æ Lö9 Mc\¡È RÕî^ SÐbõ V×e¸ W“å�% ]â$2@ f)Y f)== f=¦¹5 io>w mû`"À wÇÝ xáR/" y¡r5' ƒô>RI „‚ ¨ ‹æt ŒHÈ ŒH< �Ü *( � nDÁ ‘$þ> ’.@åÄ “þ’ — i¦  ¢× c £Ü p £Ü n3 £Ü ö ¬ü%°X ¯ÙJ� ¯ÙJ>é ´Ž#I ¿t.�à ÂkÔô ÃÓ‡É ÈMĽ§ ÈÇÞ ÊN>j( ̺óNc Ï&Þ‘ž Ô-DO& ÖØ.lœ Û·å»Â Ýc>IQ àrM  âkÔÐ+ âkÔ Ñ èU)Yç êéž ðË<!Î óŸãÒÐ óŸãòy õ0ËàÆ ö”Ĉ §é™À z+ —  „R—  „Y ŒIHZ ‚%MZ èNpÝ öá/ ©´þC xH\Š ƒòr  ®8> ®Þ .Éã-Ó 7F´þ >ÏòTq >ÏòU$ >ÏòUÙ >Ïò\ >ÏòfÀ >Ïòlì >Ïò…m >Ïò¢P ?t|ûú D€T ; IëË-X P@Þ  RVŽBg RVŽç RV®¸¥ S.ŸìÑ SGùˆP SÀ�ÀÎ Yå„ Yçõz¢ [•›ú c`¾eÊ hÛ®Gù j7o:Ø p¡Ã. v�ôtæ †šž3 ŒÁ.Éõ ŒÑBda Žè× �½T1¿ �½Ts3 �½T�& �½T—à ‘ñ¤$ ’›¢e/ “èÄ3 “èÄ’¡ ”Å HŽ –‚™°Š œüS› �)d„% Ÿ§Tq ©‰ùL ¬;>yê ¬Á.1÷ ¬Á.`ª ¬Á.sµ ¬Á.Œš ¬Á.�y ¬Á.Ëñ ­—ò °†Ôë® µÑ…¨ ¸a‚> » y!‚ »±Žoò ¾e.@Ç ÉhNpb Î>Xá Ò‚î$5 àó· æ%´1 èíuà ë¬åzö ñ­Þ8È ó|ôÒ� ô’Þlš úùh ýXtd ÿün‰ ¿9ýØ tÈ6 aðœ >7 :bZ. Uqwb à€’� O.<º Êœ,¿  Á]4 #$î•ñ #=—Äf %™nqb (I$çš (öN0\ +>º/& +kž‚– 0ÒE« 64Ó] ;ɾõc Fg•š K×9†S Ptµym Ptµ T»>R® W þH’ dBâg fèeÍö fèe, g­³Ë iFCÚ iØÄ@ iØÄÚV jÓ®¶î kGn m9Ä× n¤î'd u®áž uüÁðL v îo@ v&¥›å v{ðG w®Î‚ w®æÇ w® * w}¤Î° w}¤æò w}¤ V |[®+; €®”’ ƒÈôP¤ ƒÈôVÁ †¥%ü¾ ŽJ©]Ö —Ã^{• ¢}Òkä ªôRû= ±žP ¶²†Â ¾xN £ ÇÒUp ɰe·h ÍïF}, Ûùž'­ ÜX< ä&Þ*î êD� ë¼óAh ìÕ+Ô ðt5xÚ ðt5ß ð¨Cé òŽa2 ö¯>€ü ø¾z ø¾x ø)¤ y ú¾"�Rw¤ÅØ @af˜�T)‘‡Û¯‡Û;oîA°gT)ÜÚî4Í*‡«'ü*‡«n/ÇE(î/ÇE€€=êBi+IÌ_ZxK·õ�‘OO”pˆXRuúwXÑ4 [ š[Ÿ ·a.ÅŸ½a‚./›gcèºnyG*GvÉ…‚y$Èå€~¹[¼ƒ>GŽÞÎn¥“ª4‰y¦&®m ¨'î@«Ó4üƒ´÷Sf�»®^¢÷½Ç— žèŽ0¶¿ß:™ŽÇB¤&àÊæÂúãÎ�ìÜrµncÝ–þ±ò[y«Ð÷Þ^{‹úrÁ¬ íÒh íÒ>JG¾3#lDÅb–þ%®"#Ìo$ÚUE%º45¸%º4DÀ-v›ø…0i)߀0’Àà1�c�2wTßL<óT<(Î]›D¢Ã#~HúùJd[IK¡òêñKå#høL$.ÍW÷¾bbc5Ïdc5 ¬g3ºãiC¼Ðmhž�™pþŘTyƒC${~aÞî6$èY5 K�&ò‡ï�&ò–_‹{îj]•`é¨Cœ¿nS¡[ô!Ú¢÷>T†®þ&G¯·¯·>‡¹>b¼‰ý�¾N:I¿„¿À EÂ"~ÄÜLdåÉrÔ)1ÉrÔô?Ðky¥ªàLn~“è¼kéB÷¿LéPé­îøt2+Þû¾r¢û¾‹šû¾É`û¾Ë^þ”d¹vÿUµü7ižbp<html>RcbR0—ó˜‘VÞe>‹¾Y <b>%1</b>ÿ <br/>[ƒRRSØN:Sïu(^vNQwg fôšØv„OQH~§0</html>xSwitching to the audio playback device %1
      which just became available and has higher preference. AudioOutputl<html>—ó˜‘VÞe>‹¾Y <b>%1</b> l¡g ]åO\0<br/>VÞnÚR0 <b>%2</b>0</html>^The audio playback device %1 does not work.
      Falling back to %2. AudioOutput`bY R0‹¾Y %1 Revert back to device '%1' AudioOutput Qs•íh{~˜u Close Tab CloseButton QsNŽ %1About %1MAC_APPLICATION_MENU–�…Ï%1Hide %1MAC_APPLICATION_MENU–�…ÏQvNÖ Hide OthersMAC_APPLICATION_MENU POY}‹¾n &Preferences...MAC_APPLICATION_MENU �Qú %1Quit %1MAC_APPLICATION_MENUg R¡ServicesMAC_APPLICATION_MENUQh�èf>y:Show AllMAC_APPLICATION_MENU eà–œx�s¯Xƒ AccessibilityPhonon::�‹¯ CommunicationPhonon::n8bGamesPhonon::—óNPMusicPhonon::�wå NotificationsPhonon::‰Æ˜‘VideoPhonon::f‹fTJÿw �wgeÿ `¨l¡g [‰ˆÅWúx@v„ GStreamer cÒNö0 b@g v„—ó˜‘TŒ‰Æ˜‘e/c�ý]ò~ψ«Qs•í0~Warning: You do not seem to have the base GStreamer plugins installed. All audio and video support has been disabledPhonon::Gstreamer::Backendv‹fTJÿw �wgeÿ `¨l¡g [‰ˆÅ gstreamer0.10-plugins-good S0 NN›‰Æ˜‘ry`']ò~ψ«Qs•í0„Warning: You do not seem to have the package gstreamer0.10-plugins-good installed. Some video features have been disabled.Phonon::Gstreamer::Backend>:\NN*—‰�v„‰ãxVh0`¨—‰�[‰ˆÅY‚N ‰ãxVhged­e>�ÙN*Q…[¹ÿ%0`A required codec is missing. You need to install the following codec(s) to play this content: %0Phonon::Gstreamer::MediaObject€N €ý_YËVÞe>0 ‹÷hÀgå`¨v„ Gstreamer [‰ˆÅ^vNxn‹¤`¨ ]ò~Ï[‰ˆÅ libgstreamer-plugins-base0wCannot start playback. Check your Gstreamer installation and make sure you have libgstreamer-plugins-base installed.Phonon::Gstreamer::MediaObjectN €ý‰ãxZ’OSn�0Could not decode media source.Phonon::Gstreamer::MediaObjectN €ý[šOMZ’OSn�0Could not locate media source.Phonon::Gstreamer::MediaObject&N €ýbS_—󘑋¾Y0�ÙN*‹¾YkcW(ˆ«Ou(0:Could not open audio device. The device is already in use.Phonon::Gstreamer::MediaObjectN €ýbS_Z’OSn�0Could not open media source.Phonon::Gstreamer::MediaObjecteàeHv„n�|{W‹0Invalid source type.Phonon::Gstreamer::MediaObject0‹÷Ou(�ÙN*nÑWWŒ‚‚—ó‘Ï0g]æN:%0ÿ gSóN:%1%WUse this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1%Phonon::VolumeSlider —ó‘Ïÿ%1% Volume: %1%Phonon::VolumeSlider%1ÿ %2g*[šNI%1, %2 not definedQ3AccelN fxnv„%1l¡g ˆ«YtAmbiguous %1 not handledQ3AccelR –dDelete Q3DataTablePGFalse Q3DataTablecÒQeInsert Q3DataTablewTrue Q3DataTablefôe°Update Q3DataTable*e‡Nö%1 g*b~R00 ‹÷hÀgå�ï_„TŒe‡NöT 0 +%1 File not found. Check path and filename. Q3FileDialog R –d(&D)&Delete Q3FileDialog T&(&N)&No Q3FileDialog xn[š(&O)&OK Q3FileDialog bS_(&O)&Open Q3FileDialog‘ÍT}T (&R)&Rename Q3FileDialog OÝ[X(&S)&Save Q3FileDialogg*c’Rv„(&U) &Unsorted Q3FileDialog f/(&Y)&Yes Q3FileDialog0<qt>O`xn‹¤O``óR –d%1ÿ %2 ÿ</qt>1Are you sure you wish to delete %1 "%2"? Q3FileDialogb@g e‡Nö (*) All Files (*) Q3FileDialogb@g e‡Nö (*.*)All Files (*.*) Q3FileDialog\^`' Attributes Q3FileDialogT�Back Q3FileDialogSÖmˆCancel Q3FileDialogY R6b€yûR¨NN*e‡NöCopy or Move a File Q3FileDialog R^úe°e‡NöY9Create New Folder Q3FileDialogeågDate Q3FileDialogR –d%1 Delete %1 Q3FileDialog‹æ~ƉÆVþ Detail View Q3FileDialogvî_UDir Q3FileDialogvî_U Directories Q3FileDialogvî_Uÿ Directory: Q3FileDialog•‹ïError Q3FileDialoge‡NöFile Q3FileDialoge‡NöT yð(&N)ÿ File &name: Q3FileDialoge‡Nö|{W‹(&T)ÿ File &type: Q3FileDialoggåb~vî_UFind Directory Q3FileDialog N Sï‹¿•îv„ Inaccessible Q3FileDialogRˆh‰ÆVþ List View Q3FileDialoggåb~ƒVô(&I)ÿ Look &in: Q3FileDialogT yðName Q3FileDialog e°^úe‡NöY9 New Folder Q3FileDialoge°^úe‡NöY9%1 New Folder %1 Q3FileDialog e°^úe‡NöY91 New Folder 1 Q3FileDialogTN N~§One directory up Q3FileDialogbS_Open Q3FileDialogbS_Open  Q3FileDialog ˜„‰Èe‡NöQ…[¹Preview File Contents Q3FileDialog ˜„‰Èe‡NöOá`oPreview File Info Q3FileDialog‘Íe°�}Qe(&E)R&eload Q3FileDialogSê‹û Read-only Q3FileDialog‹ûQ™ Read-write Q3FileDialog ‹ûSÖÿ%1Read: %1 Q3FileDialogSæ[XN:Save As Q3FileDialog � béNN*vî_USelect a Directory Q3FileDialogf>y:–�…Ïe‡Nö(&H)Show &hidden files Q3FileDialogY'\Size Q3FileDialogc’RSort Q3FileDialogc eågc’R(&D) Sort by &Date Q3FileDialogc T yðc’R(&N) Sort by &Name Q3FileDialogc Y'\c’R(&S) Sort by &Size Q3FileDialogrykŠSpecial Q3FileDialogvî_Uv„|û~ß”þc¥Symlink to Directory Q3FileDialoge‡Növ„|û~ß”þc¥Symlink to File Q3FileDialogrykŠv„|û~ß”þc¥Symlink to Special Q3FileDialog|{W‹Type Q3FileDialogSêQ™ Write-only Q3FileDialog Q™Qeÿ%1 Write: %1 Q3FileDialogvî_U the directory Q3FileDialoge‡Nöthe file Q3FileDialog|û~ß”þc¥ the symlink Q3FileDialogN €ýR^úvî_U %1Could not create directory %1 Q3LocalFsN €ýbS_ %1Could not open %1 Q3LocalFsN €ý‹ûSÖvî_U %1Could not read directory %1 Q3LocalFsN €ýyû–de‡Nöb€vî_U %1%Could not remove file or directory %1 Q3LocalFsN €ýbŠ %1 ‘ÍT}T N: %2Could not rename %1 to %2 Q3LocalFsN €ýQ™Qe %1Could not write %1 Q3LocalFs �ê[šNI... Customize... Q3MainWindowc’RLine up Q3MainWindowdÍO\ˆ«u(b7P\kbOperation stopped by the userQ3NetworkProtocolSÖmˆCancelQ3ProgressDialog^”u(Apply Q3TabDialogSÖmˆCancel Q3TabDialogžØ‹¤Defaults Q3TabDialog^.R©Help Q3TabDialogxn‹¤OK Q3TabDialog Y R6(&C)&Copy Q3TextEdit |˜�4(&P)&Paste Q3TextEdit `bY (&R)&Redo Q3TextEdit d¤mˆ(&U)&Undo Q3TextEditnzzClear Q3TextEdit RjR(&T)Cu&t Q3TextEdit� béQh�è Select All Q3TextEditQs•íClose Q3TitleBarQs•íz—SãCloses the window Q3TitleBarST+dÍO\z—Sãv„T}Nä0*Contains commands to manipulate the window Q3TitleBar f>y:z—SãT yð^vNST+~ôb¤[ƒv„c§NöFDisplays the name of the window and contains controls to manipulate it Q3TitleBar z—SãQh\OSMakes the window full screen Q3TitleBargY'SMaximize Q3TitleBarg\SMinimize Q3TitleBarbŠz—SãyûR0Y—bMoves the window out of the way Q3TitleBarbŠNN*gY'Sz—Sã`bY N:fn�r¶`&Puts a maximized window back to normal Q3TitleBarbŠNN*g\Sz—Sã`bY N:fn�r¶`Puts a minimized back to normal Q3TitleBarTN `bY  Restore down Q3TitleBarTN `bY  Restore up Q3TitleBar|û~ßSystem Q3TitleBar fôY...More... Q3ToolBar (g*wåv„) (unknown) Q3UrlOperator*SO‹® %1 N e/cY R6b€yûR¨e‡Nöb€vî_UIThe protocol `%1' does not support copying or moving files or directories Q3UrlOperatorSO‹® %1 N e/cR^úe°vî_U;The protocol `%1' does not support creating new directories Q3UrlOperatorSO‹® %1 N e/cƒ·SÖe‡Nö0The protocol `%1' does not support getting files Q3UrlOperatorSO‹® %1 N e/cRQúvî_U6The protocol `%1' does not support listing directories Q3UrlOperatorSO‹® %1 N e/cN O e‡Nö0The protocol `%1' does not support putting files Q3UrlOperator"SO‹® %1 N e/cyû–de‡Nöb€vî_U@The protocol `%1' does not support removing files or directories Q3UrlOperator$SO‹® %1 N e/c‘ÍT}T e‡Nöb€vî_U@The protocol `%1' does not support renaming files or directories Q3UrlOperatorSO‹® %1 N ˆ«e/c"The protocol `%1' is not supported Q3UrlOperator SÖmˆ(&C)&CancelQ3Wizard [Œb(&F)&FinishQ3Wizard ^.R©(&H)&HelpQ3WizardN Nke(&N) >&Next >Q3Wizard< N Nke(&B)< &BackQ3Wizard �Þc¥ˆ«bÒ~ÝConnection refusedQAbstractSocket�Þc¥�…eöConnection timed outQAbstractSocket N;g:g*b~R0Host not foundQAbstractSocket Q~ÜN €ý‹¿•îNetwork unreachableQAbstractSocketSocketdÍO\N ˆ«e/c$Operation on socket is not supportedQAbstractSocketYWc¥[Wl¡g ˆ«�Þc¥Socket is not connectedQAbstractSocketYWc¥[WdÍO\�…eöSocket operation timed outQAbstractSocket� béQh�è(&S) &Select AllQAbstractSpinBox XžR (&S)&Step upQAbstractSpinBox QÏ\(&D) Step &downQAbstractSpinBoxoÀm;Activate QApplicationoÀm;�ÙN*z ^�v„N;z—Sã#Activates the program's main window QApplication0bgˆL %1 —‰�Qt %2ÿ Sêb~R0N†Qt %30,Executable '%1' requires Qt %2, found Qt %3. QApplicationN Q|[¹v„Qt•‹ïIncompatible Qt Library Error QApplication SÖmˆ(&C)&Cancel QAxSelectCOM[ùŒa(&O)ÿ COM &Object: QAxSelectxn[šOK QAxSelect� béActiveXc§NöSelect ActiveX Control QAxSelect� N-Check QCheckBoxRcbToggle QCheckBoxSÖmˆ� N-Uncheck QCheckBoxmûR R0�ê[šNI˜œ‚r(&A)&Add to Custom Colors QColorDialogWúg,˜œ‚r(&B) &Basic colors QColorDialog�ê[šNI˜œ‚r(&C)&Custom colors QColorDialog~ÿ‚r(&G)ÿ&Green: QColorDialog~¢‚r(&R)ÿ&Red: QColorDialog™qTŒ^¦(&S)ÿ&Sat: QColorDialogN®^¦(&V)ÿ&Val: QColorDialogAlpha��S(&A)ÿA&lpha channel: QColorDialog„Ý‚r(&U)ÿBl&ue: QColorDialog‚rŒ(&E)ÿHu&e: QColorDialog� b阜‚r Select Color QColorDialogQs•íClose QComboBoxPGFalse QComboBoxbS_Open QComboBoxwTrue QComboBox%1ÿftok Y1�%%1: ftok failedQCoreApplication%1ÿ•.f/zzv„%1: key is emptyQCoreApplication%1ÿN €ýR6� •.%1: unable to make keyQCoreApplication N €ýcÐN¤N‹R¡Unable to commit transaction QDB2DriverN €ý�Þc¥Unable to connect QDB2Driver N €ýVÞnÚN‹R¡Unable to rollback transaction QDB2DriverN €ý‹¾n�êR¨cÐN¤Unable to set autocommit QDB2Driver N €ý^.[šSØ‘ÏUnable to bind variable QDB2Result N €ýbgˆL‹íSåUnable to execute statement QDB2ResultN €ýƒ·SÖ{,NN*Unable to fetch first QDB2ResultN €ýƒ·SÖN NN*Unable to fetch next QDB2ResultN €ýƒ·SÖ‹°_U%1Unable to fetch record %1 QDB2Result N €ýQÆY‹íSåUnable to prepare statement QDB2ResultAMAM QDateTimeEditPMPM QDateTimeEditamam QDateTimeEditpmpm QDateTimeEdit QDialQDialQDialSliderHandle SliderHandleQDialSpeedoMeter SpeedoMeterQDial[ŒbDoneQDialog �Ùf/NÀNHÿ What's This?QDialog eågˆ«Oîe9 Date Modified QDirModel|{W‹Kind QDirModelT yðName QDirModelY'\Size QDirModel|{W‹Type QDirModelQs•íClose QDockWidget•c¥Dock QDockWidgetmnR¨Float QDockWidgetfô\LessQDoubleSpinBoxfôYMoreQDoubleSpinBox xn[š(&O)&OK QErrorMessageQ�k!f>y:�ÙN*mˆ`o(&S)&Show this message again QErrorMessage Œ‹Õmˆ`oÿDebug Message: QErrorMessage �ôT}•‹ïÿ Fatal Error: QErrorMessage‹fTJÿWarning: QErrorMessageeàlÕR^ú %1 Cannot create %1 for outputQFileeàlÕ�“Qe %1 Cannot open %1 for inputQFileeàlÕ�“QúCannot open for outputQFilevîhe‡Nö]ò[XW(Destination file existsQFileQ™WWY1�%Failure to write blockQFile.vî_U%1 l¡g b~R00 ‹÷h8[ž]ò~Ù[škcxnvî_UT 0K%1 Directory not found. Please verify the correct directory name was given. QFileDialog.e‡Nö%1 l¡g b~R00 ‹÷h8[ž]ò~Ù[škcxne‡NöT 0A%1 File not found. Please verify the correct file name was given. QFileDialog %1]ò~Ï[XW(0 O``ó‰�fÿcb[ƒNHÿ-%1 already exists. Do you want to replace it? QFileDialog � bé(&C)&Choose QFileDialog R –d(&D)&Delete QFileDialoge°^úe‡NöY9(&N) &New Folder QFileDialog bS_(&O)&Open QFileDialog‘ÍT}T (&R)&Rename QFileDialog OÝ[X(&S)&Save QFileDialog( %1 f/Q™OÝb¤v„0 O`�Øf/`óR –d[ƒNHÿ9'%1' is write protected. Do you want to delete it anyway? QFileDialogb@g e‡Nö (*) All Files (*) QFileDialogb@g e‡Nö (*.*)All Files (*.*) QFileDialogO`xn‹¤O``óR –d %1 ÿ!Are sure you want to delete '%1'? QFileDialogT�Back QFileDialogN €ýR –dvî_U0Could not delete directory. QFileDialog R^úe°e‡NöY9Create New Folder QFileDialog‹æ~ƉÆVþ Detail View QFileDialogvî_U Directories QFileDialogvî_Uÿ Directory: QFileDialogšqR¨VhDrive QFileDialoge‡NöFile QFileDialoge‡NöT yð(&N)ÿ File &name: QFileDialog e‡Nö|{W‹ÿFiles of type: QFileDialoggåb~vî_UFind Directory QFileDialogRM�ÛForward QFileDialogRˆh‰ÆVþ List View QFileDialoggåw ÿLook in: QFileDialog bv„‹¡{—g: My Computer QFileDialog e°^úe‡NöY9 New Folder QFileDialogbS_Open QFileDialogr6vî_UParent Directory QFileDialog g�Ñv„W0e¹ Recent Places QFileDialogyû–dRemove QFileDialogSæ[XN:Save As QFileDialogf>y: Show  QFileDialogf>y:–�…Ïe‡Nö(&H)Show &hidden files QFileDialogg*wåv„Unknown QFileDialog %1 GB%1 GBQFileSystemModel %1SC[W‚‚%1 KBQFileSystemModel %1 MB%1 MBQFileSystemModel %1 TB%1 TBQFileSystemModel%1[W‚‚%1 bytesQFileSystemModel`<b>T yð %1 N €ýˆ«Ou(0</b><p>‹÷Ou(SæYNN*ST+fô\[W{&b€N T+g hp¹{&S÷v„T yð0oThe name "%1" can not be used.

      Try using another name, with fewer characters or no punctuations marks.QFileSystemModel‹¡{—g:ComputerQFileSystemModel eågˆ«Oîe9 Date ModifiedQFileSystemModel eàeHe‡NöT Invalid filenameQFileSystemModel|{W‹KindQFileSystemModel bv„‹¡{—g: My ComputerQFileSystemModelT yðNameQFileSystemModelY'\SizeQFileSystemModel|{W‹TypeQFileSystemModelNûaAny QFontDatabase–?bÉO/e‡Arabic QFontDatabase NšŽ\_N†Request abortedQHttpSSL cábKY1�%SSL handshake failedQHttpg R¡Vh_^8W0Qs•íN†�Þc¥%Server closed connection unexpectedlyQHttp g*wåv„•‹ï Unknown errorQHttpb@c[šv„SO‹®f/g*wåv„Unknown protocol specifiedQHttp•‹ïv„Q…[¹•^¦Wrong content lengthQHttp—‰�‹¤‹ÁAuthentication requiredQHttpSocketEngineg*e6R0Nãtv„HTTPTÍ^”(Did not receive HTTP response from proxyQHttpSocketEngineTŒHTTPNãt�‹¯eöSÑu•‹ï#Error communicating with HTTP proxyQHttpSocketEngine‰ãg�Nãtv„‹¤‹Á‹÷lBQú•/Error parsing authentication request from proxyQHttpSocketEngineNãt�Þc¥�ÇeéQs•í#Proxy connection closed prematurelyQHttpSocketEngineNãt�Þc¥ˆ«bÒ~ÝProxy connection refusedQHttpSocketEngine NãtbÒ~Ý�Þc¥Proxy denied connectionQHttpSocketEngineNãtg R¡Vh�Þc¥�…eö!Proxy server connection timed outQHttpSocketEngineg*b~R0Nãtg R¡VhProxy server not foundQHttpSocketEngine N €ý_YËN‹R¡Could not start transaction QIBaseDriverbS_epcn^“•‹ïError opening database QIBaseDriver N €ýcÐN¤N‹R¡Unable to commit transaction QIBaseDriver N €ýVÞnÚN‹R¡Unable to rollback transaction QIBaseDriver N €ýR‘M‹íSåCould not allocate statement QIBaseResultN €ýcÏ�ð�“Qe‹íSå"Could not describe input statement QIBaseResult N €ýcÏ�ð‹íSåCould not describe statement QIBaseResultN €ýƒ·SÖN N˜yCould not fetch next item QIBaseResult N €ýb~R0ep~ÄCould not find array QIBaseResultN €ý_—R0ep~ÄepcnCould not get array data QIBaseResultN €ý_—R0gå‹âOá`oCould not get query info QIBaseResultN €ý_—R0‹íSåOá`oCould not get statement info QIBaseResult N €ýQÆY‹íSåCould not prepare statement QIBaseResult N €ý_YËN‹R¡Could not start transaction QIBaseResult N €ýQs•í‹íSåUnable to close statement QIBaseResult N €ýcÐN¤N‹R¡Unable to commit transaction QIBaseResultN €ýR^úBLOBUnable to create BLOB QIBaseResult N €ýbgˆLgå‹âUnable to execute query QIBaseResultN €ýbS_BLOBUnable to open BLOB QIBaseResultN €ý‹ûSÖBLOBUnable to read BLOB QIBaseResultN €ýQ™QeBLOBUnable to write BLOB QIBaseResult‹¾YN l¡g zz•ôN†No space left on device QIODevicel¡g �ÙN*e‡Nöb€vî_UNo such file or directory QIODevice gC–Pˆ«bÒ~ÝPermission denied QIODeviceY*YbS_v„e‡NöToo many open files QIODevice g*wåv„•‹ï Unknown error QIODeviceMac OS X�“QelÕMac OS X input method QInputContextWindows�“QelÕWindows input method QInputContextXIMXIM QInputContext XIM�“QelÕXIM input method QInputContext �“QeNN*P<ÿEnter a value: QInputDialogeàlÕR �}^“%1ÿ%2Cannot load library %1: %2QLibrary"eàlÕ‰ãg�%2N-v„{&S÷ %1 ÿ%3$Cannot resolve symbol "%1" in %2: %3QLibraryeàlÕSx�}^“%1ÿ%2Cannot unload library %1: %2QLibraryN €ýf \ %1 ÿ%2Could not mmap '%1': %2QLibraryN €ýSÖmˆf \ %1 ÿ%2Could not unmap '%1': %2QLibrary %1 N-v„cÒNöšŒ‹ÁepcnN S9‘M)Plugin verification data mismatch in '%1'QLibrary e‡Nö %1 N f/g eHv„QtcÒNö0'The file '%1' is not a valid Qt plugin.QLibrary@cÒNö %1 Ou(N†N Q|[¹v„Qt^“0(%2.%3.%4) [%5]=The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]QLibraryJcÒNö %1 Ou(N†N Q|[¹v„Qt^“0(N €ým÷TOu(^“v„Œ‹ÕrHg,TŒSÑ^rHg,0)WThe plugin '%1' uses incompatible Qt library. (Cannot mix debug and release libraries.)QLibraryLcÒNö %1 Ou(N†N Q|[¹v„Qt^“0g_…v„g„^ú•.f/ %2 ÿ _—R0v„Stf/ %3 OThe plugin '%1' uses incompatible Qt library. Expected build key "%2", got "%3"QLibraryQqN«^“l¡g ˆ«b~R00!The shared library was not found.QLibrary g*wåv„•‹ï Unknown errorQLibrary Y R6(&C)&Copy QLineEdit |˜�4(&P)&Paste QLineEdit `bY (&R)&Redo QLineEdit d¤mˆ(&U)&Undo QLineEdit RjR(&T)Cu&t QLineEditR –dDelete QLineEdit� béQh�è Select All QLineEdit%1ÿW0W@kcW(ˆ«Ou(%1: Address in use QLocalServer%1: T yð•‹ï%1: Name error QLocalServer%1ÿgC–Pˆ«bÒ~Ý%1: Permission denied QLocalServer%1ÿg*wå•‹ï %2%1: Unknown error %2 QLocalServer%1ÿ�Þc¥•‹ï%1: Connection error QLocalSocket%1ÿ�Þc¥ˆ«bÒ~Ý%1: Connection refused QLocalSocket%1ÿepcnb¥Y*Y'%1: Datagram too large QLocalSocket%1ÿeàeHT yð%1: Invalid name QLocalSocket%1ÿ�Üz ]òQs•í%1: Remote closed QLocalSocket%1ÿYWc¥[W‹¿•î•‹ï%1: Socket access error QLocalSocket%1ÿYWc¥[WdÍO\�…eö%1: Socket operation timed out QLocalSocket%1ÿYWc¥[W�Dn�•‹ï%1: Socket resource error QLocalSocket%1ÿYWc¥[WdÍO\N ˆ«e/c)%1: The socket operation is not supported QLocalSocket%1ÿg*wå•‹ï%1: Unknown error QLocalSocket%1ÿg*wå•‹ï %2%1: Unknown error %2 QLocalSocket N €ý_YËN‹R¡Unable to begin transaction QMYSQLDriver N €ýcÐN¤N‹R¡Unable to commit transaction QMYSQLDriverN €ý�Þc¥Unable to connect QMYSQLDriverN €ýbS_epcn^“Unable to open database ' QMYSQLDriver N €ýVÞnÚN‹R¡Unable to rollback transaction QMYSQLDriver N €ý~Ñ[šYP<Unable to bind outvalues QMYSQLResult N €ý~Ñ[šP<Unable to bind value QMYSQLResultN €ýbgˆLN NN*gå‹âUnable to execute next query QMYSQLResult N €ýbgˆLgå‹âUnable to execute query QMYSQLResult N €ýbgˆL‹íSåUnable to execute statement QMYSQLResult N €ýƒ·SÖepcnUnable to fetch data QMYSQLResult N €ýQÆY‹íSåUnable to prepare statement QMYSQLResult N €ý‘Ín‹íSåUnable to reset statement QMYSQLResultN €ý[XP¨N NN*~ÓgœUnable to store next result QMYSQLResult N €ý[XP¨~ÓgœUnable to store result QMYSQLResultN €ý[XP¨‹íSå~Ógœ!Unable to store statement results QMYSQLResult (g*T}T v„) (Untitled)QMdiArea%1 - [%2] %1 - [%2] QMdiSubWindow Qs•í(&C)&Close QMdiSubWindow yûR¨(&M)&Move QMdiSubWindow `bY (&R)&Restore QMdiSubWindow Y'\(&S)&Size QMdiSubWindow - [%1]- [%1] QMdiSubWindowQs•íClose QMdiSubWindow^.R©Help QMdiSubWindowgY'S(&X) Ma&ximize QMdiSubWindowgY'SMaximize QMdiSubWindowƒÜSUMenu QMdiSubWindowg\S(&N) Mi&nimize QMdiSubWindowg\SMinimize QMdiSubWindow`bY Restore QMdiSubWindowTN `bY  Restore Down QMdiSubWindow�n…=Shade QMdiSubWindow`;W(gRM(&T) Stay on &Top QMdiSubWindowSÖmˆ�n…=Unshade QMdiSubWindowQs•íCloseQMenubgˆLExecuteQMenubS_OpenQMenuQsNŽQtAbout Qt QMessageBox^.R©Help QMessageBox –�…Ï~Æ‚‚ & &Hide Details... QMessageBoxxn[šOK QMessageBox f>y:~Æ‚‚ & &Show Details... QMessageBox � bé�“QelÕ Select IMQMultiInputContextY�“QelÕRcbVhMultiple input method switcherQMultiInputContextPlugin*Ou(e‡g,z—Sã�èNöN N e‡ƒÜSUv„Y�“QelÕRcbVhMMultiple input method switcher that uses the context menu of the text widgetsQMultiInputContextPlugin SæNN*YWc¥[W]ò~ÏkcW(vÑT,T NzïSã4Another socket is already listening on the same portQNativeSocketEngine2‹ÕVþW(N e/cIPv6e/cv„^sSðN Ou(IPv6YWc¥[W=Attempt to use IPv6 socket on a platform with no IPv6 supportQNativeSocketEngine �Þc¥ˆ«bÒ~ÝConnection refusedQNativeSocketEngine�Þc¥�…eöConnection timed outQNativeSocketEngineN €ýSÑ��ÇY'v„epcnb¥Datagram was too large to sendQNativeSocketEngine N;g:N €ý‹¿•îHost unreachableQNativeSocketEngineeàeHv„YWc¥[WcÏ�ð{&Invalid socket descriptorQNativeSocketEngineQ~Ü•‹ï Network errorQNativeSocketEngine Q~ÜdÍO\�…eöNetwork operation timed outQNativeSocketEngine Q~ÜN €ý‹¿•îNetwork unreachableQNativeSocketEngine[ù—^YWc¥[WdÍO\Operation on non-socketQNativeSocketEngine �Dn�€\=N†Out of resourcesQNativeSocketEngine gC–Pˆ«bÒ~ÝPermission deniedQNativeSocketEngineSO‹®|{W‹N ˆ«e/cProtocol type not supportedQNativeSocketEngine�ÙN*W0W@N Sïu(The address is not availableQNativeSocketEngine�ÙN*W0W@ˆ«OÝb¤N†The address is protectedQNativeSocketEngine‰�T/u(v„W0W@]ò~ψ«Ou(#The bound address is already in useQNativeSocketEngine[ùNŽ�ÙN*dÍO\Nãt|{W‹f/eàeHv„0,The proxy type is invalid for this operationQNativeSocketEngine�ÜzïN;g:Qs•íN†�ÙN*�Þc¥%The remote host closed the connectionQNativeSocketEngineN €ýRYËS^d­YWc¥[W%Unable to initialize broadcast socketQNativeSocketEngineN €ýRYËS—^–;X^YWc¥[W(Unable to initialize non-blocking socketQNativeSocketEngineN €ýc¥e6NN*mˆ`oUnable to receive a messageQNativeSocketEngineN €ýSÑ�NN*mˆ`oUnable to send a messageQNativeSocketEngineN €ýQ™QeUnable to writeQNativeSocketEngine g*wåv„•‹ï Unknown errorQNativeSocketEngineN ˆ«e/cv„YWc¥[WdÍO\Unsupported socket operationQNativeSocketEnginebS_%1SÑu•‹ïError opening %1QNetworkAccessCacheBackendeàlÕbS_ %1ÿ�ï_„f/NN*vî_U#Cannot open %1: Path is a directoryQNetworkAccessFileBackendbS_ %1 •‹ïÿ%2Error opening %1: %2QNetworkAccessFileBackend‹ûSÖ %1 •‹ïÿ%2Read error reading from %1: %2QNetworkAccessFileBackend kcW(bS_—^g,W0e‡Nö %1 v„‹÷lB%Request for opening non-local file %1QNetworkAccessFileBackendQ™Qe %1 •‹ïÿ%2Write error writing to %1: %2QNetworkAccessFileBackendeàlÕ‹ûSÖ %1ÿf/NN*vî_UCannot open %1: is a directoryQNetworkAccessFtpBackendN �} %1 eö•‹ïÿ%2Error while downloading %1: %2QNetworkAccessFtpBackendN �} %1 eö•‹ïÿ%2Error while uploading %1: %2QNetworkAccessFtpBackendv{Qe %1 Y1�%ÿ—‰�šŒ‹Á0Logging in to %1 failed: authentication requiredQNetworkAccessFtpBackendg*b~R0T�v„NãtNo suitable proxy foundQNetworkAccessFtpBackendg*b~R0T�v„NãtNo suitable proxy foundQNetworkAccessHttpBackend&N �} %1 •‹ï - g R¡VhVÞY ÿ%2)Error downloading %1 - server replied: %2 QNetworkReplySO‹® %1 f/g*wåv„Protocol "%1" is unknown QNetworkReply dÍO\ˆ«SÖmˆOperation canceledQNetworkReplyImpl N €ý_YËN‹R¡Unable to begin transaction QOCIDriver N €ýcÐN¤N‹R¡Unable to commit transaction QOCIDriver N €ýRYËSUnable to initialize QOCIDriverN €ýv{_UUnable to logon QOCIDriver N €ýVÞnÚN‹R¡Unable to rollback transaction QOCIDriver N €ýR‘M‹íSåUnable to alloc statement QOCIResultN €ý~Ñ[šbyYtbgˆLv„R'Unable to bind column for batch execute QOCIResult N €ý~Ñ[šP<Unable to bind value QOCIResultN €ýbgˆLbyYt‹íSå!Unable to execute batch statement QOCIResult N €ýbgˆL‹íSåUnable to execute statement QOCIResultN €ý�ÛQeN NN*Unable to goto next QOCIResult N €ýQÆY‹íSåUnable to prepare statement QOCIResult N €ýcÐN¤N‹R¡Unable to commit transaction QODBCDriverN €ý�Þc¥Unable to connect QODBCDriver N €ý�Þc¥ šqR¨z ^�N e/cb@g RŸ€ýCUnable to connect - Driver doesn't support all needed functionality QODBCDriverN €ýy�kb�êR¨cÐN¤Unable to disable autocommit QODBCDriverN €ýbS_�êR¨cÐN¤Unable to enable autocommit QODBCDriver N €ýVÞnÚN‹R¡Unable to rollback transaction QODBCDriver„QODBCResult::reset: N €ýbŠ SQL_CURSOR_STATIC ‹¾nN:‹íSå\^`'0‹÷hÀgåO`v„ODBCšqR¨z ^�‹¾n0yQODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration QODBCResult N €ý^.[šSØ‘ÏUnable to bind variable QODBCResult N €ýbgˆL‹íSåUnable to execute statement QODBCResultN €ýƒ·SÖUnable to fetch QODBCResultN €ýƒ·SÖ{,NN*Unable to fetch first QODBCResultN €ýƒ·SÖgTNN*Unable to fetch last QODBCResultN €ýƒ·SÖN NN*Unable to fetch next QODBCResultN €ýƒ·SÖN NN*Unable to fetch previous QODBCResult N €ýQÆY‹íSåUnable to prepare statement QODBCResult[¶HomeQObjecteàeHv„ URIÿ%1Invalid URI: %1QObject g*c[šN;g:T No host name givenQObjectW( %1 N N ˆ«e/cv„dÍO\Operation not supported on %1QObject SO‹®•‹ïÿe6R0N†Y'\N: 0 v„S)Protocol error: packet of size 0 receivedQObject‹ûSÖ %1 •‹ïÿ%2Read error reading from %1: %2QObject*�Üz N;g:�ÇeéW0Qs•íN†W( %1 N v„�ÙN*�Þc¥3Remote host closed the connection prematurely on %1QObject%1 N v„YWc¥[W•‹ïÿ%2Socket error on %1: %2QObjectQ™Qe %1 •‹ïÿ%2Write error writing to %1: %2QObjectT yðNameQPPDOptionsModelP<ValueQPPDOptionsModel N €ý_YËN‹R¡Could not begin transaction QPSQLDriver N €ýcÐN¤N‹R¡Could not commit transaction QPSQLDriver N €ýVÞnÚN‹R¡Could not rollback transaction QPSQLDriverN €ý�Þc¥Unable to connect QPSQLDriverN €ý‹¢–Unable to subscribe QPSQLDriver N €ýSÖmˆ‹¢–Unable to unsubscribe QPSQLDriver N €ýR^úgå‹âUnable to create query QPSQLResult N €ýQÆY‹íSåUnable to prepare statement QPSQLResultS˜|s (cm)Centimeters (cm)QPageSetupWidgetz—OSFormQPageSetupWidgetšØ^¦ÿHeight:QPageSetupWidget‚ñ[ø (in) Inches (in)QPageSetupWidgetj*T LandscapeQPageSetupWidget�¹�ÝMarginsQPageSetupWidgetkë|s (mm)Millimeters (mm)QPageSetupWidgete¹T OrientationQPageSetupWidget ~¸_ Y'\ÿ Page size:QPageSetupWidget~¸_ PaperQPageSetupWidget~¸_ n�ÿ Paper source:QPageSetupWidget p¹ (pt) Points (pt)QPageSetupWidget~µTPortraitQPageSetupWidgetSÍTj*TReverse landscapeQPageSetupWidgetSÍT~µTReverse portraitQPageSetupWidget[½^¦ÿWidth:QPageSetupWidgetN �¹�Ý bottom marginQPageSetupWidget]æ�¹�Ý left marginQPageSetupWidgetSó�¹�Ý right marginQPageSetupWidgetN �¹�Ý top marginQPageSetupWidget SÖmˆ(&C)&CancelQPlatformTheme Qs•í(&C)&CloseQPlatformTheme T&(&N)&NoQPlatformTheme xn[š(&O)&OKQPlatformTheme OÝ[X(&S)&SaveQPlatformTheme f/(&Y)&YesQPlatformThemee>_AbortQPlatformTheme^”u(ApplyQPlatformThemeSÖmˆCancelQPlatformThemeQs•íCloseQPlatformTheme N OÝ[XQs•íClose without SavingQPlatformThemeb›_DiscardQPlatformThemeN OÝ[X Don't SaveQPlatformTheme^.R©HelpQPlatformTheme_ýueIgnoreQPlatformThemeQh�èT&(&O) N&o to AllQPlatformThemexn[šOKQPlatformThemebS_OpenQPlatformTheme‘ÍnResetQPlatformTheme`bY žØ‹¤Restore DefaultsQPlatformTheme‘Í‹ÕRetryQPlatformThemeOÝ[XSaveQPlatformThemeOÝ[XQh�èSave AllQPlatformThemeQh�èf/(&A) Yes to &AllQPlatformThemecÒNöl¡g ˆ«�}Qe0The plugin was not loaded. QPluginLoader g*wåv„•‹ï Unknown error QPluginLoader%1]ò~Ï[XW(0 O``ó‰†vÖ[ƒNHÿ/%1 already exists. Do you want to overwrite it? QPrintDialog&%1f/vî_U0 ‹÷� béNN*N T v„e‡NöT 07%1 is a directory. Please choose a different file name. QPrintDialog� ˜y(&O) << &Options << QPrintDialog� ˜y(&O) >> &Options >> QPrintDialog bSSp(&P)&Print QPrintDialog <qt>O``ó‰†vÖ[ƒNHÿ</qt>%Do you want to overwrite it? QPrintDialogA0A0 QPrintDialog$A0 (841 x 1189 kë|s)A0 (841 x 1189 mm) QPrintDialogA1A1 QPrintDialog"A1 (594 x 841 kë|s)A1 (594 x 841 mm) QPrintDialogA2A2 QPrintDialog"A2 (420 x 594 kë|s)A2 (420 x 594 mm) QPrintDialogA3A3 QPrintDialog"A3 (297 x 420 kë|s)A3 (297 x 420 mm) QPrintDialogA4A4 QPrintDialog@A4 (210 x 297 kë|sÿ 8.26 x 11.7 ‚ñ[ø)%A4 (210 x 297 mm, 8.26 x 11.7 inches) QPrintDialogA5A5 QPrintDialog"A5 (148 x 210 kë|s)A5 (148 x 210 mm) QPrintDialogA6A6 QPrintDialog"A6 (105 x 148 kë|s)A6 (105 x 148 mm) QPrintDialogA7A7 QPrintDialog A7 (74 x 105 kë|s)A7 (74 x 105 mm) QPrintDialogA8A8 QPrintDialogA8 (52 x 74 kë|s)A8 (52 x 74 mm) QPrintDialogA9A9 QPrintDialogA9 (37 x 52 kë|s)A9 (37 x 52 mm) QPrintDialog R+T ÿ%1 Aliases: %1 QPrintDialogB0B0 QPrintDialog&B0 (1000 x 1414 kë|s)B0 (1000 x 1414 mm) QPrintDialogB1B1 QPrintDialog$B1 (707 x 1000 kë|s)B1 (707 x 1000 mm) QPrintDialogB10B10 QPrintDialog B10 (31 x 44 kë|s)B10 (31 x 44 mm) QPrintDialogB2B2 QPrintDialog"B2 (500 x 707 kë|s)B2 (500 x 707 mm) QPrintDialogB3B3 QPrintDialog"B3 (353 x 500 kë|s)B3 (353 x 500 mm) QPrintDialogB4B4 QPrintDialog"B4 (250 x 353 kë|s)B4 (250 x 353 mm) QPrintDialogB5B5 QPrintDialog@B5 (176 x 250 kë|sÿ 6.93 x 9.84 ‚ñ[ø)%B5 (176 x 250 mm, 6.93 x 9.84 inches) QPrintDialogB6B6 QPrintDialog"B6 (125 x 176 kë|s)B6 (125 x 176 mm) QPrintDialogB7B7 QPrintDialog B7 (88 x 125 kë|s)B7 (88 x 125 mm) QPrintDialogB8B8 QPrintDialogB8 (62 x 88 kë|s)B8 (62 x 88 mm) QPrintDialogB9B9 QPrintDialogB9 (44 x 62 kë|s)B9 (44 x 62 mm) QPrintDialogC5EC5E QPrintDialog$C5E (163 x 229 kë|s)C5E (163 x 229 mm) QPrintDialog�ê[šNICustom QPrintDialogDLEDLE QPrintDialog$DLE (110 x 220 kë|s)DLE (110 x 220 mm) QPrintDialogQ³{Ve‡Nf Executive QPrintDialogHExecutive (7.5 x 10 ‚ñ[øÿ 191 x 254 kë|s))Executive (7.5 x 10 inches, 191 x 254 mm) QPrintDialog*e‡Nö%1N SïQ™0 ‹÷� béNN*N T v„e‡NöT 0=File %1 is not writable. Please choose a different file name. QPrintDialoge‡Nö[XW( File exists QPrintDialog[ù_~¸Folio QPrintDialog(Folio (210 x 330 kë|s)Folio (210 x 330 mm) QPrintDialog^˜uLedger QPrintDialog*Ledger (432 x 279 kë|s)Ledger (432 x 279 mm) QPrintDialoglÕ_‹e‡NfLegal QPrintDialog@Legal (8.5 x 14 ‚ñ[øÿ 216 x 356 kë|s)%Legal (8.5 x 14 inches, 216 x 356 mm) QPrintDialogOá~¸Letter QPrintDialogBLetter (8.5 x 11 ‚ñ[øÿ 216 x 279 kë|s)&Letter (8.5 x 11 inches, 216 x 279 mm) QPrintDialogg,W0e‡Nö Local file QPrintDialogxn[šOK QPrintDialogbSSpPrint QPrintDialogbSSpR0e‡Nö & &Print To File ... QPrintDialogbSSpQh�è Print all QPrintDialogbSSpƒVô Print range QPrintDialogbSSp� béPrint selection QPrintDialogbSSpR0e‡Nö(PDF)Print to File (PDF) QPrintDialog"bSSpR0e‡Nö(Postscript)Print to File (Postscript) QPrintDialog\W‹b¥~¸Tabloid QPrintDialog,Tabloid (279 x 432 kë|s)Tabloid (279 x 432 mm) QPrintDialog" NÎ v„epPy:_SRM˜uShow facing pagesQPrintPreviewDialogf>y:b@g ˜uv„i‚‰ÈShow overview of all pagesQPrintPreviewDialogf>y:SU˜uShow single pageQPrintPreviewDialoge>Y'Zoom inQPrintPreviewDialog)\Zoom outQPrintPreviewDialogšØ~§AdvancedQPrintPropertiesWidgetz—OSFormQPrintPropertiesWidget˜uPageQPrintPropertiesWidgeth![ùCollateQPrintSettingsOutput_i‚rColorQPrintSettingsOutput_i‚rj!_ Color ModeQPrintSettingsOutputb÷�CopiesQPrintSettingsOutputYNýÿCopies:QPrintSettingsOutput N$�èRbSSpDuplex PrintingQPrintSettingsOutputz—OSFormQPrintSettingsOutputpp^¦ GrayscaleQPrintSettingsOutput•O§ Long sideQPrintSettingsOutputeàNoneQPrintSettingsOutput� ˜yOptionsQPrintSettingsOutput�“Qú‹¾nOutput SettingsQPrintSettingsOutput˜uepNÎ Pages fromQPrintSettingsOutputbSSpQh�è Print allQPrintSettingsOutputbSSpƒVô Print rangeQPrintSettingsOutputSÍTReverseQPrintSettingsOutput� bé SelectionQPrintSettingsOutputwíO§ Short sideQPrintSettingsOutputR0toQPrintSettingsOutputT yð(&N)ÿ&Name: QPrintWidget...... QPrintWidgetz—OSForm QPrintWidgetOMnÿ Location: QPrintWidget�“Qúe‡Nö(&F)ÿ Output &file: QPrintWidget \^`'(&R) P&roperties QPrintWidget˜„‰ÈPreview QPrintWidgetbSSpg:Printer QPrintWidget|{W‹ÿType: QPrintWidgeteàlÕbS_u(NŽ‹ûSÖv„�“Qe‘Í[šT,Could not open input redirection for readingQProcesseàlÕbS_u(NŽQ™Qev„�“Qú‘Í[šT-Could not open output redirection for writingQProcessNÎ�Ûz N-‹ûSÖeöSÑu•‹ïError reading from processQProcessT�Ûz Q™QeeöSÑu•‹ïError writing to processQProcess �Ûz ]ò])nƒProcess crashedQProcess T/R¨�Ûz Y1�%Process failed to startQProcess �Ûz Yt�…eöProcess operation timed outQProcess�Dn�•‹ï(forkY1�%)ÿ%1!Resource error (fork failure): %1QProcessd¤mˆCancelQProgressDialogbS_Open QPushButton� N-Check QRadioButton•‹ïv„[W{&|{‹ílÕbad char class syntaxQRegExp•‹ïv„˜„mK‹ílÕbad lookahead syntaxQRegExp•‹ïv„‘ÍY ‹ílÕbad repetition syntaxQRegExpOu(N†Y1eHv„ryeHdisabled feature usedQRegExpeàeHv„Qk�ÛR6epP<invalid octal valueQRegExp �GR0Q…�è–PR6met internal limitQRegExpb~N R0]æR–”{&missing left delimQRegExp l¡g •‹ïSÑuno error occurredQRegExp aYv„~Èkbunexpected endQRegExpbS_epcn^“•‹ïError to open databaseQSQLite2Driver N €ý_YËN‹R¡Unable to begin transactionQSQLite2Driver N €ýcÐN¤N‹R¡Unable to commit transactionQSQLite2Driver N €ýVÞnÚN‹R¡Unable to rollback TransactionQSQLite2Driver N €ýbgˆL‹íSåUnable to execute statementQSQLite2Result N €ýƒ·SÖ~ÓgœUnable to fetch resultsQSQLite2ResultQs•íepcn^“•‹ïError closing database QSQLiteDriverbS_epcn^“•‹ïError opening database QSQLiteDriver N €ý_YËN‹R¡Unable to begin transaction QSQLiteDriver N €ýcÐN¤N‹R¡Unable to commit transaction QSQLiteDriver N €ýVÞnÚN‹R¡Unable to rollback transaction QSQLiteDriverl¡g gå‹âNo query QSQLiteResultSÂepep‘ÏN S9‘MParameter count mismatch QSQLiteResult N €ý~Ñ[šSÂepUnable to bind parameters QSQLiteResult N €ýbgˆL‹íSåUnable to execute statement QSQLiteResult N €ýƒ·SÖˆLUnable to fetch row QSQLiteResult N €ý‘Ín‹íSåUnable to reset statement QSQLiteResult^•�èBottom QScrollBar]æ�¹ Left edge QScrollBarTN c’R Line down QScrollBarTN c’RLine up QScrollBarN N˜u Page down QScrollBar]æN˜u Page left QScrollBarSóN˜u Page right QScrollBarN N˜uPage up QScrollBarOMnPosition QScrollBarSó�¹ Right edge QScrollBarTN nÚR¨ Scroll down QScrollBar nÚR¨R0�Ù‘Ì Scroll here QScrollBarT]ænÚR¨ Scroll left QScrollBarTSónÚR¨ Scroll right QScrollBarTN nÚR¨ Scroll up QScrollBar˜v�èTop QScrollBar%1ÿ]ò~Ï[XW(%1: already exists QSharedMemory%1ÿR^úv„Y'\\NŽ 0%1: create size is less then 0 QSharedMemory %1ÿN [XW(%1: doesn't exists QSharedMemory%1ÿftok Y1�%%1: ftok failed QSharedMemory%1ÿeàeHY'\%1: invalid size QSharedMemory%1: •.•‹ï %1: key error QSharedMemory%1ÿ•.f/zzv„%1: key is empty QSharedMemory%1ÿl¡g –DR %1: not attached QSharedMemory%1ÿ�Dn�€\=N†%1: out of resources QSharedMemory%1ÿgC–Pˆ«bÒ~Ý%1: permission denied QSharedMemory%1ÿY'\gå‹âY1�%%1: size query failed QSharedMemory%1ÿ|û~ߘ„‹¾Y'\–PR6$%1: system-imposed size restrictions QSharedMemory%1ÿeàlÕ•[š%1: unable to lock QSharedMemory%1ÿN €ýR6� •.%1: unable to make key QSharedMemory%1ÿeàlÕ‹¾n•[šv„•.%1: unable to set key on lock QSharedMemory%1ÿeàlÕSÖmˆ•[š%1: unable to unlock QSharedMemory%1ÿUnix •.e‡NöN [XW( %1: unix key file doesn't exists QSharedMemory%1ÿg*wå•‹ï %2%1: unknown error %2 QSharedMemory++ QShortcutAltAlt QShortcutT�Back QShortcutBackspace Backspace QShortcutBacktabBacktab QShortcutON—óXž_: Bass Boost QShortcutŒ\ON—ó Bass Down QShortcutŒY'ON—óBass Up QShortcutT|SëCall QShortcutCaps Lock Caps Lock QShortcutCapsLockCapsLock QShortcutN N e‡1Context1 QShortcutN N e‡2Context2 QShortcutN N e‡3Context3 QShortcutN N e‡4Context4 QShortcutCtrlCtrl QShortcutDelDel QShortcut DeleteDelete QShortcutDownDown QShortcutEndEnd QShortcut EnterEnter QShortcutEscEsc QShortcut EscapeEscape QShortcutF%1F%1 QShortcutgUœr1v„ Favorites QShortcutû�lFlip QShortcutRM�ÛForward QShortcutc�wHangup QShortcutHelpHelp QShortcutHomeHome QShortcutN;˜u Home Page QShortcutInsIns QShortcut InsertInsert QShortcut T/R¨ (0) Launch (0) QShortcut T/R¨ (1) Launch (1) QShortcut T/R¨ (2) Launch (2) QShortcut T/R¨ (3) Launch (3) QShortcut T/R¨ (4) Launch (4) QShortcut T/R¨ (5) Launch (5) QShortcut T/R¨ (6) Launch (6) QShortcut T/R¨ (7) Launch (7) QShortcut T/R¨ (8) Launch (8) QShortcut T/R¨ (9) Launch (9) QShortcut T/R¨ (A) Launch (A) QShortcut T/R¨ (B) Launch (B) QShortcut T/R¨ (C) Launch (C) QShortcut T/R¨ (D) Launch (D) QShortcut T/R¨ (E) Launch (E) QShortcut T/R¨ (F) Launch (F) QShortcutT/R¨�®Nö Launch Mail QShortcut T/R¨YZ’OS Launch Media QShortcutLeftLeft QShortcut N NN*YZ’OS Media Next QShortcut YZ’OSd­e> Media Play QShortcut N NN*YZ’OSMedia Previous QShortcut YZ’OS‹°_U Media Record QShortcut YZ’OSP\kb Media Stop QShortcutMenuMenu QShortcutMetaMeta QShortcutT&No QShortcutNum LockNum Lock QShortcutNumLockNumLock QShortcutNumber Lock Number Lock QShortcut bS_URLOpen URL QShortcutPage Down Page Down QShortcutPage UpPage Up QShortcut PausePause QShortcut PgDownPgDown QShortcutPgUpPgUp QShortcut PrintPrint QShortcutPrint Screen Print Screen QShortcutR7e°Refresh QShortcut ReturnReturn QShortcut RightRight QShortcutScroll Lock Scroll Lock QShortcutScrollLock ScrollLock QShortcutd}"Search QShortcut� béSelect QShortcut ShiftShift QShortcutzzh<Space QShortcut{I_…Standby QShortcutP\kbStop QShortcut SysReqSysReq QShortcutSystem RequestSystem Request QShortcutTabTab QShortcutŒ\šØ—ó Treble Down QShortcutŒY'šØ—ó Treble Up QShortcutUpUp QShortcutŒ\—ó‘Ï Volume Down QShortcut—Y—ó Volume Mute QShortcutŒY'—ó‘Ï Volume Up QShortcutf/Yes QShortcutN N˜u Page downQSlider]æN˜u Page leftQSliderSóN˜u Page rightQSliderN N˜uPage upQSliderOMnPositionQSliderN e/cv„W0W@|{W‹Address type not supportedQSocks5SocketEngine �Þc¥N ˆ«SOCKSv5g R¡VhQA‹¸(Connection not allowed by SOCKSv5 serverQSocks5SocketEngineNãt�Þc¥�ÇeéQs•í&Connection to proxy closed prematurelyQSocks5SocketEngine NãtbÒ~Ý�Þc¥Connection to proxy refusedQSocks5SocketEngine Nãt�Þc¥�…eöConnection to proxy timed outQSocks5SocketEngine^8‰Äg R¡VhY1�%General SOCKSv5 server failureQSocks5SocketEngine Q~ÜdÍO\�…eöNetwork operation timed outQSocks5SocketEngine Nãt‹¤‹ÁY1�%Proxy authentication failedQSocks5SocketEngineNãt‹¤‹ÁY1�%: %1Proxy authentication failed: %1QSocks5SocketEngineNãtN;g:g*b~R0Proxy host not foundQSocks5SocketEngineSOCKSrHg,5SO‹®•‹ïSOCKS version 5 protocol errorQSocks5SocketEngineN e/cv„SOCKSv5T}NäSOCKSv5 command not supportedQSocks5SocketEngine TTL]ò�Çg TTL expiredQSocks5SocketEngine*g*wåSOCKSv5Nãtÿ •‹ïNãx 0x%1%Unknown SOCKSv5 proxy error code 0x%1QSocks5SocketEnginefô\LessQSpinBoxfôYMoreQSpinBoxSÖmˆCancelQSqlSÖmˆ`¨v„�‘ÿCancel your edits?QSqlxn‹¤ConfirmQSqlR –dDeleteQSqlR –d�Ùga‹°_UÿDelete this record?QSqlcÒQeInsertQSqlT&NoQSql OÝ[X�‘ÿ Save edits?QSqlfôe°UpdateQSqlf/YesQSqlN €ýcÐO›l¡g •.v„‹ÁNfÿ %1,Cannot provide a certificate with no key, %1 QSslSocketR^úSSLN N e‡•‹ïÿ%1ÿ Error creating SSL context (%1) QSslSocketR^úSSLO‹Ý•‹ïÿ %1Error creating SSL session, %1 QSslSocketR^úSSLO‹Ý•‹ïÿ%1Error creating SSL session: %1 QSslSocketSSLcábK•‹ïÿ%1Error during SSL handshake: %1 QSslSocketN €ý�}Qeg,W0‹ÁNfÿ %1#Error loading local certificate, %1 QSslSocketN €ý�}QeyÁg •.ÿ %1Error loading private key, %1 QSslSocket‹ûSÖeö•‹ïÿ%1Error while reading: %1 QSslSocketeàeHb€zzv}v„[ÆxRˆhÿ%1ÿ !Invalid or empty cipher list (%1) QSslSocketyÁg •.N €ýšŒ‹ÁQlg •.ÿ %1/Private key does not certificate public key, %1 QSslSocketN €ýQ™Qeepcnÿ%1Unable to write data: %1 QSslSocket%1ÿ]ò~Ï[XW(%1: already existsQSystemSemaphore %1ÿN [XW(%1: does not existQSystemSemaphore%1ÿ�Dn�€\=N†%1: out of resourcesQSystemSemaphore%1ÿgC–Pˆ«bÒ~Ý%1: permission deniedQSystemSemaphore%1ÿg*wå•‹ï %2%1: unknown error %2QSystemSemaphore N €ýbS_�Þc¥Unable to open connection QTDSDriverN €ýOu(epcn^“Unable to use database QTDSDriverT]ænÚR¨ Scroll LeftQTabBarTSónÚR¨ Scroll RightQTabBarsocketdÍO\N ˆ«e/c$Operation on socket is not supported QTcpServer Y R6(&C)&Copy QTextControl |˜�4(&P)&Paste QTextControl `bY (&R)&Redo QTextControl d¤mˆ(&U)&Undo QTextControlY R6”þc¥OMn(&L)Copy &Link Location QTextControl RjR(&T)Cu&t QTextControlR –dDelete QTextControl� béQh�è Select All QTextControlbS_Open QToolButtonc N Press QToolButton�ÙN*^sSðN e/cIPv6#This platform does not support IPv6 QUdpSocket`bY Redo QUndoGroupd¤•Undo QUndoGroup QUndoModel`bY Redo QUndoStackd¤•Undo QUndoStackcÒQeUnicodec§R6[W{& Insert Unicode control characterQUnicodeControlCharacterMenuLRE _YËNÎ]æR0Só]LQe$LRE Start of left-to-right embeddingQUnicodeControlCharacterMenuLRM NÎ]æR0Sóh‹°LRM Left-to-right markQUnicodeControlCharacterMenuLRO _YËNÎ]æTSó‰†vÖ#LRO Start of left-to-right overrideQUnicodeControlCharacterMenuPDF _9Qúe¹Th<_PDF Pop directional formattingQUnicodeControlCharacterMenuRLE _YËNÎSóT]æ]LQe$RLE Start of right-to-left embeddingQUnicodeControlCharacterMenuRLM NÎSóT]æh‹°RLM Right-to-left markQUnicodeControlCharacterMenuRLO _YËNÎSóT]扆vÖ#RLO Start of right-to-left overrideQUnicodeControlCharacterMenuZWJ –ö[½^¦�Þc¥VhZWJ Zero width joinerQUnicodeControlCharacterMenuZWNJ –ö[½^¦—^�Þc¥VhZWNJ Zero width non-joinerQUnicodeControlCharacterMenuZWSP –ö[½^¦zzh<ZWSP Zero width spaceQUnicodeControlCharacterMenueàlÕf>y: URLCannot show URL QWebFrameeàlÕf>y: MIMETYPECannot show mimetype QWebFrame e‡NöN [XW(File does not exist QWebFrameVàN:{VueŒetbSe­N†hbv„R �}&Frame load interruped by policy change QWebFrame ‹÷lBˆ«–;X^N†Request blocked QWebFrame ‹÷lBˆ«SÖmˆN†Request cancelled QWebFrame%1 ÿ%2x%3 PÏ} ÿ %1 (%2x%3 pixels)QWebPage %n N*e‡Nö %n file(s)QWebPage mûR R0[WQxAdd To DictionaryQWebPage•‹ïv„ HTTP ‹÷lBBad HTTP requestQWebPage|—OSBoldQWebPage^•�èBottomQWebPagehÀgå‹ílÕTŒbüQ™Check Grammar With SpellingQWebPagehÀgåbüQ™Check SpellingQWebPageW(�“QeeöhÀgåbüQ™Check Spelling While TypingQWebPage� bée‡Nö Choose FileQWebPagen–dg�Ñv„d}"Clear recent searchesQWebPageY R6CopyQWebPageY R6VþrG Copy ImageQWebPageY R6”þc¥ Copy LinkQWebPageRjRCutQWebPagežØ‹¤DefaultQWebPage R –dR0SU‹Í\>Delete to the end of the wordQWebPage R –dR0SU‹Í™–Delete to the start of the wordQWebPagee¹T DirectionQWebPage[WOSFontsQWebPageT�Go BackQWebPageRM�Û Go ForwardQWebPage–�…ÏbüQ™TŒ‹ílÕHide Spelling and GrammarQWebPage_ýueIgnoreQWebPage_ýue Ignore Grammar context menu itemIgnoreQWebPagehÀgåInspectQWebPageaY'R)OSItalicQWebPage"JavaScript‹fTJ - %1JavaScript Alert - %1QWebPage"JavaScriptxn‹¤ - %1JavaScript Confirm - %1QWebPage"JavaScriptcÐy: - %1JavaScript Prompt - %1QWebPageLTRLTRQWebPage]æ�¹ Left edgeQWebPage W([WQxN-gåb~Look Up In DictionaryQWebPageyûR¨QIhR0WW\>'Move the cursor to the end of the blockQWebPageyûR¨QIhR0e‡Nög+\>*Move the cursor to the end of the documentQWebPageyûR¨QIhR0ˆL\>&Move the cursor to the end of the lineQWebPageyûR¨QIhR0N NN*[W{&%Move the cursor to the next characterQWebPageyûR¨QIhR0N NˆL Move the cursor to the next lineQWebPageyûR¨QIhR0N NN*SU‹Í Move the cursor to the next wordQWebPageyûR¨QIhR0N NN*[W{&)Move the cursor to the previous characterQWebPageyûR¨QIhR0N NˆL$Move the cursor to the previous lineQWebPageyûR¨QIhR0N NN*SU‹Í$Move the cursor to the previous wordQWebPageyûR¨QIhR0WW™–)Move the cursor to the start of the blockQWebPageyûR¨QIhR0e‡Nö_Y4,Move the cursor to the start of the documentQWebPageyûR¨QIhR0ˆL™–(Move the cursor to the start of the lineQWebPage l¡g b~R0smKNo Guesses FoundQWebPagel¡g e‡Nöˆ«� béNo file selectedQWebPagel¡g g�Ñv„d}"No recent searchesQWebPagebS_hFg¶ Open FrameQWebPagebS_VþrG Open ImageQWebPagebS_”þc¥ Open LinkQWebPageW(e°z—SãN-bS_Open in New WindowQWebPage�n^ÓOutlineQWebPageN N˜u Page downQWebPage]æN˜u Page leftQWebPageSóN˜u Page rightQWebPageN N˜uPage upQWebPage|˜�4PasteQWebPageRTLRTLQWebPage g�Ñv„d}"Recent searchesQWebPage‘Íe°�}QeReloadQWebPage‘ÍnResetQWebPageSó�¹ Right edgeQWebPageOÝ[XVþrG Save ImageQWebPageOÝ[X”þc¥... Save Link...QWebPageTN nÚR¨ Scroll downQWebPage nÚR¨R0�Ù‘Ì Scroll hereQWebPageT]ænÚR¨ Scroll leftQWebPageTSónÚR¨ Scroll rightQWebPageTN nÚR¨ Scroll upQWebPaged}"Q˜uSearch The WebQWebPage � N-R0WW\>Select to the end of the blockQWebPage � N-R0e‡Nö\>!Select to the end of the documentQWebPage � N-R0ˆL\>Select to the end of the lineQWebPage� N-R0N NN*[W{&Select to the next characterQWebPage � N-R0N NˆLSelect to the next lineQWebPage� N-R0N NN*SU‹ÍSelect to the next wordQWebPage� N-R0N NN*[W{& Select to the previous characterQWebPage � N-R0N NˆLSelect to the previous lineQWebPage� N-R0N NN*SU‹ÍSelect to the previous wordQWebPage � N-R0WW™– Select to the start of the blockQWebPage � N-R0e‡Nö™–#Select to the start of the documentQWebPage � N-R0ˆL™–Select to the start of the lineQWebPagef>y:büQ™TŒ‹ílÕShow Spelling and GrammarQWebPagebüQ™SpellingQWebPageP\kbStopQWebPagecÐN¤SubmitQWebPagecÐN¤QSubmit (input element) alt text for elements with no alt, title, or valueSubmitQWebPagee‡g,e¹TText DirectionQWebPage.�Ùf/NN*SïNåd}"v„}"_0‹÷�“Qe‰�d}"v„Qs•.[Wÿ3This is a searchable index. Enter search keywords: QWebPage˜v�èTopQWebPageN R~¿ UnderlineQWebPageg*wåv„UnknownQWebPageQ˜uhÀgåTX - %2Web Inspector - %2QWebPage �Ùf/NÀNHÿ What's This?QWhatsThisAction**QWidget [Œb(&F)&FinishQWizard ^.R©(&H)&HelpQWizardN Nke(&N)&NextQWizardN Nke(&N) >&Next >QWizard< N Nke(&B)< &BackQWizardSÖmˆCancelQWizardcÐN¤CommitQWizard~ç~íContinueQWizard[ŒbDoneQWizard�ÔVÞGo BackQWizard^.R©HelpQWizard%1 - [%2] %1 - [%2] QWorkspace Qs•í(&C)&Close QWorkspace yûR¨(&M)&Move QWorkspace `bY (&R)&Restore QWorkspace Y'\(&S)&Size QWorkspace \U_(&U)&Unshade QWorkspaceQs•íClose QWorkspacegY'S(&X) Ma&ximize QWorkspaceg\S(&N) Mi&nimize QWorkspaceg\SMinimize QWorkspace`bY  Restore Down QWorkspace Sw�w(&A)Sh&ade QWorkspace`;W(gRM(&T) Stay on &Top QWorkspace2W(‹ûSÖXMLXðfv„eöPÿ xXðfb€rìzËXðfˆ«g_…Yencoding declaration or standalone declaration expected while reading the XML declarationQXml W(NN*Y�è[žOSv„e‡g,Xðf‘Ìg •‹ï3error in the text declaration of an external entityQXmlW(‰ãg�lè‘Êv„eöPSÑu•‹ï$error occurred while parsing commentQXmlW(‰ãg�Q…[¹v„eöPSÑu•‹ï$error occurred while parsing contentQXml W(‰ãg�e‡hc|{W‹[šNIv„eöPSÑu•‹ï5error occurred while parsing document type definitionQXmlW(‰ãg�QC} v„eöPSÑu•‹ï$error occurred while parsing elementQXmlW(‰ãg�S€v„eöPSÑu•‹ï&error occurred while parsing referenceQXmlu1mˆ�9€QúSÑv„•‹ïerror triggered by consumerQXml*W(DTDN-N QA‹¸Ou(Y�è‰ãg�v„�u([žOSS€;external parsed general entity reference not allowed in DTDQXml*W(\^`'Pg ˜�YQ…[¹0!Extra content at end of document. QXmlStream—^lÕv„T}T zz•ôXðf0Illegal namespace declaration. QXmlStreameàeHv„XML[W{&0Invalid XML character. QXmlStreameàeHv„XMLT yð0Invalid XML name. QXmlStreameàeHv„XMLrHg,[W{&N20Invalid XML version string. QXmlStreamW(XMLXðfN-eàeHv„\^`'0%Invalid attribute in XML declaration. QXmlStreameàeHv„[W{&_u(0Invalid character reference. QXmlStream eàeHv„e‡hc0Invalid document. QXmlStreameàeHv„[žOSP<0Invalid entity value. QXmlStreameàeHv„YtcNäT yð0$Invalid processing instruction name. QXmlStreamW(SÂep[žOSXðfN-g NDATA0&NDATA in parameter entity declaration. QXmlStream T}T zz•ôv„ %1 RMl¡g ˆ«Xðf"Namespace prefix '%1' not declared QXmlStream_YËh‹°TŒ~Óg_h‹°N S9‘M0 Opening and ending tag mismatch. QXmlStreame‡hc�Çeév„~Óg_0Premature end of document. QXmlStreamhÀmKR0]LYW[žOS0Recursive entity detected. QXmlStream$W(\^`'P ^�R0&Sequence ']]>' not allowed in content. QXmlStreamrìzË�ЈLSêQA‹¸f/b€T&0"Standalone accepts only yes or no. QXmlStream_YËg_…v„h‹°0Start tag expected. QXmlStream"rìzË�ЈLO*\^`'_Ř{Qús°W(xNKT0?The standalone pseudo attribute must appear after the encoding. QXmlStreamaYv„  Unexpected ' QXmlStream&W(Qlg h‹Æe‡g,N-g aYv„[W{& %1 0/Unexpected character '%1' in public id literal. QXmlStreamN ˆ«e/cv„XMLrHg,0Unsupported XML version. QXmlStream XMLXðfl¡g W(e‡hcv„_YËOMn0)XML declaration not at start of document. QXmlStream$%1 TŒ %2 S9‘MN†NˆLv„Y4TŒ\>0,%1 and %2 match the start and end of a line. QtXmlPatternseàlÕƒ·SÖ %1%1 cannot be retrieved QtXmlPatterns,%1ST+N†W(‹÷lBx%2N-N QA‹¸v„Qk�ÛOMP<0E%1 contains octets which are disallowed in the requested encoding %2. QtXmlPatternsZ%1 f/NN*Y gB|{W‹0eàlÕb›QúR0Y gB|{W‹0Vàkdÿ b›QúR0O‹Y‚ %2 �Ùh7v„SŸ[P|{W‹f/SïNåv„0s%1 is an complex type. Casting to complex types is not possible. However, casting to atomic types such as %2 works. QtXmlPatterns%1 f/NN*eàeHv„ %20%1 is an invalid %2 QtXmlPatterns0%1 f/kcRˆh�¾_N-v„NN*eàeHh‹°0g eHh‹°N:ÿ?%1 is an invalid flag for regular expressions. Valid flags are: QtXmlPatterns$%1 f/NN*eàeHv„T}T zz•ô URI0%1 is an invalid namespace URI. QtXmlPatterns(%1 f/kcRˆh�¾_N-v„NN*eàeHj!_ÿ%2/%1 is an invalid regular expression pattern: %2 QtXmlPatterns %1N f/NN*TlÕv„j!gj!_T yð0$%1 is an invalid template mode name. QtXmlPatterns%1 f/NN*g*wåv„e¹hH|{W‹0%1 is an unknown schema type. QtXmlPatterns %1 f/N ˆ«e/cv„x0%1 is an unsupported encoding. QtXmlPatterns,%1 N f/NN*g eHv„ XML 1.0 [W{&0$%1 is not a valid XML 1.0 character. QtXmlPatterns %1N f/NN*YtcNäv„TlÕT yð04%1 is not a valid name for a processing-instruction. QtXmlPatterns%1 N f/NN*g eHv„ep[W‹íNI0"%1 is not a valid numeric literal. QtXmlPatterns@%1 N f/YtcNäv„g eHvîhT yð0[ƒ_Ř{f/P< %2ÿ O‹Y‚ %30Z%1 is not a valid target name in a processing instruction. It must be a %2 value, e.g. %3. QtXmlPatterns"%1 N f/|{W‹N: %2 v„g eHP<0#%1 is not a valid value of type %2. QtXmlPatterns%1 N f/R”Ÿv„etep0$%1 is not a whole number of minutes. QtXmlPatterns(%1 N f/SŸ[P|{W‹0Sê€ýb›QúR0SŸ[P|{W‹0C%1 is not an atomic type. Casting is only possible to atomic types. QtXmlPatterns8%1 N f/ƒVôQ…\^`'Xðf0lèae¹hH[üQery`'f/N ˆ«e/cv„0g%1 is not in the in-scope attribute declarations. Note that the schema import feature is not supported. QtXmlPatterns"%1 N f/|{W‹N: %2 v„g eHP<0&%1 is not valid as a value of type %2. QtXmlPatterns%1 S9‘MN†cbˆL{&%1 matches newline characters QtXmlPatterns>%1 _Ř{ˆ« %2 b€ %3 �ß–�ÿ N €ýW(fÿcb[W{&N2v„g+\>0J%1 must be followed by %2 or %3, not at the end of the replacement string. QtXmlPatterns4%1 —‰��ó\ %n N*SÂep0Vàkd %2 f/eàeHv„0=%1 requires at least %n argument(s). %2 is therefore invalid. QtXmlPatterns6%1 gYSïNåg %n N*SÂep0Vàkd %2 f/eàeHv„09%1 takes at most %n argument(s). %2 is therefore invalid. QtXmlPatterns%1 ˆ«Œu(N†0%1 was called. QtXmlPatternslè‘ÊN €ýST+ %1A comment cannot contain %1 QtXmlPatternslè‘ÊN €ýNå %1 ~Ó\>0A comment cannot end with a %1. QtXmlPatterns,�GR0N†NN*SêQA‹¸W(XQueryN-Qús°v„g„� 0An %1-attribute must have a valid %2 as value, which %3 isn't. QtXmlPatterns*^&g P< %2 v„ %1 \^`']ò~ÏXðf�ÇN†08An %1-attribute with value %2 has already been declared. QtXmlPatterns8T yðN: %1 v„SÂep]ò~ψ«XðfN†0kÏN*SÂepT yð_Ř{U/N0UAn argument by name %1 has already been declared. Every argument name must be unique. QtXmlPatterns0NN*T yðN: %1 v„\^`']ò~ÏQús°W(�ÙN*QC} N-N†0=An attribute by name %1 has already appeared on this element. QtXmlPatterns$NN*T yðN: %1 v„\^`']ò~ψ«R^ú01An attribute by name %1 has already been created. QtXmlPatternsRNN*\^`'‚‚p¹N €ýf/NN*e‡hc‚‚p¹v„[P‚‚p¹0Vàkdÿ �ÙN*\^`' %1 b@W(OMnf/N T�v„0dAn attribute node cannot be a child of a document node. Therefore, the attribute %1 is out of place. QtXmlPatterns%2_Ř{�ó\SÈNN*[PQC} %103At least one %1 element must appear as child of %2. QtXmlPatterns"�ó\NN*QC} %1‰�Qús°W(%2NKRM0-At least one %1-element must occur before %2. QtXmlPatterns"�ó\NN*QC} %1‰�Qús°W(%2NKQ…0-At least one %1-element must occur inside %2. QtXmlPatterns�ó\g NN*~ÄNöˆ«THs°0'At least one component must be present. QtXmlPatterns*W(QC} %2v„%1\^`'N-�ó\‰�c[šNN*j!_0FAt least one mode must be specified in the %1-attribute on element %2. QtXmlPatterns0�ó\NN*eö•ô~ÄNö_Ř{Qús°W(�ÙN* %1 uL–PNKT0?At least one time component must appear after the %1-delimiter. QtXmlPatterns\^`'%1TŒ%2_|kdN’e¥0+Attribute %1 and %2 are mutually exclusive. QtXmlPatterns.\^`' %1 N €ýˆ«N2ˆLSÿ VàN:[ƒQús°W(g˜v\B0EAttribute %1 can't be serialized because it appears at the top level. QtXmlPatterns@\^`'%1N €ýQús°W(QC} %2N 0Sêg %30%4TŒhQÆ\^`'f/QA‹¸v„0]Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes. QtXmlPatterns:\^`'%1N €ýQús°W(QC} %2N 0Sêg %3TŒhQÆ\^`'f/QA‹¸v„0YAttribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes. QtXmlPatterns:\^`'%1N €ýQús°W(QC} %2N 0Sêg %3TŒhQÆ\^`'f/QA‹¸v„0^Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes. QtXmlPatterns4\^`'%1N €ýQús°W(QC} %2N 0Sêg hQÆ\^`'SïNåQús°0VAttribute %1 cannot appear on the element %2. Only the standard attributes can appear. QtXmlPatterns\^`'%1v„PeàlÕb›QúR0 %1ÿ VàN:[ƒf/NN*b½Œa|{W‹ÿ ^vNVàkdeàlÕˆ«[žO‹S0fCasting to %1 is not possible because it is an abstract type, and can therefore never be instantiated. QtXmlPatternshÀmKR0s¯Circularity detected QtXmlPatterns %1 eå[ùNŽ %2 gf/eàeHv„0Day %1 is invalid for month %2. QtXmlPatterns*%1 eåf/W( %2...%3 ƒVôNKYv„0#Day %1 is outside the range %2..%3. QtXmlPatternsW(XSL-TNð‰ÆN-ÿ N €ýOu(%1�tÿ Sê€ýOu(%2�tb€%3�t0DIn an XSL-T pattern, axis %1 cannot be used, only axis %2 or %3 can. QtXmlPatterns.W(XSL-Th7_N-ÿ Qýep%1N €ýg {,N N*SÂep0>In an XSL-T pattern, function %1 cannot have a third argument. QtXmlPatterns@W(XSL-Th7_N-ÿ Sêu(Qýep%1TŒ%2SïNåu(NŽS9‘Mÿ %3N SïNå0OIn an XSL-T pattern, only function %1 and %2, not %3, can be used for matching. QtXmlPatternsNW(XSL-Th7_N-ÿ Qýep%1v„{,NN*SÂep_Ř{f/e‡[Wb€SØ‘ÏS€ÿ NåO¿u(NŽS9‘M0yIn an XSL-T pattern, the first argument to function %1 must be a literal or a variable reference, when used for matching. QtXmlPatternsDW(XSL-Th7_N-ÿ Qýep%1v„{,NN*SÂep_Ř{f/[W{&N2ÿ NåO¿u(NŽS9‘M0hIn an XSL-T pattern, the first argument to function %1 must be a string literal, when used for matching. QtXmlPatternsFW(�ÙN*fÿcb[W{&N2N-ÿ %1 Sê€ýˆ«u(NŽ�lNI[ƒg,Ž«b€ %2ÿ € N f/ %3MIn the replacement string, %1 can only be used to escape itself or %2, not %3 QtXmlPatternsDW(�ÙN*fÿcb[W{&N2N-ÿ %1 W(l¡g ˆ«�lNIv„eöP_Ř{ˆ«�ó\NN*ep[W�ß–�0VIn the replacement string, %1 must be followed by at least one digit when not escaped. QtXmlPatterns(etep–dlÕ(%1)–d–ö(%2)f/g*[šNIv„00Integer division (%1) by zero (%2) is undefined. QtXmlPatternseàlÕ~Ñ[šR0�ÙN*RM %10+It is not possible to bind to the prefix %1 QtXmlPatternseàlÕNÎ %1 b›QúR0 %20)It is not possible to cast from %1 to %2. QtXmlPatternsN €ý‘ÍY XðfRM %10*It is not possible to redeclare prefix %1. QtXmlPatterns\N €ýƒ·SÖ %10'It will not be possible to retrieve %1. QtXmlPatterns"N €ýW(NûOUQv[ƒ|{W‹‚‚p¹TmûR \^`'0AIt's not possible to add attributes after any other kind of node. QtXmlPatterns,eàlÕNÎ|{W‹N: %2 v„P< %1 b›QúR0 %37It's not possible to cast the value %1 of type %2 to %3 QtXmlPatternsS9‘Mf/Y'\Q™N eOav„Matches are case insensitive QtXmlPatterns,j!WW[üQeN €ýQús°W(Qýep0SØ‘ÏTŒ� ˜yXðfNKRM0MModule imports must occur before function, variable, and option declarations. QtXmlPatterns(lBj!–dlÕ(%1)–d–ö(%2)f/g*[šNIv„00Modulus division (%1) by zero (%2) is undefined. QtXmlPatterns*%1 gf/W( %2...%3 ƒVôNKYv„0%Month %1 is outside the range %2..%3. QtXmlPatternsDNN*|{W‹N: %1 v„POperator %1 cannot be used on atomic values of type %2 and %3. QtXmlPatterns$dÍO\{& %1 N €ýˆ«u(NŽ|{W‹ %20&Operator %1 cannot be used on type %2. QtXmlPatterns@W(|{W‹ %2 TŒ %3 v„SŸ[PPu|{eöÿ n�|{W‹_Ř{f/T N|{W‹ÿ b€[ƒ_Ř{f/NN*[W{&N2|{W‹0|{W‹ %2 f/N ˆ«QA‹¸v„0�When casting to %1 or types derived from it, the source value must be of the same type, or it must be a string literal. Type %2 is not allowed. QtXmlPatterns:_SQýep%1ˆ«u(NŽh7_S9‘Meöÿ SÂep_Ř{f/SØ‘ÏS€b€[W{&N20vWhen function %1 is used for matching inside a pattern, the argument must be a variable reference or a string literal. QtXmlPatterns*zzv}[W{&ˆ«yû–dN†ÿ –d—^_S[ƒNìQús°W([W{&|{N-OWhitespace characters are removed, except when they appear in character classes QtXmlPatternsrXSL-TQC} N-v„XSL-T\^`'_Ř{e>W(zz(null)T}T zz•ôN-ÿ € N f/W(XSL-TT}T zz•ôN-ÿ %1Stf/�ÙN*h7[P0iXSL-T attributes on XSL-T elements must be in the null namespace, not in the XSL-T namespace which %1 is. QtXmlPatterns*%1 ^tf/eàeHv„ÿ VàN:^”‹åNÎ %2 _YË0-Year %1 is invalid because it begins with %2. QtXmlPatternszzv}empty QtXmlPatternsxnRW0N exactly one QtXmlPatterns Nb€fôY one or more QtXmlPatterns –öb€fôY zero or more QtXmlPatterns–öb€N zero or one QtXmlPatterns]ò—Y—óMuted VolumeSlider —ó‘Ïÿ%1% Volume: %1% VolumeSliderTreeLine-3.2.1/translations/treeline_de.qm000066400000000000000000003117221506556630100206000ustar00rootroot00000000000000<¸dÊÍ!¿`¡½Ý§deB°O�2b +;8+; +;É+;Hý+;š+;ÔÌ+;ßßTÇbøUgv;W6}Ñ\>Ág¤7{hD rmÔ<¯xÆCMÃ�†§¤õ§ÍÎj§Ô¨¡¦¨¥j½®!»¦óÐ%©ÇÐD«ì0­Âú^$ýú^O0K�J7þc8¨s$H5'LH5ÂU¥²ÈVE'yc wûžEí¬ô}ú¬ô“Ű5~&¹µ Àe5ðÏÇ¿0KN~¹µ�[™ÇðÇæÄw 7~D&ñ²uŸ(F"À* •þ¿*‡›…þ*¦yÒ*¨¡fë*»g*Ð%gÉ*ÖTÜ·*ÙO÷*ì0gù*ö5†e+5t é+U¥h�+‹¯j+ŒFr+˜Å ‹+˜Å ]+¬ôR½+¶:àí+į V+ÏÇi“/5/s5S4ø;0®-*ïuwU©õy¨Äa~}X=2†¯“:ʇ¦eGDˆÜô!nŽH˜lþ‘ªS¬Ü‘´"Ø—=6¡¢'³ž¨w9w¨w9—Ī6•úª6•˜7­–D ë°7ÃÝA°gc)β½zß]²×ÃUYµ¶’ܶХé¸ÉÄ)º3Œ»f3i`¼P³á½[y⿾’ÀÀ´-~Âæwp÷ÒðMŽ,ÔÝCC¯×(¤uáònÛüï¶°ïñí~2«ö}¯?døåsë#ùeÔ" üy°$®üy°é$ÿ3ó´‡E«|c† ßÄ7ñ‰E‡%v•­ð-„å-É/45Á6n��«6n�6n�OÓ;Y d¹=ÖãÃ>í6s`Gx-RŽ5¼]û‚g_ Òû¶c®áPgÎIpx?™ÈV|ŒE>ˆàíRŒ-¬ÈŒÛ‡vÔŽ‚ÎÔñ�Í@©›Ó%hQžªî0Û Z Æ[£�¹Í¯¿´\n²Òäüѳwi¯÷³õe6 ³÷… ›´~Žðµ¢‚·å.Å·™ù’-ÄÒÞ+�Ç~“ËbÒ®éqqÚùä¯BÝ<~:áCþ]ŽâJu©Qâ¿èpî ¤áûŽ49û°%o{çÚ¨Í@ßÔtað‰U[~ã ŽªT†#­¼].Eþ>1¸SÍ9ƒ“;Þ9¼C@оDî¤4çNƒ`bN¥$k'R ©‘œXŒMsÊ[óAaLlGaËJ�f@â’Ðgáô™1i 5YélwpDl¿Ó2CoFsÍŽz¨Põ}'Åïq~o§Ì€.ò‚täY&…­¨GŒü$"Þ’‡’»œH°ÈŸ_•i⨇åÉÕ«Ë®X$°ž8´´¢Ž¨»Zj]¼™£ª2À —Eh§#®zËÁ2ϳ©•Ð:ªÕÐGà…ÊÖ“„¬#Ö“„†Øú‰Æ¯áòYæþ¢ kæþ¢˜qço^�0ìÝ.Üóí¨T%sóAUi ü ’ýx5~²¼¤*;¬Të~î8._†<±ÿ¨å$&=ôkK(�Â!7+ƒô.5€´Þ£6a²ñé>?dž@B“Î@{§pZFJ‰É \8Âvh`}îIÒfÈ4¹ôgNeShŒT]µh�‰Óër…h›x½¬‚òɃÕ3­ƒð}Aß„`ZÄ�òcb\‘³µ^H—þ?¬˜G%ñ²™ì5LØšÒcbÙŸN¢)J«Í»¬J‰Ò_­ìÔHj´§Ta ¹(N&޼’.½¥•+­¿kµäÂ+%W›Æ"DÿÍ!7Ï‘ÂæÏÏÄ®$ÖeT1Óל©NäשD5eØ™ÉYàÜÇ: Lßßë XàKgÀ�àÑ´‹çkHfwè°Ô·–õ÷�õSå]èþ!žî’ÿîm /ÿîmÁ×Ns ²œt5d­7[�ñѤáZcyI±~nB%Uä‹­#ÂCTº#ÂC‹r&Ã$&î*”Á,ôBŒ.ýÓM/œ´ õ/œ´†¯/œ´«70Ä·?ÃÓIn3ƒËL½„‚RüSº;S"þ—UZzó ›ZËÚ÷]¶¨çs_PÔõhb£#�Ëe,ŶÜfÅÎXDfÈŠçÿgì„#}l¾F2r^¤1I�PÄîÖ‚h�rqƒn×sŒZV�«Iìð–Ti0Š 7³¦~©ì‘­º|ö°Ï¥;!ºÓ^޼ÀãÏ Æ¢Ç.€&IÇ.€±qÇR�&÷Ë@åÀÁË˃²8Ψê.ÚéM¢à7iôáeÓMã7ÒuLê_ΞýïÿEpñ>y>óÙlgú¼Õxºþ¸4.½YQ7.ƒ°‡&k³õ&�tO0(m3PŽ)õãs¨/ð±0nd"g7O«gU8OªfäCÎd‡CP[&žR£9T2SU“=½Uô³t\]1³"Ih¨¿f€kÝþ¨káNE­n™ó]ãn™ó¸ n™óò‰p˜rX{ìÒ¼¿}\”6ƒ¼n,»‡£o‡ÏŒá –ã]Ÿ¯‚Π—NC©¢ˆu�áª/…öŸ«ŒãJX«—âGѶ #¿ç[K·Ǩºé}Ë›ô¤¿Ï”äxÐOãÊêÕe¤è"u�ùë»Eç»ô3¤§rõã`îö§^SˆüfO€Îų`öª¯3Á äDW'а®gU¥ÂÖt*Se¬U,á0F«1cD"Ÿ1cDåz9Hùˆ“@ÍE‰�Fy¥L¶CƒŽWšÅ7øYí“í[Ú%€Ž]!¾¤bùbôn•#BöwƾWNyŒ‘v{0> ô��£P"‚ „*†‡×9bAŠéc =Šéc†öŠéc«�¤“)�–¼žK>˜Hn$ZšjTÿ�žz_ص£Â©È褢MŸÜ¦*)|„ª¬•j뵄¥·9³ß’·áo;\¸†žÐºå^м „*;¼�ÎMÇ%%›sÇ%%öfÈx` ̇µ8}ÌÉåCuÌË%œ¶ÔUå[ÕÔ¤?{‘Þ¹ê[ß‚¥)ß—eévÔèÔéâÙ‡ë+™‰ð½^³×þm“‹þÒ·Œ �Õ)Å ÍÁ‘ \~à? \~& ;´?È q#31 ƒ-- !í„'¡ 4‰EŽà 5µ – :ró¶€ Fè´äË LìóM” MgþŒ f+>hô k¸ªÛ‰ †�£µ×  d”þú ¦8ÕJ" ¨ ,ˆ ©Ï‰”É ¬\ji ­˜¤J ¯bÝŠø ±›“®û ²b*½‡ ¸ldï³ ¼ „}s ¿ß¡ ÀªQª Á Zº Áíe® Ã,óþŒ ØøÜn Ûʵ; ê�tn êØn"¾ î�åYo ñž�e øéë· ÿ Õo# ÿŽÚe& cY»Œ �{Ð ­“0( .ƒ•þ ïîxé ¾T„W ÊøM ÝW=Ê ,_$87 /öÄ;Ó 4ñ„k 5rÕ¦F 7*åì =äò5 IöTe” Ty í† UÇΆ Wܾ?$ _Ò‰/Î a� cÂóN° cÄãæ eÄÊ uo³< uõ5 = w5šA �ăcì ‚ò5Ke ‡1Ñ_ ŒÅÓ �É3ƒ4 “¼:´0 ˜Iœ ˜Iœ¿ ˜Iœ° ˜IœH{ ˜Iœ—ü ˜IœÔ• ˜IœÛÀ ˜Iœõà �CwF �8rÂE ŸÉ9iy ¤ 10 «¦ùÑ ¬,… 4 ¬6"J> ®5Õ^® ®ùµ.r ¯Þ<× ²Ê^‚ µ�Iúy µããE ¶ã ;™ ¼Œt ¼Ëˆ1 ĽNCI Ë;:½ó ÍGc+ Ð:â ´ Ð:â˜ü ÛãµO³ Û㵘´ ÛãµÜp Þ;±ZQ Þä5¬ ðe3ºÖ òóÈ®- ü˜Žðs ü˜Ž/Ð ÿôÅGÇ s¯© ½.› ÐÃ' tœò X¿‰ çKK )M¥(© -ˆ86 .25# /.”Ìy 2 Î%* 5�…>X 9²3¶ @(eÀ/ A¨qí KsM Kºþ/o L¡.Eù LÇ9ÔY WÌè Ñ X³{ [tnØ pI3�ë rËW“2 x½(ó x½(à {uÅ_Ö :379 € Í–^ €Ùs™ù ‹Ìæ ŒH  �õÂê �Ü ¯ �Ü G �ßZà ›i³c^ ›€D� ªDÄR] «Í(à· ®˜¸ ¯–]t6 ±à„S7 ´¹oß ¹D0: ¹¾´kŠ ¼BÓA ¼~Ó@/ ¼šÙÓ± Ït®µ ÖAe Ù·åïó ߺšáå àKGiÇ á²~Bæ ã\E,@ ëÜn` ëù^-g óy~ § ó²AŽ vÕ”i §éêå Óì`� šEW áJÖ š+I& PÔ%† ¼%Åü Ö#D Qôé¼ l”lá ¿�i) #“ '{í x (µEL¢ * •O 2l*Ñ 7±"3 8Ç‘vš ;yAI =ÙÓ'¦ @|5( @¿ÀÄ VÿõGo dMnÒ gÆ#:x n¾/Ú< pk¾!® t—¥3 t©Ž,Ó tÁ�zË v"¾÷ {BŸl €ÿüÿ¸ ˆ=ÎQ¢ ‰¡ãN ”ËeVÉ •h¥¿H —M¥c` ŸèTôÜ ¡ž[F ¡ô×¾E £î5© ®�Ca »²4žŒ ¼°eìP Æh‚� Æm)Õa Ò¯ã_ð Þv¥Ó ãbngø ê¬DJ” ëU1¯ îµÕ{ ðYƒü( ûìóæW þÖ\µ� -Ÿ×a …‹LV “Äl3 'Ü•6 .�“cñ 0³uTõ 0ó£!˜ 3±Þ 7yÒ@U CàÒQ G9. H³³<{ Kz9Š@ Kè„Rg MîÄ+ NðmÉ ]`^l” _ yœ a*Çš dT¾ iØäÓ¸i ûîs¥W ÿ»:kÙûñ·Éê ¼mjcÆæê"Ye‡»º…‡»ûf¾s¹e­s[i(t�¬–(·©€<-þ¹¨/+ã%ã0ó/f20ô>eä9Äó×= +óEjDH;Ó‚²L`Òo=L¿Ó…�LÊã�¬LÝ^h)V�>‹Y‚—q¢Zrþõ]~ÓK§h€j Ài?Ã]kŽ·lfcL®p#MWp£#¯q¢ƒNtޏìt/C‚ED³L$† …ª‡�^A=@™Ï-wœš¥tÃ�£±…«Í­–nr²šbê ¹ë $Úº”t Á¿ß:ê±Ék‚òÌ-î :Í`E CÔ•³ÊbÕ�ýedÚYe76à˜9�xêhÅ@ë Ã#½ëœtݤîp�‹þVC¥°ã²ø`ϨÕ[Ä;>h³‚ –ÆKcšRè‡(üÓSê6ãÅ�8 q|4<æÉúÏ@-®ZHNŽÒIöôH¶MÉÕ»9Uâƒ6Z8nH[Kô e3íÕem3U¾iFWFŸr†ÕÞ>s$Cww³r|*½d{}$7f'…?y2¾†AÔ¡Œ�ç½+�Ó�b �Ô²@–ž t÷�],(�âto�Ÿ2Iq¢m£z¤žµN#¬nçŒú¯#Hp›´êâL¹éŸ3Mº£Îu4!À$&ÖúÆ|!ÉŸ)Ò–Ëî(TÏ~Ä*ðÛ]DÖÜíísá�oB?áùÅ4‹ãÊodtåd…ù•ëŠRôßíuàöé3„ ø6‰Õ÷ùfî|ëitú&Abbrechen&Cancelcolorset&OK&OKcolorset.Button HintergrundfarbeButton background colorcolorset Button TextfarbeButton text colorcolorset"FarbeinstellungenColor Settingscolorset,unfinished">Farbschema Color Themecolorset4Anwender-definierte Farben Custom Colorscolorset4Anwender-definiertes Thema Custom themecolorsetDunkles Thema Dark themecolorset<(Voreingestelltes) SystemthemaDefault system themecolorset6Dialog für HintergrundfarbeDialog background colorcolorset(Dialog für TextfarbeDialog text colorcolorsetJFarbe für nicht verfügbare FunktionenDisabled button text colorcolorset,Textfarbe deaktivierenDisabled text foreground colorcolorset&Textfarbe von LinksLink text colorcolorset({0} Farben auswählenSelect {0} colorcolorset:Hintergrundfarbe des EintragsSelected item background colorcolorsetFVordergrundfarbe des EintragstextesSelected item text colorcolorset>Hintergrundfarbe für TextfelderText widget background colorcolorset>Vordergrundfarbe für TextfelderText widget foreground colorcolorset"Farben des Themas Theme Colorscolorset:Hintergrundfarbe für TooltipsTool tip background colorcolorset:Vordergrundfarbe für TooltipsTool tip foreground colorcolorset"&Regel hinzufügen &Add New Rule conditional&Abbrechen&Cancel conditional&Schließen&Close conditional&Löschen&Delete conditionalFilter &beenden &End Filter conditional&Filter&Filter conditional &Laden&Load conditional&OK&OK conditional&Regel löschen &Remove Rule conditionalS&peichern&Save conditional FalschFalse conditionalSuche &Nächsten Find &Next conditional"Suche &VorherigenFind &Previous conditional Name:Name: conditional@Keine Übereinstimmungen gefunden!No conditional matches were found conditionalKnotentyp Node Type conditionalRegel {0}Rule {0} conditional&Gespeicherte Regeln Saved Rules conditionalWahrTrue conditional[Alle Typen] [All Types] conditionalundand conditionalenthältcontains conditionalendet mit ends with conditionaloderor conditionalbeginnt mit starts with conditional&Anwenden&Apply configdialog&Abbrechen&Cancel configdialog&Datentyp &Data Type configdialogTyp &löschen &Delete Type configdialog,Von &Original ableiten&Derive from original configdialog&Gleichung &Equation configdialog&Feld &konfigurieren &Field Config configdialog&Feldtyp &Field Type configdialog*Erweitert &ausblenden&Hide Advanced configdialogNach &unten &Move Down configdialog&Neues Feld... &New Field... configdialog&Neuer Typ... &New Type... configdialog&OK&OK configdialog&Präfix&Prefix configdialog&Zurücksetzen&Reset configdialog&Ergebnistyp &Result Type configdialog &Alles auswählen &Select All configdialog&Erweitert &anzeigen&Show Advanced configdialog"&Sortierbedingung&Sort Criteria configdialog&&Überschrift Format &Title Format configdialogN&Leere Zeilen zwischen KnotenhinzufügenAdd &blank lines between nodes configdialogFeld hinzufügen Add Field configdialogTyp hinzufügenAdd Type configdialogDDatentypen hinzufügen oder löschenAdd or Remove Data Types configdialog:&Aufzählungspunkte hinzufügenAdd text bullet&s configdialog:&HTML Text im Format erlaubenAllow &HTML rich text in format configdialog0Arithmetische OperatorenArithmetic Operators configdialog$Automatische TypenAutomatic Types configdialog*Verfügbare &FeldlisteAvailable &Field List configdialog$Verfügbare &FelderAvailable &Fields configdialog&Bool'sches ErgebnisBoolean Result configdialognKann keinen Datentyp löschen, der noch in Benutzung ist+Cannot delete data type being used by nodes configdialog&Icon ändern Change &Icon configdialogAnzahl Kinder Child Count configdialogKind-VerweisChild Reference configdialog Kind Typ GrenzenChild Type Limits configdialog*Auswahl &zurücksetzen Clear &Select configdialog Typ &kopieren... Co&py Type... configdialogZAusgabe &Trenner für Kombination && Kindliste+Combination && Child List Output &Separator configdialog(VergleichsoperatorenComparison Operators configdialog0Datentypen konfigurierenConfigure Data Types configdialogTyp kopieren Copy Type configdialog ZählenCount configdialog.&Bedingte Typen anlegenCreate Co&nditional Types configdialog Datum Date Result configdialog:&Standardwert für neue KnotenDefault &Value for New Nodes configdialog$Standard Kind &TypDefault Child &Type configdialog&Ausdruck definierenDefine Equation configdialogDMathematischen Ausdruck definierenDefine Math Field Equation configdialogFeld &löschen Dele&te Field configdialog0Abgeleitet von &BasistypDerived from &Generic Type configdialogBeschreibung Description configdialogRichtung Direction configdialogEditorhöhe Editor Height configdialog>Name des neuen Feldes eingeben:Enter new field name: configdialogBGib den Namen des neuen Typs ein:Enter new type name: configdialog.Fehler in Gleichung: {}Equation error: {} configdialog^Fehler - Zirkulärer Verweis im berechnetem Feld2Error - circular reference in math field equations configdialog"Bewerte HTML TagsEvaluate &HTML tags configdialogZusatztext Extra Text configdialog &FeldF&ield configdialog&Feldliste F&ield List configdialogFeldField configdialog&Feldliste Field &List configdialogFeldverweisField References configdialog"Dateiinfo-VerweisFile Info Reference configdialog$Richtung &umkehrenFlip &Direction configdialog"Hilfe zum &Format Format &Help configdialogIconIcon configdialog.Mathematischer Ausdruck Math Equation configdialog*&Feldliste bearbeitenModify &Field List configdialog,&Bedingte Typen ändernModify Co&nditional Types configdialog,Nach &oben verschiebenMove &Up configdialog.Nach &unten verschieben Move Do&wn configdialog,Nach &oben verschiebenMove U&p configdialogNameName configdialogLeerNone configdialog,&Anzahl der TextzeilenNum&ber of text lines configdialogAnzahl Ergebnis Number Result configdialog"Anzahl der KinderNumber of Children configdialog$Typ des O&peratorsO&perator Type configdialog&AusgabeO&utput configdialog*Liste der Oper&atorenOper&ator List configdialogOperationen Operations configdialog6Verweise zu anderen FeldernOther Field References configdialog&AusgabeformatOut&put Format configdialog&AusgabeformatOutpu&t Format configdialogHTML Ausgabe Output HTML configdialogAusgabeoptionenOutput Options configdialogVater-VerweisParent Reference configdialogVerweis&typRefere&nce Type configdialogVerweis &StufeReference &Level configdialogVerweis &TypReference &Type configdialogVerweis&stufeReference Le&vel configdialog&Feld &umbenennen...Rena&me Field... configdialog$Typ &umbenennen...Rena&me Type... configdialogFeld umbenennen Rename Field configdialogTyp umbenennen Rename Type configdialog.Umbenennen von {} nach:Rename from {} to: configdialog$Verweis auf WurzelRoot Reference configdialog Nichts auswählen Select &None configdialog.Verweis auf sich selbstSelf Reference configdialog,Datentyp Icon zuweisenSet Data Type Icon configdialog4Typ durch Bedingung setzenSet Types Conditionally configdialog"&Sortierfelder... Sort &Keys... configdialogSortierfeldSort Key configdialogSortierfelderSort Key Fields configdialog&SuffixSuffi&x configdialog&Typliste T&ype List configdialogText OperatorenText Operators configdialogText Ergebnis Text Result configdialogXDie folgenden Zeichen sind nicht erlaubt: {},The following characters are not allowed: {} configdialog:Der Name kann nicht leer seinThe name cannot be empty configdialogRDer Name darf keine Leerzeichen enthaltenThe name cannot contain spaces configdialogLDer Name kann nicht mit "xml" beginnen The name cannot start with "xml" configdialogVDer Name muss mit einem Buchstaben beginnen!The name must start with a letter configdialogDDer Name ist bereits in VerwendungThe name was already used configdialogUhrzeit Time Result configdialog$Typ &Konfiguration Typ&e Config configdialogTypType configdialogJEine Tabelle für &Feldwerte verwendenUse a table for field &data configdialog,[Alle Typen verfügbar][All Types Available] configdialog [Leer][None] configdialogAbsolutwertabsolute value configdialoghinzufügenadd configdialogArcus Cosinus arc cosine configdialogArcus Sinusarc sine configdialogArcus Tangens arc tangent configdialogDurchschnittaverage configdialog(Logarithmus Basis 10base-10 logarithm configdialog*Text aneinanderhängenconcatenate text configdialogJText in Kleinbuchsrtaben konvertierenconvert text to lower case configdialogFText in Großbuchstaben konvertierenconvert text to upper case configdialog Cosinus Bogenmaßcosine of radians configdialog$Grad nach Bogenmaßdegrees to radians configdialogdividierendivide configdialogIst gleichequal to configdialogFakultät factorial configdialogFliesskommazahlfloating point configdialog*dividieren mit runden floor divide configdialogvorwärtsforward configdialog>>fwd configdialogIst größer greater than configdialog,Ist größer oder gleichgreater than or equal to configdialogHöhere Ganzzahlhigher integer configdialogxErsetze in 1. Argument das 2. Argument durch das 3. Argument(in 1st arg, replace 2nd arg with 3rd arg configdialogTText verbinden mit 1. Argument als Trenner$join text using 1st arg as separator configdialogIst kleiner less than configdialog.Ist kleiner oder gleichless than or equal to configdialogLogisches Und logical and configdialogLogisches Oder logical or configdialog&Niedrigere Ganzzahl lower integer configdialogMaximummaximum configdialogMinimumminimum configdialog modulomodulus configdialogmultiplizierenmultiply configdialogEulersche Zahlnatural log constant configdialog.Natürlicher Logarithmusnatural logarithm configdialog Ist nicht gleich not equal to configdialogPI pi constant configdialogexponierenpower configdialog$Bogenmaß nach Gradradians to degrees configdialog<<rev configdialogrückwärtsreverse configdialog(Runden auf n Stellenround to num digits configdialogSinus Bogenmaßsine of radians configdialogQuadratwurzel square root configdialogabziehensubtract configdialogsummieren sum of items configdialog Tangens Bogenmaßtangent of radians configdialogPWahr, wenn 1.Argument 2.Argument enthält%true if 1st text arg contains 2nd arg configdialogZWahr, wenn 1. Argument mit 2. Argument endet &true if 1st text arg ends with 2nd arg configdialog\Wahr, wenn 1. Argument mit 2. Argument beginnt(true if 1st text arg starts with 2nd arg configdialogJWahrer Wert, Bedingung, Falscher Wert"true value, condition, false value configdialog.Abgeschnittene Ganzzahltruncated integer configdialogDatei &suchen&Browse for File dataeditors&Abbrechen&Cancel dataeditors&Gehe zu Ziel &Go to Target dataeditors&OK&OK dataeditors&Verweis öffnen &Open Link dataeditors&Öffne Bild &Open Picture dataeditors6Klicke Verweis Ziel im Baum(Click link target in tree) dataeditorsAbsolutAbsolute dataeditorsAdresseAddress dataeditorsVerweis löschen Clear &Link dataeditorsAnzeigename Display Name dataeditors Externer Verweis External Link dataeditors$Verzeichnis AngabeFile Path Type dataeditors Interner Verweis Internal Link dataeditors&&Verzeichnis öffnen Open &Folder dataeditors Verweis auf Bild Picture Link dataeditorsRelativRelative dataeditors SchemaScheme dataeditors"Auf &heute setzen Set to &Now dataeditorsHeutiges &Datum Today's &Date dataeditorsDVerweis zu externer TreeLine DateiTreeLine - External Link File dataeditors$TreeLine BilddateiTreeLine - Picture File dataeditorsVerweislink dataeditors&Spalten&Columnsexportsx&Komma-getrennte Tabelle (CSV) der Nachkommen (Nummern Grad);&Comma delimited (CSV) table of descendants (level numbers)exports&Gesamter Baum &Entire treeexports &HTML&HTMLexports:&HTML formatierte Lesezeichen&HTML format bookmarksexports8einschließlich Wurzel Knoten&Include root nodesexports&ODF Struktur &ODF Outlineexports:Altes TreeLine Format (2.0.x)&Old TreeLine (2.0.x)exports2&Nur geöffnete Kindknoten&Only open node childrenexports(&Einzelne HTML Seite&Single HTML pageexports2&Titelzeile mit Tabulator&Tabbed title textexports &Text&Textexports"TreeLine Teilbaum&TreeLine SubtreeexportsT&Unformatierte Ausgabe des gesamten Textes&Unformatted output of all textexports:&XBEL formatierte Lesezeichen&XBEL format bookmarksexports &XML (generisch)&XML (generic)exports&Lesezeichen Book&marksexportsLesezeichen Bookmarksexports4Ausgabe Unterformat wählenChoose export format subtypeexports(Ausgabeformat wählenChoose export format typeexports,Ausgabeoptionen wählenChoose export optionsexportstKomma-&getrennte Tabelle (CSV) der Kinder (einzelner Grad)7Comma &delimited (CSV) table of children (single level)exportsàFehler - Kann nicht auf nicht gespeicherte TreeLine Datei verweisen. Speichere die Datei und versuche es erneut.FError - cannot link to unsaved TreeLine file. Save the file and retry.exportsœFehler - Export Vorlage nicht gefunden. Überprüfe deine TreeLine Installation.JError - export template files not found. Check your TreeLine installation.exportsDatei Export File Exportexports@&Kopf- und Fußzeile einschließenInclude &print header && footerexports†Live Baum Ansicht, verlinkt mit der TreeLine Datei (für Web Server)8Live tree view, linked to TreeLine file (for web server)exportshLive Baum Ansicht, eine Datei (Daten eingeschlossen)+Live tree view, single file (embedded data)exports6Mehrere HTML &DatentabellenMultiple HTML &data tablesexportsTMehrere HTML &Seiten mit Navigationsleiste)Multiple HTML &pages with navigation paneexportsVSie müssen Knoten vor dem Export auswählen.!Must select nodes prior to exportexports:&Stufen der NavigationsleisteNavigation pane &levelsexportsAndere Optionen Other Optionsexports ElternParentexports,&Ausgewählte TeilbäumeSelected &branchesexports&Ausgewählte &KnotenSelected &nodesexportsTEinzelne &HTML Seite mit Navigationsleiste&Single &HTML page with navigation paneexportsfTab-&getrennte Tabelle der Kinder (&einzelner Grad)0Tab &delimited table of children (&single level)exportsTree&Line Tree&LineexportsJTreeLine - Exportiere Generisches XMLTreeLine - Export Generic XMLexports4TreeLine - Exportiere HTMLTreeLine - Export HTMLexportsLTreeLine - Exportiere HTML Lesezeichen TreeLine - Export HTML Bookmarksexports<TreeLine - Exportiere ODF TextTreeLine - Export ODF Textexports4TreeLine - Exportiere TextTreeLine - Export Plain TextexportsDTreeLine - Exportiere Text TabelleTreeLine - Export Text TablesexportsNTreeLine - Exportiere TextüberschriftenTreeLine - Export Text TitlesexportsNTreeLine - Exportiere TreeLine Teilbaum"TreeLine - Export TreeLine SubtreeexportsLTreeLine - Exportiere XBEL Lesezeichen TreeLine - Export XBEL Bookmarksexports¸Warnung - kein relativer Pfad von "{0}" nach "{1}". Weitermachen mit absolutem Pfad?LWarning - no relative path from "{0}" to "{1}". Continue with absolute path?exports&Was wird exportiertWhat to Exportexports"." Zeichen .."." Character .. fieldformat"/" Zeichen //"/" Character // fieldformat00 oder 1 Wiederholung ?0 Or 1 Repetitions ? fieldformat:0 oder mehr Wiederholungen *0 Or More Repetitions * fieldformat:1 oder mehr Wiederholungen +1 Or More Repetitions + fieldformat AM/PMAM/PM %p fieldformat*Beliebiges Zeichen .Any Character . fieldformat Auto Auswahlfeld AutoChoice fieldformat*Auto-KombinationsfeldAutoCombination fieldformatBooleanBoolean fieldformat Großbuchstabe ACapital Letter A fieldformat2Große römische Ziffer ICapital Roman Numeral I fieldformatAuswahlfeldChoice fieldformat Kombinationsfeld Combination fieldformat"Komma Trenner \,Comma Separator \, fieldformat DatumDate fieldformatDatum/ZeitDateTime fieldformat,Tag (1 oder 2 Ziffern)Day (1 or 2 digits) %-d fieldformatTag (2 Ziffern)Day (2 digits) %d fieldformat4Tag des Jahres (1 bis 366)Day of year (1 to 366) %-j fieldformatDezimalkomma ,Decimal Comma , fieldformatDezimalpunkt .Decimal Point . fieldformat*Anzahl der NachkommenDescendantCount fieldformatNZiffer oder Leertaste (Extern) <space>!Digit or Space (external)  fieldformat"Punkt Trenner \.Dot Separator \. fieldformatTexteende $ End of Text $ fieldformat6Escape für Sonderzeichen \Escape a Special Character \ fieldformat"Beispiel 1/2/3/4Example 1/2/3/4 fieldformat$Exponent (Groß) EExponent (capital) E fieldformat&Exponent (Klein) eExponent (small) e fieldformat Externer Verweis ExternalLink fieldformat>Stunde (0-23, 1 oder 2 Ziffern)Hour (0-23, 1 or 2 digits) %-H fieldformat2Stunde (00-23, 2 Ziffern)Hour (00-23, 2 digits) %H fieldformat2Stunde (01-12, 2 Ziffern)Hour (01-12, 2 digits) %I fieldformat>Stunde (1-12, 1 oder 2 Ziffern)Hour (1-12, 1 or 2 digits) %-I fieldformatHtmlTextHtmlText fieldformat Interner Verweis InternalLink fieldformat Stufentrenner /Level Separator / fieldformat*Kleinbuchstabe [a-z]Lower Case Letters [a-z] fieldformatMathematischMath fieldformat0Microsekunde (6 Ziffern)Microseconds (6 digits) %f fieldformat2Minute (1 oder 2 Ziffern)Minute (1 or 2 digits) %-M fieldformat$Minute (2 Ziffern)Minute (2 digits) %M fieldformat0Monat (1 oder 2 Ziffern)Month (1 or 2 digits) %-m fieldformat"Monat (2 Ziffern)Month (2 digits) %m fieldformatMonat AbkürzungMonth Abbreviation %b fieldformatMonat Name Month Name %B fieldformat(Keine Ziffer [^0-9]Not a Number [^0-9] fieldformat HeuteNow fieldformat NummerNumber fieldformatZiffer 1Number 1 fieldformat Nummer Numbering fieldformatEinzeiler OneLineText fieldformat&Optionale Ziffer #Optional Digit # fieldformat0Optionales Vorzeichen -Optional Sign - fieldformatOder |Or | fieldformatLGliederungsbeispiel I../A../1../a)/i)!Outline Example I../A../1../a)/i) fieldformatBildPicture fieldformat$Regulärer AusdruckRegularExpression fieldformat.Erforderliche Ziffer 0Required Digit 0 fieldformat8Erforderliches Vorzeichen +Required Sign + fieldformat4Sekunde (1 oder 2 Ziffern)Second (1 or 2 digits) %-S fieldformat&Sekunde (2 Ziffern)Second (2 digits) %S fieldformat8Überschrift Beispiel 1.1.1.1Section Example 1.1.1.1 fieldformat$Sektionstrenner .Section Separator . fieldformatTrenner / Separator / fieldformat0Menge von Ziffern [0-9]Set of Numbers [0-9] fieldformat"Kleinbuchstabe aSmall Letter a fieldformat2Kleine römische Ziffer iSmall Roman Numeral i fieldformatFLeertaste Trenner (Intern) <space>"Space Separator (internal)  fieldformat4Text, Leerzeichen getrennt SpacedText fieldformatW/FT/F fieldformatTextText fieldformatZeitTime fieldformat(Großbuchstabe [A-Z]Upper Case Letters [A-Z] fieldformat.Wochennummer (0 bis 53)Week Number (0 to 53) %-U fieldformat&Wochentag AbkürzungWeekday Abbreviation %a fieldformatWochentag NameWeekday Name %A fieldformatJ/NY/N fieldformat Jahr (2 Ziffern)Year (2 digits) %y fieldformat Jahr (4 Ziffern)Year (4 digits) %Y fieldformatwahr/falsch true/false fieldformatja/neinyes/no fieldformat falschfalse genbooleanneinno genbooleanwahrtrue genbooleanjayes genbooleanAlle Dateien All Files globalref*Alle Treeline DateienAll TreeLine Files globalref4CSV Datei (Komma-getrennt)CSV (Comma Delimited) Files globalrefHTML Dateien HTML Files globalrefODF DateienODF Text Files globalref*Alte Treeline DateienOld TreeLine Files globalrefPDF Dateien PDF Files globalrefText Dateien Text Files globalref TreeLine DateienTreeLine Files globalref<TreeLine Dateien (komprimiert)TreeLine Files - Compressed globalref@TreeLine Dateien (verschlüsselt)TreeLine Files - Encrypted globalrefTreepad Dateien Treepad Files globalrefXML Dateien XML Files globalrefSuchen:  Find: helpview&Zurück&Backhelpview&Vorwärts&Forwardhelpview(&Eigenes Verzeichnis&Homehelpview &Vorwärts Suchen Find &Nexthelpview"&Rückwärts SuchenFind &Previoushelpview&Text nicht gefundenText string not foundhelpviewWerkzeugeToolshelpviewn"{0}" ist keine TreeLine Datei. Importfilter verwenden?:"{0}" is not a valid TreeLine file. Use an import filter?importsNGenerisches &XML (Keine TreeLine Datei) &Generic XML (non-TreeLine file)importsD&HTML Lesezeichen (Mozilla Format) &HTML bookmarks (Mozilla Format)importsb&Mit Tabulator eingerückter Text, Knoten je Zeile%&Tab indented text, one node per lineimportsF&XML Lesezeichendatei (XBEL-Format)&XML bookmarks (XBEL format)importsLESEZEICHENBOOKMARKimportsDFehler im CSV Format bei Zeile {0}Bad CSV format on Line {0}importsLesezeichen Bookmarksimports0Import Methode auswählenChoose Import Methodimports�Ko&mma-getrennter (CSV) Text Tabelle mit Stufe Spalte && Kopfzeile ReiheACo&mma delimited (CSV) text table with level column && header rowimportsdKo&mma-getrennter (CSV) Text Tabelle mit Kopfzeile1Comma delimited (CSV) text table &with header rowimportsFFehler - Kann Datei {0} nicht lesenError - could not read file {0}importsBFehler - ungültiges Format in {0}Error - improper format in {0}importsVERZEICHNISFOLDERimportsImport Datei Import FileimportsUngültige Datei Invalid Fileimports@Falsche Ebene Nummer on line {0} Invalid level number on line {0}imports6Fehlerhafte Ebenen StrukturInvalid level structureimportsVerweisLinkimportsFAlte Tree&Line Datei (1.x oder 2.x)Old Tree&Line File (1.x or 2.x)imports>Open &Document (ODF) GliederungOpen &Document (ODF) outlineimports AndereOtherimportsHText &Blöcke (Beendet mit Leerzeile)-Plain text ¶graphs (blank line delimited)importsZNur Text, ein &Knoten pro Zeile (CR getrennt)-Plain text, one &node per line (CR delimited)importsTRENNER SEPARATORimportsTABELLETABLEimportsNTabulator getrennter Text mit Kopfzeile)Tab delimited text table with header &rowimportsTextTextimportsDZu viele Einträge in der Zeile {0}Too many entries on Line {0}imports.TreeLine - Import DateiTreeLine - Import Fileimports2Treepad &Datei (nur Text)Treepad &file (text nodes only)imports|Verweise auf Kinder müssen in einer Funktion kombiniert werden/Child references must be combined in a functionmatheval,Ungültige Zeichen "{}"Illegal "{}" charactersmatheval.Ungültige Funktion: {0}Illegal function present: {0}mathevalNUngültiger Objekttyp oder Operator: {0}$Illegal object type or operator: {0}matheval8Ungültige Syntax in AusdruckIllegal syntax in equationmatheval&Anwenden&Apply miscdialogs&Abbrechen&Cancel miscdialogs&Schließen&Close miscdialogsFilter &Ende &End Filter miscdialogs&Gesamter Baum &Entire tree miscdialogs&Filter&Filter miscdialogsSuche &Nächster &Find Next miscdialogs&Vorwärts&Forward miscdialogs&Ignorieren&Ignore and skip miscdialogs&Schlüsselworte &Key words miscdialogs&Knotentyp &Node Type miscdialogs&OK&OK miscdialogs<&Vordefinierte Schlüsselfelder&Predefined Key Fields miscdialogs&&Regulärer Ausdruck&Regular expression miscdialogs&Ersetzen&Replace miscdialogsb&Nummerierung für nächste Geschwister neu starten"&Restart numbers for next siblings miscdialogs4&Standard wiederherstellen&Restore Defaults miscdialogs&Rückwärts&Reverse miscdialogs&Suchtext &Search Text miscdialogs&&Kinder der Auswahl&Selection's children miscdialogsNur &Titel &Titles only miscdialogs&Symbolleisten &Toolbars miscdialogs@&Leere Felder als Null behandeln&Treat blank fields as zeros miscdialogs<&Standard Schriftart verwenden&Use app default font miscdialogs:Datei&komprimierung verwenden&Use file compression miscdialogs8&System Schriftart verwenden&Use system default font miscdialogs--Trenner-- --Separator-- miscdialogsÂEin schwerer Fehler ist aufgetreten. TreeLine kann sich in einem instabilen Zustand befinden. Empfehlung, die Datei unter einem anderen Namen zu speichern und TreeLine neu zu starten. Das Debug Info unterhalb kann kopiert werden und per Mail an doug101@bellz.org geschickt werden zusammen mit Erläuterungen, unter welchen Umständen, der Fehler auftrat.A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances.  miscdialogs,&Verfügbare FunktionenA&vailable Commands miscdialogs Jedes &Vorkommen Any &match miscdialogs$StandardschriftartApp Default Font miscdialogsLösche &Taste Clear &Key miscdialogs*Schriftarten AnpassenCustomize Fonts miscdialogs6Symbolleisten konfigurierenCustomize Toolbars miscdialogs DatenData miscdialogsDaten Menü Data Menu miscdialogs6Standard - Einzeiliger TextDefault - Single Line Text miscdialogsBearbeitenEdit miscdialogsBearbeiten Menü Edit Menu miscdialogs*Schriftart für EditorEditor View Font miscdialogsDPasswort der verschlüsselten DateiEncrypted File Password miscdialogsLFehler - Ungültiger regulärer Ausdruck"Error - invalid regular expression miscdialogsBFehler - Ersetzung nicht möglich Error - replacement failed miscdialogsGanzer &Satz F&ull phrase miscdialogs FelderFields miscdialogs DateiFile miscdialogsDatei Menü File Menu miscdialogs&Datei EigenschaftenFile Properties miscdialogs"Datei Speicherung File Storage miscdialogs FilterFilter miscdialogs SuchenFind miscdialogsSuche &Nächster Find &Next miscdialogs Suche &VorherigeFind &Previous miscdialogs&Suchen und ErsetzenFind and Replace miscdialogs FormatFormat miscdialogsFormat Menü Format Menu miscdialogsGesamte &Daten Full &data miscdialogsGanze &Worte Full &words miscdialogs\Behandlung von Knoten ohne Nummerierungsfelder'Handling Nodes without Numbering Fields miscdialogs HilfeHelp miscdialogsHilfe Menü Help Menu miscdialogs Wie wird gesucht How to Search miscdialogsJKnoten der ersten Ebene einschliessenInclude top-level nodes miscdialogs&Ganze WorteKey full &words miscdialogs0Taste {0} bereits belegtKey {0} is already used miscdialogsTastaturkürzelKeyboard Shortcuts miscdialogsJSprachcode oder Wörterbuch (optional)&Language code or dictionary (optional) miscdialogsGroße Icons Large Icons miscdialogs&Mathematisches Feld Math Fields miscdialogs.Nach &unten verschieben Move &Down miscdialogs,Nach &oben verschiebenMove &Up miscdialogs&Felder N&ode Fields miscdialogsKein MenüNo menu miscdialogsDKeine Nummerierungsfelder gefunden,No numbering fields were found in data types miscdialogs KnotenNode miscdialogsKnoten&titel Node &Titles miscdialogsKnoten Menü Node Menu miscdialogs,Schriftart für AusgabeOutput View Font miscdialogs&Regulärer &AusdruckRe&gular expression miscdialogs*Passwort wiederholen:Re-Type Password: miscdialogs>Passworte stimmen nicht übereinRe-typed password did not match miscdialogsBPasswort für diese Sitzung merken%Remember password during this session miscdialogs&Alle Ersetzen Replace &All miscdialogs&{0} Stellen ersetztReplaced {0} matches miscdialogsErsetzungs&textReplacement &Text miscdialogs,Nummerierung &umkehrenReserve &numbers miscdialogsWurzelelement Root Node miscdialogs:Suchtext "{0}" nicht gefundenSearch string "{0}" not found miscdialogs:Suchtext "{0}" nicht gefundenSearch text "{0}" not found miscdialogs,Ausgewählte &TeilbäumeSelected &branches miscdialogsN&Geschwister der ausgewählten TelibäumeSelection's &siblings miscdialogsD&Kinder der ausgewählten TeilbäumeSelection's childre&n miscdialogsKleine Icons Small Icons miscdialogsSortierrichtungSort Direction miscdialogsSortiermethode Sort Method miscdialogs Konten sortieren Sort Nodes miscdialogs&Rechtschreibprüfung Spell Check miscdialogs2&Symbolleisten FunktionenTool&bar Commands miscdialogs&Symbolleisten&größe Toolbar &Size miscdialogs(Anzahl SymbolleistenToolbar Quantity miscdialogsWerkzeugTools miscdialogsWerkzeug Menü Tools Menu miscdialogs4Schriftart für BaumanzeigeTree View Font miscdialogs4TreeLine - Schwerer FehlerTreeLine - Serious Error miscdialogs*TreeLine NummerierungTreeLine Numbering miscdialogs4Passwort für {0} eingeben:Type Password for "{0}": miscdialogs$Passwort eingeben:Type Password: miscdialogs*Nummerierung erneuernUpdate Node Numbering miscdialogs>Datei&verschlüsselung verwendenUse file &encryption miscdialogsAnsichtView miscdialogsAnsicht Menü View Menu miscdialogs*Nach was wird gesuchtWhat to Search miscdialogs"Was wird sortiert What to Sort miscdialogs0Was soll erneuert werdenWhat to Update miscdialogsFensterWindow miscdialogsFenster Menü Window Menu miscdialogsFLeere Passwörter sind nicht erlaubt'Zero-length passwords are not permitted miscdialogs[Alle Felder] [All Fields] miscdialogs[Alle Typen] [All Types] miscdialogsNameName nodeformat^Aktiviere den Daten Editor bei schwebender Maus$Activate data editors on mouse hoveroptiondefaultsAussehen Appearanceoptiondefaults.Automatisches Speichern Auto SaveoptiondefaultsZDie zuletzt benutzte Datei automatisch öffnen!Automatically open last file usedoptiondefaults^Einrückung für Kinder (In Schriftart Einheiten)+Child indent offset (in font height units) optiondefaults>Klick auf Knoten zum UmbenennenClick node to renameoptiondefaults<Formate im BearbeitungsfensterData Editor Formatsoptiondefaults"DatumsdarstellungDatesoptiondefaults*Verfügbare FunktionenFeatures Availableoptiondefaults Erster WochentagFirst day of weekoptiondefaultsFreitagFridayoptiondefaultshDruckoptimierte TreeLine JSON Dateien mit Einrückung)Indent (pretty print) TreeLine JSON filesoptiondefaultsrBegrenzung der Höhe des Dateneditors auf die Fenstergröße'Limit data editor height to window sizeoptiondefaultsLMinimiere Programm in die Systemleiste#Minimize application to system trayoptiondefaultsjMinuten zwischen Speichervorgängen (0 für Abschalten)+Minutes between saves (set to 0 to disable)optiondefaults MontagMondayoptiondefaultsBAnzahl zuletzt geöffneter Dateien(Number of recent files in the file menuoptiondefaultsPAnzahl der möglichen WiederherstellungenNumber of undo levelsoptiondefaults<Öffne Dateien in neuem FensterOpen files in new windowsoptiondefaults2Zuletzt geöffnete Dateien Recent FilesoptiondefaultslLösche alle nicht vorhandenen aktuellen Datei-Einträge'Remove inaccessible recent file entriesoptiondefaultsNNeue Knoten nach dem Anlegen umbenennenRename new nodes when createdoptiondefaultsDFenstereinteilung wiederherstellen Restore previous window geometryoptiondefaultstBaumansicht von kürzlich geöffneten Dateien wierherstellen(Restore tree view states of recent filesoptiondefaultsSamstagSaturdayoptiondefaultsDZeige Breadcrumb Vorfahren AnsichtShow breadcrumb ancestor viewoptiondefaultsXZeige Kind Ausschnitt in der rechten Ansicht#Show child pane in right hand viewsoptiondefaultsFUnterknoten in der Ansicht anzeigenShow descendants in output viewoptiondefaultsBIcons in der Baumansicht anzeigenShow icons in the tree viewoptiondefaultsfMathematische Felder im Bearbeiten Fenster anzeigen&Show math fields in the Data Edit viewoptiondefaultsdNummerierungsfelder im Bearbeiten Fenster anzeigen+Show numbering fields in the Data Edit viewoptiondefaultsProgrammstartStartup ConditionoptiondefaultsSonntagSundayoptiondefaultsDonnerstagThursdayoptiondefaultsZeitdarstellungTimesoptiondefaultsXVerschieben von Bäumen mit der Maus erlaubenTree drag && drop availableoptiondefaultsDienstagTuesdayoptiondefaults@Speicher für Wiederherstellungen Undo MemoryoptiondefaultsMittwoch Wednesdayoptiondefaults&Abbrechen&Canceloptions&OK&OKoptions2Ablage Konfigurationsfile"Choose configuration file locationoptionsVProgrammverzeichnis (für portablen Einsatz)$Program directory (for portable use)options>Benutzerverzeichnis (empfohlen)#User's home directory (recommended)optionsNFehler beim Initialisieren des DruckersError initializing printer printdata4TreeLine - PDF ExportierenTreeLine - Export PDF printdataìWarnung: Randeinstellung werden vom derzeitigen Drucker nicht unterstützt. Sollen die Einstellungen berichtigt werden?JWarning: Margin settings unsupported on current printer. Save adjustments? printdata Warnung: Seitengröße und Randeinstellung werden vom derzeitigen Drucker nicht unterstützt. Sollen die Einstellungen berichtigt werden?]Warning: Page size and margin settings unsupported on current printer. Save page adjustments? printdataäWarnung: Seitengröße werden vom derzeitigen Drucker nicht unterstützt. Sollen die Einstellungen berichtigt werden?KWarning: Page size setting unsupported on current printer. Save adjustment? printdata&Unten:&Bottom: printdialogs&Abbrechen&Cancel printdialogs<Linien zu den Kindern zeichnen&Draw lines to children printdialogsGesamter Baum &Entire tree printdialogs&Schriftart&Font printdialogsSchrift&auswahl&Font Selection printdialogs2Allgemeine &Einstellungen&General Options printdialogs Kopfzeile &Links &Header Left printdialogs&Kopf-/Fußzeile&Header/Footer printdialogs2Wurzelelement hinzunehmen&Include root node printdialogs|Das erste Unterelement mit dem Elternelement zusammen anzeigen&Keep first child with parent printdialogs&Links:&Left: printdialogsSpaltenanzahl&Number of columns printdialogs&OK&OK printdialogsPräfi&x&Prefix printdialogs&Drucken... &Print... printdialogs&Rechts:&Right: printdialogs&Suffix&Suffix printdialogs &Oben:&Top: printdialogs&Einheiten&Units printdialogsL&TreeLine Ausgabe Schriftart verwenden&Use TreeLine output view font printdialogs&Breite:&Width: printdialogs"A3 (279 × 420 mm)A3 (279 x 420 mm) printdialogs"A4 (210 × 297 mm)A4 (210 x 297 mm) printdialogs"A5 (148 × 210 mm)A5 (148 x 210 mm) printdialogs>AaBbCcDcEeFfGg...TtUuVvWwXxYyZzAaBbCcDdEeFfGg...TtUuVvWvXxYyZz printdialogsZentimeter (cm)Centimeters (cm) printdialogsSpaltenColumns printdialogs0Benutzerdefinierte Größe Custom Size printdialogs&standard Schriftart Default Font printdialogsfFehler: Seitengröße oder Seitenränder sind ungültig(Error: Page size or margins are invalid printdialogsExtratext Extra Text printdialogs0Gegenüberliegende Seiten Facing Pages printdialogsEigenschaftenFeatures printdialogs FelderFiel&ds printdialogsFeldf&ormat Field For&mat printdialogs(Feldformat für "{0}"Field Format for "{0}" printdialogsSeite anpassenFit Page printdialogsBreite anpassen Fit Width printdialogsSchrifts&til Font st&yle printdialogs&Fußzeile:Foot&er: printdialogs&Fußzeile Links Footer &Left printdialogsFußzeile M&itteFooter Ce&nter printdialogs"Fusszeile &Rechts Footer Righ&t printdialogs,&Hilfe zu den Formaten Format &Help printdialogs&Kopfzeile:He&ader: printdialogs"Kopfzeile &Rechts Header &Right printdialogs Kopfzeile Mitt&eHeader C&enter printdialogs$Kopf- und FußzeileHeader and Footer printdialogs &Höhe:Height: printdialogsInch (in) Inches (in) printdialogs,Berücksichtigte KnotenIncluded Nodes printdialogsEinrückenIndent printdialogsVAbstand beim Einrücken (Einheit Zeilenhöhe)"Indent Offse&t (line height units) printdialogs&Querformat Lan&dscape printdialogs*Legal (8.5 × 14 Inch)Legal (8.5 x 14 in.) printdialogs,Letter (8.5 × 11 Inch)Letter (8.5 x 11 in.) printdialogs RänderMargins printdialogsMillimeter (mm)Millimeters (mm) printdialogsNächste Seite Next Page printdialogs@Nur Kinder von geöffneten KnotenOnl&y open node children printdialogsOrientierung Orientation printdialogsAusgabeformatOutput &Format printdialogs&Seiteneinstellungen Page &Setup printdialogsPapiergröße Paper &Size printdialogs&Hochformat Portra&it printdialogsVorherige Seite Previous Page printdialogsDruckenPrint printdialogs"Druck&vorschau...Print Pre&view... printdialogsDruckvorschau Print Preview printdialogs$Druckeinstellungen Print Setup printdialogs$DruckeinstellungenPrinting Setup printdialogsBeispielSample printdialogsWähle &DruckerSelect &Printer printdialogs(Schriftart auswählen Select Font printdialogs*Ausgewählte TeilbäumeSelected &branches printdialogs$Ausgewählte KnotenSelected &nodes printdialogs &GrößeSi&ze printdialogsEinzelne Seite Single Page printdialogs2Abstand zwischen &SpaltenSpace between colu&mns printdialogs,Tabloid (11 × 17 Inch)Tabloid (11 x 17 in.) printdialogs(TreeLine PDF DruckerTreeLine PDF Printer printdialogs"Was wird gedruckt What to print printdialogsVergrößernZoom In printdialogsVerkleinernZoom Out printdialogs&Hinzufügen&Add spellcheck&Abbrechen&Cancel spellcheck"&Alles Ignorieren &Ignore All spellcheck&Ersetzen&Replace spellcheck<Hinzufügen in &KleinbuchstabenAdd &Lowercase spellcheckKontext:Context: spellcheckžKann weder aspell.exe, ispell.exe oder hunspell.exe finden. Speicherort suchen?QCould not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? spellcheckŠRechtschreibprüfung für den Zweig beendet. Wieder von oben anfangen? 3Finished checking the branch Continue from the top? spellcheck6Rechtschreibprüfung beendetFinished spell checking spellcheck&IgnorierenIgnor&e spellcheck\Suche aspell.exe, ispell.exe oder hunspell.exe-Locate aspell.exe, ipsell.exe or hunspell.exe spellcheck&Nicht im WörterbuchNot in Dictionary spellcheck Programm (*.exe)Program (*.exe) spellcheckAlles E&rsetzen Re&place All spellcheck&Rechtschreibprüfung Spell Check spellcheckBFehler in der RechtschreibprüfungSpell Check Error spellcheckVorschläge Suggestions spellcheck8TreeLine RechtschreibprüfungTreeLine Spell Check spellcheckÔFehler bei der Rechtschreibprüfung. Stellen Sie sicher, dass aspell, ispell oder hunspell installiert istLTreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed spellcheck Wort:Word: spellcheckAuswahl im BaumSelect in Tree titlelistview KugelnBullets treeformatsKinderTyp ChildType treeformatsunfinishedChildTypeLimit treeformatsBedingungenConditionalRule treeformatsSTANDARDDEFAULT treeformatsunfinishedEvalHtml treeformatsFELDFIELD treeformats DATEIFILE treeformatsFELDTYP FieldType treeformatsFormat">FormatFormat treeformatsHTML-Format FormatHtml treeformatsGenerischerTyp GenericType treeformatsIcon">IconIcon treeformatsAnfangswert InitialValue treeformats$ListenTrennzeichen ListSeparator treeformats$ZeilennummerierungNumLines treeformatsAusgabeformat OutputFormat treeformats PrefixPrefix treeformats$AufwärtsSortierten SortForward treeformats Sortierschlüssel SortKeyNum treeformatsZwischenraum SpaceBetween treeformats SuffixSuffix treeformatsTYPTYPE treeformatsTabelleTable treeformatsTitelformat TitleFormat treeformats&Fettschrift &Bold Fonttreelocalcontrol&Kopieren&CopytreelocalcontrolKnoten &löschen &Delete NodetreelocalcontrolTrenne Klone&Detach Clonestreelocalcontrol&Exportieren... &Export...treelocalcontrol(&Externer Verweis...&External Link...treelocalcontrol"&Schriftart Größe &Font Sizetreelocalcontrol"Knoten &einrücken &Indent Nodetreelocalcontrol&Kursivschrift &Italic Fonttreelocalcontrol,Nach &oben verschieben&Move Uptreelocalcontrol&Neues Fenster &New WindowtreelocalcontrolEin&fügen&Pastetreelocalcontrol&Drucken... &Print...treelocalcontrol"W&iederherstellen&Redotreelocalcontrol*Erstelle Verweise neu&Regenerate Referencestreelocalcontrol&Umbenennen&RenametreelocalcontrolS&peichern&Savetreelocalcontrol&Knoten&typ zuweisen&Set Node Typetreelocalcontrol.&Rechtschreibprüfung...&Spell Check...treelocalcontrol&Rückgängig&Undotreelocalcontrol"Knoten &ausrücken&Unindent Nodetreelocalcontrol &Kind hinzufügen Add &ChildtreelocalcontrolLKategorie &Hierarchieebene einfügen...Add Category &Level...treelocalcontrolRNeues Kind zu aktuellem Knoten hinzufügen Add new child to selected parenttreelocalcontrolZEinen externen Verweis hinzufügen oder ändern!Add or modify an extrnal web linktreelocalcontrolNInternen Verweis ändern oder hinzufügen#Add or modify an internal node linktreelocalcontrolxOhne gemeinsame Felder kann der Baum nicht expandiert werden#Cannot expand without common fieldstreelocalcontrolKategoriefelderCategory Fieldstreelocalcontrol.&Formatierung entfernenClear For&mattingtreelocalcontrol|Die Formatierung am aktuellen oder selektierten Text entfernen)Clear current or selected text formattingtreelocalcontrol8Klone alle &passenden KnotenClone All &Matched NodestreelocalcontrolRKinder zusammenfassen und Felder vereinen&Collapse descendants by merging fieldstreelocalcontrolTKonvertiere alle passenden Knoten in Klone&Convert all matching nodes into clonestreelocalcontrol>{0} Zweige in Klone konvertiert"Converted {0} branches into clonestreelocalcontrol8Typen aus &Datei kopieren...Copy Types from &File...treelocalcontrolrDen Teilbaum oder den Text in die Zwischenablage kopieren(Copy the branch or text to the clipboardtreelocalcontrolrKonfiguration aus einer anderen TreeLine-Datei übernehmen1Copy the configuration from another TreeLine filetreelocalcontrol&AusschneidenCu&ttreelocalcontrol†Den Teilbaum oder Text ausschneiden und in die Zwischenablage legen'Cut the branch or text to the clipboardtreelocalcontrolStandardDefaulttreelocalcontrol>Die ausgewählten Knoten löschenDelete the selected nodestreelocalcontrolVTrenne alle Klone Knoten im aktuellen Zweig+Detach all cloned nodes in current branchestreelocalcontrol^Fehler: Kann Sicherheitskopie {0} nicht löschen'Error - could not delete backup file {}treelocalcontrolJFehler - Konnte Datei {0} nicht lesenError - could not read file {0}treelocalcontrolRFehler - konnte nicht auf Datei schreibenError - could not write to filetreelocalcontrolPFehler - konnte nicht nach {0} schreibenError - could not write to {}treelocalcontrolfDie Datei in unterschiedlichen Formaten exportieren(Export the file in various other formatstreelocalcontrol`Nach PDF mit aktuellen Druckoptionen exportieren+Export to PDF with current printing optionstreelocalcontrol"Datei gespeichert File savedtreelocalcontrol2&Abflachen nach KategorieFlatten &by Categorytreelocalcontrol(Schriftart &Farbe...Font C&olor...treelocalcontrolœErzwinge Aktualisierung alle konditonalen Bedingungen & Mathematischen Feldern3Force update of all conditional types & math fieldstreelocalcontrolBDie ausgewählten Knoten einrückenIndent the selected nodestreelocalcontrol&Datum einfügen Insert &DatetreelocalcontrolF&Nach ausgewähltem Element einfügenInsert Sibling &AftertreelocalcontrolD&Vor ausgewähltem Element einfügenInsert Sibling &Beforetreelocalcontrol`Kategorieebene oberhalb der Unterknoten einfügen$Insert category nodes above childrentreelocalcontrolBAktuelles Datum als Text einfügenInsert current date as texttreelocalcontrolpEin neues Element nach dem ausgewählten Element einfügen"Insert new sibling after selectiontreelocalcontrolnEin neues Element vor dem ausgewählten Element einfügen#Insert new sibling before selectiontreelocalcontrol(&Interner Verweis...Internal &Link...treelocalcontrolGroßLargetreelocalcontrol GrößerLargertreelocalcontrolAm GrößtenLargesttreelocalcontrol.Nach &unten verschieben M&ove Downtreelocalcontrol,Zum Anfang verschieben Move &Firsttreelocalcontrol(Zum Ende verschieben Move &Lasttreelocalcontrol\Die ausgewählten Knoten nach unten verschiebenMove the selected nodes downtreelocalcontroljDas ausgewählte Knoten als erstes Unterelement setzen0Move the selected nodes to be the first childrentreelocalcontrollDas ausgewählte Knoten als letztes Unterelement setzen/Move the selected nodes to be the last childrentreelocalcontrolZDie ausgewählten Knoten nach oben verschiebenMove the selected nodes uptreelocalcontrolBKeine identischen Knoten gefundenNo identical nodes foundtreelocalcontrolTNeues Fenster für die gleiche Datei öffnen#Open a new window for the same filetreelocalcontrol,&Drucken einrichten...P&rint Setup...treelocalcontrol$Nu&r Text einfügenPa&ste Plain Texttreelocalcontrol(Kind Knoten einfügen Paste C&hildtreelocalcontrol<Füge geklonten Kind Knoten einPaste Cl&oned ChildtreelocalcontrolZFüge geklo&nten Geschwwister Knoten davor einPaste Clo&ned Sibling BeforetreelocalcontrolZFüge geklonten Geschwister Knoten &danach einPaste Clone&d Sibling AftertreelocalcontrolBFüge Geschwister Knoten d&ahinterPaste Sibling &Aftertreelocalcontrol<Füge Geschwister Knoten &davorPaste Sibling &BeforetreelocalcontroljFüge geklonten Kind Knoten von der Zwischenablage ein&Paste a child clone from the clipboardtreelocalcontrolVKind Knoten von der Zwischenablage einfügen%Paste a child node from the clipboardtreelocalcontrolTFüge Geschwister Knoten hinter Auswahl einPaste a sibling after selectiontreelocalcontrolNFüge Geschwister Knoten vor Auswahl ein Paste a sibling before selectiontreelocalcontrolbFüge Geschwister Knoten Klon nach der Auswahl ein%Paste a sibling clone after selectiontreelocalcontrol`Füge Geschwister Knoten Klon vor der Auswahl ein&Paste a sibling clone before selectiontreelocalcontrol`Knoten oder Text von der Zwischenablage einfügen&Paste nodes or text from the clipboardtreelocalcontrolfUnformatierten Text von der Zwischenablage einfügen+Paste non-formatted text from the clipboardtreelocalcontrol(Nach &PDF drucken...Print &to PDF...treelocalcontrol"Druck&vorschau...Print Pre&view...treelocalcontroldBaum basierend auf aktuellen Einstellungen drucken*Print tree output based on current optionstreelocalcontrol"&Eigenschaften...Prop&erties...treelocalcontrolDDie letzte Aktion wiederherstellenRedo the previous undotreelocalcontrolLDen Titel des aktuellen Knotens ändern#Rename the current tree entry titletreelocalcontrol.Tausche Kategorie EbeneS&wap Category Levelstreelocalcontrol&Speichern &unter... Save &As...treelocalcontrolDatei speichern Save Filetreelocalcontrol<Änderungen an {0} abspeichern?Save changes to {}?treelocalcontrol.Änderungen abspeichern? Save changes?treelocalcontrol0Aktuelle Datei speichernSave the current filetreelocalcontrolVDie Datei unter einem neuen Namen speichernSave the file with a new nametreelocalcontrolFFelder für die neue Ebene auswählenSelect fields for new leveltreelocalcontrol.Schriftart Größe setzen Set Font Sizetreelocalcontrol$Knotentyp zuweisen Set Node Typetreelocalcontrol‚Datei Eigenschaften wie Komprimierung oder Verschlüsselung setzen3Set file parameters like compression and encryptiontreelocalcontrolbRänder, Seitengröße und andere Druckeinstellungen1Set margins, page size and other printing optionstreelocalcontrolvDie Größe der aktuellen oder selektierten Schriftart setzen(Set size of the current or selected texttreelocalcontrolvDie Farbe der aktuellen oder ausgewählten Schriftart setzen-Set the color of the current or selected texttreelocalcontroltDie aktuelle oder ausgewählte Schriftart auf "fett" setzen(Set the current or selected font to boldtreelocalcontrolxDie aktuelle oder ausgewählte Schriftart auf "kursiv" setzen*Set the current or selected font to italictreelocalcontrolˆDie aktuelle oder ausgewählte Schriftart auf "unterstreichen" setzen-Set the current or selected font to underlinetreelocalcontrolTDen Typ für den ausgewählten Knoten setzen$Set the node type for selected nodestreelocalcontrolJVorschau der Druckergebnisse anzeigen"Show a preview of printing resultstreelocalcontrol KleinSmalltreelocalcontrol8Rechtschreibprüfung für Text Spell check the tree's text datatreelocalcontrolNTausche Kind und Enkel Kategorie Knoten(Swap child and grandchild category nodestreelocalcontrolPTreeLine - Konfigurationsdatei schreiben"TreeLine - Open Configuration Filetreelocalcontrol4TreeLine - Speichern unterTreeLine - Save Astreelocalcontrol&UnterstreichenU&nderline FonttreelocalcontrolFDie letzte Aktion rückgängig machenUndo the previous actiontreelocalcontrol–Die ausgewählten Knoten "ausrücken" (um eine Ebene nach links verschieben) Unindent the selected nodestreelocalcontrol¬Warnung - Datei Fehler! Überspringe fehlerhafte Kind Verweise in den folgenden Knoten:OWarning - file corruption! Skipped bad child references in the following nodes:treelocalcontrol"Über &TreeLine...&About TreeLine...treemaincontrol6&Grundlegende Verwendung...&Basic Usage...treemaincontrol.Datei öffnen &abbrechen&Cancel File Opentreemaincontrol(&Bedingtes Suchen...&Conditional Find...treemaincontrol8&Datentypen konfigurieren...&Configure Data Types...treemaincontrol0Sicherungskopie &löschen&Delete Backuptreemaincontrol&Suche Text... &Find Text...treemaincontrol8&Umfassende Dokumentation...&Full Documentation...treemaincontrol8Allgemeine &Einstellungen...&General Options...treemaincontrol&Importieren... &Import...treemaincontrol&Neu...&New...treemaincontrol&Öffnen...&Open...treemaincontrol&Beenden&QuittreemaincontrolBSicherungskopie &wiederherstellen&Restore Backuptreemaincontrol &Alles auswählen &Select Alltreemaincontrol&&Beispiel auswählen&Select Sampletreemaincontrol &Vorlagenauswahl&Select Templatetreemaincontrol&Textfilter...&Text Filter...treemaincontrol¦Sicherheitskopie {} existiert. Eine vorherige Sitzung ist möglicherweise abgestürztEine nicht TreeLine Datei ladenOpen a non-TreeLine filetreemaincontrol2Eine Beispieldatei öffnenOpen a sample filetreemaincontrol.Text in Knoten ersetzen!Replace text strings in node datatreemaincontrolBGesamten Text im Editor auswählenSelect all text in an editortreemaincontrol@&Tastaturkürzel konfigurieren...Set &Keyboard Shortcuts...treemaincontrolLBenutzereinstellungen für alle Dateien"Set user preferences for all filestreemaincontrol@Zeige Struktur der Konfiguration Show C&onfiguration Structure...treemaincontrolbZeige nur-lesende Visualisierung der Typ Struktur.Show read-only visualization of type structuretreemaincontrol(Knoten&sortierung...Sor&t Nodes...treemaincontrol,Eine neue Datei öffnenStart a new filetreemaincontrol.TreeLine - Datei ÖffnenTreeLine - Open Filetreemaincontrol@TreeLine grundlegende VerwendungTreeLine Basic Usagetreemaincontrol(TreeLine Version {0}TreeLine version {0}treemaincontrol2&Nummerierung anpassen...Update &Numbering...treemaincontrol2Die Nummerierung anpassenUpdate node numbering fieldstreemaincontrolDFeldbasierte Bedingungen verwenden$Use field conditions to filter nodestreemaincontrollFeldbasierte Bedingungen verwenden um Knoten zu finden"Use field conditions to find nodestreemaincontrolVWarnung - Socket kann nicht geöffnet werden'Warning: Could not create local sockettreemaincontrol*fehlendes Verzeichnismissing directorytreemaincontrol&geschrieben von {0}written by {0}treemaincontrolNeuNewtreenodeHauptprogrammMain treestructurePBedingtes Filter hat {0} Knoten gefunden&Conditional filtering, found {0} nodestreeviewJFiltern nach {0}, {1} Knoten gefunden#Filtering by "{0}", found {1} nodestreeviewNächste: {0} Next: {0}treeview:Nächste: {0} (nicht gefunden)Next: {0} (not found)treeviewSuche nach: Search for:treeviewSuche nach: {0}Search for: {0}treeview@Suche nach: {0} (nicht gefunden)Search for: {0} (not found)treeview$Fenster &schließen &Close Window treewindow@Teilbaum vollständig &einklappen&Collapse Full Branch treewindow Da&ten&Data treewindow&Bearbeiten&Edit treewindowBTeilbaum vollständig &expandieren&Expand Full Branch treewindow &Datei&File treewindow &Hilfe&Help treewindow*&Nachfolgende Auswahl&Next Selection treewindow&Knoten&Node treewindow$&Vorherige Auswahl&Previous Selection treewindow(&Kinder mit anzeigen&Show Child Pane treewindow&Extras&Tools treewindow&Ansicht&View treewindow&Fenster&Window treewindow0Dieses Fenster schließenClose this window treewindow\Alle Kinder der selektierten Knoten einklappen+Collapse all children of the selected nodes treewindow Datenbearbeitung Data Edit treewindowDatenansicht Data Output treewindow^Alle Kinder der selektierten Knoten expandieren)Expand all children of the selected nodes treewindowFo&rmatFo&rmat treewindowPDie folgende Selektion wieder aktivieren(Go to the next tree selection in history treewindow6Nächste inkrementelle SucheNext Incremental Search treewindow:Vorherige inkrementelle SuchePrevious Incremental Search treewindowPZu der vorherigen Selektion zurückkehren%Return to the previous tree selection treewindow2Zeige &Breadcrumb AnsichtShow &Breadcrumb View treewindow6&Überschriftsliste anzeigenShow &Title List treewindow Edit&or anzeigenShow Data &Editor treewindow"&Ansicht anzeigenShow Data &Output treewindowDKinder in der Ausgabe mit anzeigenShow Output &Descendants treewindow`Den Editor in der rechten Fensterhälfte anzeigenShow data editor in right view treewindownDie Daten-Ansicht in der rechten Fensterhälfte anzeigenShow data output in right view treewindowzDie Überschriften-Liste in der rechten Fensterhälfte anzeigenShow title list in right view treewindow4Starte inkrementelle SucheStart Incremental Search treewindow"Überschriftsliste Title List treewindowTUmschalten zu Breadcrumb Vorfahren Ansicht'Toggle showing breadcrumb ancestor view treewindowfDie Kunde in der Ausgabeansicht eingerückt anzeigen/Toggle showing output view indented descendants treewindowZDie Kinder in der Ausgabeansicht mit anzeigen%Toggle showing right-hand child views treewindowˆTreeLine-3.2.1/translations/treeline_es.qm000066400000000000000000003051471506556630100206230ustar00rootroot00000000000000<¸dÊÍ!¿`¡½Ý§esBHO|Mbd+;6+;F+; 9+;CL+;—b+;Ò«+;Ý–TÇZñUgq^W6xÌ\>zÒg¤1DhDÈmÔ6 xÆ<ÄÃ|§§¤ôÍÎe §Ô !¨¡£™¨¥ež®ýO»¤~Ð%§*ÐD¨�ì0«1ú^ú^ýð0KŒU7þ[8¨nH5 ¨H5À U¥°MVE Ùc s"žEþ¬ôxõ¬ô�R°5y#¹µEÀe/­Ïǽ%0KHù¹µ|r™ÇîææÄr27~;ƒ&ñ²p¢*‡›�*¦yþ‰*¨¡^À*»^ð*Ð%_€*ÖTÚ†*ÙJ†*ì0_´*ö5�è+5t+U¥`:+‹¯ï+Œ=f+˜Å¹+˜ÅÐ+¬ôMV+¶:Þª+įÓ+ÏÇaP/5&+5S4P;0®&¡”ã}m·›”¥$›¡$³ Ì¡fE3„¡·õ3¢â3Mf¯EBr°J…Tµ¼GUMƒË ½ÎÏ‹yànЄÛjÆÔBsX¹ÖîÕÃØ1d6pÞ7àùµ(�áSÃ1Aáh:�lè9:7Ãð­§a²ò8ÞQÉõõýAæQ Y –�e#˜”/0Š1ØõP 4FTô4MÓ>52{[B"ýPE¹%„H*aLWà*Lûeôžó‰f`‡/`j.v?o‡t¤ |{yàÂ~s”¦B~âõ€„B6Ûm˜õ„䂞œw÷b¦œVÿ©ªKú©­/^h±¯Äáµ½‡K¶b.ÂøÃ¯ Çî÷?Ï×M® M×½«PuÜ·”"ÝŠ¥ Öâ N9…ïQ„³ø/Ú¤³cD¡£ !‘ ùh1 eº'U _(î•OY)yNý-ÿd9/c5ñÑ2ßt oO�¥ÈPÕ‡ÍÝU¿iá”cÔÚáf}4þJl¿Þe½m‘³¡yn·�6“r jÂsáó6 uwU§\y¨Ä\Í}X=+↯“4I‡¦eA‘ˆÜô2ŽH˜dבªSªa—=0V¢'³›¨w9˨w9”¡ª6•*ª6••­–Dv°7ÃÛ°gc"ó²½zݲ×ÃL¤¶Š¥r¸ÉÄ ›º3 ì»f3a¼P³Þà½[yàÀ´&õÂæwiÒðMŠÔÝC=$×(¡Öáònٻﶰí.ñí~)Óö}¯8óøåséFùeÔ¿üy°*üy°ç)ÿ3ò|cm ßÄ/%v•«_-„å'@6n�‰ž6n�,6n�FŠ;Y \Â=Öã}>í6nIGsLRŽ5º._ Òúc®á ÀgÎ@lx?™ÅÍ|Œ÷§#«ßϳ¦øÐ:¨^ÐGà�IÖ“„©°Ö“„ý¼Øú‰Äèæþ¢“æþ¢•Dço^šìÝ.Úºí¨TóAU`¼ü ’œýx5y§¼¤!U¬Té“î ¤.W_<¯T¨åZ&=ôbü(�Âó+ƒô$î5€´Ün6a²ð>>?d @B“ó@{§hoFJ‰Ç%\8Âq‹`}î@ÒfÈ4·£gNehŒTXþh�‰Ñ¾r…c”ƒÕ3ªžƒð};N„`Rm�òc]�‘³µV9—þ6¸˜G%ð ™ì5G?šÒc^ŸN¢ ެJ‰Ð>­ìÔ?l´§TY™¹(N¼’.Ú½¥•$ì¿kµâÂ+%OÆ"D¥Í1Ï‘ÂäÒÏÄ®¼ÖeT+–ל©I_שD/Ø™ÉTçÜÇ::ßßëÅàKg¾ZàѲçkH^bè°Ôµaõ÷&õSåUÓþ!žìŸÿîm{ÿîm¿¾Nsúœtád­0Æ[�ïFѤßcyD~n9#Uä‡Z#ÂCOC#ÂC‡#&Ã$Ž*”¾Ñ,ô;ã.ýÓC„/œ´/œ´‚/œ´¨À0Ä´à?ÃÔIn38L½„ öRüS·òS"þ”.ZzóíZËÚõG]¶¨åˆ_PÔóËb£#šÄe,Å´›fÅÎO½fÈŠæg섵l¾=(r^¤*ø�PÄìá‚h�m^ƒn×k ŒZQ�«Ië–Ti* 1r¦~©ê¨­º|ôw°Ï¥4žºÓYÓ¼ÀãÌ¿Ç.€ßÇ.€®ÈÇR� eË@徎Ë˃¯‰Ψê'ˆÚéHà7iò€áeÓ4ã7ÒpIê_ΜLïÿEžñ>t[óÙd(ú¼ÕsÕþ¸4%‹YKÌ.ƒ­ð&k³ o&�tEë(m3K)õãk¯/ð®†0nd7O«b`8OªaýCÎd‚¬P[ "R£9NÁSU“4ÏUô³ly]1³[h¨¿a¡kÝþÿ_káN<¥n™óY*n™óµèn™óðêp˜jS{ìÒºÎ}\”'ƒ¼n#©‡£oƒRŒá÷–ãXF —N:£¢ˆu‹èª/…ôø«ŒãD½«—âB"¶ ÷¿ç[F*ǨºçxË›ô¢Ï”âqÐOãÈ}ÕeQè"u� ë»EåÐô3¤¤ïõãXùö§^J“üfO{ïų\Mª¯*Õ ä=Þ'Îa®_"¥ÂÔŸ*Se©ä,á0=›1cD½1cDãi9Hù„H@ÍE…TFy¢ˆL¶C~ùWšÅ1±Yí�|[Ú%{§]!¼Íbùbòân•#m��£J±‚ „#³‡×9Z>ŠéciŠéc‚aŠéc© �¤“"²–¼žB˜HnÖšjTüÝžz_Ö¤£Â©Æk¤¢M�%¦*)w‹ª¬•eÌ·9³Ý=·áo4Ó¸†ž.ºå^®¼ „#`¼�ÌÇ%%˜VÇ%%ô»Èx[ṙµ2.ÌÉå<òÌË%™£ÔUåWÔ¤?vžÞ¹èdß‚¥ƒß—eþÁévÔæãéâÙvë+™„Öð½^±Xþm“ þÒ·‡Ä �Õ ó Í¿n \~Ýø \~© ;´9K q#- !í„; 4‰EŠÉ 5µ :ró´K Fè´âÈ LìóD! Mgþl f+>cá k¸ªÙJ †�£³ˆ ¦8ÕD… ¨ %ñ ©Ï‰‘b ¬\eJ ¯b݆­ ±›“¬T ²b*»Š ¸ldíØ ¼ „x„ ¿ß¡z ÀªH— Á UÛ Áí]© ØøÜÌ Ûʵ1ú ê�thø êØnb î�åPì ñž‹Z øééÈ ÿ Õj ÿŽÚ]3 cY¹} �vß ­“&ô .ƒ’· ïît ¾TÐ Êö� ÝW75 ,_$1ê /öÄ5F 4ñ„b¶ 5rÕ£Ç 7*å< =äðš IöT`à Ty ë› UÇÌI Wܾ8· _Ò‰)I a‹ cÂóI) cÄáå eÄ 8 uo°Ç uõ5 w5— �ă_' ‚ò5EÎ ‡1Ï �É3~• “¼:±¯ ˜Iœ ˜Iœñ ˜Iœ ˜IœBÊ ˜Iœ”× ˜IœÒv ˜IœÙ� ˜Iœô? �Cr� �8rÀ: ŸÉ9d` ¤ ( «¦ø ¬,…^ ¬6"AZ ®5ÕV¡ ®ùµ'ß ¯Þ6T ²Ê^ ð µ�Iø¸ µãã>  ¶ã 5 ¼Œt ö ¼Ëˆ* ĽN:; Ë;:¼ ÍGc$H Ð:âÞ Ð:â•Õ ÛãµJB Û㵕‹ ÛãµÚ; Þ;±QÐ Þä5z ðe3¸› òóÈ«œ ü˜Žî” ü˜Ž&„ ÿôÅ>³ s­ ½.—ÿ ÐÁD t™× X½ˆ çKE… )M¥! -ˆ8ˆ .2,# /.”Ê 2 ή 5�…5r 9²3) @(e¾ A¨lÜ KsGs Kºþ(Ì L¡.<ë LÇ9Ò8 WÌè% X± [tfÇ pI3} rËW�‰ x½( c x½(ÝÀ {uÅ[; :3.A € Í“% €Ùs–â ‹Ìä ŒH� �õÁ �Ü ! �Ü > �ßZÞ: ›i³[S ›€>$ ªDÄLæ «Í(Þt ¯–]o+ ±à„MÔ ´¹gè ¹D)à ¹¾´fq ¼BÓ ¼~Ó7+ ¼šÙш Ït®²£ Ù·åî ߺšßà àKGa| á²~9Ô ã\E%› ëÜiG ëù^$M óy~c ó²:ã vÕ�ú §éé Óì[ë šEN^ áE= š+Cu PÔ ¼%Ä Ö#=’ Qôç¹ l”gÊ ¿�d '{íÀ (µEG * •ý� 2l$ 7±"-� 8Ç‘q½ ;y:¤ =ÙÓ! @|5™ @¿ÀÂ6 Vÿõ>Y dMi· gÆ#3÷ n¾/Ø pk¾x t—¥*# t©Ž&J tÁ�uÔ v"¾ a {Bœ¥ ˆ=ÎL1 ‰¡ãD´ ”ËeN •h¥½O —M¥^Ÿ ŸèTóC ¡žRù ¡ô×¼^ £î,© ®�C- »²4›¹ ¼°eêm Æm)Óv Ò¯ãWÉ Þv¥ÐÞ ãbnbû ê¬DA´ ëU(¹ îµÕ/ ðYƒúi ûìóäL þÖ\³< -ŸÕ| …‹F» “Äcò 'Ü‘õ .�“[ì 0³uOz 0ó£Ž 7yÒ9 CàÒGà G9.i H³³3m Kz9† Kè„I^ MîÄ¡ Nðh¤ ]`^g} _ t¯ dT� iØä5è iÚ$�¯ iÚ$–V zÿíG €¢J ƒÄ2ÛÀ އij ‘݃㲠œ|õC¹ £ö=2f «c*j ˜SÉR ÇD〹 ÌÈT# ×sO ä~tž í>Ó¶B ûîs¢Ì ÿ»:fÆûÇ·Ézû ¼eIcÅê"T`‡»¸6‡»ù³¾s·­sV¢(t�ª'(·©{Q-þ·K/+ãi0ó/aS0ô>a9ÄóO= %BEj;H;Ó}ýL`Òg(L¿Ó� LÊã|ÍLÝ^_äV�8 Y‚—i­Zrþÿ¦h€jºi?ÃÿkŽ·jlfcCp#GÀq¢ƒ“t޶¥t/C}~D³Bw† …§þ�^A4B™Ï-rÓš¥tÁ˜£±…©Z­–fO²šbè ¹ë xº”t2¿ß:èÊÉk~?Ì-î½Í`EoÔ•³È Õ�ý]iÚYe0ùà˜9Œ�êhÃyë ÃëœtÛiîpšxþVC£#ã°y`ÍUÕSw;>`h‚ “—Kc wšRæš(üÓJ÷6ãÅ8 qwE<æÉù@-®*HNŽÏäIöôCMÉÕ¹U⃸Z8n?[Kôêe3ëêem3P‘iFW@®r†ÕÜs$ Xww³î|*½\€}$7^…?y,‘†AÔ Œ�ç»2�Ó�Z£�Ô²9‡–ž oò�]#�âtgˆŸ2Ikõ¢m£u¤žµHЬnçˆÕ¯#Hkˆ´êâFs¹éŸ*oº£Îì4½¡u+)À$&ÕÆ|ûÉŸ)ÐuÏ~Ä!ðÛ]>YÜííxá�o;¢áùÅ+•ãÊo_§åd…÷ÞëŠL“ôßípÿöé3‚ø6‰Ôùfîwüil÷&Cancelar&Cancelcolorset&OK&OKcolorsetColor de Tema Color Themecolorset&Añadir &Nueva Regla &Add New Rule conditional&Cancelar&Cancel conditional&Cerrar&Close conditional&Borrar&Delete conditional &Terminar filtro &End Filter conditional&Filtro&Filter conditionalCar&gar&Load conditional&OK&OK conditional&Eliminar Regla &Remove Rule conditionalGuar&dar&Save conditional FalsoFalse conditional"Buscar &Siguiente Find &Next conditional B&uscar AnteriorFind &Previous conditionalNombre:Name: conditionalTCoincidencias condicionales no encontradas!No conditional matches were found conditionalTipo de nodo Node Type conditionalRegla {0}Rule {0} conditional Reglas Guardadas Saved Rules conditionalVerdaderoTrue conditional"[Todos los tipos] [All Types] conditionalyand conditionalcontienecontains conditionaltermina con ends with conditionaloor conditionalcomienza con starts with conditional&Aplicar&Apply configdialog&Cancelar&Cancel configdialogTipo de &Datos &Data Type configdialog&Eliminar tipo &Delete Type configdialog,&Derivado del original&Derive from original configdialog&Ecuación &Equation configdialog0Configuración de &Campos &Field Config configdialogTip&o de Campo &Field Type configdialog"&Ocultar Avanzado&Hide Advanced configdialogMover Aba&jo &Move Down configdialog&Nuevo Campo... &New Field... configdialog&Nuevo Tipo... &New Type... configdialog&OK&OK configdialogP&refijo&Prefix configdialog&Reiniciar&Reset configdialog&Resultado Tipo &Result Type configdialog"&Seleccionar Todo &Select All configdialog"&Mostrar Avanzado&Show Advanced configdialog.C&riterio de Ordenación&Sort Criteria configdialog$&Formato de Título &Title Format configdialogHAgregar línea en &blanco entre nodosAdd &blank lines between nodes configdialogAñadir Campo Add Field configdialogAñadir tipoAdd Type configdialog<Añadir o Quitar Datos de TiposAdd or Remove Data Types configdialog2Agregar &viñetas al textoAdd text bullet&s configdialog^Permitir &HTML con formato de texto enriquecidoAllow &HTML rich text in format configdialog,Operadores AritméticosArithmetic Operators configdialog"Tipos AutomáticosAutomatic Types configdialog6Lista de &Campos DisponibleAvailable &Field List configdialog&Campos &DisponiblesAvailable &Fields configdialog$Resultado BooleanoBoolean Result configdialog”No se puede eliminar un tipo de datos que esté siendo usado por algún nodo+Cannot delete data type being used by nodes configdialogCambiar &Icono Change &Icon configdialog"Recuento de Hijos Child Count configdialogReferencia HijaChild Reference configdialog2Límites de los Tipos HijoChild Type Limits configdialog"Borrar &Selección Clear &Select configdialogCo&piar Tipo... Co&py Type... configdialogdCombinación && &separador lista de hijos de Salida+Combination && Child List Output &Separator configdialog.Operadores ComparativosComparison Operators configdialog2Configurar Tipos de DatosConfigure Data Types configdialogCopiar Tipo Copy Type configdialog4Crear Tipos Co&ndicionalesCreate Co&nditional Types configdialog$Resultado de Fecha Date Result configdialogH&Valor por Defecto para Nuevos NodosDefault &Value for New Nodes configdialog,Tipo Hi&jo por DefectoDefault Child &Type configdialog Definir EcuaciónDefine Equation configdialogNDefinir el Campo de Ecuación MatemáticaDefine Math Field Equation configdialog&Borrar Campo Dele&te Field configdialog6Derivado del Tipo &GenéricoDerived from &Generic Type configdialogDescripción Description configdialogDirección Direction configdialog"Altura del editor Editor Height configdialogJIntroduzca el nombre del nuevo campo:Enter new field name: configdialogBEstablecer nombre del nuevo tipo:Enter new type name: configdialog*Erron en ecuación: {}Equation error: {} configdialogzError - referencia circular en ecuaciones de campo matemático2Error - circular reference in math field equations configdialog.Evaluar etiquetas &HTMLEvaluate &HTML tags configdialogTexto Adicional Extra Text configdialog Cam&poF&ield configdialog &Lista de Campos F&ield List configdialog CampoField configdialog Lista de &Campos Field &List configdialog(Referencias de CampoField References configdialogHReferencia de información de archivoFile Info Reference configdialog$Cam&biar DirecciónFlip &Direction configdialog(Ayuda sobre &Formato Format &Help configdialog IconoIcon configdialog&Ecuación matemática Math Equation configdialog4Modificar &Lista de CamposModify &Field List configdialog<Modificar Tipos Co&ndicionalesModify Co&nditional Types configdialogMover A&rribaMove &Up configdialogMover Aba&jo Move Do&wn configdialogMo&ver ArribaMove U&p configdialog NombreName configdialogNadaNone configdialog4Número de líneas de te&xtoNum&ber of text lines configdialog$Resultado Numérico Number Result configdialog"Tipo de O&peradorO&perator Type configdialog &Salida de DatosO&utput configdialog(Lista de Oper&adoresOper&ator List configdialogOperaciones Operations configdialog6Otras Referencias de CamposOther Field References configdialog$&Formato de SalidaOut&put Format configdialog$Formato de Sa&lidaOutpu&t Format configdialogSalida HTML Output HTML configdialog$Opciones de SalidaOutput Options configdialog Referencia PadreParent Reference configdialog&Tipo de Refere&nciaRefere&nce Type configdialog(Referencia de &NivelReference &Level configdialog&Referencia de &TipoReference &Type configdialog(Niv&el de ReferenciaReference Le&vel configdialog&Renombrar Cam&po...Rena&me Field... configdialog$Renom&brar Tipo...Rena&me Type... configdialogRenombrar Campo Rename Field configdialogRenombrar tipo Rename Type configdialog$Renombrar de {} a:Rename from {} to: configdialogReferencia RaízRoot Reference configdialog(Seleccionar &Ninguno Select &None configdialogAutoreferenciaSelf Reference configdialogJEstablecer el Icono del Tipo de DatosSet Data Type Icon configdialogBConfigurar Tipos CondicionalmenteSet Types Conditionally configdialog$Ord&enar Claves... Sort &Keys... configdialog,Clave de ClasificaciónSort Key configdialog(Ordenar Campos ClaveSort Key Fields configdialogSufi&joSuffi&x configdialogLista de &Tipos T&ype List configdialog&Operadores de TextoText Operators configdialog Texto Resultante Text Result configdialogbLos siguientes caracteres no están permitidos: {},The following characters are not allowed: {} configdialog<El nombre no puede estar vacíoThe name cannot be empty configdialogHEl nombre no puede contener espaciosThe name cannot contain spaces configdialogJEl nombre no puede comenzar con "xml" The name cannot start with "xml" configdialogJEl nombre debe comenzar con una letra!The name must start with a letter configdialog0El nombre ya está en usoThe name was already used configdialog&Resultado de Tiempo Time Result configdialog Configurar &Tipo Typ&e Config configdialogTipoType configdialog@Mostrar datos de campo en tab&laUse a table for field &data configdialog:[Todos los Tipos Disponibles][All Types Available] configdialog [Nada][None] configdialogvalor absolutoabsolute value configdialog sumaradd configdialogarcocoseno arc cosine configdialogarcosenoarc sine configdialogarcotangente arc tangent configdialogpromedioaverage configdialog(logaritmo en base 10base-10 logarithm configdialog concatenar textoconcatenate text configdialog8convertir texto a minúsculasconvert text to lower case configdialog8convertir texto a mayúsculasconvert text to upper case configdialog coseno de radiáncosine of radians configdialog"grados a radianesdegrees to radians configdialogdividirdivide configdialogigual aequal to configdialogfactorial factorial configdialogpunto flotantefloating point configdialog*división por redondeo floor divide configdialogadelanteforward configdialogAdelantefwd configdialogmayor que greater than configdialog"mayor o igual quegreater than or equal to configdialogentero mayorhigher integer configdialogŒen primer argumento, reemplazar segundo argumento con tercer argumento(in 1st arg, replace 2nd arg with 3rd arg configdialoghunir texto usando como primer argumento un separador$join text using 1st arg as separator configdialogmenor que less than configdialog"menor o igual queless than or equal to configdialoglógico y logical and configdialoglógico o logical or configdialogentero menor lower integer configdialog máximomaximum configdialog mínimominimum configdialog módulomodulus configdialogmultiplicarmultiply configdialog6constante logaritmo naturalnatural log constant configdialog"logaritmo naturalnatural logarithm configdialogdistinto a not equal to configdialog*número pi (constante) pi constant configdialogpotenciapower configdialog"radianes a gradosradians to degrees configdialog Atrásrev configdialog atrásreverse configdialog:redondear a número de dígitosround to num digits configdialogseno de radiánsine of radians configdialograíz cuadrada square root configdialog restarsubtract configdialogsuma de ítems sum of items configdialog$Tangente de Radiántangent of radians configdialog’verdadero si el argumentdo del primer texto contiene un segundo argumento%true if 1st text arg contains 2nd arg configdialog˜verdadero si el argumentdo del primer texto termina con un segundo argumento&true if 1st text arg ends with 2nd arg configdialogšverdadero si el argumentdo del primer texto comienza con un segundo argumento(true if 1st text arg starts with 2nd arg configdialogNvalor verdadero, condición, valor falso"true value, condition, false value configdialogentero truncadotruncated integer configdialog(&Seleccionar Archivo&Browse for File dataeditors&Cancelar&Cancel dataeditors&Ir al Destino &Go to Target dataeditors&OK&OK dataeditors&Abrir Enlace &Open Link dataeditors&Abrir Imagen &Open Picture dataeditorsJ(Clicar objeto a enlazar en el árbol)(Click link target in tree) dataeditorsAbsolutaAbsolute dataeditorsDirecciónAddress dataeditorsBorrar En&lace Clear &Link dataeditorsMostrar Nombre Display Name dataeditorsEnlace Externo External Link dataeditors.Tipo de ruta de archivoFile Path Type dataeditorsEnlace Interno Internal Link dataeditorsAbrir &Carpeta Open &Folder dataeditors Enlace de Imagen Picture Link dataeditorsRelativaRelative dataeditorsEsquemaScheme dataeditors"Establecer A&hora Set to &Now dataeditorsFecha de &Hoy Today's &Date dataeditorsFTreeLine - Enlace a archivo externoTreeLine - External Link File dataeditors8TreeLine - Archivo de ImagenTreeLine - Picture File dataeditors enlacelink dataeditors&Columnas&ColumnsexportsŒTabla &de descendientes delimitada por comas (CSV) (número de niveles);&Comma delimited (CSV) table of descendants (level numbers)exports&Todo el Árbol &Entire treeexports &HTML&HTMLexports4Formato &HTML de favoritos&HTML format bookmarksexports6&Incluir noddos principales&Include root nodesexports(&ODF Texto (esquema) &ODF Outlineexports4&Antiguos TreeLine (2.0.x)&Old TreeLine (2.0.x)exports.Abrir s&olo nodos hijos&Only open node childrenexports&Página HTML &Simple&Single HTML pageexportsB&Texto con tabulación por títulos&Tabbed title textexports &Texto&Textexports$&Subárbol TreeLine&TreeLine SubtreeexportsL&Salida sin formato para todo el texto&Unformatted output of all textexports4Formato &XBEL de favoritos&XBEL format bookmarksexports&XML (genérico)&XML (generic)exports&Favoritos Book&marksexportsFavoritos BookmarksexportsXSeleccionar subtipo de formato para exportarChoose export format subtypeexportsRSeleccionar tipo de formato para exportarChoose export format typeexportsDSeleccionar opciones para exportarChoose export optionsexportspT&abla de hijos delimitada por comas (CSV) (nivel único)7Comma &delimited (CSV) table of children (single level)exportsÊError: No se puede vincular al archivo TreeLine no guardado. Guarde el archivo y vuelva a intentarlo.FError - cannot link to unsaved TreeLine file. Save the file and retry.exports¾Error - Exportar archivos de plantilla no encontrados. Verifique la instalación de su TreeLine.JError - export template files not found. Check your TreeLine installation.exports Exportar Archivo File ExportexportsLIncluir im&presión de encabezado y pieInclude &print header && footerexports Vista de árbol en tiempo real, vinculada al archivo TreeLine (para servidor web)8Live tree view, linked to TreeLine file (for web server)exports€Vista de árbol en tiempo real, archivo único (datos incrustados)+Live tree view, single file (embedded data)exports>Múltiples tablas de datos &HTMLMultiple HTML &data tablesexports^&Multiples páginas HTML con panel de navegación)Multiple HTML &pages with navigation paneexportsPDebe seleccionar nodos antes de exportar!Must select nodes prior to exportexports@Nive&les del Panel de NavegaciónNavigation pane &levelsexportsOtras Opciones Other Optionsexports PadreParentexports(&Ramas SeleccionadasSelected &branchesexports(&Nodos SeleccionadosSelected &nodesexportsV&Página HTML simple con panel de navegación&Single &HTML page with navigation paneexports„Ta&bla delimitada por tabulaciones según nodos hijos (nivel único)0Tab &delimited table of children (&single level)exportsTree&Line Tree&Lineexports@TreeLine - Exportar XML GenéricoTreeLine - Export Generic XMLexports0TreeLine - Exportar HTMLTreeLine - Export HTMLexportsDTreeLine - Exportar Favoritos HTML TreeLine - Export HTML Bookmarksexports$Exportar Texto ODFTreeLine - Export ODF Textexports>TreeLine - Exportar Texto PlanoTreeLine - Export Plain TextexportsFTreeLine - Exportar Tablas de TextoTreeLine - Export Text TablesexportsJTreeLine - Exportar Textos de TítulosTreeLine - Export Text TitlesexportsJTreeLine - Exportar Subárbol TreeLine"TreeLine - Export TreeLine SubtreeexportsDTreeLine - Exportar Favoritos XBEL TreeLine - Export XBEL Bookmarksexports´Advertencia: no hay una ruta relativa entre "{0}" y "{1}". Continuar con la ruta absoluta?LWarning - no relative path from "{0}" to "{1}". Continue with absolute path?exportsQué exportarWhat to Exportexports"." Carácter .."." Character .. fieldformat"/" Carácter //"/" Character // fieldformat(0 ó 1 Repeticiones ?0 Or 1 Repetitions ? fieldformat,0 o más repeticiones *0 Or More Repetitions * fieldformat,1 o más repeticiones +1 Or More Repetitions + fieldformatAM/PM %pAM/PM %p fieldformat(Cualquier Carácter .Any Character . fieldformatAutoElección AutoChoice fieldformatAutoCombinaciónAutoCombination fieldformatBooleanoBoolean fieldformatMayúsculas ACapital Letter A fieldformat<Números Romanos (mayúsculas) ICapital Roman Numeral I fieldformatElecciónChoice fieldformatCombinación Combination fieldformat"Separador Coma \,Comma Separator \, fieldformat FechaDate fieldformatFecha y horaDateTime fieldformat.Día (1 ó 2 dígitos) %-dDay (1 or 2 digits) %-d fieldformat$Día (2 dígitos) %dDay (2 digits) %d fieldformat2Día del año (1 a 366) %-jDay of year (1 to 366) %-j fieldformatComa Decimal ,Decimal Comma , fieldformatPunto Decimal .Decimal Point . fieldformat&Cuenta DescendienteDescendantCount fieldformatDDígito o Espacio (externo) <space>!Digit or Space (external)  fieldformat$Separador Punto \.Dot Separator \. fieldformat"Final del Texto $ End of Text $ fieldformat4Escape carácter especial \Escape a Special Character \ fieldformatEjemplo 1/2/3/4Example 1/2/3/4 fieldformat.Exponente (mayúscula) EExponent (capital) E fieldformat.Exponente (minúscula) eExponent (small) e fieldformatEnlace Externo ExternalLink fieldformat<Hora (0-23, 1 ó 2 dígitos) %-HHour (0-23, 1 or 2 digits) %-H fieldformat4Hora (00-23, 2 dígitos) %HHour (00-23, 2 digits) %H fieldformat4Hora (01-12, 2 dígitos) %IHour (01-12, 2 digits) %I fieldformat<Hora (1-12, 1 ó 2 dígitos) %-IHour (1-12, 1 or 2 digits) %-I fieldformatTexto HtmlHtmlText fieldformatEnlaceInterno InternalLink fieldformat(Separador de nivel /Level Separator / fieldformat Minúsculas [a-z]Lower Case Letters [a-z] fieldformatMatemáticasMath fieldformat8Microsegundos (6 dígitos) %fMicroseconds (6 digits) %f fieldformat6Minutos (1 ó 2 dígitos) %-MMinute (1 or 2 digits) %-M fieldformat,Minutos (2 dígitos) %MMinute (2 digits) %M fieldformat.Mes (1 o 2 dígitos) %-mMonth (1 or 2 digits) %-m fieldformat$Mes (2 dígitos) %mMonth (2 digits) %m fieldformat$Mes (abreviado) %bMonth Abbreviation %b fieldformat0Mes (nombre completo) %B Month Name %B fieldformat,No es un número [^0-9]Not a Number [^0-9] fieldformat AhoraNow fieldformat NúmeroNumber fieldformatNúmero 1Number 1 fieldformatNumeración Numbering fieldformat$Texto de una línea OneLineText fieldformat"Dígito Opcional #Optional Digit # fieldformat Signo Opcional -Optional Sign - fieldformatO |Or | fieldformatHEjemplo de esquema I../A../1../a)/i)!Outline Example I../A../1../a)/i) fieldformat ImagenPicture fieldformat"Expresión regularRegularExpression fieldformat$Dígito Requerido 0Required Digit 0 fieldformat"Signo Requerido +Required Sign + fieldformat8Segundos (1 ó 2 dígitos) %-SSecond (1 or 2 digits) %-S fieldformat.Segundos (2 dígitos) %SSecond (2 digits) %S fieldformat4Ejemplo de sección 1.1.1.1Section Example 1.1.1.1 fieldformat,Separador de sección .Section Separator . fieldformatSeparador / Separator / fieldformat2Conjunto de Números [0-9]Set of Numbers [0-9] fieldformatMinúsculas aSmall Letter a fieldformat<Números romanos (minúsculas) iSmall Roman Numeral i fieldformatFSeparador Espacio (interno) <space>"Space Separator (internal)  fieldformatTexto espaciado SpacedText fieldformatV/FT/F fieldformat TextoText fieldformatHoraTime fieldformat Mayúsculas [A-Z]Upper Case Letters [A-Z] fieldformat&Semana (0 a 53) %-UWeek Number (0 to 53) %-U fieldformat@Día de la semana (abreviado) %aWeekday Abbreviation %a fieldformat&Día de la semana %AWeekday Name %A fieldformatS/NY/N fieldformat$Año (2 dígitos) %yYear (2 digits) %y fieldformat$Año (4 dígitos) %YYear (4 digits) %Y fieldformatverdadero/falso true/false fieldformat sí/noyes/no fieldformat falsofalse genbooleannono genbooleanverdaderotrue genbooleansíyes genboolean$Todos los Archivos All Files globalref6Todos los Archivos TreeLineAll TreeLine Files globalrefFArchivos CSV (Delimitado por Comas)CSV (Comma Delimited) Files globalrefArchivos HTML HTML Files globalref*Archivos de Texto ODFODF Text Files globalref4Archivos TreeLine AntiguosOld TreeLine Files globalrefArchivos PDF PDF Files globalref"Archivos de Texto Text Files globalref"Archivos TreeLineTreeLine Files globalref<Archivos TreeLine - ComprimidoTreeLine Files - Compressed globalref<Archivos TreeLine - EncriptadoTreeLine Files - Encrypted globalref&Archivos de Treepad Treepad Files globalrefArchivos XML XML Files globalref Buscar:  Find: helpview&Volver&Backhelpview&Siguiente&Forwardhelpview&Inicio&Homehelpview"&Buscar Siguiente Find &Nexthelpview Buscar &AnteriorFind &Previoushelpview:Cadena de texto no encontradaText string not foundhelpviewHerramientasToolshelpview "{0}" no es un archivo válido TreeLine. ¿Usar filtro de importación de archivo?:"{0}" is not a valid TreeLine file. Use an import filter?importsRXML &genérico (No es un archivo TreeLine) &Generic XML (non-TreeLine file)importsB&HTML favoritos (Formato Mozilla) &HTML bookmarks (Mozilla Format)importsl&Sangrado de texto por tabulaciones, un nodo por línea%&Tab indented text, one node per lineimports@Favoritos en &XML (Formato XBEL)&XML bookmarks (XBEL format)importsFAVORITOBOOKMARKimports@Formato CSV.erróneo en Línea {0}Bad CSV format on Line {0}importsFavoritos Bookmarksimports:Escoger Método de ImportaciónChoose Import Methodimports´T&exto delimitado por comas (CSV) tabla de texto con nivel de columna y fila de encabezadoACo&mma delimited (CSV) text table with level column && header rowimports|Texto &delimitado por comas (CSV) tabla con fila de encabezado1Comma delimited (CSV) text table &with header rowimportsDError-no se puede leer archivo {0}Error - could not read file {0}importsBError - formato incorrecto en {0}Error - improper format in {0}importsCARPETAFOLDERimports Importar Archivo Import Fileimports"Archivo no Válido Invalid FileimportsRNúmero de nivel no válido en la línea {0} Invalid level number on line {0}imports:Estructura de nivel no válidaInvalid level structureimports EnlaceLinkimportsPArchivo Antiguo de Tree&Line (1.x o 2.x)Old Tree&Line File (1.x or 2.x)imports(Open &Document (ODF)Open &Document (ODF) outlineimportsOtroOtherimportsrTexto &plano en párrafos (delimitado por línea en blanco)-Plain text ¶graphs (blank line delimited)importsŽText&o plano, un &nodo por línea (delimitado por retorno de carro -CR-)-Plain text, one &node per line (CR delimited)importsSEPARADOR SEPARATORimports TABLATABLEimports„Tabl&a de texto delimitada por tabulaciones con fila de encabezado)Tab delimited text table with header &rowimports TextoTextimportsFDemasiadas entradas en la Línea {0}Too many entries on Line {0}imports6TreeLine - Importar archivoTreeLine - Import FileimportsX&Archivo Treepad (únicamente nodos de texto)Treepad &file (text nodes only)importsvLas referencias secundarias deben combinarse en una función/Child references must be combined in a functionmatheval:Caracteres "{}" no permitidosIllegal "{}" charactersmatheval8Función ilegal presente: {0}Illegal function present: {0}mathevalVTipo de objeto u operador no permitido: {0}$Illegal object type or operator: {0}matheval<Sintaxis ilegar en la ecuaciónIllegal syntax in equationmathevalA&plicar&Apply miscdialogs&Cancelar&Cancel miscdialogs&Cerrar&Close miscdialogsC&errar Filtro &End Filter miscdialogsÁrbol compl&eto &Entire tree miscdialogs&Filtro&Filter miscdialogs"&Buscar Siguiente &Find Next miscdialogs&Adelante&Forward miscdialogs"&Ignorar y omitir&Ignore and skip miscdialogs&Contiene &Key words miscdialogsTipo de &Nodo &Node Type miscdialogs&OK&OK miscdialogs>Nombres de Campos &Predefinidos&Predefined Key Fields miscdialogs$Exp&resión regular&Regular expression miscdialogs&Reemplazar&Replace miscdialogs^&Reiniciar números para los siguientes hermanos"&Restart numbers for next siblings miscdialogs>&Restaurar Valores por &Defecto&Restore Defaults miscdialogs At&rás&Reverse miscdialogs&Buscar texto &Search Text miscdialogs&&Selección de Hijos&Selection's children miscdialogs Sólo en &títulos &Titles only miscdialogs.Barras de herramien&tas &Toolbars miscdialogsbConsiderar los espacios en blanco como ceros (&0)&Treat blank fields as zeros miscdialogs^&Usar la fuente predeterminada de la aplicación&Use app default font miscdialogs$&Comprimir Archivo&Use file compression miscdialogsH&Usar fuente por defecto del sistema&Use system default font miscdialogs--Separador-- --Separator-- miscdialogsØSe ha producido un error grave. TreeLine podría estar en un estado inestable. Se recomienda guardar cualquier cambio de archivo con otro nombre de archivo y reiniciar TreeLine. La información de depuración que se muestra a continuación se puede copiar y enviar por correo electrónico a doug101@bellz.org junto con una explicación de las circunstancias del error. A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances.  miscdialogs*Comandos Dis&poniblesA&vailable Commands miscdialogsCo&ntiene Any &match miscdialogsFFuente por defecto de la aplicaciónApp Default Font miscdialogsBorrar Cla&ve Clear &Key miscdialogs(Personalizar FuentesCustomize Fonts miscdialogsDPersonalizar Barra de HerramientasCustomize Toolbars miscdialogs DatosData miscdialogsMenú de datos Data Menu miscdialogs:Predeterminado - Texto SimpleDefault - Single Line Text miscdialogs EditarEdit miscdialogsMenú Edición Edit Menu miscdialogs"Fuente del EditorEditor View Font miscdialogsBContraseña del Archivo EncriptadoEncrypted File Password miscdialogsFError - Expresión regular no válida"Error - invalid regular expression miscdialogs2Error - reemplazo fallidoError - replacement failed miscdialogsFrase co&mpleta F&ull phrase miscdialogs CamposFields miscdialogsArchivoFile miscdialogsMenú de Archivo File Menu miscdialogs,Propiedades de ArchivoFile Properties miscdialogs4Almacenamiento de Archivos File Storage miscdialogs FiltroFilter miscdialogs BuscarFind miscdialogs"Buscar &Siguiente Find &Next miscdialogs Buscar &AnteriorFind &Previous miscdialogs&Buscar y reemplazarFind and Replace miscdialogsFormatoFormat miscdialogsMenú Formato Format Menu miscdialogsEn to&do Full &data miscdialogsCoinci&de Full &words miscdialogsLManejar nodos sin Campos de Numeración'Handling Nodes without Numbering Fields miscdialogs AyudaHelp miscdialogsMenú Ayuda Help Menu miscdialogsCómo Buscar How to Search miscdialogs>Incluir nodos de nivel superiorInclude top-level nodes miscdialogsTexto E&xactoKey full &words miscdialogs0Clave {0} ya está en usoKey {0} is already used miscdialogs"Atajos de TecladoKeyboard Shortcuts miscdialogsRCódigo de idioma o diccionario (opcional)&Language code or dictionary (optional) miscdialogsIconos Grandes Large Icons miscdialogs$Campos Matemáticos Math Fields miscdialogsMover Aba&jo Move &Down miscdialogsMover &ArribaMove &Up miscdialogsCampos de N&odo N&ode Fields miscdialogsNo.menuNo menu miscdialogsxNo se encontraron campos de numeración en los tipos de datos,No numbering fields were found in data types miscdialogsNodoNode miscdialogs"&Títulos de Nodos Node &Titles miscdialogsMenú de Nodo Node Menu miscdialogs Fuente de SalidaOutput View Font miscdialogs$Expresión re&gularRe&gular expression miscdialogs>Escriba de nuevo la contraseña:Re-Type Password: miscdialogsFLa contraseña reescrita no coincideRe-typed password did not match miscdialogsTRecordar la contraseña durante esta sesión%Remember password during this session miscdialogs Reemplaz&ar Todo Replace &All miscdialogs<Reemplazadas {0} coincidenciasReplaced {0} matches miscdialogs"Reemplazar &TextoReplacement &Text miscdialogs Reserva &númerosReserve &numbers miscdialogsNodo Principal Root Node miscdialogsDBuscar cadena "{0}". No encontradaSearch string "{0}" not found miscdialogsLBúsqueda del texto "{0}" no encontradoSearch text "{0}" not found miscdialogs(Ramas &SeleccionadasSelected &branches miscdialogs.Her&manos seleccionadosSelection's &siblings miscdialogs(&Hijos seleccionadosSelection's childre&n miscdialogsIconos Pequeños Small Icons miscdialogs*Dirección de OrdenadoSort Direction miscdialogs$Método de ordenado Sort Method miscdialogsOrdenar Nodos Sort Nodes miscdialogs:Comprobación de la ortografía Spell Check miscdialogsJComandos de la &barra de herramientasTool&bar Commands miscdialogs:Tamaño Barra de Herramienta&s Toolbar &Size miscdialogsDCantidad de barras de herramientasToolbar Quantity miscdialogsHerramientasTools miscdialogs(Menú de Herramientas Tools Menu miscdialogs Fuente del ÁrbolTree View Font miscdialogs,TreeLine - Error GraveTreeLine - Serious Error miscdialogs&Numeración TreeLineTreeLine Numbering miscdialogsBEscriba la Contraseña para "{0}":Type Password for "{0}": miscdialogs,Escriba la Contraseña:Type Password: miscdialogs:Actualizar Numeración de NodoUpdate Node Numbering miscdialogs$&Encriptar ArchivoUse file &encryption miscdialogsVerView miscdialogsMenú Ver View Menu miscdialogsDónde BuscarWhat to Search miscdialogsQué ordenar What to Sort miscdialogsQué ActualizarWhat to Update miscdialogsVentanaWindow miscdialogsMenú Ventana Window Menu miscdialogsVNo se permiten contraseñas de longitud cero'Zero-length passwords are not permitted miscdialogs$[Todos los campos] [All Fields] miscdialogs"[Todos los tipos] [All Types] miscdialogs NombreName nodeformat‚Activar editores de datos cuando el puntero del ratón esté encima$Activate data editors on mouse hoveroptiondefaultsApariencia Appearanceoptiondefaults(Grabación automática Auto SaveoptiondefaultsZAbrir automáticamente el último archivo usado!Automatically open last file usedoptiondefaults„Corrección de sangrado de hijos (en unidades de altura de fuente) +Child indent offset (in font height units) optiondefaults:Clicar en nodo para renombrarClick node to renameoptiondefaults8Formatos del editor de datosData Editor Formatsoptiondefaults FechasDatesoptiondefaults6Funcionalidades disponiblesFeatures Availableoptiondefaults.Primer día de la semanaFirst day of weekoptiondefaultsViernesFridayoptiondefaultsbSangrado (mejor impresión) Archivos TreeLine JSON)Indent (pretty print) TreeLine JSON filesoptiondefaultsXMinimiza aplicación a la bandeja del sistema#Minimize application to system trayoptiondefaultslMinutos entre respaldos (seleccione 0 para desactivar)+Minutes between saves (set to 0 to disable)optiondefaults LunesMondayoptiondefaultshCantidad de archivos recientes en el menú de archivo(Number of recent files in the file menuoptiondefaults:Número de niveles de deshacerNumber of undo levelsoptiondefaultsFAbrir archivos en una nueva ventanaOpen files in new windowsoptiondefaults$Archivos recientes Recent Filesoptiondefaults€Eliminar archivos inaccesibles en la vista de archivos recientes'Remove inaccessible recent file entriesoptiondefaults\Renombrar los nodos nuevos cuando sean creadosRename new nodes when createdoptiondefaultsZRestaurar la geometría de la ventana anterior Restore previous window geometryoptiondefaultsrRestaurar estados de vista en árbol de archivos recientes(Restore tree view states of recent filesoptiondefaults SábadoSaturdayoptiondefaults6Mostrar panel de navegaciónShow breadcrumb ancestor viewoptiondefaultsPMotrar paneles hijos en la vista derecha#Show child pane in right hand viewsoptiondefaultsFMostrar hijos en la vista de salidaShow descendants in output viewoptiondefaultsFMostrar iconos en la vista de árbolShow icons in the tree viewoptiondefaultstMostrar campos matemáticos en la vista de Edición de Datos&Show math fields in the Data Edit viewoptiondefaultsxMostrar campos de numeración en la vista de Edición de Datos+Show numbering fields in the Data Edit viewoptiondefaults&Condición de InicioStartup ConditionoptiondefaultsDomingoSundayoptiondefaults JuevesThursdayoptiondefaults HorasTimesoptiondefaultslDisponible la opción de pulsar y arrastrar en el árbolTree drag && drop availableoptiondefaults MartesTuesdayoptiondefaultsLMemoria usada por la opción "deshacer" Undo MemoryoptiondefaultsMiércoles Wednesdayoptiondefaults&Cancelar&Canceloptions&Aceptar&OKoptions^Elija la ubicación del archivo de configuración"Choose configuration file locationoptionsPCarpeta del programa (para uso portable)$Program directory (for portable use)optionsZDirectorio de inicio de usuario (recomendado)#User's home directory (recommended)options@Error inicializando la impresoraError initializing printer printdata2TreeLine - Exportar a PDFTreeLine - Export PDF printdataÀAdvertencia: configuración de margen no compatible en la impresora actual. ¿Guardar los ajustes?JWarning: Margin settings unsupported on current printer. Save adjustments? printdataøAdvertencia: configuración de tamaño de página y margen no admitida en la impresora actual. ¿Guardar los ajustes de página?]Warning: Page size and margin settings unsupported on current printer. Save page adjustments? printdataÊAdvertencia: configuración de tamaño de página no admitida en la impresora actual. ¿Guardar ajustes?KWarning: Page size setting unsupported on current printer. Save adjustment? printdataA&bajo:&Bottom: printdialogs&Cancelar&Cancel printdialogsH&Dibujar líneas para los nodos hijos&Draw lines to children printdialogs&Árbol completo &Entire tree printdialogs&Fuente&Font printdialogs(Selección de &Fuente&Font Selection printdialogs&Opciones &Generales&General Options printdialogs*Encabezado I&zquierdo &Header Left printdialogs"&Encabezado y pie&Header/Footer printdialogs*Incluir el nodo rai&z&Include root node printdialogsT&Mantener el primer nodo hijo con el padre&Keep first child with parent printdialogsIz&quierda:&Left: printdialogs&&Número de columnas&Number of columns printdialogs&OK&OK printdialogs&Prefijo&Prefix printdialogs&Imprimir... &Print... printdialogsDerec&ha:&Right: printdialogs&Sufijo&Suffix printdialogsA&rriba:&Top: printdialogs&Unidades&Units printdialogsˆ&Usar la misma que haya configurada en "Salida de Datos" de TreeLine&Use TreeLine output view font printdialogsA&nchura:&Width: printdialogs"A3 (279 x 420 mm)A3 (279 x 420 mm) printdialogs"A4 (210 x 297 mm)A4 (210 x 297 mm) printdialogs"A5 (148 x 210 mm)A5 (148 x 210 mm) printdialogs>AaBbCcDdEeFfGg...TtUuVvWvXxYyZzAaBbCcDdEeFfGg...TtUuVvWvXxYyZz printdialogs Centímetros (cm)Centimeters (cm) printdialogsColumnasColumns printdialogs(Tamaño Personalizado Custom Size printdialogs*Fuente predeterminada Default Font printdialogsXError: Tamaño de página o márgenes inválidos(Error: Page size or margins are invalid printdialogsTexto adicional Extra Text printdialogs&Páginas enfrentadas Facing Pages printdialogsCaracterísticasFeatures printdialogsCampo&sFiel&ds printdialogs"For&mato de Campo Field For&mat printdialogs6Formato de Campo para "{0}"Field Format for "{0}" printdialogs Ajuste de páginaFit Page printdialogsAjuste de ancho Fit Width printdialogs"E&stilo de fuente Font st&yle printdialogs &Pie:Foot&er: printdialogsPie Iz&quierdo Footer &Left printdialogsPie ce&ntradoFooter Ce&nter printdialogsPie De&recho Footer Righ&t printdialogs"A&yuda de Formato Format &Help printdialogsEncabe&zado:He&ader: printdialogs&Encabezado &Derecho Header &Right printdialogs(Encabezado cen&tradoHeader C&enter printdialogs4Encabezado y pie de páginaHeader and Footer printdialogsAltura:Height: printdialogsPulgadas (in) Inches (in) printdialogsNodos IncluídosIncluded Nodes printdialogsSangrarIndent printdialogsbSangrado de &Salida (unidades de altura de línea)"Indent Offse&t (line height units) printdialogsPaisa&je Lan&dscape printdialogs(Legal (8.5 x 14 in.)Legal (8.5 x 14 in.) printdialogs(Carta (8.5 x 11 in.)Letter (8.5 x 11 in.) printdialogsMárgenesMargins printdialogsMilímetros (mm)Millimeters (mm) printdialogs Página Siguiente Next Page printdialogs2Incluir solo nodos &hijosOnl&y open node children printdialogsOrientación Orientation printdialogsSalida &FormatoOutput &Format printdialogs0Configuración de &Página Page &Setup printdialogs"Tamaño del Pape&l Paper &Size printdialogsRetra&to Portra&it printdialogsPágina anterior Previous Page printdialogsImprimirPrint printdialogs &Vista Previa...Print Pre&view... printdialogs2Vista Previa de Impresión Print Preview printdialogs4Configuración de Impresión Print Setup printdialogs4Configuración de ImpresiónPrinting Setup printdialogsEjemploSample printdialogs,Seleccionar Im&presoraSelect &Printer printdialogs$Seleccionar Fuente Select Font printdialogs(&Ramas seleccionadasSelected &branches printdialogs(&Nodos seleccionadosSelected &nodes printdialogs&TamañoSi&ze printdialogsPágina sencilla Single Page printdialogs.Espacio entre colu&mnasSpace between colu&mns printdialogs,Tabloide (11 x 17 in.)Tabloid (11 x 17 in.) printdialogs,TreeLine Impresora PDFTreeLine PDF Printer printdialogsQué imprimir What to print printdialogsZoom AumentarZoom In printdialogsZorrm ReducirZoom Out printdialogs&Añadir&Add spellcheck&Cancelar&Cancel spellcheck&Ignorar todo &Ignore All spellcheck&Reemplazar&Replace spellcheck"Añadir &minúsculaAdd &Lowercase spellcheckContexto:Context: spellcheck No se pudo encontrar aspell.exe, ispell.exe o hunspell.exe ¿Buscar la ubicación?QCould not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? spellcheck€Terminada revisión de la rama Continuar desde la parte superior?3Finished checking the branch Continue from the top? spellcheckFComprobación ortográfica finalizadaFinished spell checking spellcheckIgnor&arIgnor&e spellcheckXUbique aspell.exe, ipsell.exe o hunspell.exe-Locate aspell.exe, ipsell.exe or hunspell.exe spellcheck2No está en el diccionarioNot in Dictionary spellcheck Programa (*.exe)Program (*.exe) spellcheck Reem&plazar todo Re&place All spellcheck:Comprobación de la ortografía Spell Check spellcheck"Error ortográficoSpell Check Error spellcheckSugerencias Suggestions spellcheckHComprobación ortográfica de TreeLIneTreeLine Spell Check spellcheckÂError de comprobación ortográfica TreeLine Comprobar que esté instalado aspell, ispell o hunspellLTreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed spellcheckPalabra:Word: spellcheck(Seleccionar en ÁrbolSelect in Tree titlelistviewPREDETERMINADODEFAULT treeformats CAMPOFIELD treeformatsARCHIVOFILE treeformatsTipoCampo FieldType treeformatsFormatoFormat treeformats IconoIcon treeformatsTIPOTYPE treeformats&Negrita &Bold Fonttreelocalcontrol&Copiar&Copytreelocalcontrol&Eliminar Nodo &Delete Nodetreelocalcontrol&Separar Clones&Detach Clonestreelocalcontrol&Exportar... &Export...treelocalcontrol$Enlace &Externo...&External Link...treelocalcontrol"&Tamaño de Fuente &Font Sizetreelocalcontrol&Sangrar Nodos &Indent Nodetreelocalcontrol&Cursiva &Italic FonttreelocalcontrolMover A&rriba&Move Uptreelocalcontrol&Nueva Ventana &New Windowtreelocalcontrol &Pegar&Pastetreelocalcontrol&Imprimir... &Print...treelocalcontrol&Rehacer&Redotreelocalcontrol,Re&generar Referencias&Regenerate Referencestreelocalcontrol&Renombrar&Renametreelocalcontrol&Guardar&Savetreelocalcontrol0&Establecer Tipo de Nodo&Set Node Typetreelocalcontrol2Corrector &Ortográfico...&Spell Check...treelocalcontrol&Deshacer&Undotreelocalcontrol4Deshacer Sangrado de &Nodo&Unindent Nodetreelocalcontrol&Añadir Hijo Add &Childtreelocalcontrol:Añadir Ni&vel de Categoría...Add Category &Level...treelocalcontrolNAñadir nuevo hijo al padre seleccionado Add new child to selected parenttreelocalcontrolPAñadir o modificar un enlace web externo!Add or modify an extrnal web linktreelocalcontrolVAñadir o modificar un enlace interno a nodo#Add or modify an internal node linktreelocalcontrolRNo es posible expandir sin campos comunes#Cannot expand without common fieldstreelocalcontrol0Campos de las categoríasCategory Fieldstreelocalcontrol&Borrar FormatoClear For&mattingtreelocalcontrolZBorrar actual o seleccionado formato de texto)Clear current or selected text formattingtreelocalcontrolFClonar &Todos los Nodos EmparejadosClone All &Matched Nodestreelocalcontrol`Contraer descendientes cuando se fusionen campos&Collapse descendants by merging fieldstreelocalcontrol`Convertir todos los nodos coincidentes en clones&Convert all matching nodes into clonestreelocalcontrol:Convierte ramas {0} en clones"Converted {0} branches into clonestreelocalcontrol<&Copiar Tipos desde Archivo...Copy Types from &File...treelocalcontrolLCopiar la rama o texto al portapapeles(Copy the branch or text to the clipboardtreelocalcontrollCopiar la configuración desde otro archivo de TreeLine1Copy the configuration from another TreeLine filetreelocalcontrolCor&tarCu&ttreelocalcontrolRCortar la rama o el texto al portapapeles'Cut the branch or text to the clipboardtreelocalcontrolPredeterminadoDefaulttreelocalcontrol@Eliminar los nodos seleccionadosDelete the selected nodestreelocalcontrollSeparar todos los nodos clonados en las ramas actuales+Detach all cloned nodes in current branchestreelocalcontrolhError - No se puede borrar el archivo de respaldo {}'Error - could not delete backup file {}treelocalcontrolJError: no se pudo leer el archivo {0}Error - could not read file {0}treelocalcontrolRError - no se pudo escribir en el archivoError - could not write to filetreelocalcontrolBError - No se pudo escribir en {}Error - could not write to {}treelocalcontrolLExportar el archivo en varios formatos(Export the file in various other formatstreelocalcontroljExportar a PDF con las opciones de impresión actuales+Export to PDF with current printing optionstreelocalcontrol Archivo guardado File savedtreelocalcontrol,&Acoplar por CategoríaFlatten &by Categorytreelocalcontrol&Color de &Fuente...Font C&olor...treelocalcontrol”Forzar actualización de todos los tipos condicionales y campos matemáticos3Force update of all conditional types & math fieldstreelocalcontrol>Sangrar los nodos seleccionadosIndent the selected nodestreelocalcontrol.Añadir Hermano &DespuésInsert Sibling &Aftertreelocalcontrol*Añadir &Hermano AntesInsert Sibling &BeforetreelocalcontrolvAñadir los nodos con las categorías por encima de los hijos$Insert category nodes above childrentreelocalcontrolXAñadir nuevo hermano despues de la selección"Insert new sibling after selectiontreelocalcontrolTAñadir nuevo hermano antes de la selección#Insert new sibling before selectiontreelocalcontrol$Enlace &Interno...Internal &Link...treelocalcontrol GrandeLargetreelocalcontrolMás grandeLargertreelocalcontrolEl más grandeLargesttreelocalcontrolMover Aba&jo M&ove Downtreelocalcontrol&Mover al &Principio Move &FirsttreelocalcontrolMover al &Final Move &LasttreelocalcontrolZDesplazar hacia abajo los nodos seleccionadosMove the selected nodes downtreelocalcontroljMover nodos seleccionados para ser los primeros hijos0Move the selected nodes to be the first childrentreelocalcontrolhMover nodos seleccionados para ser los últimos hijos/Move the selected nodes to be the last childrentreelocalcontrol\Desplazar hacia arriba los nodos seleccionadosMove the selected nodes uptreelocalcontrol4No existen nodos idénticosNo identical nodes foundtreelocalcontrolRAbrir nueva ventana para el mismo archivo#Open a new window for the same filetreelocalcontrol<Config&uración de Impresión...P&rint Setup...treelocalcontrol0Pegar Texto sin &FormatoPa&ste Plain TexttreelocalcontrolPegar &Hijo Paste C&hildtreelocalcontrol&Pegar Hijo C&lonadoPaste Cl&oned Childtreelocalcontrol8Pegar Hermano Clo&nado AntesPaste Clo&ned Sibling Beforetreelocalcontrol<Pegar Hermano Clonad&o DespuésPaste Clone&d Sibling Aftertreelocalcontrol,Pegar Hermano Despué&sPaste Sibling &Aftertreelocalcontrol(Pegar Hermano &AntesPaste Sibling &BeforetreelocalcontrolPPegar hijo clonado desde el portapapeles&Paste a child clone from the clipboardtreelocalcontrolPPegar un nodo hijo desde el portapapeles%Paste a child node from the clipboardtreelocalcontrolPPegar un hermano después de la selecciónPaste a sibling after selectiontreelocalcontrolFPegar hermano antes de la selección Paste a sibling before selectiontreelocalcontrolZPegar un clon hermano después de la selección%Paste a sibling clone after selectiontreelocalcontrolVPegar un clon hermano antes de la selección&Paste a sibling clone before selectiontreelocalcontrolRPegar nodos o texto desde el portapapeles&Paste nodes or text from the clipboardtreelocalcontrolPPegar texto sin formato del portapapeles+Paste non-formatted text from the clipboardtreelocalcontrol$Imprimir a PD&F...Print &to PDF...treelocalcontrol:&Vista Previa de Impresión...Print Pre&view...treelocalcontrolpImprimir salida de árbol en base a las opciones actuales*Print tree output based on current optionstreelocalcontrol&Propiedades...Prop&erties...treelocalcontrolzRehacer la última acción sobre la que se ha aplicado deshacerRedo the previous undotreelocalcontrolTRenombrar título completo del árbol en uso#Rename the current tree entry titletreelocalcontrolD&Intercambiar Niveles de CategoríaS&wap Category Levelstreelocalcontrol Guardar &Como... Save &As...treelocalcontrolGuardar archivo Save Filetreelocalcontrol.¿Guardar cambios en {}?Save changes to {}?treelocalcontrol"¿Guardar cambios? Save changes?treelocalcontrol2Guardar el archivo actualSave the current filetreelocalcontrolLGuardar el archivo con un nombre nuevoSave the file with a new nametreelocalcontrolFSeleccionar campos para nuevo nivelSelect fields for new leveltreelocalcontrol0Definir tamaño de fuente Set Font Sizetreelocalcontrol.Establecer tipo de nodo Set Node Typetreelocalcontrol~Establecer parámetros de archivo como compresión y encriptación3Set file parameters like compression and encryptiontreelocalcontrol†Establecer márgenes, tamaño de página y otras opciones de impresión1Set margins, page size and other printing optionstreelocalcontrolhEstablecer el tamaño del texto actual o seleccionado(Set size of the current or selected texttreelocalcontrolfEstablecer el color del texto actual o seleccionado-Set the color of the current or selected texttreelocalcontroljEstablecer la fuente actual o seleccionada en negrita(Set the current or selected font to boldtreelocalcontroljEstablecer la fuente actual o seleccionada en cursiva*Set the current or selected font to italictreelocalcontrolpEstablecer la fuente actual o seleccionada para subrayar-Set the current or selected font to underlinetreelocalcontrolhEstablecer tipo de nodo para los nodos seleccionados$Set the node type for selected nodestreelocalcontrolVVista previa de los resultados de impresión"Show a preview of printing resultstreelocalcontrolPequeñoSmalltreelocalcontrolHRevisar los datos de texto del árbol Spell check the tree's text datatreelocalcontrolVIntercambiar categoría nodos hijos y nietos(Swap child and grandchild category nodestreelocalcontrolRTreeLine - Abrir archivo de configuración"TreeLine - Open Configuration Filetreelocalcontrol.TreeLine - Guardar comoTreeLine - Save Astreelocalcontrol&SubrayadoU&nderline Fonttreelocalcontrol6Deshacer la acción anteriorUndo the previous actiontreelocalcontrolXEliminar sangrado de los nodos seleccionadosUnindent the selected nodestreelocalcontrolìAdvertencia: ¡archivo corrupto! Se omitieron referencias de elementos secundarios incorrectos en los siguientes nodos:OWarning - file corruption! Skipped bad child references in the following nodes:treelocalcontrol,&Acerca de TreeLine...&About TreeLine...treemaincontrolUso &Básico...&Basic Usage...treemaincontrol2&Cancelar archivo abierto&Cancel File Opentreemaincontrol0Búsqueda &Condicional...&Conditional Find...treemaincontrol:Configurar Tipos de &Datos...&Configure Data Types...treemaincontrol8Eliminar copia de segurida&d&Delete Backuptreemaincontrol &Buscar Texto... &Find Text...treemaincontrol4&Documentación completa...&Full Documentation...treemaincontrol,Opciones &Generales...&General Options...treemaincontrolImporta&r... &Import...treemaincontrol&Nuevo...&New...treemaincontrol&Abrir...&Open...treemaincontrol &Salir&Quittreemaincontrol:&Restaurar copia de seguridad&Restore Backuptreemaincontrol"Seleccionar T&odo &Select Alltreemaincontrol(&Seleccionar Ejemplo&Select Sampletreemaincontrol,&Seleccionar Plantilla&Select Templatetreemaincontrol&Filtro de &Texto...&Text Filter...treemaincontrol Existe un archivo de respaldo: "{}". Una sesión anterior puede haberse bloqueadoAbrir un archivo desde el discoOpen a file from disktreemaincontrol<Abriri un arhchivo no-TreeLineOpen a non-TreeLine filetreemaincontrol6Abrir un archivo de ejemploOpen a sample filetreemaincontrolXReemplazar cadenas de texto en datos de nodo!Replace text strings in node datatreemaincontrolLSeleccionar todo el texto en un editorSelect all text in an editortreemaincontrol@Establecer &Atajos de Teclado...Set &Keyboard Shortcuts...treemaincontrolfConfigurar las preferencias para todos los archivos"Set user preferences for all filestreemaincontrolNMostrar Confi&guración de Estructura... Show C&onfiguration Structure...treemaincontrolxMostrar visualización de solo lectura del tipo de estructura.Show read-only visualization of type structuretreemaincontrol"&Ordenar Nodos...Sor&t Nodes...treemaincontrol2Comenzar un archivo nuevoStart a new filetreemaincontrol0TreeLine - Abrir ArchivoTreeLine - Open Filetreemaincontrol&TreeLine Uso BásicoTreeLine Basic Usagetreemaincontrol(TreeLine version {0}TreeLine version {0}treemaincontrol2Actualizar &Numeración...Update &Numbering...treemaincontrolPActualizar campos de numeración de nodosUpdate node numbering fieldstreemaincontrolXUsar condiciones de campo para filtrar nodos$Use field conditions to filter nodestreemaincontrolZUse condiciones de campo para encontrar nodos"Use field conditions to find nodestreemaincontrolZAdvertencia: no se pudo crear el socket local'Warning: Could not create local sockettreemaincontrol0Directorio no encontradomissing directorytreemaincontrolescrito por {}written by {0}treemaincontrol NuevoNewtreenodePrincipalMain treestructureVFiltrado condicional, encontrados {0} nodos&Conditional filtering, found {0} nodestreeviewTFiltrando por "{0}", encontrados.{1} nodos#Filtering by "{0}", found {1} nodestreeviewSiguiente: {0} Next: {0}treeview>Siguiente: {0} (no encontrado)Next: {0} (not found)treeviewBuscar: Search for:treeviewBuscar {0}Search for: {0}treeview6Buscar {0} (no encontrado)Search for: {0} (not found)treeview&Cerrar Ventana &Close Window treewindow*&Reducir Toda la Rama&Collapse Full Branch treewindow &Datos&Data treewindow&Editar&Edit treewindow,&Expandir Toda la Rama&Expand Full Branch treewindow&Archivo&File treewindow A&yuda&Help treewindow(Selección &Siguiente&Next Selection treewindow &Nodo&Node treewindow"Selección &Previa&Previous Selection treewindow&Mostrar Panel &Hijo&Show Child Pane treewindow&Herramientas&Tools treewindow&Ver&View treewindowVen&tana&Window treewindow&Cerrar esta ventanaClose this window treewindowdReducir todos los hijos de los nodos seleccionados+Collapse all children of the selected nodes treewindowEditor de Datos Data Edit treewindowSalida de Datos Data Output treewindowfExpandir todos los hijos de los nodos seleccionados)Expand all children of the selected nodes treewindow&FormatoFo&rmat treewindowhIr a la siguiente selección de árbol en el historial(Go to the next tree selection in history treewindow<Búsqueda incremental siguienteNext Incremental Search treewindow:Búsqueda incremental anteriorPrevious Incremental Search treewindowNVolver a la selección de árbol anterior%Return to the previous tree selection treewindowDMostrar &vista panel de navegaciónShow &Breadcrumb View treewindow2Mostrar &Lista de TítulosShow &Title List treewindow0Mostrar Editor de &DatosShow Data &Editor treewindow0&Mostrar Salida de DatosShow Data &Output treewindowPMostrar Salida de Datos y Des&cendientesShow Output &Descendants treewindowhMostrar el editor de datos en la vista de la derechaShow data editor in right view treewindow\Mostrar la salida de datos en la vista derechaShow data output in right view treewindowjMostrar la lista de títulos en la vista de la derechaShow title list in right view treewindow8Iniciar búsqueda incrementalStart Incremental Search treewindow Lista de Títulos Title List treewindow^Alternar mostrando vista anterior de navegación'Toggle showing breadcrumb ancestor view treewindow|Alternar mostrando la vista de salida sangría de descendients/Toggle showing output view indented descendants treewindow:Alternar mostrando resultados%Toggle showing right-hand child views treewindowˆTreeLine-3.2.1/translations/treeline_pt.qm000066400000000000000000002405261506556630100206360ustar00rootroot00000000000000<¸dÊÍ!¿`¡½Ý§pt_PTBðOdÉbB+;6+;¨+; +;@3+;y+;ªþ+;±ÕTÇ¥Ug\sW6c \>côg¤.AhD®mÔ3=xÆ9áÃe'§¤ÇÍÎVí§Ôܨ¡€k¨¥W,»�jÐ%„6ÐD…žì0ˆú^¡ú^Ï10KpW7þÍ8¨[ÐH5ÜH5œçU¥�;VE c ^/¬ôc2¬ôrå°5c`¹µ+Àe-ÏÇš¹µdð™Ç¬æÄ]E7~þ¼*‡›hº*¦yÏž*¨¡Þ*»*Ð%ª*ÖT®á*ÙEu*ì0à*ö5i'+U¥b+‹¯Ò³+Œ—+˜Å+˜ÅÓ/+¬ôGu+¶:²é+įÔ*+ÏÇ’/5ìÞ5S4 T;0®$avˆÜôæ‚‘ªS‡"¢'³}B¨w9§¨w9v”ª6•ìª6•w­–DÔ³°7ïg°gc ˲½z±C²×Ãf¶Š¥Ò6¸ÉÄ {º3 ì»f3U¼P³³½[y´)À´$±Âæw%oÒðMoÔÝC:U×(]áòn®ï¶°ÀÔñí~ïÒö}¯6øås¼¸ùeÔçüy°Rüy°º¥ÿ3Å�|cà× ßÄõ%v•ˆ>-„å$ò6n�n6n�Þb6n� ÑG^[RŽ5—<_ ÒÌfc®á ¢gΩ|Œÿˆà¾ßŒÛ‡] Ž‚Î«#�Í7/›Ó%U<žªîîn Z  ‡£�¹¤g²Òä̓³wiŠa³õeó³÷…Ói´~ŽbÇ~“£’Úù䉠Ý<~äžáCþjâJuƒºî ¤OûŽ4/Åû°%YççÃy¨Í7cÔtPW~ã×”ªY#­—†9ƒ“ø…9¼Ùž@mªDî¤+õNƒÞR ©pó[ó7—aLWXf@âq¸gáôxi 5½lwpÑ¡oFs¤öz¨F}'ÅÁ.~o‚I€.âC‚täJz…­‚ÈŒü$@’‡’ûœH‹FŸ_•V¹¨‡å¢°žõ³´¢o˜»Z F¼™£„­À —<$§#ˆÄϳ„Ð:Â…jÐGàh€Øú‰ çæþ¢ æþ¢w7ço^|<ìÝ.¯óAUæü ’ã¬T½îˆ.ô¨å”&=ô!L(�ÂæM+ƒôë‹5€´°«>?dè@{§$ÔFJ‰¡¾\8Â\ `}îfÈ4”ÇgNeÐÆh�‰ª/r…U|ƒÕ3‡sƒð}8u„`¼�òcPÑ‘³µ—þûg˜G%ÃÁ™ì5C~šÒcQR¬J‰¨«­ìÔ™´§T¹(Në!¼’.‚½¥•"¶¿kµ¶*Â+%[Æ"D9ÍÕϑ¸&ÏÄ®é0ÖeT)שD,YÜÇ:ìßßëÖàKg›DàÑ�çkH|è°Ô’õ÷ÑîõSå¾þ!žÀ5ÿîmcÿîmœœœt§d­-¿[�ÃѤ³T~nüJUän#ÂCHÕ#ÂCmÞ*”›·,ô9.ýÓÛ/œ´/œ´iW/œ´…Ô0Ä‘ò?Ãà,In3feL½„ àRüS•S"þv+ZzóÓZËÚÈh]¶¨¸Ü_PÔÆâb£#|íe,Å‘ÁfÅÎfÈŠ¹tgì„ïl¾Yr^¤(s�PÄÀu‚h�[�«I¾–Ti'ˆ .w¦~©¾ ­º|Lj°Ï¥1·ºÓMòÇ.€ýÇ.€‹áÇR�“Ë@å›vË˃ŒwΨê%@ÚéCýà7iÅúê_Î}¾ïÿE\ñ>_fóÙ"^ú¼Õ^âþ¸4ì,.ƒŠÿ&k³ Y&�t 2)õã&Ý/ð‹•0ndço7O«T„8OªT!CÎdiõP[FUô³'‰h¨¿SÇkÝþÐ#káNÿØn™óMCn™ó“n™óÄD}\”á�‡£oj‡ŒáØŽ–ãL“ —Nýàª/…È «ŒãA!«—â?¶ �¿ç[BeǨººôÏ”¶€ÐOã£ÕeÑè"up…ë»E¹(ô3¤�Ùõãpö§^ EüfOdgųOaª¯ðÚ ä; '§®J¥Â¬Ú,á0Ê1cD÷1cD¶Ñ9Hùks@ÍEl™Fy¯L¶Cf$WšÅ.¸[Ú%d]!™�n•#9ˆwƾ{0>ÓÆ��£E ‚ „!›ŠécÏŠéci¤Šéc†$�¤“ Ž–¼žI˜HnþšjTÎò£Â©¡&¤¢M~¹¦*)aз9³±~·áo1츆ž ºå^J¼ „!6¼�¥³Ç%%z}Ç%%ÇÎÈxN†̇µ/9ÌÉå:ÌË%{°ÔUåKòÔ¤?`ÙÞ¹»âß‚¥_ß—eÏÖévÔºSéâÙáÞë+™lð½^Ž\þm“÷ ÍœN \~²7 \~Òm ;´6h q#*s 4‰EoÄ 5µÔf :ró‘o Lìóx Mgþ f+>UÇ k¸ª­« †�£�š ¦8Õ@é ¨ #» ©Ï‰sy ±›“‰? ²b*˜8 ¸ldÁ| ¼ „bÅ Àª Þ ØøÜ¨ Ûʵ÷Ç ê�tX{ êØnç î�å9 øé½8 ÿ ÕY… cY–“ �a ­“í« .ƒtÈ ïî_ ¾Tg ÝW4Z ,_$.ó /öÄ2_ 4ñ„ ü 5rÕ€£ 7*å =äÃö IöTRå Ty ¿ Wܾ5Ö _Ò‰&¬ ap cÂóDû cĵô eÄ ( uo�· uõ5° w5y; �ăR_ ‚ò5Aù ‡1§© “¼:޳ ˜Iœ ˜Iœ³ ˜IœÞ ˜Iœ?­ ˜IœvÊ ˜IœªÉ ˜Iœ­à ˜IœÇP �C]Ž ŸÉ9VN ¤ îÁ «¦Êm ¬6"• ®5Õˆ ®ùµ%Ÿ ¯Þ3w ²Ê^Ò µ�IË µãã;É ¶ã 2# ¼ŒtÜú ¼Ëˆ(= ĽNýz Ë;:˜º ÍGc!ú Ð:âq Ð:âwÊ ÛãµE/ Ûãµw‚ Ûãµ®” Þ;±+ Þä5 ðe3•³ òóȈ{ ü˜ŽÂ: ü˜Ží= ÿôÅæ sŠ ½.z& Ð�Q t{ð Xšf çKA® )M¥¤ -ˆ8h .2ò& /.”£å 2 ÎÐ 5�…ú @(ešö A¨Z� Kºþ&= L¡. LÇ9ª… WÌè X�ò [t#“ rËWr x½( C x½(±ÿ :3ô2 € Íu, €Ùsxá ‹Ì·g ŒHÒí �õ� �Ü  �Ü 7 �ßZ²y ›i³ ›€;Q ªDÄG «Í(²³ ±à„G¢ ¹D' ¼BÓâ– ¼~ÓûÐ ¼šÙ©ï Ït®�± Ù·åÁ¸ ߺš³ï àKG¾ á²~ý ã\E#e ëÜXÄ óy~å» ó²8 vÕs §é¼n ÓìNÿ šE· áAX š+@\ PÔ" ¼%  Ö#:» Qô»3 ¿�Uü '{íñ (µECF 7±"*î 8Ç‘\Ò ;y7É =ÙÓ: @¿ÀžE Vÿõˆ dMY8 gÆ#1 pk¾æÆ t—¥ð" t©Ž$ tÁ�` v"¾; {B~3 ˆ=ÎFD ‰¡ã÷ ”Ëeq •h¥š- —M¥QÓ ŸèTÆ^ ¡žB ¡ô×™ £îò¦ ®�CÁ ¼°e½å Æm)«Á Ò¯ã\ Þv¥©W ãbnTç ê¬Dï ëUï6 îµÕÿ ðYƒÌÔ ûìó·œ þÖ\�L …‹Bô 'Üt .�“  0³uI 0ó£. 7yÒ6á CàÒ ! G9.ã× H³³ù4 Kz9m8 Kè„ ¡ Mîĉ ]`^W© _ _¾ dT& iØä2ÿ iÚ$hò iÚ$xQ zÿí h ƒÄ2° އÄQ ‘݃· œ|õ@¢ £ö=/k «c'ã ÇDãgò ×sH› ä~tÑ` í>Ó“`ûå-ê"Jχ»•`‡»Ì¾s”"­sKZ(t�†Ô-þ”k/+ã‰0ó/Sy0ô>S+9Äó7= # EjþVH;ÓešL`Ò#ôL¿Óh?LÊãeOLÝ^V�5Y‚—&ZrþÐjh€j`kŽ·Dlfc\p#C¶q¢ƒØ2tŽ“»D³®† …… ™Ï-]àš¥t�££±…†x²šb»‹¹ë ê º”tÕ‹¿ß:¼8ÉkeÞÌ-îÕÍ`EÑÔ•³¢¨ÚYe-öêhŸ~ë Ã;ëœt¯´îp|£þVC÷ã�g`¥êÕ¼;>�‚ uœKc mšRº(üÓ Ÿ6ãÅãt8 qa€<æÉËs@-®ÐHNލSIöô?æMÉÕ–&U⃠Z8n@[Kô„e3¿dem3J iFW=­r†Õ°^s$ÜLww³ Ö}$74…?y*†AÔ Œ�ç—â�Ô²6¤�ât$^¤žµDŠ´êâB°¹éŸðpº£Î¿¬½¡uñ2À$&­JÆ|�ÉŸ)¨âÛ];ŠÜííÝ®á�o8ÉáùÅñžåd…Ê7ëŠF¶ôßí\öé3f±ø6‰¬Yùfîb9i(;&Cancelar&Cancelcolorset&OK&OKcolorset*Adicionar &Nova Regra &Add New Rule conditional&Cancelar&Cancel conditional&Fechar&Close conditional&&Terminar Filtragem &End Filter conditionalF&iltrar&Filter conditional&OK&OK conditional&Eliminar Regra &Remove Rule conditional&Guardar&Save conditional FalsoFalse conditional&Encontrar &Seguinte Find &Next conditional&Encontrar &AnteriorFind &Previous conditionalLNenhum resultado satisfaz as condições!No conditional matches were found conditionalTipo de ramo Node Type conditionalRegra {0}Rule {0} conditionalVerdadeiroTrue conditional [Todos os Tipos] [All Types] conditionaleand conditional contémcontains conditionalacaba com ends with conditionalouor conditionalcomeça com starts with conditional&Aplicar&Apply configdialog&Cancelar&Cancel configdialogTipo de &Dados &Data Type configdialog&Eliminar Tipo &Delete Type configdialog,&Derivadar de Original&Derive from original configdialog&Equação &Equation configdialog.C&onfiguração de Campos &Field Config configdialogT&ipo de Campo &Field Type configdialog$&Ocultar Avançadas&Hide Advanced configdialog"Mover para &Baixo &Move Down configdialog&Novo Campo... &New Field... configdialog&Novo Tipo... &New Type... configdialog&OK&OK configdialog&Prefixo&Prefix configdialog &Repor&Reset configdialog&&Tipo de Resultados &Result Type configdialog"&Seleccionar Tudo &Select All configdialog$&Mostrar Avançadas&Show Advanced configdialog0&Critério de Ordenamento&Sort Criteria configdialog*&Formatação do Título &Title Format configdialogHAdicionar linhas &vazias entre ramosAdd &blank lines between nodes configdialogAdicionar Campo Add Field configdialogAdicionar TipoAdd Type configdialogFAdicionar ou Remover Tipos de DadosAdd or Remove Data Types configdialog6Adicionar &pontos de tópicoAdd text bullet&s configdialogBPermitir texto formatado em &HTMLAllow &HTML rich text in format configdialog,Operadores AritméticosArithmetic Operators configdialog"Tipos AutomáticosAutomatic Types configdialog8Lista de &Campos DisponíveisAvailable &Field List configdialog&Campos &DisponíveisAvailable &Fields configdialog"Resultado BoleanoBoolean Result configdialogvNão é possivel apagar tipo de dados em utilização por ramos+Cannot delete data type being used by nodes configdialogMudar &Ícone Change &Icon configdialog,Número de Descendentes Child Count configdialog2Referência a DescendentesChild Reference configdialog &Limpar Selecção Clear &Select configdialogCo&piar Tipo... Co&py Type... configdialogzCarácter de &Separação de Combinações e Lista de Descendentes+Combination && Child List Output &Separator configdialog0Operadores de ComparaçãoComparison Operators configdialog2Configurar Tipos de DadosConfigure Data Types configdialogCopiar Tipo Copy Type configdialog2&Criar Tipos CondicionaisCreate Co&nditional Types configdialog"Resultado de Data Date Result configdialogHValor pré &definido para novos ramosDefault &Value for New Nodes configdialogBTipo de &descendente pré definidoDefault Child &Type configdialogDefinir EquaçãoDefine Equation configdialogFDefinir equação do campo matemáticoDefine Math Field Equation configdialog&Eliminar Campo Dele&te Field configdialog4&Derivado de Tipo GenéricoDerived from &Generic Type configdialogDescrição Description configdialogDirecção Direction configdialog:Altura da Caixa de Introdução Editor Height configdialog>Introduza o nome do novo campo:Enter new field name: configdialog@Introduza novo nome para o tipo:Enter new type name: configdialog&Erro na equação: {}Equation error: {} configdialogvErro - referência cíclica em equações de campos matemáticos2Error - circular reference in math field equations configdialogTexto adicional Extra Text configdialog Ca&mpoF&ield configdialog Li&sta de Campos F&ield List configdialog CampoField configdialog Lista de &Campos Field &List configdialog(Referências a CamposField References configdialog6Informação sobre o ficheiroFile Info Reference configdialog$&Inverter DirecçãoFlip &Direction configdialog"&Ajuda de Formato Format &Help configdialog ÍconeIcon configdialog$Equação Matemática Math Equation configdialog4&Modificar Lista de CamposModify &Field List configdialog:&Modificar Tipos CondicionaisModify Co&nditional Types configdialog Mover para &CimaMove &Up configdialog"Mover para &Baixo Move Do&wn configdialog Mover para &cimaMove U&p configdialogNomeName configdialog NenhumNone configdialog4&Número de linhas de textoNum&ber of text lines configdialog"&Tipo de OperadorO&perator Type configdialog&ApresentaçãoO&utput configdialog(&Lista de OperadoresOper&ator List configdialogOperações Operations configdialog4Referências a outros campoOther Field References configdialog6&Formatação de ApresentaçãoOut&put Format configdialog0&Formato de ApresentaçãoOutpu&t Format configdialog,Opções de apresentaçãoOutput Options configdialog0Referência a AscendentesParent Reference configdialog&&Tipo de ReferênciaRefere&nce Type configdialog(&Nível de ReferênciaReference &Level configdialog&&Tipo de ReferênciaReference &Type configdialog(&Nível de ReferênciaReference Le&vel configdialogM&udar Nome...Rena&me Field... configdialog &Mudar o Nome...Rena&me Type... configdialogMudar Nome Rename Field configdialog"Mudar Nome a Tipo Rename Type configdialog,Mudar nome de {} para:Rename from {} to: configdialog"Referência à RaizRoot Reference configdialogAuto ReferênciaSelf Reference configdialog<Definir Ícone do Tipo de DadosSet Data Type Icon configdialog<Definir tipos condicionalmenteSet Types Conditionally configdialog:&Prioridade de Ordenamento... Sort &Keys... configdialog2Prioridade de OrdenamentoSort Key configdialog*Campos de OrdenamentoSort Key Fields configdialog&SufixoSuffi&x configdialog&Lista de Tipos T&ype List configdialog&Operadores de TextoText Operators configdialog"Resultado Textual Text Result configdialog\Os seguintes carácteres não são permitidos: {},The following characters are not allowed: {} configdialog2O nome não pode ser vazioThe name cannot be empty configdialog<O nome não pode conter espaçosThe name cannot contain spaces configdialogBO nome não pode começar com "xml" The name cannot start with "xml" configdialogBO nome deve começar com uma letra!The name must start with a letter configdialog*Nome já em utilizaçãoThe name was already used configdialog$Resultado de Tempo Time Result configdialog,Configuração de &Tipos Typ&e Config configdialogTipoType configdialogT&Utilizar uma tabela para dados dos camposUse a table for field &data configdialog[Nenhum][None] configdialogvalor absolutoabsolute value configdialogadicionaradd configdialogarco coseno arc cosine configdialogarco senoarc sine configdialogarco tangente arc tangent configdialog médiaaverage configdialog(logarítmo de base 10base-10 logarithm configdialog concatenar textoconcatenate text configdialog>converter texto para minúsculasconvert text to lower case configdialog>converter texto para maiúsculasconvert text to upper case configdialog$coseno de radianoscosine of radians configdialog&graus para radianosdegrees to radians configdialogdividirdivide configdialogigual aequal to configdialogfactorial factorial configdialogponto flutuantefloating point configdialog&Divisão arredondada floor divide configdialogDescendenteforward configdialogDescendentefwd configdialogmaior que greater than configdialogmaior ou igualgreater than or equal to configdialog inteiro superiorhigher integer configdialogxno 1º argumento, substituir o 2º argumento pelo 3º argumento(in 1st arg, replace 2nd arg with 3rd arg configdialogvjuntar texto utilizando o primeiro argumento como separador$join text using 1st arg as separator configdialogmenor que less than configdialog menor ou igual aless than or equal to configdialoge lógico logical and configdialogou lógico logical or configdialog inteiro inferior lower integer configdialog máximomaximum configdialog mínimominimum configdialog restomodulus configdialogmultiplicarmultiply configdialog8constante logarítmo natural natural log constant configdialog"logarítmo naturalnatural logarithm configdialogdiferente de not equal to configdialogconstante pi pi constant configdialogpotênciapower configdialog&radianos para grausradians to degrees configdialogAscendenterev configdialogAscendentereverse configdialog2arredondar para x dígitosround to num digits configdialog seno de radianossine of radians configdialograiz quadrada square root configdialogsubtrairsubtract configdialogsumatório sum of items configdialog(tangente de radianostangent of radians configdialogzverdadeiro se o 1º argumento de texto contiver o 2º argumento%true if 1st text arg contains 2nd arg configdialog‚verdadeiro se o 1º argumento de texto terminar com o 2º argumento&true if 1st text arg ends with 2nd arg configdialog€verdadeiro se o 1º argumento de texto começar com o 2º argumento(true if 1st text arg starts with 2nd arg configdialogNvalor verdadeiro, condição, valor falso"true value, condition, false value configdialog inteiro truncadotruncated integer configdialog$Procurar &Ficheiro&Browse for File dataeditors&Cancelar&Cancel dataeditors &Ir para Destino &Go to Target dataeditors&OK&OK dataeditors&Abrir Ligação &Open Link dataeditors&Abrir Imagem &Open Picture dataeditorsAbsolutoAbsolute dataeditorsEndereçoAddress dataeditors*Texto de Apresentação Display Name dataeditorsLigação Externa External Link dataeditors>Tipo de Caminho para o FicheiroFile Path Type dataeditorsLigação Interna Internal Link dataeditorsAbrir &Pasta Open &Folder dataeditors&Ligação para imagem Picture Link dataeditorsRelativoRelative dataeditorsProtocoloScheme dataeditorsData de &Hoje Today's &Date dataeditorsPTreeLine - Ligação para Ficheiro ExternoTreeLine - External Link File dataeditors:TreeLine - Ficheiro de ImagemTreeLine - Picture File dataeditors&Colunas&ColumnsexportsÁrvore &Inteira &Entire treeexports &HTML&HTMLexports4Favoritos em formato &HTML&HTML format bookmarksexportsÍndice &ODF &ODF Outlineexports>&Apenas descendentes expandidos&Only open node childrenexports$HTML Página &Única&Single HTML pageexports@&Títulos separados por tabulação&Tabbed title textexports &Texto&TextexportsXConteúdo não &formatado para todos os textos&Unformatted output of all textexports4Favoritos em formato &XBEL&XBEL format bookmarksexports&Favoritos Book&marksexportsFavoritos BookmarksexportsTEscolha o subtipo do formato de exportaçãoChoose export format subtypeexports>Escolha o formato de exportaçãoChoose export format typeexports>Escolha as opções de exportaçãoChoose export optionsexports.Exportação de ficheiros File ExportexportsPIncluir &cabeçalho e rodapé de impressãoInclude &print header && footerexportsbMultiplas páginas HTML com &tabelas de informaçãoMultiple HTML &data tablesexports\&Multiplas páginas HTML com barra de navegação)Multiple HTML &pages with navigation paneexports:&Níveis da barra de navegaçãoNavigation pane &levelsexportsOutras Opções Other Optionsexports.&Subramos SeleccionadosSelected &branchesexports(&Ramos SeleccionadosSelected &nodesexportsRHTML página única com barra de &navegação&Single &HTML page with navigation paneexports@TreeLine - Exportar XML GenéricoTreeLine - Export Generic XMLexports0TreeLine - Exportar HTMLTreeLine - Export HTMLexportsJTreeLine - Exportar Favoritos em HTML TreeLine - Export HTML Bookmarksexports:TreeLine - Exportar Texto ODFTreeLine - Export ODF TextexportsBTreeLine - Exportar Texto SimplesTreeLine - Export Plain TextexportsHTreeLine - Exportar Tabelas de TextoTreeLine - Export Text TablesexportsHTreeLine - Exportar Texto de TítulosTreeLine - Export Text TitlesexportsNTreeLine - Exportar Sub Árvore TreeLine"TreeLine - Export TreeLine SubtreeexportsJTreeLine - Exportar Favoritos em XBEL TreeLine - Export XBEL BookmarksexportsO que exportarWhat to ExportexportsCarácter "." .."." Character .. fieldformatCarácter "/" //"/" Character // fieldformat&0 Ou 1 Repetições ?0 Or 1 Repetitions ? fieldformat,0 ou Mais Repetições *0 Or More Repetitions * fieldformat,1 Ou Mais Repetições +1 Or More Repetitions + fieldformat&Qualquer carácter .Any Character . fieldformatAutoEscolha AutoChoice fieldformatAutoCombinaçãoAutoCombination fieldformatBoleanoBoolean fieldformat"Letra Maiúscula ACapital Letter A fieldformat4Numeral Romano Maiúsculo ICapital Roman Numeral I fieldformatEscolhaChoice fieldformatCombinação Combination fieldformatDataDate fieldformat"Vírgula Decimal ,Decimal Comma , fieldformatPonto Decimal .Decimal Point . fieldformatDDígito ou espaço (externo) <space>!Digit or Space (external)  fieldformatFim de texto $ End of Text $ fieldformat8Terminar Carácter Especial \Escape a Special Character \ fieldformatExemplo 1/2/3/4Example 1/2/3/4 fieldformat.Exponente (maiúscula) EExponent (capital) E fieldformat.Exponente (minúscula) eExponent (small) e fieldformatLigaçãoExterna ExternalLink fieldformatTextoHTMLHtmlText fieldformatLigaçãoInterna InternalLink fieldformat(Separador de Nível /Level Separator / fieldformat.Letras Minúsculas [a-z]Lower Case Letters [a-z] fieldformatMatemáticaMath fieldformat8Carácter não numérico [^0-9]Not a Number [^0-9] fieldformat AgoraNow fieldformat NúmeroNumber fieldformatNúmero 1Number 1 fieldformatNumeração Numbering fieldformatTextoLinhaUnica OneLineText fieldformat"Dígito Opcional #Optional Digit # fieldformat Sinal Opcional -Optional Sign - fieldformatOu |Or | fieldformatFExemplo de Índice I../A../1../a)/i)!Outline Example I../A../1../a)/i) fieldformat ImagemPicture fieldformat ExpressãoRegularRegularExpression fieldformat(Dígito Obrigatório 0Required Digit 0 fieldformat&Sinal Obrigatório +Required Sign + fieldformat2Exemplo de Secção 1.1.1.1Section Example 1.1.1.1 fieldformat*Separador de Secção .Section Separator . fieldformatSeparador / Separator / fieldformat2Conjunto de Números [0-9]Set of Numbers [0-9] fieldformat"Letra Minúscula aSmall Letter a fieldformat4Numeral Romano Minúsculo iSmall Roman Numeral i fieldformatJEspaço de Separação (interno) <space>"Space Separator (internal)  fieldformatTextoEspaçado SpacedText fieldformatV/FT/F fieldformat TextoText fieldformat TempoTime fieldformat.Letras Maiúsculas [A-Z]Upper Case Letters [A-Z] fieldformatS/NY/N fieldformat verdadeiro/falso true/false fieldformatsim/nãoyes/no fieldformat falsofalse genbooleannãono genbooleanverdadeirotrue genbooleansimyes genboolean$Todos os Ficheiros All Files globalrefFicheiros HTML HTML Files globalrefFicheiros ODFODF Text Files globalrefFicheiros PDF PDF Files globalref$Ficheiros de Texto Text Files globalref$Ficheiros TreeLineTreeLine Files globalref@Ficheiros TreeLine - ComprimidosTreeLine Files - Compressed globalref@Ficheiros TreeLine - EncriptadosTreeLine Files - Encrypted globalref"Ficheiros Treepad Treepad Files globalrefFicheiros XML XML Files globalrefEncontrar:  Find: helpview&Retroceder&Backhelpview&Avançar&Forwardhelpview&Início&Homehelpview&Encontrar &Seguinte Find &Nexthelpview&Encontrar &AnteriorFind &Previoushelpview(Texto não encontradoText string not foundhelpviewFerramentasToolshelpview–"{0}" não é um ficheiro TreeLine válido. Utilizar um filtro de importação?:"{0}" is not a valid TreeLine file. Use an import filter?importsf&XML Genérico (ficheiro não específico do TreeLine) &Generic XML (non-TreeLine file)importsHFavoritos em &HTML (Formato Mozilla) &HTML bookmarks (Mozilla Format)imports^&Texto recuado por tabulação, um ramo por linha%&Tab indented text, one node per lineimports:&Favoritos XML (Formato XBEL)&XML bookmarks (XBEL format)importsFAVORITOBOOKMARKimportsFavoritos Bookmarksimports:Escolher Método de ImportaçãoChoose Import MethodimportsTErro - não foi possível ler o ficheiro {0}Error - could not read file {0}importsPErro - formato de ficheiro impróprio {0}Error - improper format in {0}imports PASTAFOLDERimports"Importar Ficheiro Import Fileimports"Ficheiro Inválido Invalid FileimportsLigaçãoLinkimports6Índice &Open Document (ODF)Open &Document (ODF) outlineimports|&Parágrafos de texto simples (delimitados por linha em branco)-Plain text ¶graphs (blank line delimited)importsSEPARADOR SEPARATORimports TABELATABLEimports„Tabela de texto delimitada por tabulação com &cabeçalhos e colunas)Tab delimited text table with header &rowimports TextoTextimports8TreeLine - Importar FicheiroTreeLine - Import FileimportsR&Ficheiro Treepad (ramos de texto apenas)Treepad &file (text nodes only)importsvReferências a descendentes devem ser combinadas numa função/Child references must be combined in a functionmatheval0Carácteres "{0}" ilegaisIllegal "{}" charactersmatheval6Função ilegal presente: {0}Illegal function present: {0}mathevalNOperador ou tipo de objecto ilegal: {0}$Illegal object type or operator: {0}matheval2Sintaxe ilegal na equaçãoIllegal syntax in equationmatheval&Aplicar&Apply miscdialogs&Cancelar&Cancel miscdialogs&Fechar&Close miscdialogs &Terminar Filtro &End Filter miscdialogs&Toda a árvore &Entire tree miscdialogs&Filtrar&Filter miscdialogs&Encontrar &Seguinte &Find Next miscdialogs&Ascendente&Forward miscdialogs"&Ignorar e saltar&Ignore and skip miscdialogs0&Palavras chave parciais &Key words miscdialogs&Tipo de ramo &Node Type miscdialogs&OK&OK miscdialogsH&Campos de ordenamento pré definidos&Predefined Key Fields miscdialogs$&Expressão regular&Regular expression miscdialogs&Substituir&Replace miscdialogsP&Reiniciar contagem para próximos irmãos"&Restart numbers for next siblings miscdialogs2&Restaurar pré definições&Restore Defaults miscdialogs&Descendente&Reverse miscdialogs &Pesquisar Texto &Search Text miscdialogs2&Descendentes da Selecção&Selection's children miscdialogsApenas &Títulos &Titles only miscdialogs,&Barras de Ferramentas &Toolbars miscdialogs@&Tratar campos vazios como zeros&Treat blank fields as zeros miscdialogs@Utilizar &compressão de ficheiro&Use file compression miscdialogsNUtilizar fonte pré definida do &sistema&Use system default font miscdialogs--Separador-- --Separator-- miscdialogs*Comandos &DisponíveisA&vailable Commands miscdialogs(&Qualquer ocorrência Any &match miscdialogs&Remover Atalho Clear &Key miscdialogsBPersonalizar Barra de FerramentasCustomize Toolbars miscdialogsInformaçãoData miscdialogsMenu Informação Data Menu miscdialogsFPré definido - Texto em linha únicaDefault - Single Line Text miscdialogs EditarEdit miscdialogsMenu Editar Edit Menu miscdialogs@Tipo de Letra da Vista de EdiçãoEditor View Font miscdialogsHPalavra Passe de Ficheiro EncriptadoEncrypted File Password miscdialogsBErro - Expressão Regular inválida"Error - invalid regular expression miscdialogs4Erro - substituição falhouError - replacement failed miscdialogs&Frase completa F&ull phrase miscdialogs CamposFields miscdialogsFicheiroFile miscdialogsMenu Ficheiro File Menu miscdialogs0Propriedades do FicheiroFile Properties miscdialogs2Armazenamento do Ficheiro File Storage miscdialogsFiltrarFilter miscdialogsEncontrarFind miscdialogs&Encontrar &Seguinte Find &Next miscdialogs&Encontrar &AnteriorFind &Previous miscdialogs,Encontrar e SubstituirFind and Replace miscdialogs$Toda a &informação Full &data miscdialogs&Palavras &Completas Full &words miscdialogsVCritério para Ramos sem Campos de Numeração'Handling Nodes without Numbering Fields miscdialogs AjudaHelp miscdialogsMenu Ajuda Help Menu miscdialogsComo pesquisar How to Search miscdialogsDIcluir ramos dos níveis superioresInclude top-level nodes miscdialogs2Palavras chave &completasKey full &words miscdialogs4Tecla {0} já em utilizaçãoKey {0} is already used miscdialogs$Atalhos de TecladoKeyboard Shortcuts miscdialogsXCódigo de linguagem ou dicionário (opcional)&Language code or dictionary (optional) miscdialogsÍcones Grandes Large Icons miscdialogs$Campos Matemáticos Math Fields miscdialogs"Mover para &Baixo Move &Down miscdialogs Mover para &CimaMove &Up miscdialogs"&Campos dos Ramos N&ode Fields miscdialogsxNão foram encontrados campos de numeração nos tipos de dados,No numbering fields were found in data types miscdialogsRamoNode miscdialogs$Títulos dos &Ramos Node &Titles miscdialogsMenu Ramo Node Menu miscdialogs:Tipo de Letra de ApresentaçãoOutput View Font miscdialogs$&Expressão regularRe&gular expression miscdialogs:Re-Introduza a Palavra Passe:Re-Type Password: miscdialogsTPalavras passe introduzidas são diferentesRe-typed password did not match miscdialogsVLembrar a palavra passe durante esta sessão%Remember password during this session miscdialogs"Substituir &Todos Replace &All miscdialogsDForam substituidas {0} ocorrênciasReplaced {0} matches miscdialogs,Texto de &SubstituiçãoReplacement &Text miscdialogs"&Reservar númerosReserve &numbers miscdialogsRaiz Root Node miscdialogsPTermos de pesquisa "{0}" não encontradosSearch string "{0}" not found miscdialogsLTermo de pesquisa "{0}" não encontradoSearch text "{0}" not found miscdialogs(Ramos &SeleccionadosSelected &branches miscdialogs&&Irmãos da selecçãoSelection's &siblings miscdialogs2&Descendentes da selecçãoSelection's childre&n miscdialogsÍcones Pequenos Small Icons miscdialogs.Direcção de OrdenamentoSort Direction miscdialogs*Método de Ordenamento Sort Method miscdialogsOrdenar Ramos Sort Nodes miscdialogs(Verificar Ortografia Spell Check miscdialogsBComandos da &Barra de FerramentasTool&bar Commands miscdialogs@&Tamanho da Barra de Ferramentas Toolbar &Size miscdialogs>Número de Barras de FerramentasToolbar Quantity miscdialogsFerramentasTools miscdialogs Menu Ferramentas Tools Menu miscdialogs.Tipo de Letra da ÁrvoreTree View Font miscdialogs$Numeração TreeLineTreeLine Numbering miscdialogsJIntroduza a palavra passe para "{0}":Type Password for "{0}": miscdialogs4Introduza a Palavra Passe:Type Password: miscdialogs<Actualizar Numeração dos RamosUpdate Node Numbering miscdialogsBUtilizar &encriptação de ficheiroUse file &encryption miscdialogsVerView miscdialogsMenu Ver View Menu miscdialogsOnde pesquisarWhat to Search miscdialogsO que Ordenar What to Sort miscdialogs O que ActualizarWhat to Update miscdialogs JanelaWindow miscdialogsMenu Janela Window Menu miscdialogsPPalavras passe vazias não são permitidas'Zero-length passwords are not permitted miscdialogs"[Todos os Campos] [All Fields] miscdialogs [Todos os Tipos] [All Types] miscdialogsNomeName nodeformatAparência Appearanceoptiondefaults&Gravação Automática Auto Saveoptiondefaults^Abrir automaticamente último ficheiro utilizado!Automatically open last file usedoptiondefaultspRecuo dos descendentes (em unidades de altura da fonte) +Child indent offset (in font height units) optiondefaultsDClicar nos ramos para alterar nomeClick node to renameoptiondefaults6Formatos do Editor de DadosData Editor Formatsoptiondefaults DatasDatesoptiondefaults6Funcionalidades DisponíveisFeatures Availableoptiondefaults,Primeiro dia da semanaFirst day of weekoptiondefaultsSexta-FeiraFridayoptiondefaultsJMinutos entre gravações (0 desactiva)+Minutes between saves (set to 0 to disable)optiondefaultsSegunda-FeiraMondayoptiondefaults\Número de ficheiros recentes no menu ficheiro(Number of recent files in the file menuoptiondefaults6Número de passos a desfazerNumber of undo levelsoptiondefaults@Abrir ficheiros em novas janelasOpen files in new windowsoptiondefaults$Ficheiros Recentes Recent FilesoptiondefaultsBEditar nome de ramos após criaçãoRename new nodes when createdoptiondefaultsLRepor a anterior disposição de janelas Restore previous window geometryoptiondefaultsrRestaurar o estado de visualização dos ficheiros recentes(Restore tree view states of recent filesoptiondefaults SábadoSaturdayoptiondefaultsZMostrar descendentes na vista de apresentaçãoShow descendants in output viewoptiondefaultsBMostrar ícones na vista em árvoreShow icons in the tree viewoptiondefaultsZMostrar campos matemáticos na Vista de Edição&Show math fields in the Data Edit viewoptiondefaults\Mostrar campos de numeração na Vista de Edição+Show numbering fields in the Data Edit viewoptiondefaults$Opções de ArranqueStartup ConditionoptiondefaultsDomingoSundayoptiondefaultsQuinta-FeiraThursdayoptiondefaults TempoTimesoptiondefaultsZPermitir arrastar e largar na vista da árvoreTree drag && drop availableoptiondefaultsTerça-FeiraTuesdayoptiondefaults(Memória de operações Undo MemoryoptiondefaultsQuarta-Feira Wednesdayoptiondefaults&Cancelar&Canceloptions&OK&OKoptions`Escolher localização do ficheiro de configuração"Choose configuration file locationoptionsXPasta do programa (para utilização portátil)$Program directory (for portable use)optionsBPasta do utilizador (recomendado)#User's home directory (recommended)options8Erro ao iniciar a impressoraError initializing printer printdata.TreeLine - Exportar PDFTreeLine - Export PDF printdata &Base:&Bottom: printdialogs&Cancelar&Cancel printdialogsB&Desenhar linhas até descendentes&Draw lines to children printdialogs &Árvore completa &Entire tree printdialogs &Fonte&Font printdialogs$Selecção de &Fonte&Font Selection printdialogs&Opções Gerais&General Options printdialogs,&Esquerda do Cabeçalho &Header Left printdialogs"&Cabeçalho/Rodapé&Header/Footer printdialogs&Incluir Raiz&Include root node printdialogsZ&Manter primeiro descendente com o ascendente&Keep first child with parent printdialogs&Esquerda:&Left: printdialogs$&Número de colunas&Number of columns printdialogs&OK&OK printdialogs&Prefixo&Prefix printdialogs&Imprimir... &Print... printdialogs&Direita:&Right: printdialogs&Sufixo&Suffix printdialogs &Topo:&Top: printdialogs&Unidades&Units printdialogs\Utilizar a fonte de apresentação do &TreeLine &Use TreeLine output view font printdialogs&Largura:&Width: printdialogs"A3 (279 x 420 mm)A3 (279 x 420 mm) printdialogs"A4 (210 x 297 mm)A4 (210 x 297 mm) printdialogs"A5 (148 x 210 mm)A5 (148 x 210 mm) printdialogs>AaBbCcDdEeFfGg...TtUuVvWvXxYyZzAaBbCcDdEeFfGg...TtUuVvWvXxYyZz printdialogs Centímetros (cm)Centimeters (cm) printdialogsColunasColumns printdialogs*Tamanho personalizado Custom Size printdialogs$Fonte Pré Definida Default Font printdialogsTexto Extra Extra Text printdialogs(Páginas Consecutivas Facing Pages printdialogs OpçõesFeatures printdialogs&CamposFiel&ds printdialogs&&Formato dos Campos Field For&mat printdialogs6Formato de campo para "{0}"Field Format for "{0}" printdialogs Ajustar à PáginaFit Page printdialogs"Ajustar à Largura Fit Width printdialogs &Estilo de Fonte Font st&yle printdialogs&Rodapé:Foot&er: printdialogs&E&squerda do Rodapé Footer &Left printdialogs$Ce&ntro do RodapéFooter Ce&nter printdialogs$Direi&ta do Rodapé Footer Righ&t printdialogs"&Ajuda de Formato Format &Help printdialogs&Cabeçalho:He&ader: printdialogs*&Direita do Cabeçalho Header &Right printdialogs(&Centro do CabeçalhoHeader C&enter printdialogs$Cabeçalho e RodapéHeader and Footer printdialogsAltura:Height: printdialogsPolegadas (pol) Inches (in) printdialogsRamos IncluídosIncluded Nodes printdialogs AvançoIndent printdialogsj&Distancia do Avanço (em unidades de altura de linha)"Indent Offse&t (line height units) printdialogsAo &alto Lan&dscape printdialogs*Legal (8.5 x 14 pol.)Legal (8.5 x 14 in.) printdialogs*Carta (8.5 x 11 pol.)Letter (8.5 x 11 in.) printdialogsMargensMargins printdialogsMilímetros (mm)Millimeters (mm) printdialogsPágina Seguinte Next Page printdialogsPApenas descendentes de ramos &expandidosOnl&y open node children printdialogsOrientação Orientation printdialogs0Formato de &ApresentaçãoOutput &Format printdialogs.Configuração de &Página Page &Setup printdialogs"&Tamanho do Papel Paper &Size printdialogsAo &baixo Portra&it printdialogsPágina Anterior Previous Page printdialogsImprimirPrint printdialogs@&Previsualização de Impressão...Print Pre&view... printdialogs8Previsualização de Impressão Print Preview printdialogs.Definições de Impressão Print Setup printdialogs&Opções de impressãoPrinting Setup printdialogsAmostraSample printdialogs"Seleccionar Fonte Select Font printdialogsF&Ramos e descendentes seleccionadosSelected &branches printdialogs(Ramos &SeleccioandosSelected &nodes printdialogs&TamanhoSi&ze printdialogsPágina única Single Page printdialogs4&Espaçamento entre colunasSpace between colu&mns printdialogs.Tablóide (11 x 17 pol.)Tabloid (11 x 17 in.) printdialogsO que imprimir What to print printdialogsAproximarZoom In printdialogsAfastarZoom Out printdialogs&Adicionar&Add spellcheck&Cancelar&Cancel spellcheckIgnorar &Todas &Ignore All spellcheck&Substituir&Replace spellcheck0Adicionar em &MinúsculasAdd &Lowercase spellcheckContexto:Context: spellcheck®Não foi possível encontrar aspell.exe, ispell.exe ou hunspell.exe Procurar localização?QCould not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? spellcheckBTerminada verificação ortográficaFinished spell checking spellcheck&IgnorarIgnor&e spellcheck`Localizar aspell.exe, ispell.exe ou hunspell.exe-Locate aspell.exe, ipsell.exe or hunspell.exe spellcheck*Ausente no DicionárioNot in Dictionary spellcheck Programa (*.exe)Program (*.exe) spellcheck"S&ubstituir Todas Re&place All spellcheck.Verificação Ortográfica Spell Check spellcheck>Erro de Verificação OrtográficaSpell Check Error spellcheckSugestões Suggestions spellcheck@Verificação Ortográfica TreeLineTreeLine Spell Check spellcheckÐErro de verificação Ortográfica do TreeLine Cerifique-se que aspell, ispell ou hunspell estão instaladosLTreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed spellcheckPalavra:Word: spellcheckPRÉ DEFINIDODEFAULT treeformats ÍconeIcon treeformats&Negrito &Bold Fonttreelocalcontrol&Copiar&Copytreelocalcontrol&Eliminar Ramo &Delete Nodetreelocalcontrol&Exportar... &Export...treelocalcontrol&&Ligação Externa...&External Link...treelocalcontrol"&Tamanho do texto &Font Sizetreelocalcontrol&Recuar Ramo &Indent Nodetreelocalcontrol&Itálico &Italic Fonttreelocalcontrol Mover para &Cima&Move Uptreelocalcontrol&Nova Janela &New Windowtreelocalcontrol C&olar&Pastetreelocalcontrol&Imprimir... &Print...treelocalcontrol&Refazer&Redotreelocalcontrol&Mudar Nome&Renametreelocalcontrol&Guardar&Savetreelocalcontrol*Definir &Tipo de Ramo&Set Node Typetreelocalcontrol0&Verificar Ortografia...&Spell Check...treelocalcontrol&Desfazer&UndotreelocalcontrolA&vançar Ramo&Unindent Nodetreelocalcontrol,Adicionar De&scendente Add &ChildtreelocalcontrolB&Adicionar Nível por Categoria...Add Category &Level...treelocalcontrolNAdicionar sub ramo ao ramo seleccionado Add new child to selected parenttreelocalcontroltAdicionar ou modificar uma ligação externa para a internet!Add or modify an extrnal web linktreelocalcontroltAdicionar ou modificar uma ligação interna para outro ramo#Add or modify an internal node linktreelocalcontrolVNão é possível expandir sem campos em comum#Cannot expand without common fieldstreelocalcontrol(Campos de CategoriasCategory Fieldstreelocalcontrol$Limpar &FormataçãoClear For&mattingtreelocalcontrolhRemover a formatação do texto actual ou seleccionado)Clear current or selected text formattingtreelocalcontrolJColapsar descendentes juntando campos&Collapse descendants by merging fieldstreelocalcontrolDCopiar Tipos de Outro &Ficheiro...Copy Types from &File...treelocalcontrolbCopiar o ramo ou texto para a memória de trabalho(Copy the branch or text to the clipboardtreelocalcontrol\Copiar configuração de outro ficheiro TreeLine1Copy the configuration from another TreeLine filetreelocalcontrolCor&tarCu&ttreelocalcontrolbCortar o ramo ou texto para a memória de trabalho'Cut the branch or text to the clipboardtreelocalcontrol NormalDefaulttreelocalcontrol>Eliminar os ramos seleccionadosDelete the selected nodestreelocalcontrolhErro - não foi possível apagar cópia de segurança {}'Error - could not delete backup file {}treelocalcontrolTErro - não foi possível ler o ficheiro {0}Error - could not read file {0}treelocalcontrol`Erro - não foi possível escrever para o ficheiroError - could not write to filetreelocalcontrolLErro - não é possível escrever para {}Error - could not write to {}treelocalcontrol^Exportar o ficheiro em diversos outros formatos(Export the file in various other formatstreelocalcontrolhExportar para PDF com as actuais opções de impressão+Export to PDF with current printing optionstreelocalcontrol Ficheiro gravado File savedtreelocalcontrol,&Nivelar por categoriaFlatten &by Categorytreelocalcontrol Co&r do Texto...Font C&olor...treelocalcontrol<Avançar os ramos seleccionadosIndent the selected nodestreelocalcontrol*Inserir Irmão &DepoisInsert Sibling &Aftertreelocalcontrol(Inserir Irmão &AntesInsert Sibling &Beforetreelocalcontrol~Insere ramos sobre descendentes classificanado segundo um campo$Insert category nodes above childrentreelocalcontrolHInserir novo ramo abaixo da selecção"Insert new sibling after selectiontreelocalcontrolFInserir novo ramo acima da selecção#Insert new sibling before selectiontreelocalcontrol&Ligação &Interna...Internal &Link...treelocalcontrol GrandeLargetreelocalcontrol MaiorLargertreelocalcontrolMuito GrandeLargesttreelocalcontrol"Mover para &Baixo M&ove Downtreelocalcontrol(Colocar em &Primeiro Move &Firsttreelocalcontrol$Colocar em &Último Move &LasttreelocalcontrolNMover para baixo os ramos seleccionadosMove the selected nodes downtreelocalcontrolŠMover os ramos seleccionados para que sejam os primeiros descendentes0Move the selected nodes to be the first childrentreelocalcontrol†Mover os ramos seleccionados para que sejam os últimos descendentes/Move the selected nodes to be the last childrentreelocalcontrolLMover para cima os ramos seleccionadosMove the selected nodes uptreelocalcontrolDAbrir nova vista do mesmo ficheiro#Open a new window for the same filetreelocalcontrol6&Definições de Impressão...P&rint Setup...treelocalcontrolVColar ramos ou texto da memória de trabalho&Paste nodes or text from the clipboardtreelocalcontrolbColar texto sem formatação da memória de trabalho+Paste non-formatted text from the clipboardtreelocalcontrol*Imprimir para &PDF...Print &to PDF...treelocalcontrol8Pré &visualizar impressão...Print Pre&view...treelocalcontroltImprimir apresentação da árvore baseada nas opções actuais*Print tree output based on current optionstreelocalcontrol &Propriedades...Prop&erties...treelocalcontrol:Repõe a última acção desfeitaRedo the previous undotreelocalcontrolTAlterar o nome da entrada actual na árvore#Rename the current tree entry titletreelocalcontrol Guardar &Como... Save &As...treelocalcontrol Guardar Ficheiro Save Filetreelocalcontrol2Guardar alterações em {}?Save changes to {}?treelocalcontrol&Guardar alterações? Save changes?treelocalcontrol2Guardar o ficheiro actualSave the current filetreelocalcontrolFGuardar o ficheiro com um novo nomeSave the file with a new nametreelocalcontrol@Seleccione campo para novo nívelSelect fields for new leveltreelocalcontrol0Definir tamanho do texto Set Font Sizetreelocalcontrol(Definir Tipo de Ramo Set Node TypetreelocalcontrolxDefinir parâmetros do ficheiro como compressão e encriptação3Set file parameters like compression and encryptiontreelocalcontrol|Definir margens, tamanho de papel e outras opções de impressão1Set margins, page size and other printing optionstreelocalcontrolbDefinir o tamanho do texto actual ou seleccionado(Set size of the current or selected texttreelocalcontrolZDefinir a cor do texto actual ou seleccionado-Set the color of the current or selected texttreelocalcontrolfDefinir o texto actual ou seleccionado como negrito(Set the current or selected font to boldtreelocalcontrolfDefinir o texto actual ou seleccionado como itálico*Set the current or selected font to italictreelocalcontrollDefinir o texto actual ou seleccionado como sublinhado-Set the current or selected font to underlinetreelocalcontrolfDefinir o tipo de dados para os ramos seleccionados$Set the node type for selected nodestreelocalcontrollMostrar uma pré visualização do resultado da impressão"Show a preview of printing resultstreelocalcontrolPequenoSmalltreelocalcontrolRTreeLine - Abrir Ficheiro de Configuração"TreeLine - Open Configuration Filetreelocalcontrol.TreeLine - Guardar ComoTreeLine - Save Astreelocalcontrol&SublinhadoU&nderline Fonttreelocalcontrol,Reverte a última acçãoUndo the previous actiontreelocalcontrol:Recuar os ramos seleccionadosUnindent the selected nodestreelocalcontrol,&Acerca do TreeLine...&About TreeLine...treemaincontrol*Utilização &Básica...&Basic Usage...treemaincontrol<&Cancelar Abertura de Ficheiro&Cancel File Opentreemaincontrol.&Procura Condicional...&Conditional Find...treemaincontrol:&Configurar Tipos de Dados...&Configure Data Types...treemaincontrol4&Apagar Cópia de Segurança&Delete Backuptreemaincontrol&&Encontrar Texto... &Find Text...treemaincontrol2&Documentação Completa...&Full Documentation...treemaincontrol"&Opções Gerais...&General Options...treemaincontrol&Importar... &Import...treemaincontrol&Novo...&New...treemaincontrol&Abrir...&Open...treemaincontrol &Sair&Quittreemaincontrol:&Restaurar Cópia de Segurança&Restore Backuptreemaincontrol"&Seleccionar Tudo &Select Alltreemaincontrol,&Seleccione um exemplo&Select Sampletreemaincontrol&Seleccionar &Modelo&Select Templatetreemaincontrol&Filtro de &Texto...&Text Filter...treemaincontrol°Cópia de segurança {0} existente. Uma sessão anterior pode ter terminado inesperadamenteƒXg¤9"hD tmÔ>.xÆEÃ…§¤ñ8ÍÎl‹§Ô[¨¡¨¨¥m(®û⻨ùÐ%«­ÐD¬ëì0¯˜ú^&»ú^ý0K”7þ]48¨vH5(øH5ÃNU¥´&VE)#c {TžEÿЬô�O¬ô˜ °5�}¹µ Àe7¾ÏÇÀ 0KQŸ¹µ„ê™ÇìVæÄzP7~>'&ñ²xÊ(F"¬* •úR*‡›‰m*¦yy*¨¡`¯*»`á*Ð%ao*ÖTØ£*ÙS*ì0a�*ö5‰Î+5t Ç+U¥b+‹¯ +Œ@ +˜Å u+˜Åæ+¬ôUö+¶:ܱ+įã+ÏÇcK/5)ö5S4&;0®.àxB,ÙaÓDß jWJlTaJŠÃÆJÚûµLƒ• ®Lü$$ÕO($)²RˆÕ®TƒŠ uUwÓ}´V®Â•HW�Të¬XW—:Y¾îËYÙĈOZ8,7öZy%ÿ´[ÃÒÕ[f3Šþ[f3½p\`ðí^#[^hzù�ecâêeqå©7g„}w—hzÔ ¢lƒ•„—wmÂDiwÓ´{u}�«|˜³œUS3¾�lãVû�ýt*Öƒ©å=£‹[³¡š�`~1 �¨c`ð�¨cî}”¬MHq”ã}u©›”¥,æ¡$³ ¡fE;~¡·õ:û¢â3P ¯EJž°J…VȼGUV#ÅDŒË ÁIÏ‹yÞOЄÛr”Ñ~eúïÔBs`'ÖîÕÅ5Ø1d:¸Þ›àùµ0òáSÃ4¤ð­§c§ò8ÞZ]õGýAä" Y žºe# Ö/41ØõX˜4FT!Ý4MÓŒ52{£B"ýlE¹% “H*aNÐLõãùWà*O²eôžðÃf`‡7sj.~uo‡t¨}|{yÞ£~s”ªÃ~âò„B>ð†„Ûtö˜õ„âAžœwô¨¦œY(©ªKø­/^o·±¯Äõµ½‡ ™¶b6M‹XÂøÃ³Çî÷H/×M® �×½«RæÜ·”*¢ÝŠ¥–â N—r kãsáó:QuwU«Ùy¨Äd9}X=4[†¯“í6veG{‚RŽ5½«]û‚ _ Ò÷[c®á˜gÎC x?™È<|Œ>àˆàè·Œ-¬üyŒÛ‡zŽ‚ÎÔÍ�ÍBF›Ó%jÖžªî+¢£�¹Ìý¯¿´_/²Òäør³õe0´³÷…$´~Žbµ¢ ·å0¡·™ù–0ÄÒÞ&'Ç~“ËbÒ®ét*Úùä±Ý<~ýáCþWžâJu«1â¿èræî ¤/ûŽ4:šû°%r,çßËÍB~Ôtd«‰UI~ã SªNt#­½õ.EùÍ1¸Sö9ƒ“6²9¼ Ö@ŽADî¤6ÉNƒZXN¥$m”R ©•uXŒMvÏ[óB´aLn¾aËM.f@â–ÿgáôž:i 5S³lwpõl¿Ó-oFsÍ”z¨T}'ÅêÖ~o©Ä€.ù‚tä[�…­ª5Œü$$^’‡’•œH²Ÿ_•l[¨‡åÉá°ž3W´¢’i»Zc÷¼™£¬À —Gw§#°LËÁ2¼ϳ«Ð:¬¯ÐGà‰=Ö“„­ÿÖ“„üGØú‰ÆŸáòëæþ¢ -æþ¢�bço^¢©ìÝ.ØÕí¨T "óAUb¡ü ’ïýx5‚¼¤$ê¬Tç„îf.Y†<³C¨å%–&=ôdÛ(�Âæ+ƒô(©5€´Ú}6a²í�>?dª@B“ Y@{§iâFJ‰É¢\8Ây¯`}îClfÈ4»LgNe hŒT`ph�‰ÓÛr…kx½þ]‚òý~ƒÕ3¯ ƒð}C–„`T˜�òce'‘³µXP—þ;˜G%í]™ì5O¹šÒce¬ŸN¢#÷«ÍÿR¬J‰Ò]­ìÔB´§T[¾¹(N!¼’.D½¥•-Y¿kµßúÂ+%Q…Æ"DÍ"�Ï‘Ââ‰ÏÄ®ãÖeT4ל©R שD7+Ø™É\YÜÇ:!¶ßßëéàKgÁÛàѵëçkH`Uè°Ô¹õ÷FõSåWøþ!žéùÿîm 5ÿîmÃNs ´œt­[�ìÂѤÝ2cyL6~n;÷Uä� #ÂCWã#ÂCŽë&Ã$!y*”ÂF,ôD-.ýÓFÏ/œ´ Û/œ´Š/œ´­0ĸ�?ÃêIn3‡\L½„ÆRüS»™S"þ›ÚZzó ™ZËÚò‰]¶¨ã3_PÔðýb£#£fe,ŸJfÅÎR,fÈŠãÓgì„%l¾?Êr^¤3y�PÄê9‚h�uNƒn×l.ŒZYv�«IèU–Ti2œ 9T¦~©çö­º|ñ¡°Ï¥<®ºÓa9¼ÀãÏ Æ¢ªÇ.€(Ç.€²µÇR�(«Ë@å Ë˃³ŠΨê/ÙÚéP£à7iï¾áeÓJã7ÒxYê_ΤÂïÿE0ñ>|™óÙeíú¼Õ|þ¸4)DYTL.ƒ±Ñ&k³?&�tI(m3S«)õãlÚ/ð²i0nd.7O«iô8Oªi‘CÎdŠ–P[(^R£9W]SU“9Uô³mt]1³#­h¨¿i=kÝþUkáN?=n™ó`¢n™ó¹}n™óî*p˜k€{ìÒ¾U}\”/ƒ¼n'V‡£o‹6Œá 3–ã_¼Ÿ¯‚r —N=M¢ˆu“¢ª/…ò&«ŒãLý«—âJB¶ ¿ç[NvǨºåeË›ô¦£Ï”àDÐOãÊìÕeWè"u”Ìë»Eãƒô3¤©võã[ ö§^MhüfO„eųc¹ª¯.” äFP'Ц®a¥ÂÖ¤*Se®?,á0@A1cD$ 1cDá.9HùŒ4@ÍE�6Fy§ L¶C‡#WšÅ9“Yí˜J[Ú%„%]!À4bùbð n•#D³wƾQ.yŒ‘ƒ {0>}��£SI‚ „,‡×9\aŠéc %ŠécŠIŠéc­c�¤“+)–¼žDê˜Hn&šjTû<£Â©ÈÒ¤¢M¥³¦*)»ª¬•mTµ„¥üÅ·9³ÛH·áo<縆žâºå^!¼ „+ż�Î3Ç%% œÇ%%ñíÈxbÔ̇µ: ÌÉåE0ÌË%¢ÔUå^˜Ô¤?~ÔÞ¹æUß‚¥5ß—e¹évÔäºéâÙxë+™Œ¶ð½^µ1þm“ÝþÒ·�Œ �Õ$p ÍÂÏ \~Ûÿ \~É ;´Ag q#5S ƒ-þÔ !í„"< 4‰E’• 5µ :ró·ì Fè´à• LìóGZ Mgþ â f+>k] k¸ª×y †�£·7  d”ú‘ ¦8ÕLÁ ¨ .4 ©Ï‰™6 ¬\lÊ ­˜¤ÿç ¯bÝŽu ±›“°½ ²b*¿ ¸ldë ¼ „€¸ ¿ß¡‚’ ÀªK– Á ]I Áí_¨ Ã,óú ØøÜz Ûʵ6 ê�tp¤ êØn© î�åSG ñž“" ÿ Õq¾ ÿŽÚ_4 cY½ � ­“*Ç .ƒšs ïî|@ ¾T‡ê Êóä ÝW?E ,_$9Ì /öÄ=V 4ñ„d• 5rÕ¨> 7*åô =äíâ IöTh[ Ty èç UÇÎl Wܾ@Ó _Ò‰1À a’à cÂóQÙ cÄßÄ eÄ uo´ž uõ5 = w5Ÿf �ăf¹ ‚ò5N ‡1ÑQ ŒÅÓþ �É3†» “¼:µŽ ˜Iœ ˜Iœ‹ ˜Iœ¾ ˜IœJæ ˜Iœœ÷ ˜IœÔw ˜Iœ×° ˜Iœñm �CzŸ �8rÃw ŸÉ9kò ¤ +í «¦õZ ¬,…ö ¬6"Cè ®5ÕX¶ ®ùµ08 ¯Þ>V ²Ê^° µ�Iö( µããG ¶ã = ¼ŒtH ¼Ëˆ3= ĽN<ñ Ë;:¿ƒ ÍGc,Ÿ Ð:â „ Ð:â�û ÛãµRà Ûãµ�¹ ÛãµØ` Þ;±T Þä5Ð ðe3¼6 òóȰ ü˜ŽëÞ ü˜Ž*K ÿôÅAW s±� ½. ? ÐÄ] t¢a XÁ çKMÇ )M¥*W -ˆ8@ .2/Ô /.”Ìe 2 Î&ì 5�…9 9²3C @(eÁ“ A¨t¢ KsOñ Kºþ1U L¡.?� LÇ9ÔA WÌè Ñ X´Ù [thX fô¤8à pI3…x rËW—i x½(! x½(Ûà {uÅb� :31Î € ÍšÙ €ÙsŸ ‹ÌáÖ ŒHž �õÄ* �Ü á �Ü @À �ßZÜ= ›i³]h ›€Fž ªDÄUˆ «Í(Üu ®˜ ¯–]w= ±à„Vv ´¹i{ ¹D2F ¹¾´mû ¼BÓ6 ¼~Ó;‡ ¼šÙÓ£ Ït®¶n ÖAeÙ Ù·åëX ߺšÝà àKGcw á²~<� ã\E-î ëÜpí ëù^( óy~F ó²C! vÕ˜Ê §éæõ ÓìcU šEPé áMƒ š+K� PÔ'J ¼%ÆH Ö#F Qôå¶ l”oh ¿�k  #“ýß '{í v (µEOw * •ü 2l,[ 7±"5Î 8Ç‘yß ;yBè =ÙÓ)V @|5"¾ VÿõA dMqq gÆ#< pk¾_ t—¥-Þ t©Ž.ƒ tÁ�~ v"¾ {B¥' €ÿüû{ ˆ=ÎT» ‰¡ãGÛ ”ËeP© •h¥ÀÊ —M¥f- ŸèTð} ¡žU ¡ô×¿Ï £î0R ®�C_ »²4¤7 ¼°eç· Æh‚6 Æm)Õ[ Ò¯ãYê Þv¥Ó ãbnj‰ ê¬DD< ëU,f îµÕ ðYƒ÷à ûìóâ þÖ\¶ñ …‹O “Äe¹ 'Ü™» .�“]÷ 0³uX 0ó£"à 3±þ• 7yÒAò CàÒJõ G9.à H³³7G Kz9�Í Kè„LC MîÄw Nðp> ]`^o _ |ñ a*Ç’ dTº iØä=ú iÚ$‰› iÚ$ž„ m¢.ÿ zÿíJH ~Dµ$ €¢LÓ ƒÄ2Ù¹ Ž‡Ä  ‘݃á� œ|õKá Ÿúâý £ö=:B «c2ã ºDDþ ˜S˱ ÇD㈿ ÌÈV2 ×sW« ä~t¤ í>Ó¹Ï ûîs§S ÿ»:nNû¢·Éƒ� ¼fæcÆÖê"[Ї»»á‡»÷¾sº§­s^(t�®€(·©ƒÓ-þºò/+ã'©0ó/hó0ô>h©9Äó!= -ŸEj=»H;Ó†AL`Òh½L¿Ó‰LÊã…?LÝ^aÑV�?öY‚—jòZrþ¨]~ÓEIh€j"i?ÃkŽ· lfcFXp#PTp£#‹q¢ƒ ãtŽº>t/C…ÌD³EÀ† …¬_�^A82™Ï-zûš¥tÄ¥£±…­³­–g沚bæ¹ë £º”t@¿ß:æ¿Ék†}Ì-îÉÍ`E )Ô•³ÊxÕ�ý_hÚYe8Íà˜9”=êhŲë Ã%IëœtÙpîp£þVC§¢ã´R`ϰÕUŒ;>bM‚ ›EKcKšRäi(üÓMÆ6ãÅg8 qm<æÉör@-®”HNŽÑ÷IöôKMÉÕ¼ŸU⃢Z8nA©[Kô!^e3é6em3YiFWHôr†ÕÚs$–ww³¼|*½^‰}$7`…?y4ê†AÔïŒ�ç¾Ã�Ó�\Æ�Ô²A«–ž x�]&¿�âtiŸ2Isâm£}D¤žµQ,¬nç�™¯#Hs\´êâNϹéŸ.(º£Î鄽¡u.îÀ$&ׯ| aÉŸ)ÒœËî)üÏ~Ä%�Û]FÕÜíí¦á�oCðáùÅ/TãÊog9åd…õëŠU+ôßíyöé3‡¢ø6‰Öùfî€ in&B<5=0&Cancelcolorset&OK&OKcolorset &25B D>=0 :=>?:8Button background colorcolorset$&25B H@8DB0 :=>?:8Button text colorcolorset 0AB@>9:0 &25B>2Color Settingscolorset&25B>20O "5<0 Color Themecolorset$&25B0 >;L7>20B5;O Custom Colorscolorset""5<0 ?>;L7>20B5;O Custom themecolorset"5<=0O B5<0 Dark themecolorset2"5<0 A8AB5<K ?> C<>;G0=8NDefault system themecolorset(&25B D>=0 8=B5@D59A0Dialog background colorcolorset,&25B H@8DB0 8=B5@D59A0Dialog text colorcolorset:&25B H@8DB0 =50:B82=>9 :=>?:8Disabled button text colorcolorset<&25B H@8DB0 =50:B82=>3> B5:AB0Disabled text foreground colorcolorset.&25B H@8DB0 38?5@AAK;:8Link text colorcolorset 01@0BL {0} F25BSelect {0} colorcolorset@&25B D>=0 2K1@0==>3> ?C=:B0 <5=NSelected item background colorcolorsetD&25B H@8DB0 2K1@0==>3> ?C=:B0 <5=NSelected item text colorcolorset<&25B D>=0 M;5<5=B>2 8=B5@D59A0Text widget background colorcolorsetN&25B D>=0 A8<2>;>2 M;5<5=B>2 8=B5@D59A0Text widget foreground colorcolorset&25B0 "5<K Theme Colorscolorset>&25B D>=0 2A?;K20NI59 ?>4A:07:8Tool tip background colorcolorsetP&25B D>=0 A8<2>;>2 2A?;K20NI59 ?>4A:07:8Tool tip foreground colorcolorset.&>1028BL >2>5 @028;> &Add New Rule conditional&B<5=0&Cancel conditional&0:@KBL&Close conditional&#40;8BL&Delete conditional,@5:@0B8BL &$8;LB@0F8N &End Filter conditionalB&D8;LB@>20BL&Filter conditional&03@C78BL&Load conditional&OK&OK conditional &#40;8BL @028;> &Remove Rule conditional&!>E@0=8BL&Save conditional>6LFalse conditional 09B8 &!;54CNI89 Find &Next conditional"09B8 &@54K4CI89Find &Previous conditional<O:Name: conditionalZ#4>2;5B2>@ONI85 CA;>28N A>2?045=8O =5 =0945=K!No conditional matches were found conditional"8? #7;0 Node Type conditional@028;> {0}Rule {0} conditional&!>E@0=5==K5 @028;0 Saved Rules conditional AB8=0True conditional[A5 "8?K] [All Types] conditional8and conditionalA>45@68Bcontains conditional>:0=G8205BAO =0 ends with conditional8;8or conditional=0G8=05BAO A starts with conditional&@8<5=8BL&Apply configdialog&B<5=0&Cancel configdialog"8? &0==KE &Data Type configdialog&#40;8BL "8? &Delete Type configdialog20A;54>20BL >B &8AB>G=8:0&Derive from original configdialog&K@065=85 &Equation configdialog0AB@>9:0 &>;O &Field Config configdialog"8? &>;O &Field Type configdialog@&!:@KBL >?>;=8B5;L=K5 0AB@>9:8&Hide Advanced configdialog"5@5<5AB8BL &=87 &Move Down configdialog&>2>5 >;5... &New Field... configdialog&>2K9 "8?... &New Type... configdialog&OK&OK configdialog&@8AB02:0&Prefix configdialog&!1@>A8BL&Reset configdialog&"8?  57C;LB0B0 &Result Type configdialogK1@0BL &A5 &Select All configdialogD>:070BL &>?>;=8B5;L=K5 0AB@>9:8&Show Advanced configdialog(@8B5@88 &!>@B8@>2:8&Sort Criteria configdialog"$>@<0B &03>;>2:0 &Title Format configdialogH>1028BL &?CABK5 AB@>:8 <564C C7;0<8Add &blank lines between nodes configdialog>1028BL >;5 Add Field configdialog>1028BL "8?Add Type configdialog@>1028BL 8;8 #40;8BL "8?K 0==KEAdd or Remove Data Types configdialog0>1028BL &<0@:5@K B5:AB0Add text bullet&s configdialogV#G8BK20BL ?@8 D>@<0B8@>20=88 &HTML-@07<5B:CAllow &HTML rich text in format configdialog0@8D<5B8G5A:85 ?5@0B>@KArithmetic Operators configdialog&2B><0B8G5A:85 "8?KAutomatic Types configdialog0!?8A>: >?CAB8<KE &>;59Available &Field List configdialog >?CAB8<K5 &>;OAvailable &Fields configdialogDB>3>2>5 =0G5=85 >38G5A:>3> "8?0Boolean Result configdialogt52>7<>6=> C40;8BL B8?, 2 C7;0E :>B>@>3> A>45@60BAO 40==K5+Cannot delete data type being used by nodes configdialog!<5=8BL &=0G>: Change &Icon configdialogB'8A;> >4AG8B0==KE >G5@=8E #7;>2 Child Count configdialog:!AK;:0 =0 >;5 >G5@=53> #7;0Child Reference configdialog>3@0=8G5=8O "8?0 >G5@=53> #7;0Child Type Limits configdialogG8AB8BL &K1>@ Clear &Select configdialog&!&:>?8@>20BL "8?... Co&py Type... configdialog~& 0745;8B5;L =0G5=89 "8?0 ><18=0F8O && !?8A:>2 >G5@=8E #7;>2+Combination && Child List Output &Separator configdialog&?5@0B>@K !@02=5=8OComparison Operators configdialog,0AB@>9:0 "8?>2 0==KEConfigure Data Types configdialog>?8@>20BL "8? Copy Type configdialog>4AG8B0BLCount configdialog,!>740BL #&A;>2=K5 "8?KCreate Co&nditional Types configdialogB>3>20O 0B0 Date Result configdialogL=0G5=85 ?> &#<>;G0=8N 4;O >2KE #7;>2Default &Value for New Nodes configdialog@"8? &>G5@=53> #7;0 ?> #<>;G0=8NDefault Child &Type configdialog 040BL K@065=85Define Equation configdialogJ040BL K@065=85 0B5<0B8G5A:>3> >;ODefine Math Field Equation configdialog&#40;8BL >;5 Dele&te Field configdialogF!45;0BL @>872>4=K< >B &1I53> "8?0Derived from &Generic Type configdialog?8A0=85 Description configdialog0?@02;5=85 Direction configdialog*KA>B0 >;O  540:B>@0 Editor Height configdialog02548B5 8<O =>2>3> ?>;O:Enter new field name: configdialog02548B5 8<O =>2>3> B8?0:Enter new type name: configdialog,H81:0 2 2K@065=88: {}Equation error: {} configdialogzH81:0  F8:;8G5A:0O AAK;:0 2 2K@065=8OE <0B5<0B8G5A:>3> ?>;O2Error - circular reference in math field equations configdialog*?@545;OBL B538 &HTMLEvaluate &HTML tags configdialog(>?>;=8B5;L=K9 "5:AB Extra Text configdialog &>;5F&ield configdialog!?8A>: &>;59 F&ield List configdialog>;5Field configdialog!?8A>: &>;59 Field &List configdialog!AK;:8 =0 >;5Field References configdialog8!AK;:0 =0 =D>@<0F8N > $09;5File Info Reference configdialog(!<5=8BL &0?@02;5=85Flip &Direction configdialog4!?@02:0 ?> &$>@<0B8@>20=8N Format &Help configdialog =0G>:Icon configdialog00B5<0B8G5A:>5 K@065=85 Math Equation configdialog,7<5=8BL !?8A>: &>;59Modify &Field List configdialog.7<5=8BL &#A;>2=K5 "8?KModify Co&nditional Types configdialog$5@5<5AB8BL &25@EMove &Up configdialog"5@5<5AB8BL &=87 Move Do&wn configdialog$5@5<5AB8BL &25@EMove U&p configdialog<OName configdialog8 >48=None configdialog&&'8A;> AB@>: B5:AB0Num&ber of text lines configdialogB>3>2>5 '8A;> Number Result configdialog('8A;> >G5@=8E #7;>2Number of Children configdialog"8? &?5@0B>@0O&perator Type configdialog &K2>4O&utput configdialog$!?8A>: &?5@0B>@>2Oper&ator List configdialog?5@0F88 Operations configdialog*!AK;:8 =0 @C385 >;OOther Field References configdialog$>@<0B &K2>40Out&put Format configdialog$>@<0B &K2>40Outpu&t Format configdialogK2>4 2 HTML Output HTML configdialog?F88 K2>40Output Options configdialogB!AK;:0 =0 >;O  >48B5;LA:>3> #7;0Parent Reference configdialog"8? &!AK;:8Refere&nce Type configdialog&#@>25=L !AK;:8Reference &Level configdialog&"8? !AK;:8Reference &Type configdialog&#@>25=L !AK;:8Reference Le&vel configdialog,5&@58<5=>20BL >;5...Rena&me Field... configdialog*&5@58<5=>20BL "8?...Rena&me Type... configdialog$5@58<5=>20BL >;5 Rename Field configdialog"5@58<5=>20BL "8? Rename Type configdialog,5@58<5=>20BL 87 {} 2:Rename from {} to: configdialog:!AK;:0 =0 >;5 >@=52>3> #7;0Root Reference configdialog$5 K1@0BL &8G53> Select &None configdialog4!AK;:0 =0 >;O !2>53> #7;0Self Reference configdialog807=0G8BL =0G>: "8?0 0==KESet Data Type Icon configdialogN07=0G8BL "8?K 2 7028A8<>AB8 >B #A;>289Set Types Conditionally configdialog(;NG8 &!>@B8@>2:8... Sort &Keys... configdialog;NG !>@B8@>2:8Sort Key configdialog*>;O ;NG0 !>@B8@>2:8Sort Key Fields configdialog&:>=G0=85Suffi&x configdialog!?8A>: &"8?>2 T&ype List configdialog&"5:AB>2K5 ?5@0B>@KText Operators configdialogB>3>2K9 "5:AB Text Result configdialogB!;54CNI85 A8<2>;K =54>?CAB8<K: {},The following characters are not allowed: {} configdialog0<O =5 <>65B 1KBL ?CABK<The name cannot be empty configdialog<<O =5 <>65B A>45@60BL ?@>15;KThe name cannot contain spaces configdialog><O =5 <>65B =0G8=0BLAO A "xml" The name cannot start with "xml" configdialog:<O 4>;6=> =0G8=0BLAO A 1C:2K!The name must start with a letter configdialog(<O C65 8A?>;L7>20=>The name was already used configdialogB>3>2>5 @5<O Time Result configdialog0AB@>9:0 &"8?0 Typ&e Config configdialog"8?Type configdialogJA?>;L7>20BL B01;8FC 4;O &40==KE ?>;OUse a table for field &data configdialog([A5 "8?K >?CAB8<K][All Types Available] configdialog&01A>;NB=>5 7=0G5=85absolute value configdialogA;>68BLadd configdialog0@::>A8=CA arc cosine configdialog0@:A8=CAarc sine configdialog0@:B0=35=A arc tangent configdialogA@54=55average configdialog&45AOB8G=K9 ;>30@8D<base-10 logarithm configdialog0AF5?8BL B5:AB>2K5 AB@>:8concatenate text configdialogH?@5>1@07>20BL B5:AB 2 =86=89 @538AB@convert text to lower case configdialogJ?@5>1@07>20BL B5:AB 2 25@E=89 @538AB@convert text to upper case configdialog$:>A8=CA 2 @0480=0Ecosine of radians configdialog"3@04CAK 2 @0480=Kdegrees to radians configdialog@0745;8BLdivide configdialog @02=>equal to configdialogD0:B>@80; factorial configdialog?;020NI0O B>G:0floating point configdialog*F5;>G8A;5==>5 45;5=85 floor divide configdialog 2?5@54forward configdialog>>fwd configdialog1>;LH5 G5< greater than configdialog 1>;LH5 8;8 @02=>greater than or equal to configdialog&1>;LH55 F5;>5 G8A;>higher integer configdialogh70<5=8BL 2 1-< 0@3C<5=B5 2-9 0@3C<5=B 3-< 0@3C<5=B><(in 1st arg, replace 2nd arg with 3rd arg configdialog˜?@8A>548=8BL B5:AB, 8A?>;L7CO 7=0G5=85 1-3> 0@3C<5=B0 2 :0G5AB25 @0745;8B5;O$join text using 1st arg as separator configdialog<5=LH5 G5< less than configdialog <5=LH5 8;8 @02=>less than or equal to configdialog;>38G5A:>5  logical and configdialog;>38G5A:>5  logical or configdialog&<5=LH55 F5;>5 G8A;> lower integer configdialog<0:A8<C<maximum configdialog<8=8<C<minimum configdialog <>4C;Lmodulus configdialogC<=>68BLmultiply configdialog@>A=>20=85 =0BC@0;L=>3> ;>30@8D<0natural log constant configdialog(=0BC@0;L=K9 ;>30@8D<natural logarithm configdialog=5 @02=> not equal to configdialogG8A;> ?8 pi constant configdialog$2>725AB8 2 AB5?5=Lpower configdialog"@0480=K 2 3@04CAKradians to degrees configdialog<<rev configdialog>A<5=8BL =0?@02;5=85 =0 >1@0B=>5reverse configdialog6>:@C3;8BL 4> G8A;0 @07@O4>2round to num digits configdialog A8=CA 2 @0480=0Esine of radians configdialog":204@0B=K9 :>@5=L square root configdialog2KG5ABLsubtract configdialogAC<<0 M;5<5=B>2 sum of items configdialog$B0=35=A 2 @0480=0Etangent of radians configdialogr8AB8=0, 5A;8 1-9 B5:AB>2K9 0@3C<5=B A>45@68B 2-9 0@3C<5=B%true if 1st text arg contains 2nd arg configdialog~8AB8=0, 5A;8 1-9 B5:AB>2K9 0@3C<5=B >:0=G8205BAO 2-< 0@3C<5=B><&true if 1st text arg ends with 2nd arg configdialogl8AB8=0, 5A;8 1-9 0@3C<5=B =0G8=05BAO A> 2-3> 0@3C<5=B0(true if 1st text arg starts with 2nd arg configdialogV8AB8==>5 7=0G5=85, CA;>285, ;>6=>5 7=0G5=85"true value, condition, false value configdialog*CA5G5==>5 F5;>5 G8A;>truncated integer configdialog&>8A: $09;0&Browse for File dataeditors&B<5=0&Cancel dataeditors&5@59B8 : &5;8 &Go to Target dataeditors&OK&OK dataeditors(&B:@KBL 8?5@AAK;:C &Open Link dataeditors(&B:@KBL 7>1@065=85 &Open Picture dataeditorsP;8:=8B5 =0 F5;52CN 38?5@AAK;:C 2 45@525(Click link target in tree) dataeditors1A>;NB=K9Absolute dataeditors 4@5AAddress dataeditors*G8AB8BL &8?5@AAK;:C Clear &Link dataeditors>:070BL <O Display Name dataeditors&=5H=OO 8?5@AAK;:0 External Link dataeditors.040BL "8? CB8 : $09;CFile Path Type dataeditors,=CB@5==OO 8?5@AAK;:0 Internal Link dataeditorsB:@KBL &0?:C Open &Folder dataeditors48?5@AAK;:0 =0 7>1@065=85 Picture Link dataeditorsB=>A8B5;L=K9Relative dataeditors!B@C:BC@0Scheme dataeditors8#AB0=>28BL &!53>4=OH=NN 0BC Set to &Now dataeditors"!53>4=OH=OO &0B0 Today's &Date dataeditorsLTreeLine  8?5@AAK;:0 =0 =5H=89 $09;TreeLine - External Link File dataeditors<TreeLine  $09; A 7>1@065=85<TreeLine - Picture File dataeditors38?5@AAK;:0link dataeditors&!B>;1FK&Columnsexports|"01;8F0 ?>B><:>2 (=><5@0 C@>2=59), @07<5G5==0O &70?OBK<8 (CSV);&Comma delimited (CSV) table of descendants (level numbers)exports&A5 5@52> &Entire treeexports &HTML&HTMLexports00:;04:8 2 D>@<0B5 &HTML&HTML format bookmarksexports.&:;NG8BL :>@=52K5 C7;K&Include root nodesexports!B@C:BC@0 &ODF &ODF Outlineexports>&!B0@0O 25@A8O Treeline (2.0.x)&Old TreeLine (2.0.x)exports<&">;L:> >B:@KBK5 4>G5@=85 C7;K&Only open node childrenexports048=>G=0O AB@0=8F0 &HTML&Single HTML pageexports@&"01C;8@>20==K9 B5:AB 703>;>2:>2&Tabbed title textexports &"5:AB&Textexports&>445@52> &TreeLine&TreeLine SubtreeexportsJ&5D>@<0B8@>20==K9 2K2>4 2A53> B5:AB0&Unformatted output of all textexports00:;04:8 2 D>@<0B5 &XBEL&XBEL format bookmarksexports$&XML (>1I53> 2840)&XML (generic)exports0&:;04:8 Book&marksexports0:;04:8 BookmarksexportsHK15@8B5 ?>4B8? D>@<0B0 4;O M:A?>@B0Choose export format subtypeexportsBK15@8B5 B8? D>@<0B0 4;O M:A?>@B0Choose export format typeexports6K15@8B5 =0AB@>9:8 M:A?>@B0Choose export optionsexports”"01;8F0 4>G5@=8E C7;>2, @07<5G5==0O &70?OBK<8 (CSV) (548=AB25==K9 C@>25=L)7Comma &delimited (CSV) table of children (single level)exportsÐH81:0  =52>7<>6=> CAB0=>28BL AAK;:C =0 =5A>E@0=5==K9 D09; Treeline. !>E@0=8B5 D09; 8 ?>?@>1C9B5 A=>20.FError - cannot link to unsaved TreeLine file. Save the file and retry.exports-:A?>@B $09;0 File ExportexportsN&:;NG8BL 25@E=89 && =86=89 :>;>=B8BC;KInclude &print header && footerexportsœ=B5@0:B82=K9 ?@>A<>B@ 45@520, ?@82O70==>3> : D09;C Treeline (4;O 251-A5@25@0)8Live tree view, linked to TreeLine file (for web server)exports‚=B5@0:B82=K9 ?@>A<>B@ 45@520, >48=>G=K9 D09; (2AB@>5==K5 40==K5)+Live tree view, single file (embedded data)exportsP=>3>AB@0=8G=K9 HTML A B01;8F0<8 &40==KEMultiple HTML &data tablesexportsR=>3>AB@0=8G=K9 &HTML A ?0=5;LN =02830F88)Multiple HTML &pages with navigation paneexportsP5@54 M:A?>@B>< 4>;6=K 1KBL 2K1@0=K C7;K!Must select nodes prior to exportexports8&#@>2=8 =02830F8>==>9 ?0=5;8Navigation pane &levelsexports @C385 0AB@>9:8 Other Optionsexports >48B5;LParentexports K1@0==K5 &25B28Selected &branchesexportsK1@0==K5 &C7;KSelected &nodesexportsX48=>G=0O AB@0=8F0 &HTML A ?0=5;LN =02830F88&Single &HTML page with navigation paneexports~"01;8F0 4>G5@=8E C7;>2, @07<5G5==0O Tab (&548=AB25==K9 C@>25=L)0Tab &delimited table of children (&single level)exportsTree&Line Tree&LineexportsHTreeLine  -:A?>@B 2 XML 1I53> 840TreeLine - Export Generic XMLexports2TreeLine  -:A?>@B 2 HTMLTreeLine - Export HTMLexportsDTreeLine  -:A?>@B 2 0:;04:8 HTML TreeLine - Export HTML Bookmarksexports<TreeLine  -:A?>@B 2 ODF "5:ABTreeLine - Export ODF TextexportsDTreeLine  -:A?>@B 2 @>AB>9 "5:ABTreeLine - Export Plain TextexportsLTreeLine  -:A?>@B 2 "5:AB>2K5 "01;8FKTreeLine - Export Text TablesexportsHTreeLine  -:A?>@B 03>;>2:>2 "5:AB0TreeLine - Export Text TitlesexportsNTreeLine  -:A?>@B 2 >445@52> Treeline"TreeLine - Export TreeLine SubtreeexportsDTreeLine  -:A?>@B 2 0:;04:8 XBEL TreeLine - Export XBEL Bookmarksexportsº=8<0=85  >BACBAB2C5B >B=>A8B5;L=K9 ?CBL >B{0} : {1}. @>4>;68BL, 8A?>;L7CO 01A>;NB=K9 ?CBL?LWarning - no relative path from "{0}" to "{1}". Continue with absolute path?exports$'B> -:A?>@B8@>20BLWhat to Exportexports"." !8<2>; .."." Character .. fieldformat"/" !8<2>; //"/" Character // fieldformat 0 ;8 1 >2B>@ ?0 Or 1 Repetitions ? fieldformat,0 ;8 >;55 >2B>@>2 *0 Or More Repetitions * fieldformat,1 ;8 >;55 >2B>@>2 +1 Or More Repetitions + fieldformat AM/PMAM/PM %p fieldformatN1>9 !8<2>; .Any Character . fieldformat2B>K1>@ AutoChoice fieldformat2B>><18=0F8OAutoCombination fieldformat>38G5A:89 "8?Boolean fieldformat"03;02=0O C:20 ACapital Letter A fieldformat203;02=0O  8<A:0O &8D@0 ICapital Roman Numeral I fieldformat K1>@Choice fieldformat><18=0F8O Combination fieldformat, 0745;8B5;L 0?OB0O \,Comma Separator \, fieldformat0B0Date fieldformat0B0 8 @5<ODateTime fieldformat05=L (1 8;8 2 F8D@K) %-dDay (1 or 2 digits) %-d fieldformat"5=L (2 F8D@K) %dDay (2 digits) %d fieldformat65=L >40 (>B 1 4> 366) %-jDay of year (1 to 366) %-j fieldformat(5AOB8G=0O 0?OB0O ,Decimal Comma , fieldformat$5AOB8G=0O ">G:0 .Decimal Point . fieldformat >4AG5B >B><:>2DescendantCount fieldformatF&8D@0 8;8 @>15; (2=5H=89) <space>!Digit or Space (external)  fieldformat6 0745;8B5;L 2 2845 ">G:8 \.Dot Separator \. fieldformat>=5F !B@>:8 $ End of Text $ fieldformatH-:@0=8@>20=85 !?5F80;L=>3> !8<2>;0 \Escape a Special Character \ fieldformat1@075F 1/2/3/4Example 1/2/3/4 fieldformat:A=>20=85 AB5?5=8 (1>;LH>5) EExponent (capital) E fieldformat6A=>20=85 AB5?5=8 (<0;>5) eExponent (small) e fieldformat&=5H=OO 8?5@AAK;:0 ExternalLink fieldformat8'0A (0-23, 1 8;8 2 F8D@K) %HHour (0-23, 1 or 2 digits) %-H fieldformat.'0A (00-23, 2 F8D@K) %HHour (00-23, 2 digits) %H fieldformat.'0A (01-12, 2 F8D@K) %IHour (01-12, 2 digits) %I fieldformat:'0A (1-12, 1 8;8 2 F8D@K) %-IHour (1-12, 1 or 2 digits) %-I fieldformat,"5:AB A @07<5B:>9 HTMLHtmlText fieldformat,=CB@5==OO 8?5@AAK;:0 InternalLink fieldformat* 0745;8B5;L #@>2=59 /Level Separator / fieldformat:C:2K 2 86=5<  538AB@5 [0-O]Lower Case Letters [a-z] fieldformat&0B5<0B8G5A:>5 >;5Math fieldformat08:@>A5:C=40 (6 F8D@) %fMicroseconds (6 digits) %f fieldformat48=CB0 (1 8;8 2 F8D@K) %-MMinute (1 or 2 digits) %-M fieldformat&8=CB0 (2 F8D@K) %MMinute (2 digits) %M fieldformat25AOF (1 8;8 2 F8D@K) %-mMonth (1 or 2 digits) %-m fieldformat$5AOF (2 F8D@K) %mMonth (2 digits) %m fieldformat<!>:@0I5==>5 0720=85 5AOF0 %bMonth Abbreviation %b fieldformat$0720=85 5AOF0 %B Month Name %B fieldformat5 &8D@0 [^0-9]Not a Number [^0-9] fieldformat !53>4=O 8 !59G0ANow fieldformat '8A;>Number fieldformat><5@ 1Number 1 fieldformatC<5@0F8O Numbering fieldformat$4=>AB@>G=K9 "5:AB OneLineText fieldformat,5>1O70B5;L=0O &8D@0 #Optional Digit # fieldformat*5>1O70B5;L=K9 =0: -Optional Sign - fieldformat  |Or | fieldformat@1@075F 0:5B0 I../A../1../a)/i)!Outline Example I../A../1../a)/i) fieldformat7>1@065=85Picture fieldformat( 53C;O@=>5 K@065=85RegularExpression fieldformat(1O70B5;L=0O &8D@0 0Required Digit 0 fieldformat$5>1E>48<K9 =0: +Required Sign + fieldformat6!5:C=40 (1 8;8 2 F8D@K) %-SSecond (1 or 2 digits) %-S fieldformat(!5:C=4a (2 F8D@K) %SSecond (2 digits) %S fieldformat.1@075F  0745;0 1.1.1.1Section Example 1.1.1.1 fieldformat, 0745;8B5;L  0745;>2 .Section Separator . fieldformat 0745;8B5;L / Separator / fieldformat 01>@ &8D@ [0-9]Set of Numbers [0-9] fieldformat !B@>G=0O 1C:20 aSmall Letter a fieldformat0!B@>G=0O  8<A:0O &8D@0 iSmall Roman Numeral i fieldformatV@>15;L=K9  0745;8B5;L (2=CB@5==89) <space>"Space Separator (internal)  fieldformatD"5:AB A 564CAB@>G=K<8 =B5@20;0<8 SpacedText fieldformat/T/F fieldformat "5:ABText fieldformat @5<OTime fieldformat<C:2K 2 5@E=5<  538AB@5 [-/]Upper Case Letters [A-Z] fieldformat:><5@ 545;8 (>B 0 4> 53) %-UWeek Number (0 to 53) %-U fieldformatD!>:@0I5==>5 0720=85 =O 545;8 %aWeekday Abbreviation %a fieldformat5=L 545;8 %AWeekday Name %A fieldformat/Y/N fieldformat >4 (2 F8D@K) %yYear (2 digits) %y fieldformat >4 (4 F8D@K) %YYear (4 digits) %Y fieldformat8AB8=0/;>6L true/false fieldformat 40/=5Byes/no fieldformat;>6Lfalse genboolean=5Bno genboolean 8AB8=0true genboolean40yes genbooleanA5 $09;K All Files globalref$A5 $09;K TreelineAll TreeLine Files globalref<$09;K CSV ( 07<5G5=K 0?OBK<8)CSV (Comma Delimited) Files globalref$09;K HTML HTML Files globalref$09;K ODFODF Text Files globalref8$09;K !B0@>9 5@A88 TreeLineOld TreeLine Files globalref$09;K PDF PDF Files globalref"5:AB>2K5 $09;K Text Files globalref$09;K TreeLineTreeLine Files globalref,$09;K TreeLine  !60BKTreeLine Files - Compressed globalref8$09;K TreeLine  0H8D@>20=KTreeLine Files - Encrypted globalref$09;K Treepad Treepad Files globalref$09;K XML XML Files globalref 09B8: Find: helpview &0704&Backhelpview&?5@54&Forwardhelpview& 0G0;C&Homehelpview &09B8 !;54CNI89 Find &Nexthelpview"09B8 &@54K4CI89Find &Previoushelpview6"5:AB>20O AB@>:0 =5 =0945=0Text string not foundhelpview=AB@C<5=BKToolshelpview¨"{0}" =5 O2;O2;O5BAO D09;><, ?>4E>4OI8< 4;O Treeline. @8<5=8BL D8;LB@ 4;O 8<?>@B0?:"{0}" is not a valid TreeLine file. Use an import filter?importsFXML &1I53> 840 (=5 D09; Treeline) &Generic XML (non-TreeLine file)importsD0:;04:8 &HTML (2 D>@<0B5 Mozilla) &HTML bookmarks (Mozilla Format)importsV"5:AB A &Tab->BABC?0<8, >48= C75; =0 AB@>:C%&Tab indented text, one node per lineimports<0:;04:8 &XML (2 D>@<0B5 XBEL)&XML bookmarks (XBEL format)importsBOOKMARKimports@525@=K9 D>@<0B CSV 2 AB@>:5 {0}Bad CSV format on Line {0}imports0:;04:8 Bookmarksimports<K15@8B5 !?>A>1 <?>@B8@>20=8OChoose Import Methodimports°"5:AB>20O B01;8F0, @07<5G5==0O 70&?OBK<8 (CSV), A> AB>;1F>< C@>2=59 && AB@>:>9 703>;>2:0ACo&mma delimited (CSV) text table with level column && header rowimports†"5:AB>20O B01;8F0, @07<5G5==0O 70&?OBK<8 (CSV) A> AB@>:>9 703>;>2:01Comma delimited (CSV) text table &with header rowimportsLH81:0  =52>7<>6=> ?@>G8B0BL D09; {0}Error - could not read file {0}imports<H81:0  =525@=K9 D>@<0B 2 {0}Error - improper format in {0}imports FOLDERimports$<?>@B8@>20BL $09; Import Fileimports525@=K9 $09; Invalid FileimportsD525@=K9 =><5@ C@>2=O 2 AB@>:5 {0} Invalid level number on line {0}imports2525@=0O AB@C:BC@0 C@>2=OInvalid level structureimports8?5@AAK;:0LinkimportsT$09; Tree&Line !B0@>9 5@A88 (1.x 8;8 2.x)Old Tree&Line File (1.x or 2.x)importsDB:@KBL !B@C:BC@C &>:C<5=B0 (ODF)Open &Document (ODF) outlineimports @C385Otherimportsr&@>AB>9 B5:AB A 0170F0<8 (@073@0=8G5=K ?CABK<8 AB@>:0<8)-Plain text ¶graphs (blank line delimited)imports†@>AB>9 B5:AB, >48= &C75; =0 AB@>:C (>3@0=8G5==K9 ?5@5=>A>< AB@>:8)-Plain text, one &node per line (CR delimited)imports ", SEPARATORimports"&TABLEimportsr"5:AB>20O B01;8F0, @07<5G5==0O Tab, A> AB&@>:>9 703>;>2:0)Tab delimited text table with header &rowimports "5:ABTextimportsH!;8H:>< <=>3> M;5<5=B>2 2 !B@>:5 {0}Too many entries on Line {0}imports:TreeLine  <?>@B8@>20BL $09;TreeLine - Import FileimportsJ&$09; Treepad (B>;L:> B5:AB>2K5 C7;K)Treepad &file (text nodes only)importsl!AK;:8 =0 4>G5@=85 C7;K 4>;6=K 1KBL 2:;NG5=K 2 DC=:F8N/Child references must be combined in a functionmatheval254>?CAB8<K5 "{}" A8<2>;KIllegal "{}" charactersmatheval254>?CAB8<0O DC=:F8O: {0}Illegal function present: {0}mathevalT54>?CAB8<K9 B8? >1J5:B0 8;8 >?5@0B>@: {0}$Illegal object type or operator: {0}mathevalD54>?CAB8<K9 A8=B0:A8A 2 2K@065=88Illegal syntax in equationmatheval4525@=K5 <>48D8:0B>@K ?>;OInvalid field modifiersmatheval&@8<5=8BL&Apply miscdialogs&B<5=0&Cancel miscdialogs&0:@KBL&Close miscdialogs,&@5:@0B8BL $8;LB@0F8N &End Filter miscdialogsA5 &45@52> &Entire tree miscdialogs&$8;LB@>20BL&Filter miscdialogs 09B8 &!;54CNI89 &Find Next miscdialogs&?5@54&Forward miscdialogs4&3=>@8@>20BL 8 ?@>?CAB8BL&Ignore and skip miscdialogs&;NG52K5 A;>20 &Key words miscdialogs"8? &#7;0 &Node Type miscdialogs&OK&OK miscdialogs>&@54>?@545;5==K5 ;NG52K5 >;O&Predefined Key Fields miscdialogs*& 53C;O@=>5 2K@065=85&Regular expression miscdialogs&0<5=8BL&Replace miscdialogs‚&5@570?CAB8BL =C<5@0F8N A =0G0;0 4;O A;54CNI8E A5AB@8=A:8E C7;>2"&Restart numbers for next siblings miscdialogsF>AAB0=>28BL =0G5=8O ?> &#<>;G0=8N&Restore Defaults miscdialogs(&!<5=8BL =0?@02;5=85&Reverse miscdialogs&A:><K9 "5:AB &Search Text miscdialogs4&>G5@=85 C7;K 2 2K1@0==><&Selection's children miscdialogs(">;L:> 2 &703>;>2:0E &Titles only miscdialogs(&0=5;8 =AB@C<5=B>2 &Toolbars miscdialogsD&1@010BK20BL ?CABK5 ?>;O :0: =C;8&Treat blank fields as zeros miscdialogsV&A?>;L7>20BL H@8DB ?@8;>65=8O ?> C<>;G0=8N&Use app default font miscdialogs0@8<5=8BL A&60B85 D09;>2&Use file compression miscdialogsTA?>;L7>20BL &A8AB5<=K9 H@8DB ?> C<>;G0=8N&Use system default font miscdialogs-- 0745;8B5;L-- --Separator-- miscdialogs&>&?CAB8<K5 ><0=4KA&vailable Commands miscdialogs"N1>5 &A>2?045=85 Any &match miscdialogs:(@8DB @8;>65=8O ?> #<>;G0=8NApp Default Font miscdialogsG8AB8BL &;NG Clear &Key miscdialogs 0AB@>8BL (@8DBKCustomize Fonts miscdialogs:0AB@>8BL 0=5;8 =AB@C<5=B>2Customize Toolbars miscdialogs 0==K5Data miscdialogs5=N 0==K5 Data Menu miscdialogsB> #<>;G0=8N  4=>AB@>G=K9 "5:ABDefault - Single Line Text miscdialogs 540:B8@>20BLEdit miscdialogs5=N @02:0 Edit Menu miscdialogs(@8DB  540:B>@0Editor View Font miscdialogs:0@>;L : 0H8D@>20==><C $09;CEncrypted File Password miscdialogsLH81:0  =525@=>5 @53C;O@=>5 2K@065=85"Error - invalid regular expression miscdialogs4H81:0  70<5=0 =52>7<>6=0Error - replacement failed miscdialogs">;=>5 &2K@065=85 F&ull phrase miscdialogs>;OFields miscdialogs$09;File miscdialogs5=N $09; File Menu miscdialogs!2>9AB20 $09;0File Properties miscdialogs$$09;>2>5 %@0=8;8I5 File Storage miscdialogs$8;LB@>20BLFilter miscdialogs >8A:Find miscdialogs 09B8 &!;54CNI89 Find &Next miscdialogs"09B8 &@54K4CI89Find &Previous miscdialogs>8A: 8 0<5=0Find and Replace miscdialogs$>@<0B8@>20BLFormat miscdialogs5=N $>@<0B Format Menu miscdialogs> 2A5E &40==KE Full &data miscdialogs&5;K5 &A;>20 Full &words miscdialogsF1@01>B:0 #7;>2 157 >;59 C<5@0F88'Handling Nodes without Numbering Fields miscdialogs!?@02:0Help miscdialogs5=N !?@02:8 Help Menu miscdialogs0: A:0BL How to Search miscdialogs::;NG8BL C7;K 25@E=8E C@>2=59Include top-level nodes miscdialogs,>;=K5 :;NG52K5 &A;>20Key full &words miscdialogs2;NG {0} C65 8A?>;L7C5BAOKey {0} is already used miscdialogs>@OG85 ;028H8Keyboard Shortcuts miscdialogs>;LH85 =0G:8 Large Icons miscdialogs&0B5<0B8G5A:85 >;O Math Fields miscdialogs"5@5<5AB8BL &=87 Move &Down miscdialogs$5@5<5AB8BL &25@EMove &Up miscdialogs>;O &#7;>2 N&ode Fields miscdialogs 5=N >BACBAB2C5BNo menu miscdialogsP>;O =C<5@0F88 2 B8?0E 40==KE =5 =0945=K,No numbering fields were found in data types miscdialogs#75;Node miscdialogs &03>;>2:8 #7;>2 Node &Titles miscdialogs5=N #75; Node Menu miscdialogs((@8DB 2 $>@<5 K2>40Output View Font miscdialogs* 5&3C;O@=>5 2K@065=85Re&gular expression miscdialogs,2548B5 0@>;L 0=>2>:Re-Type Password: miscdialogsD=>2L =01@0==K9 ?0@>;L =5 ?>4E>48BRe-typed password did not match miscdialogs>0?><=8BL ?0@>;L B5:CI59 A5AA88%Remember password during this session miscdialogs0<5=8BL &A5 Replace &All miscdialogs.0<5=5=> {0} A>2?045=89Replaced {0} matches miscdialogs"0<5=ONI89 &"5:ABReplacement &Text miscdialogs.0&@575@28@>20BL =><5@0Reserve &numbers miscdialogs>@=52>9 #75; Root Node miscdialogs>A:><0O AB@>:0 "{0}" =5 =0945=0Search string "{0}" not found miscdialogs:A:><K9 B5:AB "{0}" =5 =0945=Search text "{0}" not found miscdialogs K1@0==K5 &25B28Selected &branches miscdialogs:&!5AB@8=A:85 C7;K 2 2K1@0==><Selection's &siblings miscdialogs4&>G5@=85 C7;K 2 2K1@0==><Selection's childre&n miscdialogs 0;5=L:85 =0G:8 Small Icons miscdialogs,0?@02;5=85 !>@B8@>2:8Sort Direction miscdialogs"!?>A>1 !>@B8@>2:8 Sort Method miscdialogs!>@B8@>20BL#7;K Sort Nodes miscdialogs*@>25@:0 @02>?8A0=8O Spell Check miscdialogs8><0=4K &0=5;8 =AB@C<5=B>2Tool&bar Commands miscdialogs6& 07<5@ 0=5;8 =AB@C<5=B>2 Toolbar &Size miscdialogs>>;8G5AB2> 0=5;59 =AB@C<5=B>2Toolbar Quantity miscdialogs=AB@C<5=BKTools miscdialogs 5=N =AB@C<5=BK Tools Menu miscdialogs2(8DB 4;O @>A<>B@0 5@520Tree View Font miscdialogs6TreeLine  !5@L57=0O H81:0TreeLine - Serious Error miscdialogs$C<5@0F8O TreeLineTreeLine Numbering miscdialogs22548B5 0@>;L 4;O "{0}":Type Password for "{0}": miscdialogs2548B5 0@>;L:Type Password: miscdialogs01=>28BL C<5@0F8N #7;>2Update Node Numbering miscdialogs8@8<5=8BL &H8D@>20=85 D09;>2Use file &encryption miscdialogs84View miscdialogs5=N 84 View Menu miscdialogs '5< A:0BLWhat to Search miscdialogs'B> !>@B8@>20BL What to Sort miscdialogs'B> 1=>2;OBLWhat to Update miscdialogs:=>Window miscdialogs5=N :=> Window Menu miscdialogsB0@>;8 =C;52>9 4;8=K =5 4>?CAB8<K'Zero-length passwords are not permitted miscdialogs[A5 >;O] [All Fields] miscdialogs[A5 "8?K] [All Types] miscdialogs<OName nodeformatl:B828@>20BL ?>;O @540:B>@0 40==KE ?@8 =02545=88 <KHLN$Activate data editors on mouse hoveroptiondefaults84 Appearanceoptiondefaults2B>!>E@0=5=85 Auto SaveoptiondefaultsL2B><0B8G5A:8 >B:@K20BL ?>A;54=89 D09;!Automatically open last file usedoptiondefaultsF5@58<5=>2K20BL C7;K ?> I5;G:C <KH8Click node to renameoptiondefaults0$>@<0BK  540:B>@0 0==KEData Editor Formatsoptiondefaults0B0Datesoptiondefaults">ABC?=K5 $C=:F88Features AvailableoptiondefaultsOB=8F0Fridayoptiondefaultsp!<5I0BL 2?@02> (4;O :@0A82>9 ?5G0B8) JSON D09;K Treeline)Indent (pretty print) TreeLine JSON filesoptiondefaults`3@0=8G8BL 2KA>BC @540:B>@0 40==KE @07<5@>< >:=0'Limit data editor height to window sizeoptiondefaultsP!2>@0G820BL ?@8;>65=85 2 A8AB5<=K9 ;>B>:#Minimize application to system trayoptiondefaults‚>;8G5AB2> <8=CB <564C A>E@0=5=8O<8 (CAB0=>28B5 0 4;O >B:;NG5=8O)+Minutes between saves (set to 0 to disable)optiondefaults>=545;L=8:MondayoptiondefaultsL'8A;> ?>A;54=8E D09;>2 2 D09;>2>< <5=N(Number of recent files in the file menuoptiondefaults<'8A;> 2>7<>6=KE >B<5= 459AB289Number of undo levelsoptiondefaults:B:@K20BL D09;K 2 =>2KE >:=0EOpen files in new windowsoptiondefaults >A;54=85 $09;K  Recent Filesoptiondefaultsj#40;OBL =54>ABC?=K5 40==K5, 2>H54H85 2 ?>A;54=89 D09;'Remove inaccessible recent file entriesoptiondefaultsX 540:B8@>20BL 8<5=0 =>2KE C7;>2 ?@8 A>740=88Rename new nodes when createdoptiondefaultsT>AAB0=02;820BL CAB0=>2:8 >:=0 ?@8 70?CA:5 Restore previous window geometryoptiondefaultsT>AAB0=02;820BL A>AB>O=85 ?>A;54=53> D09;0(Restore tree view states of recent filesoptiondefaults!C11>B0Saturdayoptiondefaults`:;NG8BL ?@>A<>B@ =02830F8>==>9 F5?>G:8 : ?@54:CShow breadcrumb ancestor viewoptiondefaults^>:07K20BL ?0=5;L 4>G5@=53> C7;0 2 D>@<5 A?@020#Show child pane in right hand viewsoptiondefaultsB>:07K20BL ?>B><:>2 2 >:=5 2K2>40Show descendants in output viewoptiondefaults4>:07K20BL 7=0G:8 2 45@525Show icons in the tree viewoptiondefaultsb>:07K20BL <0B5<0B8G5A:85 ?>;O 2  540:B>@5 0==KE&Show math fields in the Data Edit viewoptiondefaultsX>:07K20BL ?>;O =C<5@0F88 2  540:B>@5 0==KE+Show numbering fields in the Data Edit viewoptiondefaults2#A;>28O 0?CA:0 @>3@0<<KStartup Conditionoptiondefaults>A:@5A5=L5Sundayoptiondefaults'5B25@3Thursdayoptiondefaults @5<OTimesoptiondefaults^ 07@5H8BL ?5@5B0A:820=85 M;5<5=B>2 45@520 <KHLNTree drag && drop availableoptiondefaultsB>@=8:Tuesdayoptiondefaults8!>E@0=OBL 4;O >AAB0=>2;5=8O Undo Memoryoptiondefaults !@540 Wednesdayoptiondefaults&B<5=0&Canceloptions&OK&OKoptionsPK15@8B5 @0A?>;>65=85 D09;0 :>=D83C@0F88"Choose configuration file locationoptionsj8@5:B>@8O ?@>3@0<<K (4;O ?>@B0B82=>3> 8A?>;L7>20=8O)$Program directory (for portable use)options`><0H=OO 48@5:B>@8O ?>;L7>20B5;O (@5:><5=4C5BAO)#User's home directory (recommended)options:H81:0 8=8F80;870F88 ?@8=B5@0Error initializing printer printdata0TreeLine  -:A?>@B 2 PDFTreeLine - Export PDF printdata&!=87C:&Bottom: printdialogs&B<5=0&Cancel printdialogsB&B>1@060BL ?CB8 : 4>G5@=8< C7;0<&Draw lines to children printdialogs&A5 5@52> &Entire tree printdialogs &(@8DB&Font printdialogs&K1>@ (@8DB0&Font Selection printdialogs &1I85 0AB@>9:8&General Options printdialogs5@E=89 !&;520 &Header Left printdialogs4&5@E=89/86=89 >;>=B8BC;&Header/Footer printdialogs.&:;NG8BL :>@=52>9 C75;&Include root node printdialogsX>&:07K20BL ?5@2K9 4>G5@=89 C75; A @>48B5;5<&Keep first child with parent printdialogs!&;520:&Left: printdialogs&'8A;> AB>;1F>2&Number of columns printdialogs&OK&OK printdialogs&@8AB02:0&Prefix printdialogs&5G0BL... &Print... printdialogs!&?@020:&Right: printdialogs&:>=G0=85&Suffix printdialogs&!25@EC:&Top: printdialogs$&48=8FK 7<5@5=8O&Units printdialogsR&A?>;L7>20BL H@8DB D>@<K 2K2>40 TreeLine&Use TreeLine output view font printdialogs&(8@8=0:&Width: printdialogs"A3 (279 × 420 <<)A3 (279 x 420 mm) printdialogs"A4 (210 × 297 <<)A4 (210 x 297 mm) printdialogs"A5 (148 × 210 <<)A5 (148 x 210 mm) printdialogs>0123456...&F(H)I,L-M.N/OAaBbCcDdEeFfGg...TtUuVvWvXxYyZz printdialogs!0=B8<5B@K (A<)Centimeters (cm) printdialogs!B>;1FKColumns printdialogs040==K9  07<5@ Custom Size printdialogs$(@8DB ?> #<>;G0=8N Default Font printdialogsPH81:0:  07<5@ 8;8 ?>;O AB@0=8FK =525@=K(Error: Page size or margins are invalid printdialogs(>?>;=8B5;L=K9 B5:AB Extra Text printdialogs(!B@0=8FK 2  072>@>B5 Facing Pages printdialogs!2>9AB20Features printdialogs >&;OFiel&ds printdialogs&>;5 $>@<0B0 Field For&mat printdialogs*$>@<0B ?>;O 4;O "{0}"Field Format for "{0}" printdialogs !B@0=8F0 &5;8:><Fit Page printdialogs&0?>;=8BL ?> (8@8=5 Fit Width printdialogs$&0G5@B0=85 (@8DB0 Font st&yle printdialogs&86=89 &>;>=B8BC;:Foot&er: printdialogs86=89 &!;520 Footer &Left printdialogs"86=89 ?> &&5=B@CFooter Ce&nter printdialogs86=89 !&?@020 Footer Righ&t printdialogs4&!?@02:0 ?> $>@<0B8@>20=8N Format &Help printdialogs(&5@E=89 >;>=B8BC;:He&ader: printdialogs5@E=89 !&?@020 Header &Right printdialogs$5@E=89 ?> &&5=B@CHeader C&enter printdialogs85@E=89 8 86=89 >;>=B8BC;KHeader and Footer printdialogsKA>B0:Height: printdialogsN9<K (in.) Inches (in) printdialogs:;NG5==K5 #7;KIncluded Nodes printdialogs BABC?Indent printdialogs&;L1><=0O Lan&dscape printdialogs*Legal (8.5 × 14 Inch)Legal (8.5 x 14 in.) printdialogs,Letter (8.5 × 11 Inch)Letter (8.5 x 11 in.) printdialogs>;OMargins printdialogs8;;8<5B@K (<<)Millimeters (mm) printdialogs$!;54CNI0O !B@0=8F0 Next Page printdialogs<">&;L:> >B:@KBK5 4>G5@=85 C7;KOnl&y open node children printdialogs@85=B0F8O Orientation printdialogs&$>@<0B K2>40Output &Format printdialogs&&0@0<5B@K !B@0=8FK Page &Setup printdialogs& 07<5@ C<038 Paper &Size printdialogs&=86=0O Portra&it printdialogs&@54K4CI0O !B@0=8F0 Previous Page printdialogs 5G0BLPrint printdialogsF@5420@8B5;L=K9 @>&A<>B@ 5G0B8...Print Pre&view... printdialogs>@5420@8B5;L=K9 @>A<>B@ 5G0B8 Print Preview printdialogs 0AB@>9:0 5G0B8 Print Setup printdialogs 0AB@>9:0 5G0B8Printing Setup printdialogs @8<5@Sample printdialogs"K15@8B5 &@8=B5@Select &Printer printdialogsK15@8B5 (@8DB Select Font printdialogs K1@0==K5 &25B28Selected &branches printdialogsK1@0==K5 &C7;KSelected &nodes printdialogs &07<5@Si&ze printdialogs&4=8=>G=0O !B@0=8F0 Single Page printdialogs6 0AAB>O=85 <564C A&B>;1F0<8Space between colu&mns printdialogs,Tabloid (11 × 17 Inch)Tabloid (11 x 17 in.) printdialogs(PDF @8=B5@ TreeLineTreeLine PDF Printer printdialogs'B> ?5G0B0BL What to print printdialogs#25;8G8BLZoom In printdialogs#<5=LH8BLZoom Out printdialogs&>1028BL&Add spellcheck&B<5=0&Cancel spellcheck"3=>@8@>20BL &A5 &Ignore All spellcheck&0<5=8BL&Replace spellcheck6>1028BL 2 &86=5< @538AB@5Add &Lowercase spellcheck>=B5:AB:Context: spellcheck²52>7<>6=> =09B8 =8 aspell.exe, =8 ispell.exe 8;8 hunspell.exe K1@0BL <5AB>@0A?>;>65=85?QCould not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? spellcheckr@>25@:0 ?@02>?8A0=8O 2 25B28 >:>=G5=0 @>4>;68BL A25@EC?3Finished checking the branch Continue from the top? spellcheck<@>25@:0 ?@02>?8A0=8O >:>=G5=0Finished spell checking spellcheck&3=>@8@>20BLIgnor&e spellcheck‚#:068B5 <5AB>@0A?>;>65=85 aspell.exe, ispell.exe 8;8 hunspell.exe-Locate aspell.exe, ipsell.exe or hunspell.exe spellcheck5B 2 !;>20@5Not in Dictionary spellcheck"@>3@0<<0 (*.exe)Program (*.exe) spellcheck0<5=8BL &A5 Re&place All spellcheck*@>25@:0 @02>?8A0=8O Spell Check spellcheck8H81:0 @>25@:8 @02>?8A0=8OSpell Check Error spellcheck@54;>65=8O Suggestions spellcheck<@>25@:0 @02>?8A0=8O TreeLineTreeLine Spell Check spellcheckÀH81:0 @>25@:8 @02>?8A0=8O TreeLine #4>AB>25@LB5AL, GB> aspell, ispell 8;8 hunspell CAB0=>2;5=LTreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed spellcheck !;>2>:Word: spellcheck K1@0BL 2 5@525Select in Tree titlelistview0@:5@KBullets treeformats>G5@=89"8? ChildType treeformats03@0=8G5=85>G5@=53>"8?0ChildTypeLimit treeformats#A;>2=>5@028;>ConditionalRule treeformats #'.DEFAULT treeformats?@54HTMLEvalHtml treeformatsFIELD treeformats$FILE treeformats"8? >;O FieldType treeformats $>@<0BFormat treeformats"$>@<0B8@>20BLHTML FormatHtml treeformats1I89"8? GenericType treeformats =0G>:Icon treeformats"0G0;L=>5=0G5=85 InitialValue treeformats4 0745;8B5;L-;5<5=B>2!?8A:0 ListSeparator treeformatsC<!B@>:8NumLines treeformats$>@<0BK2>40 OutputFormat treeformats@8AB02:0Prefix treeformats!>@B?5@54 SortForward treeformats><!>@B; SortKeyNum treeformats@>15;564C SpaceBetween treeformats:>=G0=85Suffix treeformats"TYPE treeformats"01;8F0Table treeformats$>@<0B03>;>2:0 TitleFormat treeformats&8@=K9 (@8DB &Bold Fonttreelocalcontrol&>?8@>20BL&Copytreelocalcontrol&#40;8BL #75; &Delete Nodetreelocalcontrol&B45;8BL ;>=K&Detach Clonestreelocalcontrol$&-:A?>@B8@>20BL... &Export...treelocalcontrol.&=5H=OO 8?5@AAK;:0...&External Link...treelocalcontrol& 07<5@ (@8DB0 &Font Sizetreelocalcontrol&428=CBL #75; &Indent Nodetreelocalcontrol &0:;>==K9 (@8DB &Italic Fonttreelocalcontrol$&5@5<5AB8BL 25@E&Move Uptreelocalcontrol&>2>5 :=> &New Windowtreelocalcontrol&AB028BL&Pastetreelocalcontrol&5G0BL... &Print...treelocalcontrol&>2B>@&Redotreelocalcontrol &1=>28BL !AK;:8&Regenerate Referencestreelocalcontrol&5@58<5=>20BL&Renametreelocalcontrol&!>E@0=8BL&Savetreelocalcontrol&&07=0G8BL "8? #7;0&Set Node Typetreelocalcontrol2&@>25@:0 @02>?8A0=8O...&Spell Check...treelocalcontrol&B<5=0&Undotreelocalcontrol&K428=CBL #75;&Unindent Nodetreelocalcontrol.>1028BL &>G5@=89 #75; Add &Childtreelocalcontrol<>1028BL &#@>25=L 0B53>@88...Add Category &Level...treelocalcontrold>1028BL =>2K9 4>G5@=89 C75; : 2K1@0==><C @>48B5;N Add new child to selected parenttreelocalcontrolt>1028BL 8;8 87<5=8BL 2=5H==NN 38?5@AAK;:C =0 web-AB@0=8FC!Add or modify an extrnal web linktreelocalcontrolh>1028BL 8;8 87<5=8BL 2=CB@5==NN 38?5@AAK;:C =0 C75;#Add or modify an internal node linktreelocalcontrolH52>7<>6=> @0AH8@8BL 157 >1I8E ?>;59#Cannot expand without common fieldstreelocalcontrol>;O 0B53>@88Category Fieldstreelocalcontrol0G8AB8BL $>&@<0B8@>20=85Clear For&mattingtreelocalcontrolrG8AB8BL =0AB@>9:8 D>@<0B0 B5:CI53> 8;8 2K1@0==>3> B5:AB0)Clear current or selected text formattingtreelocalcontrol@;>=8@>20BL A5 &>4>H54H85 #7;KClone All &Matched NodestreelocalcontrolD1J548=8BL ?>B><:>2 A;8O=85< ?>;59&Collapse descendants by merging fieldstreelocalcontrolT>=25@B8@>20BL 2A5 ?>4>H54H85 C7;K 2 :;>=K&Convert all matching nodes into clonestreelocalcontrolB>=25@B8@>20=> {0} 25B259 2 :;>=K"Converted {0} branches into clonestreelocalcontrol8>?8@>20BL "8?K 87 &$09;0...Copy Types from &File...treelocalcontrolR>?8@>20BL 25B2L 8;8 B5:AB 2 1CD5@ >1<5=0(Copy the branch or text to the clipboardtreelocalcontrold!:>?8@>20BL :>=D83C@0F8N 87 4@C3>3> D09;0 Treeline1Copy the configuration from another TreeLine filetreelocalcontrolK&@570BLCu&ttreelocalcontrolfK@570BL 25B2L 8;8 B5:AB 8 ?><5AB8BL 2 1CD5@ >1<5=0'Cut the branch or text to the clipboardtreelocalcontrol> #<>;G0=8NDefaulttreelocalcontrol,#40;8BL 2K1@0==K5 C7;KDelete the selected nodestreelocalcontrol`B45;8BL 2A5 :;>=8@>20==K5 C7;K 2 B5:CI8E 25B2OE+Detach all cloned nodes in current branchestreelocalcontroljH81:0  =52>7<>6=> C40;8BL @575@2=CN :>?8N D09;0 {0}'Error - could not delete backup file {}treelocalcontrolFH81:0  =5 <>3C ?@>G8B0BL D09; {0}Error - could not read file {0}treelocalcontrolBH81:0  =52>7<>6=> 70?8A0BL D09;Error - could not write to filetreelocalcontrol<H81:0  =5 <>3C 70?8A0BL 2 {}Error - could not write to {}treelocalcontrolR-:A?>@B8@>20BL D09; 2 @O4 4@C38E D>@<0B>2(Export the file in various other formatstreelocalcontrolV-:A?>@B 2 PDF A B5:CI8<8 =0AB@>9:0<8 ?5G0B8+Export to PDF with current printing optionstreelocalcontrol$09; A>E@0=5= File savedtreelocalcontrolH!25AB8 =0 48= #@>25=L &?> 0B53>@88Flatten &by Categorytreelocalcontrol&&25B (@8DB0...Font C&olor...treelocalcontrol”@8=C48B5;L=>5 >1=>2;5=85 2A5E CA;>2=KE B8?>2 & ?>;59 <0B5<0B8G5A:8E ?>;593Force update of all conditional types & math fieldstreelocalcontrol.428=CBL 2K1@0==K5 C7;KIndent the selected nodestreelocalcontrolAB028BL &0BC Insert &Datetreelocalcontrol>!>740BL !5AB@8=A:89 #75; &>A;5Insert Sibling &Aftertreelocalcontrol>!>740BL !5AB@8=A:89 #75; &5@54Insert Sibling &BeforetreelocalcontrolV!>740BL C7;K :0B53>@89 =04 4>G5@=8<8 C7;0<8$Insert category nodes above childrentreelocalcontrol>AB028BL B5:CICN 40BC :0: B5:ABInsert current date as texttreelocalcontrol^!>740BL =>2K9 A5AB@8=A:89 C75; ?>A;5 2K1@0==>3>"Insert new sibling after selectiontreelocalcontrol\!>740BL =>2K9 A5AB@8=A:89 C75; ?5@54 2K1@0==K<#Insert new sibling before selectiontreelocalcontrol2&=CB@5=OO 8?5@AAK;:0...Internal &Link...treelocalcontrol>;LH>9Largetreelocalcontrol>;LH89Largertreelocalcontrol081>;LH89Largesttreelocalcontrol"5&@5<5AB8BL =87 M&ove DowntreelocalcontrolN5@5<5AB8BL 2 &0G0;> [2=CB@8 @>48B5;O] Move &FirsttreelocalcontrolL5@5<5AB8BL 2 &>=5F [2=CB@8 @>48B5;O] Move &Lasttreelocalcontrol>5@5<5AB8BL 2K1@0==K5 C7;K 2=87Move the selected nodes downtreelocalcontrolf5@5<5AB8BL 2K1@0==K5 C7;K =0 <5AB> ?5@2KE 4>G5@=8E0Move the selected nodes to be the first childrentreelocalcontroll5@5<5AB8BL 2K1@0==K5 C7;K =0 <5AB> ?>A;54=8E 4>G5@=8E/Move the selected nodes to be the last childrentreelocalcontrol@5@5<5AB8BL 2K1@0==K5 C7;K 225@EMove the selected nodes uptreelocalcontrol445=B8G=K5 C7;K =5 =0945=KNo identical nodes foundtreelocalcontrolBB:@KBL MB>B 65 D09; 2 =>2>< >:=5#Open a new window for the same filetreelocalcontrol(0AB@>9:0 &5G0B8...P&rint Setup...treelocalcontrol.&AB028BL @>AB>9 "5:ABPa&ste Plain Texttreelocalcontrol.AB028BL &>G5@=89 #75; Paste C&hildtreelocalcontrolJAB028BL &;>=8@>20==K9 >G5@=89 #75;Paste Cl&oned Childtreelocalcontrol\AB028BL &;>=8@>20==K9 !5AB@8=A:89 #75; 5@54Paste Clo&ned Sibling Beforetreelocalcontrol\AB028BL &;>=8@>20==K9 !5AB@8=A:89 #75; >A;5Paste Clone&d Sibling Aftertreelocalcontrol@AB028BL !5AB@8=A:89 #75; &>A;5Paste Sibling &Aftertreelocalcontrol@AB028BL !5AB@8=A:89 #75; &5@54Paste Sibling &BeforetreelocalcontrolZAB028BL :;>= 4>G5@=53> C7;0 87 1CD5@0 >1<5=0&Paste a child clone from the clipboardtreelocalcontrolNAB028BL 4>G5@=89 C75; 87 1CD5@0 >1<5=0%Paste a child node from the clipboardtreelocalcontrolTAB028BL A5AB@8=A:89 C75; ?>A;5 2K1@0==>3>Paste a sibling after selectiontreelocalcontrolRAB028BL A5AB@8=A:89 C75; ?5@54 2K1@0==K< Paste a sibling before selectiontreelocalcontrol`AB028BL :;>= A5AB@8=A:>3> C7;0 ?>A;5 2K1@0==>3>%Paste a sibling clone after selectiontreelocalcontrol^AB028BL :;>= A5AB@8=A:>3> C7;0 ?5@54 2K1@0==K<&Paste a sibling clone before selectiontreelocalcontrolPAB028BL C7;K 8;8 B5:AB 87 1CD5@0 >1<5=0&Paste nodes or text from the clipboardtreelocalcontrolbAB028BL =5D>@<0B8@>20==K9 B5:AB 87 1CD5@0 >1<5=0+Paste non-formatted text from the clipboardtreelocalcontrol 5G0BL 2 &PDF...Print &to PDF...treelocalcontrolF@5420@8B5;L=K9 @>&A<>B@ 5G0B8...Print Pre&view...treelocalcontrolŒ 0A?5G0B0BL 284 45@520 =0 2KE>45 2 A>>B25BAB288 A B5:CI8<8 =0AB@>9:0<8*Print tree output based on current optionstreelocalcontrol&!2>9AB20...Prop&erties...treelocalcontrol>>2B>@8BL ?@54H5AB2CNICN >B<5=CRedo the previous undotreelocalcontrol`5@58<5=>20BL 703>;>2>: B5:CI53> M;5<5=B0 45@520#Rename the current tree entry titletreelocalcontrolD&><5=OBL 5AB0<8 #@>2=8 0B53>@88S&wap Category Levelstreelocalcontrol"!>E@0=8BL &0:... Save &As...treelocalcontrol!>E@0=8BL $09; Save Filetreelocalcontrol4!>E@0=8BL 87<5=5=8O 2 {0}?Save changes to {}?treelocalcontrol(!>E@0=8BL 87<5=5=8O? Save changes?treelocalcontrol,!>E@0=8BL B5:CI89 D09;Save the current filetreelocalcontrol>!>E@0=8BL D09; ?>4 =>2K< 8<5=5<Save the file with a new nametreelocalcontrol>K15@8B5 ?>;O 4;O =>2>3> C@>2=OSelect fields for new leveltreelocalcontrol0#AB0=>28BL  07<5@ (@8DB0 Set Font Sizetreelocalcontrol$07=0G8BL "8? #7;0 Set Node Typetreelocalcontroll07=0G8BL B0:85 ?0@0<5B@K, :0: :><?@5AA8O 8 H8D@>20=853Set file parameters like compression and encryptiontreelocalcontrolˆ0AB@>8BL ?>;O, @07<5@ AB@0=8FK 8 CAB0=>28BL 4@C385 =0AB@>9:8 ?5G0B81Set margins, page size and other printing optionstreelocalcontrol^07=0G8BL @07<5@ B5:CI53> 8;8 2K1@0==>3> B5:AB0(Set size of the current or selected texttreelocalcontrolZ07=0G8BL F25B B5:CI53> 8;8 2K1@0==>3> B5:AB0-Set the color of the current or selected texttreelocalcontrolT!45;0BL B5:CI89 8;8 2K1@0==K9 H@8DB 68@=K<(Set the current or selected font to boldtreelocalcontrolZ!45;0BL B5:CI89 8;8 2K1@0==K9 H@8DB =0:;>==K<*Set the current or selected font to italictreelocalcontrol^!45;0BL B5:CI89 8;8 2K1@0==K9 B5:AB 70G5@:=CBK<0Set the current or selected font to strikethoughtreelocalcontrol`!45;0BL B5:CI89 8;8 2K1@0==K9 B5:AB ?>4G5@:=CBK<-Set the current or selected font to underlinetreelocalcontrolL07=0G8BL B8? C7;0 4;O 2K1@0==KE C7;>2$Set the node type for selected nodestreelocalcontrolh>:070BL ?@5420@8B5;L=K9 ?@>A<>B@ @57C;LB0B>2 ?5G0B8"Show a preview of printing resultstreelocalcontrol0;5=L:89SmalltreelocalcontrolL@>25@8BL ?@02>?8A0=85 B5:AB0 2 45@525 Spell check the tree's text datatreelocalcontrol$&0G5@:=CBK9 (@8DBSt&rikethrough FonttreelocalcontrolV><5=OBL C7;K 4>G5@=59 8 2=CG0B>9 :0B53>@89(Swap child and grandchild category nodestreelocalcontrolHTreeLine  B:@KBL $09; >=D83C@0F88"TreeLine - Open Configuration Filetreelocalcontrol0TreeLine  !>E@0=8BL 0:TreeLine - Save Astreelocalcontrol&>4&G5@:=CBK9 (@8DBU&nderline Fonttreelocalcontrol8B<5=8BL ?@54K4CI55 459AB285Undo the previous actiontreelocalcontrol0K428=CBL 2K1@0==K5 C7;KUnindent the selected nodestreelocalcontrol& TreeLine...&About TreeLine...treemaincontrol&A=>2K...&Basic Usage...treemaincontrol,&B<5=0 B:@KB8O $09;0&Cancel File Opentreemaincontrol$&#A;>2=K9 >8A:...&Conditional Find...treemaincontrol2&0AB@>8BL "8?K 0==KE...&Configure Data Types...treemaincontrol:#40;8BL D09; & 575@2=>9 >?88&Delete Backuptreemaincontrol &>8A: "5:AB0... &Find Text...treemaincontrol.&>;=0O >:C<5=B0F8O...&Full Documentation...treemaincontrol&&1I85 0@0<5B@K...&General Options...treemaincontrol"&<?>@B8@>20BL... &Import...treemaincontrol&>2K9...&New...treemaincontrol&B:@KBL...&Open...treemaincontrol &KE>4&QuittreemaincontrolL&>AAB0=>28BL 87 @575@2=>9 :>?88 D09;0&Restore Backuptreemaincontrol&K1@0BL 2A5 &Select Alltreemaincontrol&K1@0BL @8<5@&Select Sampletreemaincontrol&K1@0BL (01;>=&Select Templatetreemaincontrol(&"5:AB>2K9 $8;LB@...&Text Filter...treemaincontrol¨<55BAO @575@2=0O :>?8O D09;0 {}. >7<>6=> ?@54K4CI0O A5AA8O 1K;0 020@89=> 7025@H5=02=K9 $8;LB@...C&onditional Filter...treemaincontrolB&0AB@>8BL 0=5;8 8=AB@C<5=B>2...C&ustomize Toolbars...treemaincontrol#A;>2=K9 $8;LB@Conditional Filtertreemaincontrol#A;>2=K9 >8A:Conditional Findtreemaincontrol&0AB@>8BL &&25B0...Custo&mize Colors...treemaincontrol(0AB@>8BL (&@8DBK...Customize Fo&nts...treemaincontrol40AB@>8BL F25B0 8 B5<K GUICustomize GUI colors and themestreemaincontrolT0AB@>8BL H@8DBK 4;O @07=KE D>@< ?@>A<>B@0 Customize fonts in various viewstreemaincontrol80AB@>8BL :><0=4K :;0280BC@KCustomize keyboard commandstreemaincontrolN0AB@>8BL :=>?:8 =0 ?0=5;8 8=AB@C<5=B>2Customize toolbar buttonstreemaincontrolB040BL ?0@0<5B@K A>@B8@>2:8 C7;>2Define node sort operationstreemaincontrolR>:070BL >A=>2=K5 8A?>;L7C5<K5 8=AB@C:F88 Display basic usage instructionstreemaincontrolH>:070BL A2545=8O > 25@A88 ?@>3@0<<K'Display version info about this programtreemaincontrolpH81:0  D09; A?@02:8 ?> >A=>20< 8A?>;L7>20=8O =5 =0945=!Error - basic help file not foundtreemaincontrolLH81:0  =52>7<>6=> ?@>G8B0BL D09; {0}Error - could not read file {0}treemaincontrolbH81:0  =52>7<>6=> C40;8BL @575@2=CN :>?8N D09;0'Error - could not remove backup file {}treemaincontrolVH81:0  =52>7<>6=> ?5@58<5=>20BL {0} 2 {1}'Error - could not rename "{0}" to "{1}"treemaincontrol`H81:0  =5 <>3C 70?8A0BL D09; :>=D83C@0F88 2 {})Error - could not write config file to {}treemaincontrolHH81:0  D09; 4>:C<5=B0F88 =5 =0945=$Error - documentation file not foundtreemaincontrolPH81:0  =525@=K9 D09; D09; Treeline {0}!Error - invalid TreeLine file {0}treemaincontrol&K9B8 87 ?@8;>65=8OExit the applicationtreemaincontrold$8;LB@>20BL C7;K, ?>:0702 B>;L:> A>2?045=8O B5:AB0&Filter nodes to only show text matchestreemaincontrol$>8A: 8 &0<5=0...Find and &Replace...treemaincontrolN09B8 B5:AB 2 703>;>2:0E C7;>2 & 40==KEFind text in node titles & datatreemaincontrol1I85 0@0<5B@KGeneral Optionstreemaincontrol"5@A88 181;8>B5::Library versions:treemaincontrolT7<5=8BL B8?K 40==KE, ?>;O & AB@>:8 2K2>40(Modify data types, fields & output linestreemaincontrol>2K9 $09;New FiletreemaincontrolB:@KBL $09; Open Filetreemaincontrol$B:@KBL &@8<5@...Open Sa&mple...treemaincontrolB:@KBL @8<5@ Open Sampletreemaincontrol(B:@KBL $09; @8<5@0Open Sample FiletreemaincontroljB:@KBL D09; Treeline, A>45@60I89 ?>;=CN 4>:C<5=B0F8N,Open a TreeLine file with full documentationtreemaincontrol(B:@KBL D09; A 48A:0Open a file from disktreemaincontrol0B:@KBL =5-Treeline D09;Open a non-TreeLine filetreemaincontrol(B:@KBL D09; ?@8<5@0Open a sample filetreemaincontrolB0<5=8BL B5:AB>2K5 AB@>:8 2 C7;0E!Replace text strings in node datatreemaincontrol<K1@0BL 25AL B5:AB 2 @540:B>@5Select all text in an editortreemaincontrol:&07=0G8BL >@OG85 ;028H8...Set &Keyboard Shortcuts...treemaincontrol`07=0G8BL CAB0=>2:8 ?>;L7>20B5;O 4;O 2A5E D09;>2"Set user preferences for all filestreemaincontrolR>:070BL !&:>=D83C@8@>20==CN !B@C:BC@C... Show C&onfiguration Structure...treemaincontrol„>:070BL 4>ABC?=>5 B>;L:> 4;O GB5=8O ?@54AB02;5=85 AB@C:BC@K B8?>2.Show read-only visualization of type structuretreemaincontrol(&!>@B8@>20BL #7;K...Sor&t Nodes...treemaincontrol$!>740BL =>2K9 D09;Start a new filetreemaincontrol.TreeLine  B:@KBL $09;TreeLine - Open Filetreemaincontrol:A=>2K 8A?>;L7>20=8O TreeLineTreeLine Basic Usagetreemaincontrol&5@A8O TreeLine {0}TreeLine version {0}treemaincontrol,1=>28BL &C<5@0F8N...Update &Numbering...treemaincontrol.1=>28BL ?>;O =C<5@0F88Update node numbering fieldstreemaincontrollA?>;L7>20BL CA;>28O 2K1>@0 ?>;59 4;O D8;LB@0F88 C7;>2$Use field conditions to filter nodestreemaincontrollA?>;L7>20BL CA;>28O 2K1>@0 ?>;59 4;O D8;LB@0F88 C7;>2"Use field conditions to find nodestreemaincontrolX=8<0=85: 52>7<>6=> A>740BL ;>:0;L=K9 A>:5B'Warning: Could not create local sockettreemaincontrol0>BACBAB2CNI0O 48@5:B>@8Omissing directorytreemaincontrol02B>@ {0}written by {0}treemaincontrol >2K9Newtreenode;02=K9Main treestructureL#A;>2=0O D8;LB@0F8O, C7;>2 =0945=> {0}&Conditional filtering, found {0} nodestreeviewRBD8;LB@>20=> ?> "{0}", C7;>2 =0945=> {0}#Filtering by "{0}", found {1} nodestreeview!;54CNI89: {0} Next: {0}treeview6!;54CNI89: {0} (=5 =0945=>)Next: {0} (not found)treeview 09B8: Search for:treeview09B8: {0}Search for: {0}treeview.09B8: {0} (=5 =0945=>)Search for: {0} (not found)treeview&0:@KBL :=> &Close Window treewindow&&!25@=CBL AN 5B2L&Collapse Full Branch treewindow&0==K5&Data treewindow&@02:0&Edit treewindow*& 0725@=CBL AN 5B2L&Expand Full Branch treewindow &$09;&File treewindow&!?@02:0&Help treewindow &!;54CNI89 K1>@&Next Selection treewindow &#75;&Node treewindow"&@54K4CI89 K1>@&Previous Selection treewindow>&>:070BL 0=5;L >G5@=53> #7;0&Show Child Pane treewindow&=AB@C<5=BK&Tools treewindow&84&View treewindow &:=>&Window treewindow 0:@KBL MB> >:=>Close this window treewindowT!25@=CBL 2A5 4>G5@=85 C7;K 2K1@0==KE C7;>2+Collapse all children of the selected nodes treewindow 540:B>@ 0==KE Data Edit treewindowK2>4 0==KE Data Output treewindowT 0A:@KBL 2A5 4>G5@=85 C7;K 2K1@0==KE C7;>2)Expand all children of the selected nodes treewindow&$>@<0BFo&rmat treewindowJ5@59B8 : A;54CNI5<C 2K1>@C 2 8AB>@88(Go to the next tree selection in history treewindow2>H03>2> A:0BL !;54CNI89Next Incremental Search treewindow4>H03>2> A:0BL @54K4CI89Previous Incremental Search treewindowN5@=CBLAO : ?@54K4CI5<C 2K1>@C 2 45@525%Return to the previous tree selection treewindow>>:070BL &02830F8>==CN F5?>G:CShow &Breadcrumb View treewindow6>:070BL !?8A>: &03>;>2:>2Show &Title List treewindow2>:070BL & 540:B>@ 0==KEShow Data &Editor treewindow,>:070BL &K2>4 0==KEShow Data &Output treewindow0>:070BL K2>4 &>B><:>2Show Output &Descendants treewindowN>:070BL @540:B>@ 40==KE 2 D>@<5 A?@020Show data editor in right view treewindowH>:070BL 2K2>4 40==KE 2 D>@<5 A?@020Show data output in right view treewindowR>:070BL A?8A>: 703>;>2:>2 2 D>@<5 A?@020Show title list in right view treewindow,0G0BL >H03>2K9 >8A:Start Incremental Search treewindow"!?8A>: 03>;>2:>2 Title List treewindowf5@5:;NG8BL =0 ?>:07 =02830F8>==>9 F5?>G:8 : ?@54:C'Toggle showing breadcrumb ancestor view treewindowL5@5:;NG8BL ?>:07 ?>B><:>2 A >BABC?0<8/Toggle showing output view indented descendants treewindowd5@5:;NG8BL =0 ?>:07 4>G5@=8E C7;>2 2 D>@<5 A?@020%Toggle showing right-hand child views treewindowˆ ý) ÿý, TreeLine-3.2.1/translations/treeline_zh.qm000066400000000000000000002173621506556630100206360ustar00rootroot00000000000000<¸dÊÍ!¿`¡½Ý§zh_CNBèOZÞb6+;0+;+;g+;0¹+;m±+;”¸+;›�TÇôÖUgR9W6WÛ\>Yg¤#ãhD°mÔ'exÆ,IÃ[&§¤¬ÅÍÎHX§ÔÂr¨¡ul¨¥HÉ®´K»vÐ%wûÐDxéì0zöú^yú^µ70KeÞ7þôú8¨OŒH5H5‰fU¥~ˆVE9c S�žE·¬ôX¬ôh‹°5X,¹µSÀe"¼ÏLJD0K5¹µ[™Ç©æÄRå7~à8&ñ²Q¹* •³%*‡›^ª*¦y·Ø*¨¡÷¥*»÷Õ*Ð%øK*ÖT™I*Ù6%*ì0ø{*ö5_ +5tÑ+U¥øë+‹¯ºÌ+Œá×+˜Åm+˜Å»‹+¬ô8A+¶:œ—+į¼R+ÏÇùÑ/5Òê5S4 „;0®¬|cÅÐ ßÄØn‰Eµ_%v•{-„å+6n�d6n�Ä[6n�ç½;Y ö=Öã!>í6O´GS¹RŽ5…-_ Ò± c®á ¶gÎãñx?™Œò|Œàψà¦`Œ-¬´ÎŒÛ‡R¸Ž‚Δã�Í*W›Ó%GžªîÓê Z Œ £�¹�ׯ¿´>®²Òä±Õ³wi|�³õe×J³÷…»Á´~Ž |·åÙ·™ùg_ÄÒÞÐÇ~“ŽèÒ®éN%Úùä| Ý<~ÈÇáCþñ âJuw“â¿èLåî ¤ ßûŽ4% û°%LoçÃmàÍ*ƒÔtB–‰U\~ã¾~ªêØ#­…_.E²¼1¸SÃ…9ƒ“Ú�9¼À@b Dî¤"NƒóBN¥$I!R ©fôXŒMP[ó*¯aLJaË2f@âgÐgáôl�i 5î©lwp¹Ül¿ÓÔÔoFs�,z¨6×}'ŧû~ov¨€.ÆÀ‚tä?dn@B“¿Â@{§þbFJ‰�Â\8ÂR``}îäCfÈ4ƒ°gNe¹hŒT?yh�‰”!r…GIx½¶*‚òµ‘ƒÕ3z™ƒð}+G„`ïN�òcBµñª—þÝ%˜G%©´™ì53¸šÒcCIŸN¢Ï%«Í¶ï¬J‰“­ìÔãc´§Tóø¹(NÍK¼’.F½¥•a¿kµŸzÂ+%íÆ"DuÍϑ¡MÏÄ®ËãÖeT )ל©5jשD"KØ™É<þÜÇ:ðßßë½ÂàKgˆ?àÑÝçkH÷]è°Ô‚õ÷ºõSåñhþ!ž§Pÿîmyÿîm‰/Ns œt ¹d­#�[�©IѤœücy1_~nÞhUäbÁ#ÂC9Ä#ÂCb˜&Ã$Í•*”ˆœ,ô+².ýÓæ /œ´Å/œ´_7/œ´y0Ä�¿?ÃÅmIn3\õL½„ ŒRüSƒãS"þkZzóÕZËÚ­Ð]¶¨¡É_PÔ¬˜b£#pCe,Å��fÅÎí’fÈŠ¢7gì„Gl¾á™r^¤µ�Pħ€‚h�Oƒn×ÿÐŒZ:¹�«I¦–Ti $ ¦~©¥­­º|­&°Ï¥&KºÓ@¼Àã‘Ç.€oÇ.€}…ÇR�ÛË@åˆiË˃~"ΨêaÚé4`à7i«‡áeÓÇ ã7ÒQxê_ÎqïÿEŒñ>TŒóÙûÅú¼ÕT&þ¸4Ò€Y7 .ƒ|ë&k³ 3&�tç\(m36–)õã*/ð}O0ndÊä7O«F]8OªFCÎd_­P[¤R£99VSU“Û¾Uô³�]1³5h¨¿EÒkÝþ¸’káNán™ó?�n™ó‚in™óªUp˜ÿ\{ìÒ…—}\”Æ<ƒ¼nÑD‡£o`Œá¿–ã? —Nß ¢ˆueŸª/…­“«Œã1Ü«—â/§¶ Ë¿ç[2åǨº£_Ë›ôt�Ï”Ÿ°ÐO㎚Õe¹^è"ufkë»E¡ûô3¤vjõãóžö§^ê8üfOZ†ųAÚª¯Õæ ä- '’®ø¥Â•Ú*Seyñ,á0â 1cD{1cD F9Hù`¥@ÍEamFyt½L¶C\ÄWšÅ$:Yíh¯[Ú%ZH]!†übùb«án•#,wƾìÆyŒ‘YB{0>¼��£6P‚ „|‡×9ô[ŠécŠéc_pŠécyM�¤“Ë–¼žå˜HnüšjT³Ãžz_— £Â©�P¤¢Mq´¦*)Vþª¬•Hñµ„¥µ·9³›P·áo&t¸†ž¼ºå^м „=¼���Ç%%nsÇ%%­`ÈxA)̇µ$›ÌÉå,qÌË%oJÔUå>EÔ¤?VKÞ¹¤ß‚¥3ß—e¸évÔ¢æéâÙÆuë+™a ð½^Yþm“ �þÒ·bý �ÕÏr ͈÷ \~›ó \~ºŒ ;´)ž q#! ƒ-¶‡ !í„Î 4‰Edè 5µ¼ˆ :ró�N Fè´Ÿå LìóæV MgþZ f+>G€ k¸ª˜Y †�£€Å  d”³T ¦8Õ1° ¨ " ©Ï‰iK ¬\H‡ ­˜¤·j ¯bÝbH ±›“{Ç ²b*†5 ¸ld¨7 ¼ „W© ¿ß¡Xý Àªèü Á =Œ ÁíöÎ Ã,ó²ö ØøÜp ÛʵÚ ê�tKa êØnË# î�åîO ñžeI øé¥ ÿ ÕL) ÿŽÚöf cY„Ê �V€ ­“Ó… .ƒj ïîTQ ¾T]e ʮŠÝW(X ,_$$i /öÄ&Ï 4ñ„úÑ 5rÕu” 7*åø =äª! IöTE Ty ¦Œ UÇ�À Wܾ)2 _Ò‰Œ ae cÂó5< cÄŸP eÄ ¾ uo~ì uõ5½ w5mw �ăD ‚ò52« ‡1’y �É3\~ “¼:ž ˜Iœ ˜IœË ˜IœÄ ˜Iœ0I ˜Iœk€ ˜Iœ”‰ ˜Iœ˜Ž ˜Iœ¬ô �CS �8r‰� ŸÉ9Gç ¤ Ô/ «¦¯¥ ¬,…0 ¬6"ä— ®5Õò ®ùµ¤ ¯Þ'� ²Ê^& µ�I°9 µãã-Ÿ ¶ã &¡ ¼Œtà ¼Ëˆ� ĽNßR Ë;:†ƒ ÍGcó Ð:âž Ð:âlZ Ûãµ5ï Ûãµl Ûãµ™ Þ;±îï Þä5ü ðe3„H òóÈ{O ü˜Ž¨Ë ü˜ŽÓ9 ÿôÅâÔ s|Q ½.n. Њ to~ X‡� çK2v )M¥ -ˆ8Z .2Ö¼ /.”�… 2 ΢ 5�…Ü# 9²3» @(eˆ A¨N› Ks3â KºþI L¡.á\ LÇ9”W WÌè X [týJ pI3[y rËWh x½(— x½(›¿ {uÅ@ò :3×ø € ÍjX €Ùsm? ‹Ì ® ŒH»Q �õ‰î �Ü ; �Ü âO �ßZœ/ ›i³õ" ›€-? ªDÄ7ÿ «Í(œc ¯–]Pr ±à„8· ´¹þ ¹DÔ ¹¾´Ip ¼BÓÇ ¼~ÓÝp ¼šÙ“ñ Ït®€0 Ù·å¨m ߺš�c àKGú á²~ß ã\Eâ ëÜKš ëù^Ѱ óy~É’ ó²+ vÕhû §é¤w ÓìA† šEì‘ á2B š+0è PÔÚ ¼%‹Ì Ö#,Ù Qô£– l”J‹ ¿�G« #“µÈ '{íî (µE3Œ * •´s 2l» 7±"!V 8Ç‘RŠ ;y*Û =ÙÓ` @|5Îp @¿ÀŠ­ Vÿõ⎠dMKæ gÆ#%Ø n¾/—À pk¾Êi t—¥Õf t©Žc tÁ�U» v"¾­ {Bqd €ÿü³î ˆ=Î7j ‰¡ãæ¥ ”Ëeì_ •h¥‡l —M¥C¤ ŸèT¬6 ¡žï  ¡ô׆» £î× ®�CK »²4pÎ ¼°e¥v Æm)•1 Ò¯ãòð Þv¥“© ãbnFÜ ê¬Dä× ëUÔx îµÕ ë ðYƒ±\ ûìó Û þÖ\€‰ -Ÿ–w …‹3X “Äû“ 'Üi° .�“õ 0³u9í 0ó£ 3±¶T 7yÒ* CàÒè… G9.Èh H³³Úà Kz9aÌ Kè„éi MîÄ S NðK# ]`^JR _ TÈ dTŠ iØä'9 iÚ$^Ø iÚ$lÉ m¢.¶» zÿíè €¢éÉ ƒÄ2š7 އÄË ‘݃ y œ|õ1" £ö=$Ç «cE ºDDµö ˜S�! ÇDã^ ÌÈðX ×s9’ ä~t¹Ÿ í>Ó‚­ ûîstõ ÿ»:I³ûÉ,·ÉY¨ ¼üdcŒxê"<©‡»„‡»°î¾sƒI­s=ó(t�z$(·©Yø-þƒz/+ã!0ó/E�0ô>EN9Äó = ¡EjßöH;Ó\L`Òý�L¿Ó^OLÊã[JLÝ^ø«V�(ÍY‚—ÿ Zrþ¸Óh€j8i?øOkŽ·ôlfcå¼p#4#q¢ƒ¾ÚtŽ‚üt/C[ÁD³åb† …x‹�^AÛe™Ï-STš¥tŠS£±…y�­–ý²šb£Ò¹ë ÌUº”t½e¿ß:¤KÉk\DÌ-î½Í`E1Ô•³ŽXÕ�ýö”ÚYe#®à˜9fêh‹\ë Ãëœt™üîppþVCu.ã~°`‘nÕïú;>ù‚ j¨Kc ïšR¢©(üÓêx6ãÅÈ8 qVÄ<æÉ°s@-®€HNŽ’ãIöô0|MÉÕ„‹U⃠Z8nã[Kô¸e3¦Ëem3:|iFW.Ýr†Õšxs$§ww³ Ü|*½õá}$7÷!…?y †AÔ õŒ�ç…ï�Ó�ô˜�Ô²)Жž Q'�]Ðá�âtýÓŸ2IM¾¢m£U¤žµ4¿¬nçc–¯#HMY´êâ3¹éŸÕœº£Î¦û½¡uÖ"À$&–$Æ| ÉŸ)“NËîÜÏ~ÄÐ#Û]-jÜííÃñá�o+�áùÅÖhãÊoDråd…¯sëŠ7ºôßíQòöé3]%ø6‰•‡ùfîWCiæ SÖmˆ(&C)&Cancelcolorset xn‹¤(&O)&OKcolorset‚r_iN;˜˜ Color ThemecolorsetmûR e°‰ÄR(&A) &Add New Rule conditional SÖmˆ(&C)&Cancel conditional Qs•í(&C)&Close conditional R –d(&D)&Delete conditional~Óg_�Çnä(&E) &End Filter conditional �Çnä(&F)&Filter conditional �}Qe(&L)&Load conditional xn‹¤(&O)&OK conditionalR –d‰ÄR(&R) &Remove Rule conditional OÝ[X(&S)&Save conditionalPGFalse conditionalgåb~N NN*(&N) Find &Next conditionalgåb~N NN*(&P)Find &Previous conditionalT [W:Name: conditionall¡g b~R0gaNöS9‘M!No conditional matches were found conditional‚‚p¹|{W‹ Node Type conditional ‰ÄR{0}Rule {0} conditionalOÝ[X‰ÄR Saved Rules conditionalwTrue conditional [b@g |{W‹] [All Types] conditionalNand conditionalST+contains conditional Nå...~Ó\> ends with conditionalbor conditional Nå..._YË starts with conditional ^”u((&A)&Apply configdialog SÖmˆ(&C)&Cancel configdialogepcn|{W‹(&D) &Data Type configdialogR –d|{W‹(&D) &Delete Type configdialogNÎSŸge|{W‹ˆMu(&D)&Derive from original configdialoge¹z _(&E) &Equation configdialog[Wkµ‘Mn(&F) &Field Config configdialog[Wkµ|{W‹(&F) &Field Type configdialog–�…ÏšØ~§(&H)&Hide Advanced configdialog N yû(&M) &Move Down configdialoge°[Wkµ(&N)... &New Field... configdialoge°|{W‹(&N)... &New Type... configdialog xn‹¤(&O)&OK configdialog RM(&P)&Prefix configdialog ‘Ín(&R)&Reset configdialog~Ógœ|{W‹(&R) &Result Type configdialog� béb@g (&S) &Select All configdialogf>y:šØ~§(&S)&Show Advanced configdialogc’^�hQÆ(&S)&Sort Criteria configdialogh˜˜h<_(&T) &Title Format configdialogW(‚‚p¹NK•ômûR zzˆL(&b)Add &blank lines between nodes configdialogmûR [Wkµ Add Field configdialogmûR |{W‹Add Type configdialogmûR bR –depcn|{W‹Add or Remove Data Types configdialogmûR e‡g,˜yvî{&S÷(&s)Add text bullet&s configdialogQA‹¸&HTMLYh<_e‡g,Allow &HTML rich text in format configdialog {—g/�Ð{—{&Arithmetic Operators configdialog�êR¨|{W‹Automatic Types configdialogSïu([WkµRˆh(&F)Available &Field List configdialogSïu([Wkµ(&F)Available &Fields configdialog^\~ÓgœBoolean Result configdialogeàlÕR –d‚‚p¹Ou(v„epcn|{W‹+Cannot delete data type being used by nodes configdialoge9SØVþh(&I) Change &Icon configdialog[P‹¡ep Child Count configdialog[P_u(Child Reference configdialog [P|{W‹–PR6Child Type Limits configdialogn–d� bé(&S) Clear &Select configdialogb÷�|{W‹(&p)... Co&py Type... configdialog ~ÄT&&[PRˆh�“QúR–”{&(&S)+Combination && Child List Output &Separator configdialog kÔ�ƒ�Ð{—{&Comparison Operators configdialog ‘Mnepcn|{W‹Configure Data Types configdialogY R6|{W‹ Copy Type configdialog‹¡epCount configdialogR^úgaNö|{W‹(&n)Create Co&nditional Types configdialogeåg~Ógœ Date Result configdialoge°‚‚p¹v„:wP<(&V)Default &Value for New Nodes configdialogžØ‹¤[P‚‚p¹|{W‹(&T)Default Child &Type configdialog [šNIe¹z _Define Equation configdialog[šNIep[f[Wkµe¹z Define Math Field Equation configdialogR –d[Wkµ(&t) Dele&te Field configdialogNÎ�u(|{W‹ˆMu(&G)Derived from &Generic Type configdialogcÏ�ð Description configdialoge¹T Direction configdialog �‘VhšØ^¦ Editor Height configdialog�“Qee°v„[WkµT yð:Enter new field name: configdialog�“Qee°|{W‹v„T [W:Enter new type name: configdialoge¹z _•‹ïÿ{}Equation error: {} configdialog •‹ï - ep[fW:e¹z N-v„_ªs¯_u(2Error - circular reference in math field equations configdialog‹ÄO0&HTMLh‹°Evaluate &HTML tags configdialog˜�Ye‡[W Extra Text configdialog [Wkµ(&i)F&ield configdialog[WkµRˆh(&i) F&ield List configdialog[WkµField configdialog[WkµRˆh(&L) Field &List configdialog[Wkµ_u(Field References configdialog e‡NöOá`oS€File Info Reference configdialogû�le¹T(&D)Flip &Direction configdialogh<_^.R©(&H) Format &Help configdialogVþhIcon configdialog ep[fe¹z _ Math Equation configdialogOîe9[WkµRˆh(&F)Modify &Field List configdialogOîe9gaNö|{W‹(&n)Modify Co&nditional Types configdialog N yû(&U)Move &Up configdialog N yû(&w) Move Do&wn configdialog N yû(&p)Move U&p configdialogT [WName configdialogeàNone configdialoge‡g,ˆLep(&b)Num&ber of text lines configdialogep[W~Ógœ Number Result configdialog [P‚‚p¹ep‘ÏNumber of Children configdialog�Ð{—|{W‹(&p)O&perator Type configdialog �“Qú(&u)O&utput configdialog�Ð{—Rˆh(&a)Oper&ator List configdialog�Ð{— Operations configdialog QvNÖ[WkµS€Other Field References configdialog�“Qúh<_(&p)Out&put Format configdialog�“Qúh<_(&t)Outpu&t Format configdialog �“QúHTML Output HTML configdialog�“Qú� ˜yOutput Options configdialogr6_u(Parent Reference configdialogS€|{W‹(&n)Refere&nce Type configdialog_u(~§R+(&L)Reference &Level configdialog_u(|{W‹(&T)Reference &Type configdialogS€~§R+(&v)Reference Le&vel configdialog‘ÍT}T [Wkµ(&m)...Rena&me Field... configdialog‘ÍT}T |{W‹(&m)...Rena&me Type... configdialog ‘ÍT}T [Wkµ Rename Field configdialog ‘ÍT}T |{W‹ Rename Type configdialogNÎ{}‘ÍT}T N::Rename from {} to: configdialogh9_u(Root Reference configdialog�ýN � (&N) Select &None configdialog�ê_u(Self Reference configdialog‹¾nepcn|{W‹VþhSet Data Type Icon configdialogg gaNöW0‹¾n|{W‹Set Types Conditionally configdialogc’^�•.(&K)... Sort &Keys... configdialogc’^�•.Sort Key configdialog c’^�Qs•.[WkµSort Key Fields configdialog T(&x)Suffi&x configdialog|{W‹Rˆh(&y) T&ype List configdialog e‡g,�Ð{—{&Text Operators configdialoge‡g,~Ógœ Text Result configdialogN QA‹¸Ou(NåN [W{&ÿ{},The following characters are not allowed: {} configdialog T yðN €ýN:zzThe name cannot be empty configdialogT yðN €ýST+zzh<The name cannot contain spaces configdialogT yðN €ýNå xml _Y4 The name cannot start with "xml" configdialogT yð_Ř{Nå[WkÍ_Y4!The name must start with a letter configdialog‹åT yð]òˆ«Ou(The name was already used configdialogeö•ô~Ógœ Time Result configdialog|{W‹‘Mn(&e) Typ&e Config configdialog|{W‹Type configdialogN:[WkµepcnOu(ˆhh<(&d)Use a table for field &data configdialog[b@g Sïu(|{W‹][All Types Available] configdialog[eà][None] configdialog~Ý[ùP<absolute value configdialogR add configdialogSÍOY_& arc cosine configdialogkc_&lâarc sine configdialogSÍkcR arc tangent configdialog^sWGaverage configdialogNå10N:^•v„[ùepbase-10 logarithm configdialog�Þc¥e‡g,concatenate text configdialog\e‡g,�lcbN:\Q™convert text to lower case configdialog\e‡g,�lcbN:Y'Q™convert text to upper case configdialogOY_&cosine of radians configdialog ^¦epR0_'^¦degrees to radians configdialog–ddivide configdialog{INŽequal to configdialog–6NX factorial configdialogmnp¹floating point configdialog TN SÖet–d floor divide configdialogkcTforward configdialogkcTfwd configdialogY'NŽ greater than configdialogY'NŽ{INŽgreater than or equal to configdialog*fôšØv„etep(higher integer)higher integer configdialog,W({,NN*SÂepN-ÿ \{,NŒN*SÂepfÿcbN:{,N N*SÂep(in 1st arg, replace 2nd arg with 3rd arg configdialog Ou({,NN*SÂepO\N:R–”{&�Þc¥e‡g,$join text using 1st arg as separator configdialog\NŽ less than configdialog\NŽ{INŽless than or equal to configdialog�;�‘N logical and configdialog�;�‘b logical or configdialog(�ƒONv„etep(lower integer) lower integer configdialoggY'maximum configdialogg\minimum configdialog|ûepmodulus configdialogNXmultiply configdialog �êq6[ùep^8epnatural log constant configdialog�êq6[ùepnatural logarithm configdialogN {I not equal to configdialogÀ^8ep pi constant configdialogNXe¹power configdialog_'^¦R0^¦radians to degrees configdialog�Trev configdialog�Treverse configdialogVÛ‚ N”Qeround to num digits configdialogkc_&sine of radians configdialog^se¹h9 square root configdialogQÏsubtract configdialog˜yvî`;TŒ sum of items configdialog,R~¿(tangent of radians)tangent of radians configdialog(Y‚gœ{,NN*e‡g,SÂepST+{,NŒN*SÂepÿ RN:w%true if 1st text arg contains 2nd arg configdialog*Y‚gœ{,NN*e‡g,SÂepNå{,NŒN*SÂep~Ó\>ÿ RN:w&true if 1st text arg ends with 2nd arg configdialog*Y‚gœ{,NN*e‡g,SÂepNå{,NŒN*SÂep_Y4ÿ RN:w(true if 1st text arg starts with 2nd arg configdialogwP<, gaNö, PGP<"true value, condition, false value configdialog0b*e­v„etep(truncated integer)truncated integer configdialogmO‰Èe‡Nö(&B)&Browse for File dataeditors SÖmˆ(&C)&Cancel dataeditors�lR0vîh(&G) &Go to Target dataeditors xn‹¤(&O)&OK dataeditorsbS_”þc¥(&O) &Open Link dataeditorsbS_VþrG(&O) &Open Picture dataeditors(W(hN-p¹Qû”þc¥vîh)(Click link target in tree) dataeditors~Ý[ùAbsolute dataeditorsW0W@Address dataeditorsn–d”þc¥(&L) Clear &Link dataeditorsf>y:T yð Display Name dataeditorsY�è”þc¥ External Link dataeditors e‡Nö�ï_„|{W‹File Path Type dataeditorsQ…�è”þc¥ Internal Link dataeditorsbS_e‡NöY9(&F) Open &Folder dataeditorsVþrG”þc¥ Picture Link dataeditorsvø[ùRelative dataeditorse¹hHScheme dataeditors‹¾nN:_SRMeö•ô(&N) Set to &Now dataeditors_SRMeåg(&D) Today's &Date dataeditors"TreeLine - Y�è”þc¥e‡NöTreeLine - External Link File dataeditorsTreeLine - VþrGe‡NöTreeLine - Picture File dataeditors”þc¥link dataeditors R(&C)&Columnsexports.�S÷R–”(CSV)TNãˆhh<(~§R+S÷)(&C);&Comma delimited (CSV) table of descendants (level numbers)exportsethõh(&E) &Entire treeexports &HTML&HTMLexports&HTMLh<_v„Nf{~&HTML format bookmarksexportsSbìh9‚‚p¹(&I)&Include root nodesexports &ODFY'~² &ODF Outlineexports.€rHg,TreeLine (2.0.x)(&O)&Old TreeLine (2.0.x)exportsSêg bS_‚‚p¹v„[P‚‚p¹(&O)&Only open node childrenexportsSUN*HTML˜u—b(&S)&Single HTML pageexportsh{~h˜˜e‡[W(&T)&Tabbed title textexports e‡g,(&T)&TextexportsTreeLine[Ph(&T)&TreeLine Subtreeexportsg*h<_Sv„b@g e‡g,�“Qú(&U)&Unformatted output of all textexports&XBELh<_v„Nf{~&XBEL format bookmarksexports&XML (�u()&XML (generic)exports Nf{~(&m) Book&marksexportsNf{~ Bookmarksexports� bé[üQúh<_[P|{W‹Choose export format subtypeexports� bé[üQúh<_|{W‹Choose export format typeexports � bé[üQú� ˜yChoose export optionsexports(�S÷R–”(CSV)[Pˆhh<(SU~§)(&d)7Comma &delimited (CSV) table of children (single level)exportsD•‹ï - eàlÕ”þc¥R0g*OÝ[Xv„TreeLinee‡Nö0 OÝ[Xe‡Nö^v‘Í‹Õ0FError - cannot link to unsaved TreeLine file. Save the file and retry.exports:•‹ï - g*b~R0[üQúj!ge‡Nö0 hÀgåTreeLine[‰ˆÅ0JError - export template files not found. Check your TreeLine installation.exportse‡Nö[üQú File ExportexportsSbìbSSph˜˜TŒ˜u�(&p)Include &print header && footerexports:[žeöh‰ÆVþÿ ”þc¥R0TreeLinee‡Nö(u(NŽWebg R¡Vh)8Live tree view, linked to TreeLine file (for web server)exports [žeöh‰ÆVþÿ SUN*e‡Nö(]LQeepcn)+Live tree view, single file (embedded data)exportsYN*HTMLTŒepcnˆh(&d)Multiple HTML &data tablesexports$^&[ü‚*z—h!Digit or Space (external)  fieldformatp¹R–”{& \.Dot Separator \. fieldformat e‡g,~Ó\> $ End of Text $ fieldformatrykŠ[W{&�lNI \Escape a Special Character \ fieldformatO‹[P 1/2/3/4Example 1/2/3/4 fieldformatcep (Y'Q™) EExponent (capital) E fieldformatcep(\Q™) eExponent (small) e fieldformatY�è”þc¥ ExternalLink fieldformat6\eö(0-23, 1 or 2 digits) %-HHour (0-23, 1 or 2 digits) %-H fieldformat,\eö(00-23, 2 digits) %HHour (00-23, 2 digits) %H fieldformat.\eö (01-12, 2 digits) %IHour (01-12, 2 digits) %I fieldformat8\eö (1-12, 1 or 2 digits) %-IHour (1-12, 1 or 2 digits) %-I fieldformat Htmle‡g,HtmlText fieldformatQ…�è”þc¥ InternalLink fieldformat ~§R–”{& /Level Separator / fieldformat\Q™[WkÍ [a-z]Lower Case Letters [a-z] fieldformatep[fMath fieldformat këyÒ (6 digits) %fMicroseconds (6 digits) %f fieldformat*R (1 or 2 digits) %-MMinute (1 or 2 digits) %-M fieldformatR (2 digits) %MMinute (2 digits) %M fieldformat*g (1 or 2 digits) %-mMonth (1 or 2 digits) %-m fieldformatg (2 digits) %mMonth (2 digits) %m fieldformat g)Q™ %bMonth Abbreviation %b fieldformat gT [W %B Month Name %B fieldformat—^ep[W [^0-9]Not a Number [^0-9] fieldformats°W(Now fieldformatep[WNumber fieldformatep 1Number 1 fieldformatS÷ Numbering fieldformatSUˆLe‡g, OneLineText fieldformat Sï� ep[W #Optional Digit # fieldformat Sï� h_× -Optional Sign - fieldformatb |Or | fieldformat,Y'~²O‹[P I../A../1../a)/i)!Outline Example I../A../1../a)/i) fieldformatVþrGPicture fieldformat kcRˆh�¾_RegularExpression fieldformat _Å—ep[W 0Required Digit 0 fieldformat_Å—v„h_× +Required Sign + fieldformat*yÒ (1 or 2 digits) %-SSecond (1 or 2 digits) %-S fieldformatyÒ (2 digits) %SSecond (2 digits) %S fieldformatkµ„=O‹[P 1.1.1.1Section Example 1.1.1.1 fieldformatkµ„=R–”{& .Section Separator . fieldformat R–”{& / Separator / fieldformatep[W [0-9]Set of Numbers [0-9] fieldformat \Q™[WkÍ aSmall Letter a fieldformat\Q™Wšlep[W iSmall Roman Numeral i fieldformat$zzh"Space Separator (internal)  fieldformat•ô–”e‡g, SpacedText fieldformatT/FT/F fieldformate‡g,Text fieldformateö•ôTime fieldformatY'Q™[WkÍ [A-Z]Upper Case Letters [A-Z] fieldformat$fgep[W (0 to 53) %-UWeek Number (0 to 53) %-U fieldformatfg)Q™ %aWeekday Abbreviation %a fieldformatfgT [W %AWeekday Name %A fieldformatY/NY/N fieldformat^t (2 digits) %yYear (2 digits) %y fieldformat^t (4 digits) %YYear (4 digits) %Y fieldformattrue/false true/false fieldformat yes/noyes/no fieldformatPGfalse genbooleanT&no genbooleanwtrue genbooleanf/yes genbooleanb@g e‡Nö All Files globalrefb@g TreeLinee‡NöAll TreeLine Files globalrefCSV(�S÷R–”)e‡NöCSV (Comma Delimited) Files globalref HTMLe‡Nö HTML Files globalrefODFe‡g,e‡NöODF Text Files globalref€TreeLinee‡NöOld TreeLine Files globalref PDFe‡Nö PDF Files globalrefe‡g,e‡Nö Text Files globalrefTreeLinee‡NöTreeLine Files globalrefTreeLinee‡Nö - S‹)TreeLine Files - Compressed globalrefTreeLinee‡Nö - R [ÆTreeLine Files - Encrypted globalrefTreepade‡Nö Treepad Files globalref XMLe‡Nö XML Files globalrefgåb~ÿ Find: helpview �ÔVÞ(&B)&Backhelpview RM�Û(&F)&Forwardhelpview N;˜u(&H)&Homehelpviewgåb~TNN*(&N) Find &Nexthelpviewgåb~RMNN*(&P)Find &Previoushelpview l¡b~R0e‡g,N2Text string not foundhelpview]åQwToolshelpview>"{0}"N f/g eHv„TreeLinee‡Nö0 Ou([üQe�ÇnäVhÿ:"{0}" is not a valid TreeLine file. Use an import filter?imports,�u(XML(—^TreeLinee‡Nö)(&G) &Generic XML (non-TreeLine file)imports$&HTMLNf{~(Mozillah<_) &HTML bookmarks (Mozilla Format)imports&Tab)�Ûe‡g,ÿ kψLNN*‚‚p¹%&Tab indented text, one node per lineimports&XMLNf{~(XBELh<_)&XML bookmarks (XBEL format)importsNf{~BOOKMARKimportsˆL{0}N v„•‹ïCSVh<_Bad CSV format on Line {0}importsNf{~ Bookmarksimports � bé[üQee¹_Choose Import Methodimports<^&g ~§R+R && h˜˜ˆLv„�S÷R–”(CSV)e‡g,ˆhh<(&m)ACo&mma delimited (CSV) text table with level column && header rowimports.^&g h˜˜ˆLv„�S÷R–”(CSV)e‡g,ˆhh<(&w)1Comma delimited (CSV) text table &with header rowimports•‹ï - eàlÕ‹ûSÖe‡Nö{0}Error - could not read file {0}imports •‹ï - {0}N-v„h<_N kcxnError - improper format in {0}importsvî_UFOLDERimports[üQee‡Nö Import Fileimports eàeHv„e‡Nö Invalid Fileimports{,{0}ˆLN v„~§R+S÷eàeH Invalid level number on line {0}imports ~§R+~Óg„eàeHInvalid level structureimports”þc¥Linkimports.€rHg,Tree&Linee‡Nö(1.xb2.x)Old Tree&Line File (1.x or 2.x)imports,Open &Document (ODF)Y'~²Open &Document (ODF) outlineimportsQvNÖOtherimports"~¯e‡g,Nkµ„=(zzv}ˆLR–”)(&p)-Plain text ¶graphs (blank line delimited)imports(~¯e‡g,ÿ kψLNN*‚‚p¹(VÞ�fR–”)(&n)-Plain text, one &node per line (CR delimited)importsR–”{& SEPARATORimportsˆhh<TABLEimports&^&h˜˜TŒˆLv„TabR–”e‡g,ˆhh<(&r))Tab delimited text table with header &rowimportse‡g,TextimportsˆL{0}N v„gavîY*YToo many entries on Line {0}importsTreeLine - [üQee‡NöTreeLine - Import Fileimports*Treepade‡Nö(NÅ–Pe‡g,‚‚p¹)(&f)Treepad &file (text nodes only)imports_Ř{W(QýepN-~ÄT[P_u(/Child references must be combined in a functionmatheval—^lÕv„"{}"[W{&Illegal "{}" charactersmatheval[XW(—^lÕQýep: {0}Illegal function present: {0}matheval—^lÕ[ùŒa|{W‹b�Ð{—{&: {0}$Illegal object type or operator: {0}matheval{I_N-v„—^lÕ‹ílÕIllegal syntax in equationmatheval ^”u((&A)&Apply miscdialogs SÖmˆ(&C)&Cancel miscdialogs Qs•í(&C)&Close miscdialogs~Óg_�Çnä(&E) &End Filter miscdialogsethõh(&E) &Entire tree miscdialogs �Çnä(&F)&Filter miscdialogsgåb~N NN*(&F) &Find Next miscdialogs kcT(&F)&Forward miscdialogs_ýue^v�ó�Ç(&I)&Ignore and skip miscdialogsQs•.‹Í(&K) &Key words miscdialogs‚‚p¹|{W‹(&N) &Node Type miscdialogs xn‹¤(&O)&OK miscdialogs˜„[šNIv„Qs•.[Wkµ(&P)&Predefined Key Fields miscdialogskcRˆh�¾_(&R)&Regular expression miscdialogs fÿcb(&R)&Replace miscdialogs ‘ÍT/N NN*T ~§‚‚p¹v„S÷(&R)"&Restart numbers for next siblings miscdialogs`bY žØ‹¤(&R)&Restore Defaults miscdialogs SÍT(&R)&Reverse miscdialogsd}"e‡[W(&S) &Search Text miscdialogs� bé‚‚p¹v„[P‚‚p¹(&S)&Selection's children miscdialogsSêg h˜˜(&T) &Titles only miscdialogs]åQwh(&T) &Toolbars miscdialogs\zzv}[Wkµ‰ÆN:–ö(&T)&Treat blank fields as zeros miscdialogsOu(^”u(žØ‹¤[WOS(&U)&Use app default font miscdialogsOu(e‡NöS‹)(&U)&Use file compression miscdialogsOu(|û~ߞ؋¤[WOS(&U)&Use system default font miscdialogs - R–”{& -  --Separator-- miscdialogsÜSÑuN†N%‘Í•‹ï0 TreeLineSï€ýYNŽN z3[šr¶`. ^ú‹®W(SæNN*e‡NöT N OÝ[XNûOUe‡Nöfôe9^v‘Íe°T/R¨TreeLine. N —bf>y:v„Œ‹ÕOá`oSïNåY R6^v��Çu5[P�®NöSÑ�R0doug101@bellz.org [ù`ÅQµv„‰ã‘Ê.A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances.  miscdialogsSïu(T}Nä(&v)A&vailable Commands miscdialogsNûaS9‘M(&m) Any &match miscdialogs ^”u(žØ‹¤[WOSApp Default Font miscdialogsn–d•.(&K) Clear &Key miscdialogs �ê[šNI[WOSCustomize Fonts miscdialogs �ê[šNI]åQwhCustomize Toolbars miscdialogsepcnData miscdialogsepcnƒÜSU Data Menu miscdialogsžØ‹¤ - SUˆLe‡[WDefault - Single Line Text miscdialogs�‘Edit miscdialogs�‘ƒÜSU Edit Menu miscdialogs�‘Vh‰ÆVþ[WOSEditor View Font miscdialogs R [Æe‡Nö[ÆxEncrypted File Password miscdialogs•‹ï - eàeHv„kcRˆh�¾_"Error - invalid regular expression miscdialogs•‹ï - fÿcbY1�%Error - replacement failed miscdialogs[Œetv„wí‹í(&u) F&ull phrase miscdialogs[WkµFields miscdialogse‡NöFile miscdialogse‡NöƒÜSU File Menu miscdialogse‡Nö\^`'File Properties miscdialogse‡Nö[XP¨ File Storage miscdialogs�ÇnäFilter miscdialogsgåb~Find miscdialogsgåb~N NN*(&N) Find &Next miscdialogsgåb~N NN*(&P)Find &Previous miscdialogs gåb~TŒfÿcbFind and Replace miscdialogsh<_Format miscdialogsh<_ƒÜSU Format Menu miscdialogs[Œetepcn(&d) Full &data miscdialogs[Œetv„‹Í(&w) Full &words miscdialogsYtl¡g S÷[Wkµv„‚‚p¹'Handling Nodes without Numbering Fields miscdialogs^.R©Help miscdialogs^.R©ƒÜSU Help Menu miscdialogsY‚OUd}" How to Search miscdialogs Sbì˜v~§‚‚p¹Include top-level nodes miscdialogs[Œetv„Qs•.‹Í(&w)Key full &words miscdialogs•.{0}]òˆ«Ou(Key {0} is already used miscdialogs •.vØ_ëcw•.Keyboard Shortcuts miscdialogs‹íŠNãxb [WQx(Sï� )&Language code or dictionary (optional) miscdialogsY'Vþh Large Icons miscdialogsep[f[Wkµ Math Fields miscdialogs N yû(&D) Move &Down miscdialogs N yû(&U)Move &Up miscdialogs‚‚p¹[Wkµ(&o) N&ode Fields miscdialogseàƒÜSUNo menu miscdialogsW(epcn|{W‹N-b~N R0S÷[Wkµ,No numbering fields were found in data types miscdialogs‚‚p¹Node miscdialogs‚‚p¹h˜˜(&T) Node &Titles miscdialogs‚‚p¹ƒÜSU Node Menu miscdialogs �“Qú‰ÆVþ[WOSOutput View Font miscdialogskcRˆh�¾_(&g)Re&gular expression miscdialogs‘Íe°�“Qe[Æx:Re-Type Password: miscdialogs‘Íe°�“Qev„[ÆxN S9‘MRe-typed password did not match miscdialogsW(kdO‹Ýg•ô‹°OO[Æx%Remember password during this session miscdialogsfÿcbQh�è(&A) Replace &All miscdialogsfÿcbN†{0}N*S9‘M˜yReplaced {0} matches miscdialogsfÿcbe‡[W(&T)Replacement &Text miscdialogsOÝuYv„S÷(&n)Reserve &numbers miscdialogsh9‚‚p¹ Root Node miscdialogsd}"[W{&N2 {0} g*b~R0Search string "{0}" not found miscdialogsd}"e‡g, {0} g*b~R0Search text "{0}" not found miscdialogs� [šv„Re/(&b)Selected &branches miscdialogs� bé‚‚p¹v„T ~§‚‚p¹(&s)Selection's &siblings miscdialogs� bé‚‚p¹v„[P‚‚p¹(&n)Selection's childre&n miscdialogs\Vþh Small Icons miscdialogsc’^�e¹TSort Direction miscdialogsc’^�e¹lÕ Sort Method miscdialogs‚‚p¹c’^� Sort Nodes miscdialogsbüQ™hÀgå Spell Check miscdialogs]åQwhT}Nä(&b)Tool&bar Commands miscdialogs]åQwh\:[ø(&S) Toolbar &Size miscdialogs ]åQwhep‘ÏToolbar Quantity miscdialogs]åQwTools miscdialogs]åQwƒÜSU Tools Menu miscdialogs h‰ÆVþ[WOSTree View Font miscdialogs TreeLine - N%‘Í•‹ïTreeLine - Serious Error miscdialogsTreeLineS÷TreeLine Numbering miscdialogs�“Qe {0} v„[Æx:Type Password for "{0}": miscdialogs �“Qe[Æx:Type Password: miscdialogs fôe°‚‚p¹S÷Update Node Numbering miscdialogsOu(e‡NöR [Æ(&e)Use file &encryption miscdialogs‰ÆVþView miscdialogs‰ÆVþƒÜSU View Menu miscdialogsd}"Q…[¹What to Search miscdialogsc’^�Q…[¹ What to Sort miscdialogs fôe°v„Q…[¹What to Update miscdialogsz—SãWindow miscdialogsz—SãƒÜSU Window Menu miscdialogsN QA‹¸Ou(–ö•^¦[Æx'Zero-length passwords are not permitted miscdialogs [b@g [Wkµ] [All Fields] miscdialogs [b@g |{W‹] [All Types] miscdialogsT [WName nodeformatW(Ÿ h`¬P\eöoÀm;epcn�‘Vh$Activate data editors on mouse hoveroptiondefaultsTHs° Appearanceoptiondefaults�êR¨OÝ[X Auto Saveoptiondefaults�êR¨bS_N k!Ou(v„e‡Nö!Automatically open last file usedoptiondefaults[P)�ÛPOyû ([WOSšØ^¦SUOM)+Child indent offset (in font height units) optiondefaultsSUQû‚‚p¹‘ÍT}T Click node to renameoptiondefaultsepcn�‘Vhh<_Data Editor FormatsoptiondefaultseågDatesoptiondefaultsSïu(RŸ€ýFeatures Availableoptiondefaults {,NY) kÏThFirst day of weekoptiondefaultsfgN”Fridayoptiondefaults.)�Û(O–ÅbSSp)TreeLine JSONe‡Nö)Indent (pretty print) TreeLine JSON filesoptiondefaultsg\S^”u(z ^�R0|û~ßbXvØ#Minimize application to system trayoptiondefaults$OÝ[XNK•ôv„R”Ÿep (‹¾N:0ˆhy:y�u()+Minutes between saves (set to 0 to disable)optiondefaultsfgNMondayoptiondefaultsg�Ñe‡Növ„ep‘Ï W(e‡NöƒÜSUN-(Number of recent files in the file menuoptiondefaults d¤mˆ~§R+epNumber of undo levelsoptiondefaultsW(e°z—SãN-bS_e‡NöOpen files in new windowsoptiondefaults g�Ñv„e‡Nö Recent FilesoptiondefaultsR –deàlÕ‹¿•îv„g�Ñe‡Nögavî'Remove inaccessible recent file entriesoptiondefaultsR^úeö‘ÍT}T e°‚‚p¹Rename new nodes when createdoptiondefaults`bY N NN*z—SãQàOU Restore previous window geometryoptiondefaults`bY g�Ñe‡Növ„h‰ÆVþr¶`(Restore tree view states of recent filesoptiondefaultsfgQmSaturdayoptiondefaultsf>y:—bS\QyVQH‰ÆVþShow breadcrumb ancestor viewoptiondefaultsW(SóbK‰ÆVþN-f>y:[Pz—h<#Show child pane in right hand viewsoptiondefaultsW(�“Qú‰ÆVþN-f>y:TNãShow descendants in output viewoptiondefaultsW(h‰ÆVþN-f>y:VþhShow icons in the tree viewoptiondefaultsW(epcn�‘‰ÆVþN-f>y:ep[f[Wkµ&Show math fields in the Data Edit viewoptiondefaultsW(epcn�‘‰ÆVþN-f>y:S÷[Wkµ+Show numbering fields in the Data Edit viewoptiondefaultsT/R¨gaNöStartup ConditionoptiondefaultsfgeåSundayoptiondefaultsfgVÛThursdayoptiondefaultseöTimesoptiondefaults hbÖe>Sïu(Tree drag && drop availableoptiondefaultsfgNŒTuesdayoptiondefaultsd¤mˆQ…[X Undo MemoryoptiondefaultsfgN  Wednesdayoptiondefaults SÖmˆ(&C)&Canceloptions xn‹¤(&O)&OKoptions� bé‘Mne‡NöOMn"Choose configuration file locationoptionsz ^�vî_U(O¿d:_Ou()$Program directory (for portable use)optionsu(b7v„N;vî_U(c¨ƒP)#User's home directory (recommended)optionsRYËSbSSpg:eöQú•Error initializing printer printdata TreeLine - [üQúPDFTreeLine - Export PDF printdata,‹fTJÿ_SRMbSSpg:N e/c�¹�Ý‹¾n0 OÝ[XŒetÿJWarning: Margin settings unsupported on current printer. Save adjustments? printdata:‹fTJÿ_SRMbSSpg:N e/c˜u—bY'\TŒ�¹�Ý‹¾n0 OÝ[X˜u—bŒetÿ]Warning: Page size and margin settings unsupported on current printer. Save page adjustments? printdata0‹fTJÿ_SRMbSSpg:N e/c˜u—bY'\‹¾n0 OÝ[XŒetÿKWarning: Page size setting unsupported on current printer. Save adjustment? printdata N (&B):&Bottom: printdialogs SÖmˆ(&C)&Cancel printdialogs~Ù[P‚‚p¹u;~¿(&D)&Draw lines to children printdialogsethõh(&E) &Entire tree printdialogs [WOS(&F)&Font printdialogs[WOS� bé(&F)&Font Selection printdialogs^8‰Ä� ˜y(&G)&General Options printdialogs˜uw ]æ(&H) &Header Left printdialogs˜uw /˜u�(&H)&Header/Footer printdialogsSbìh9‚‚p¹(&I)&Include root node printdialogs"OÝc{,NN*[P‚‚p¹W(r6‚‚p¹N (&K)&Keep first child with parent printdialogs ]æ(&L):&Left: printdialogs Rep(&N)&Number of columns printdialogs xn‹¤(&O)&OK printdialogs RM(&P)&Prefix printdialogsbSSp(&P)... &Print... printdialogs Só(&R):&Right: printdialogs T(&S)&Suffix printdialogs N (&T):&Top: printdialogs SUOM(&U)&Units printdialogs(Ou(TreeLine�“Qú‰ÆVþ[WOS(&U)&Use TreeLine output view font printdialogs [½(&W):&Width: printdialogs"A3 (279 x 420 mm)A3 (279 x 420 mm) printdialogs"A4 (210 x 297 mm)A4 (210 x 297 mm) printdialogs"A5 (148 x 210 mm)A5 (148 x 210 mm) printdialogs>AaBbCcDdEeFfGg...TtUuVvWvXxYyZzAaBbCcDdEeFfGg...TtUuVvWvXxYyZz printdialogsS˜|s (cm)Centimeters (cm) printdialogsRColumns printdialogs �ê[šNIY'\ Custom Size printdialogsžØ‹¤[WOS Default Font printdialogs•‹ïÿ˜u—bY'\b�¹�ÝeàeH(Error: Page size or margins are invalid printdialogs˜�Ye‡[W Extra Text printdialogs—b[ù˜u—b Facing Pages printdialogsry_�Features printdialogs [Wkµ(&d)Fiel&ds printdialogs[Wkµh<_(&m) Field For&mat printdialogs"{0}"v„[Wkµh<_Field Format for "{0}" printdialogs�T˜u—bFit Page printdialogs�T[½^¦ Fit Width printdialogs[WOSh7_(&y) Font st&yle printdialogs˜u�(&e):Foot&er: printdialogs˜u�]æ(&L) Footer &Left printdialogs˜u�N-(&n)Footer Ce&nter printdialogs˜u�Só(&t) Footer Righ&t printdialogsh<_^.R©(&H) Format &Help printdialogs˜uw (&a):He&ader: printdialogs˜uw Só(&R) Header &Right printdialogs˜uw N-(&e)Header C&enter printdialogs ˜uw TŒ˜u�Header and Footer printdialogsšØ:Height: printdialogs ‚ñ[ø(in) Inches (in) printdialogs Sbìv„‚‚p¹Included Nodes printdialogs)�ÛIndent printdialogs )�ÛPOyû‘Ï(&t) (~¿šØSUOM)"Indent Offse&t (line height units) printdialogs l4^s(&d) Lan&dscape printdialogs&lÕ_‹e‡Nf (8.5 x 14 in.)Legal (8.5 x 14 in.) printdialogs"Oá~¸ (8.5 x 11 in.)Letter (8.5 x 11 in.) printdialogs�¹�ÝMargins printdialogskë|s (mm)Millimeters (mm) printdialogsTN˜u Next Page printdialogsSêg bS_‚‚p¹v„[P‚‚p¹(&y)Onl&y open node children printdialogse¹T Orientation printdialogs�“Qúh<_(&F)Output &Format printdialogs˜u—b‹¾n(&S) Page &Setup printdialogs~¸_ \:[ø(&S) Paper &Size printdialogs zÖT(&i) Portra&it printdialogsRMN˜u Previous Page printdialogsbSSpPrint printdialogsbSSp˜„‰È(&v)...Print Pre&view... printdialogsbSSp˜„‰È Print Preview printdialogsbSSp‹¾n Print Setup printdialogsbSSp‹¾nPrinting Setup printdialogsy:O‹Sample printdialogs� bébSSpg:(&P)Select &Printer printdialogs� bé[WOS Select Font printdialogs� [šv„Re/(&b)Selected &branches printdialogs� [šv„‚‚p¹(&n)Selected &nodes printdialogs \:[ø(&z)Si&ze printdialogsSU˜u Single Page printdialogsRNK•ôzzh<(&m)Space between colu&mns printdialogs$\W‹b¥~¸ (11 x 17 in.)Tabloid (11 x 17 in.) printdialogs TreeLine PDF bSSpg:TreeLine PDF Printer printdialogsbSSpNÀNH What to print printdialogse>Y'Zoom In printdialogs)\Zoom Out printdialogs mûR (&A)&Add spellcheck SÖmˆ(&C)&Cancel spellcheck_ýueQh�è(&I) &Ignore All spellcheck fÿcb(&R)&Replace spellcheckmûR \Q™(&L)Add &Lowercase spellcheckN N e‡:Context: spellcheckVb~N R0aspell.exeÿ ispell.exebhunspell.exe c[šOMnÿQCould not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? spellcheck[ŒbhÀgåRe/ NΘv�è~ç~íÿ3Finished checking the branch Continue from the top? spellcheck [ŒbbüQ™hÀgåFinished spell checking spellcheck _ýue(&e)Ignor&e spellcheckH[šOMaspell.exeÿ ipsell.exebhunspell.exe-Locate aspell.exe, ipsell.exe or hunspell.exe spellcheck N W([WQxN-Not in Dictionary spellcheckz ^�(*.exe)Program (*.exe) spellcheckfÿcbQh�è(&p) Re&place All spellcheckbüQ™hÀgå Spell Check spellcheck büQ™hÀgå•‹ïSpell Check Error spellcheck^ú‹® Suggestions spellcheckTreeLinebüQ™hÀgåTreeLine Spell Check spellcheckTTreeLinebüQ™hÀgå•‹ï xnOÝ[‰ˆÅN†aspellÿ ispellbhunspellLTreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed spellcheck‹Í:Word: spellcheck W(hN-� béSelect in Tree titlelistview˜yvî{&S÷Bullets treeformats[P|{W‹ ChildType treeformats [P|{W‹–PR6ChildTypeLimit treeformatsgaNö‰ÄRConditionalRule treeformatsžØ‹¤DEFAULT treeformats ‹ÄO0HtmlEvalHtml treeformats[WkµFIELD treeformatse‡NöFILE treeformats[Wkµ|{W‹ FieldType treeformatsh<_Format treeformats h<_Html FormatHtml treeformatsN‚,|{W‹ GenericType treeformatsVþhIcon treeformatsRYËP< InitialValue treeformats RˆhRRr{& ListSeparator treeformatsep[W~¿NumLines treeformats�“Qúh<_ OutputFormat treeformatsRMPrefix treeformatsTRMc’^� SortForward treeformats c’^�•.S÷ SortKeyNum treeformatsN-•ôzzh< SpaceBetween treeformatsTSuffix treeformats|{W‹TYPE treeformatsˆhh<Table treeformatsh˜˜h<_ TitleFormat treeformats |—OS(&B) &Bold Fonttreelocalcontrol b÷�(&C)&CopytreelocalcontrolR –d‚‚p¹(&D) &Delete NodetreelocalcontrolRy»QK–†(&D)&Detach Clonestreelocalcontrol[üQú(&E)... &Export...treelocalcontrolY�è”þc¥(&E)...&External Link...treelocalcontrol[WOSY'\(&F) &Font Sizetreelocalcontrol)�Û‚‚p¹(&I) &Indent Nodetreelocalcontrol eœOS(&I) &Italic Fonttreelocalcontrol N yû(&M)&Move Uptreelocalcontrole°^úz—Sã(&N) &New Windowtreelocalcontrol |˜�4(&P)&PastetreelocalcontrolbSSp(&P)... &Print...treelocalcontrol ‘ÍPZ(&R)&Redotreelocalcontrol‘Íe°ubS€(&R)&Regenerate Referencestreelocalcontrol‘ÍT}T (&R)&Renametreelocalcontrol OÝ[X(&S)&Savetreelocalcontrol‹¾n‚‚p¹|{W‹(&S)&Set Node TypetreelocalcontrolbüQ™hÀgå(&S)...&Spell Check...treelocalcontrol d¤mˆ(&U)&UndotreelocalcontrolSÖmˆ)�Û‚‚p¹(&U)&Unindent NodetreelocalcontrolmûR [P‚‚p¹(&C) Add &ChildtreelocalcontrolmûR |{R+~§R+(&L)...Add Category &Level...treelocalcontrol\e°[P˜ymûR R0� [šv„r6˜y Add new child to selected parenttreelocalcontrolmûR bOîe9Y�èWeb”þc¥!Add or modify an extrnal web linktreelocalcontrolmûR bOîe9Q…�è‚‚p¹”þc¥#Add or modify an internal node linktreelocalcontroll¡g ^8‰Á[WkµeàlÕbi\U#Cannot expand without common fieldstreelocalcontrol|{R+[WkµCategory Fieldstreelocalcontroln–dh<_(&m)Clear For&mattingtreelocalcontroln–d_SRMb� [šv„e‡g,h<_)Clear current or selected text formattingtreelocalcontrolQK–†b@g S9‘Mv„‚‚p¹(&M)Clone All &Matched Nodestreelocalcontrol��ÇT^v[Wkµb˜SàTNã&Collapse descendants by merging fieldstreelocalcontrol\b@g S9‘Mv„‚‚p¹�lcbN:QK–†&Convert all matching nodes into clonestreelocalcontrol\{0}Re/�lcbN:QK–†"Converted {0} branches into clonestreelocalcontrolNÎe‡NöY R6|{W‹(&F)...Copy Types from &File...treelocalcontrol\Re/be‡g,Y R6R0Rj�4g(Copy the branch or text to the clipboardtreelocalcontrol$NÎSæNN*TreeLinee‡NöY R6‘Mn1Copy the configuration from another TreeLine filetreelocalcontrol RjR(&t)Cu&ttreelocalcontrol\Re/be‡g,RjRR0Rj�4g'Cut the branch or text to the clipboardtreelocalcontrolžØ‹¤Defaulttreelocalcontrol R –db@� ‚‚p¹Delete the selected nodestreelocalcontrolRy»_SRMRe/N-v„b@g QK–†‚‚p¹+Detach all cloned nodes in current branchestreelocalcontrol•‹ï - eàlÕR –dYNýe‡Nö{}'Error - could not delete backup file {}treelocalcontrol•‹ï - eàlÕ‹ûSÖe‡Nö{0}Error - could not read file {0}treelocalcontrol•‹ï - eàlÕQ™Qee‡NöError - could not write to filetreelocalcontrol•‹ï - eàlÕQ™Qe{}Error - could not write to {}treelocalcontrolNåTyÍQvNÖh<_[üQúe‡Nö(Export the file in various other formatstreelocalcontrolOu(_SRMbSSp� ˜y[üQúN:PDF+Export to PDF with current printing optionstreelocalcontrol e‡Nö]òOÝ[X File savedtreelocalcontrolc |{R+büT(&b)Flatten &by Categorytreelocalcontrol[WOS˜œ‚r(&o)...Font C&olor...treelocalcontrol_:R6fôe°b@g gaNö|{W‹TŒep[f[Wkµ3Force update of all conditional types & math fieldstreelocalcontrol)�Û� [šv„‚‚p¹Indent the selected nodestreelocalcontrolNKTcÒQeT ~§(&A)Insert Sibling &AftertreelocalcontrolNKRMcÒQeT ~§(&B)Insert Sibling &BeforetreelocalcontrolW([P˜yN e¹cÒQe|{R+‚‚p¹$Insert category nodes above childrentreelocalcontrolW(� bé‚‚p¹NKTcÒQee°v„T ~§‚‚p¹"Insert new sibling after selectiontreelocalcontrolW(� bé‚‚p¹NKRMcÒQee°v„T ~§‚‚p¹#Insert new sibling before selectiontreelocalcontrolQ…�è”þc¥(&L)...Internal &Link...treelocalcontrolY'LargetreelocalcontrolfôY'LargertreelocalcontrolgY'Largesttreelocalcontrol N yû(&o) M&ove DowntreelocalcontrolyûR0™–OM(&F) Move &FirsttreelocalcontrolyûR0gT(&L) Move &LasttreelocalcontrolN yû� [šv„‚‚p¹Move the selected nodes downtreelocalcontrol\b@� ‚‚p¹yûR¨N:{,NN*[P‚‚p¹0Move the selected nodes to be the first childrentreelocalcontrol\b@� ‚‚p¹yûR¨N:gTNN*[P‚‚p¹/Move the selected nodes to be the last childrentreelocalcontrolN yû� [šv„‚‚p¹Move the selected nodes uptreelocalcontrolb~N R0vøT v„‚‚p¹No identical nodes foundtreelocalcontrolbS_T Ne‡Növ„e°z—Sã#Open a new window for the same filetreelocalcontrolbSSp‹¾n(&r)...P&rint Setup...treelocalcontrol|˜�4~¯e‡g,(&s)Pa&ste Plain Texttreelocalcontrol|˜�4[P‚‚p¹(&h) Paste C&hildtreelocalcontrol|˜�4QK–†v„[P‚‚p¹(&o)Paste Cl&oned ChildtreelocalcontrolNKRM|˜�4QK–†v„T ~§(&n)Paste Clo&ned Sibling BeforetreelocalcontrolNKT|˜�4QK–†v„T ~§(&d)Paste Clone&d Sibling AftertreelocalcontrolNKT|˜�4T ~§(&A)Paste Sibling &AftertreelocalcontrolNKRM|˜�4T ~§(&B)Paste Sibling &BeforetreelocalcontrolNÎRj�4g|˜�4QK–†v„[P‚‚p¹&Paste a child clone from the clipboardtreelocalcontrolNÎRj�4g|˜�4[P‚‚p¹%Paste a child node from the clipboardtreelocalcontrolW(� bé‚‚p¹NKT|˜�4e°v„T ~§‚‚p¹Paste a sibling after selectiontreelocalcontrolW(� bé‚‚p¹NKRM|˜�4e°v„T ~§‚‚p¹ Paste a sibling before selectiontreelocalcontrol"W(� bé‚‚p¹NKT|˜�4e°v„T ~§QK–†‚‚p¹%Paste a sibling clone after selectiontreelocalcontrol"W(� bé‚‚p¹NKRM|˜�4e°v„T ~§QK–†‚‚p¹&Paste a sibling clone before selectiontreelocalcontrol|˜�4Rj�4gN-v„‚‚p¹be‡g,&Paste nodes or text from the clipboardtreelocalcontrolNÎRj�4g|˜�4g*h<_Sv„e‡g,+Paste non-formatted text from the clipboardtreelocalcontrolbSSpR0PDF(&t)...Print &to PDF...treelocalcontrolbSSp˜„‰È(&v)...Print Pre&view...treelocalcontrolh9cn_SRM� ˜ybSSph�“Qú*Print tree output based on current optionstreelocalcontrol\^`'(&e)...Prop&erties...treelocalcontrol‘ÍPZN NN*d¤mˆRedo the previous undotreelocalcontrol‘ÍT}T _SRMhgavîh˜˜#Rename the current tree entry titletreelocalcontrolN¤cb|{R+~§R+(&w)S&wap Category LevelstreelocalcontrolSæ[XN:(&A)... Save &As...treelocalcontrolOÝ[Xe‡Nö Save Filetreelocalcontrol\fôe9OÝ[XR0{}ÿSave changes to {}?treelocalcontrol OÝ[Xfôe9ÿ Save changes?treelocalcontrol OÝ[X_SRMe‡NöSave the current filetreelocalcontrolOu(e°T yðOÝ[Xe‡NöSave the file with a new nametreelocalcontrol� bée°~§R+v„[WkµSelect fields for new leveltreelocalcontrol ‹¾n[WOSY'\ Set Font Sizetreelocalcontrol ‹¾n‚‚p¹|{W‹ Set Node Typetreelocalcontrol‹¾nS‹)TŒR [Æ{Ie‡NöSÂep3Set file parameters like compression and encryptiontreelocalcontrol ‹¾n�¹�Ýÿ ˜u—bY'\TŒQvNÖbSSp� ˜y1Set margins, page size and other printing optionstreelocalcontrol‹¾n_SRMbb@� e‡g,v„Y'\(Set size of the current or selected texttreelocalcontrol‹¾n_SRMbb@� e‡g,v„˜œ‚r-Set the color of the current or selected texttreelocalcontrol\_SRMb� [šv„[WOS‹¾nN:|—OS(Set the current or selected font to boldtreelocalcontrol\_SRMb� [šv„[WOS‹¾nN:eœOS*Set the current or selected font to italictreelocalcontrol\_SRMb� [šv„[WOS‹¾nN:N R~¿-Set the current or selected font to underlinetreelocalcontrol‹¾nb@� ‚‚p¹v„‚‚p¹|{W‹$Set the node type for selected nodestreelocalcontrolf>y:bSSp~Ógœv„˜„‰È"Show a preview of printing resultstreelocalcontrol\SmalltreelocalcontrolbüQ™hÀgåhv„e‡g,epcn Spell check the tree's text datatreelocalcontrolN¤cb[P‚‚p¹TŒ[Y‚‚p¹|{‚‚p¹(Swap child and grandchild category nodestreelocalcontrol$TreeLine - bS_‘Mne‡Nö"TreeLine - Open Configuration FiletreelocalcontrolTreeLine - Sæ[XN:TreeLine - Save AstreelocalcontrolN R~¿(&n)U&nderline Fonttreelocalcontrold¤mˆN NN*dÍO\Undo the previous actiontreelocalcontrolSÖmˆ)�Û� [šv„‚‚p¹Unindent the selected nodestreelocalcontrol2‹fTJ - e‡Nöc_WOÿ W(NåN ‚‚p¹N-�ó�ÇN†WO[P_u(ÿOWarning - file corruption! Skipped bad child references in the following nodes:treelocalcontrol"QsNŽTreeLine(&A)...&About TreeLine...treemaincontrolWúg,u(lÕ(&B)...&Basic Usage...treemaincontrolSÖmˆe‡NöbS_(&C)&Cancel File OpentreemaincontrolgaNögåb~(&C)...&Conditional Find...treemaincontrol‘Mnepcn|{W‹(&C)...&Configure Data Types...treemaincontrolR –dYNý(&D)&Delete Backuptreemaincontrolgåb~e‡g,(&F)... &Find Text...treemaincontrol[Œete‡hc(&F)...&Full Documentation...treemaincontrol^8‰Ä� ˜y(&G)...&General Options...treemaincontrol[üQe(&I)... &Import...treemaincontrole°^ú(&N)...&New...treemaincontrolbS_(&O)...&Open...treemaincontrol �Qú(&Q)&Quittreemaincontrol`bY YNý(&R)&Restore Backuptreemaincontrol� béb@g (&S) &Select Alltreemaincontrol� béy:O‹e‡Nö(&S)&Select Sampletreemaincontrol� béj!g(&S)&Select Templatetreemaincontrole‡g,�ÇnäVh(&T)...&Text Filter...treemaincontrol.YNýe‡Nö {} [XW(0 NKRMv„O‹ÝSï€ý]ò~Ï])nƒy:Wúg,Ou(‹ôf Display basic usage instructionstreemaincontrolf>y:g Qskdz ^�v„rHg,Oá`o'Display version info about this programtreemaincontrol•‹ï - b~N R0Wúg,^.R©e‡Nö!Error - basic help file not foundtreemaincontrol•‹ï - eàlÕ‹ûSÖe‡Nö{0}Error - could not read file {0}treemaincontrol•‹ï - eàlÕR –dYNýe‡Nö{}'Error - could not remove backup file {}treemaincontrol,•‹ï - eàlÕ\ {0} ‘ÍT}T N: {1} 'Error - could not rename "{0}" to "{1}"treemaincontrol •‹ï - eàlÕ\‘Mne‡NöQ™Qe{})Error - could not write config file to {}treemaincontrol•‹ï - b~N R0e‡hce‡Nö$Error - documentation file not foundtreemaincontrol*•‹ï - eàeHv„TreeLinee‡Nö{0}!Error - invalid TreeLine file {0}treemaincontrol�Qú^”u(Exit the applicationtreemaincontrol�Çnä‚‚p¹NÅf>y:S9‘Me‡g,&Filter nodes to only show text matchestreemaincontrolgåb~TŒfÿcb(&R)...Find and &Replace...treemaincontrolW(h˜˜TŒepcnN-gåb~e‡g,Find text in node titles & datatreemaincontrol^8‰Ä� ˜yGeneral Optionstreemaincontrol^“rHg,:Library versions:treemaincontrol�‘epcn|{W‹ÿ [WkµTŒ�“QúˆL(Modify data types, fields & output linestreemaincontrole°e‡NöNew FiletreemaincontrolbS_e‡Nö Open FiletreemaincontrolbS_y:O‹e‡Nö(&m)...Open Sa&mple...treemaincontrol bS_y:O‹e‡Nö Open SampletreemaincontrolbS_NN*y:O‹e‡NöOpen Sample Filetreemaincontrol$Ou([Œete‡hcbS_TreeLinee‡Nö,Open a TreeLine file with full documentationtreemaincontrolNÎxÁvØN bS_e‡NöOpen a file from disktreemaincontrolbS_NN*—^TreeLinee‡NöOpen a non-TreeLine filetreemaincontrolbS_NN*y:O‹e‡NöOpen a sample filetreemaincontrolfÿcb‚‚p¹epcnN-v„e‡g,[W{&N2!Replace text strings in node datatreemaincontrolW(�‘Vh‘Ì� béb@g Select all text in an editortreemaincontrol‹¾n•.vØ_ëcw•.(&K)...Set &Keyboard Shortcuts...treemaincontrol‹¾nb@g e‡Növ„u(b7™–� ˜y"Set user preferences for all filestreemaincontrolf>y:‘Mn~Óg„(&o)... Show C&onfiguration Structure...treemaincontrolf>y:Sê‹ûv„|{W‹~Óg„Sï‰ÆS.Show read-only visualization of type structuretreemaincontrol‚‚p¹c’^�(&t)...Sor&t Nodes...treemaincontrol_YËNN*e°e‡NöStart a new filetreemaincontrolTreeLine - bS_e‡NöTreeLine - Open FiletreemaincontrolTreeLineWúg,u(lÕTreeLine Basic UsagetreemaincontrolTreeLinerHg,{0}TreeLine version {0}treemaincontrolfôe°S÷(&N)...Update &Numbering...treemaincontrolfôe°‚‚p¹epPy:[Pz—h<(&S)&Show Child Pane treewindow ]åQw(&T)&Tools treewindow ‰ÆVþ(&V)&View treewindow z—Sã(&W)&Window treewindow Qs•í�ÙN*z—SãClose this window treewindowb˜Sà� [š‚‚p¹v„b@g [P‚‚p¹+Collapse all children of the selected nodes treewindowepcn�‘ Data Edit treewindowepcn�“Qú Data Output treewindow\U_� [š‚‚p¹v„b@g [P‚‚p¹)Expand all children of the selected nodes treewindow h<_(&r)Fo&rmat treewindowS»R0N NN*S†Sòh� bé(Go to the next tree selection in history treewindowN NN*Xž‘Ïd}"Next Incremental Search treewindowN NN*Xž‘Ïd}"Previous Incremental Search treewindow�ÔVÞN NN*h� bé%Return to the previous tree selection treewindowf>y:—bS\Q‰ÆVþ(&B)Show &Breadcrumb View treewindowf>y:h˜˜Rˆh(&T)Show &Title List treewindowf>y:epcn�‘Vh(&E)Show Data &Editor treewindowf>y:epcn�“Qú(&O)Show Data &Output treewindowf>y:�“QúTNã(&D)Show Output &Descendants treewindowW(SóO§‰ÆVþf>y:epcn�‘VhShow data editor in right view treewindowW(SóO§‰ÆVþf>y:epcn�“QúShow data output in right view treewindowW(SóO§‰ÆVþf>y:h˜˜RˆhShow title list in right view treewindow _YËXž‘Ïd}"Start Incremental Search treewindowh˜˜Rˆh Title List treewindowRcbf>y:—bS\QyV‰ÆVþ'Toggle showing breadcrumb ancestor view treewindowRcbf>y:�“Qú‰ÆVþ)�ÛTNã/Toggle showing output view indented descendants treewindowRcbf>y:SóO§[P‰ÆVþ%Toggle showing right-hand child views treewindowTreeLine-3.2.1/treeline.desktop000066400000000000000000000003511506556630100164340ustar00rootroot00000000000000[Desktop Entry] Type=Application Version=1.1 Name=TreeLine GenericName=Outliner Comment=Organize text information in a tree structure Exec=treeline %f Icon=treeline-icon StartupNotify=true Terminal=false Categories=Office;TextTools; TreeLine-3.2.1/uninstall.py000077500000000000000000000052761506556630100156330ustar00rootroot00000000000000#!/usr/bin/env python """ **************************************************************************** uninstall.py, Linux uninstall script for TreeLine Copyright (C) 2018, Douglas W. Bell This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, either Version 2 or any later version. This program is distributed in the hope that it will be useful, but WITTHOUT ANY WARRANTY. See the included LICENSE file for details. ***************************************************************************** """ import sys import os.path import getopt import shutil prefixDir = '/usr/local' progName = 'treeline' def usage(exitCode=2): """Display usage info and exit. Arguments: exitCode -- the code to retuen when exiting. """ global prefixDir print('Usage:') print(' python uninstall.py [-h] [-p dir]') print('where:') print(' -h display this help message') print(' -p dir install prefix [default: {0}]'.format(prefixDir)) sys.exit(exitCode) def removeAll(path): """Remove path, whether it is a file or a directory, print status""" print(' Removing {0}...'.format(path)) try: if os.path.isdir(path): shutil.rmtree(path) elif os.path.isfile(path): os.remove(path) else: print(' not found') return print(' done') except OSError as e: if str(e).find('Permission denied') >= 0: print('\nError - must be root to remove files') sys.exit(4) raise def main(): """Main uninstaller function. """ try: opts, args = getopt.getopt(sys.argv[1:], 'hp:') except getopt.GetoptError: usage(2) global prefixDir for opt, val in opts: if opt == '-h': usage(0) elif opt == '-p': prefixDir = val print('Removing files...') global progName removeAll(os.path.join(prefixDir, 'lib', progName)) removeAll(os.path.join(prefixDir, 'share', 'doc', progName)) removeAll(os.path.join(prefixDir, 'share', progName)) removeAll(os.path.join(prefixDir, 'share', 'icons', progName)) removeAll(os.path.join(prefixDir, 'share', 'icons', 'hicolor', '48x48', 'apps', progName + '-icon.png')) removeAll(os.path.join(prefixDir, 'share', 'icons', 'hicolor', 'scalable', 'apps', progName + '-icon.svg')) removeAll(os.path.join(prefixDir, 'share', 'applications', progName + '.desktop')) removeAll(os.path.join(prefixDir, 'bin', progName)) print('Uninstall complete.') if __name__ == '__main__': main() TreeLine-3.2.1/win/000077500000000000000000000000001506556630100140305ustar00rootroot00000000000000TreeLine-3.2.1/win/treeline-all.iss000066400000000000000000000102341506556630100171250ustar00rootroot00000000000000; treeline-all.iss ; Inno Setup installer script for Treeline, an information storage program. ; This will install for a all users, admin rights are required. [Setup] AppName=TreeLine AppVersion=3.2.1 ChangesAssociations=yes DefaultDirName={commonpf}\TreeLine-3 DefaultGroupName=TreeLine DisableProgramGroupPage=yes OutputDir=. OutputBaseFilename=treeline-3.2.1-install-all PrivilegesRequired=poweruser SetupIconFile=treeline.ico Uninstallable=WizardIsTaskSelected('adduninstall') UninstallDisplayIcon={app}\treeline.exe,0 [Tasks] Name: "fileassoc"; Description: "Add *.trln file association" Name: "startmenu"; Description: "Add start menu shortcuts" Name: "deskicon"; Description: "Add a desktop shortcut" Name: "adduninstall"; Description: "Create an uninstaller" Name: "translate"; Description: "Include language translations" Name: "source"; Description: "Include source code" [InstallDelete] Type: files; Name: "{app}\library.zip" Type: files; Name: "{app}\python*.zip" Type: files; Name: "{app}\*.pyd" Type: files; Name: "{app}\*.dll" Type: files; Name: "{app}\doc\documentation.trl" Type: filesandordirs; Name: "{app}\lib" Type: filesandordirs; Name: "{app}\imageformats" Type: filesandordirs; Name: "{app}\platforms" Type: dirifempty; Name: "{app}\plugins" Type: files; Name: "{app}\samples\*.trl" Type: files; Name: "{app}\source\*.py" Type: files; Name: "{app}\templates\*.trl" Type: files; Name: "{app}\translations\*.qm" [Files] Source: "treeline.exe"; DestDir: "{app}" Source: "base_library.zip"; DestDir: "{app}" Source: "*.dll"; DestDir: "{app}" Source: "*.pyd"; DestDir: "{app}" Source: "PyQt6\*"; DestDir: "{app}\PyQt6"; Flags: recursesubdirs Source: "doc\LICENSE"; DestDir: "{app}\doc" Source: "doc\basichelp.html"; DestDir: "{app}\doc" Source: "doc\documentation.trln"; DestDir: "{app}\doc"; Attribs: readonly; \ Flags: overwritereadonly uninsremovereadonly Source: "doc\*.html"; DestDir: "{app}\doc"; Tasks: "translate" Source: "doc\*.trln"; DestDir: "{app}\doc"; Attribs: readonly; \ Tasks: "translate"; Flags: overwritereadonly uninsremovereadonly Source: "samples\*.trln"; DestDir: "{app}\samples"; Attribs: readonly; \ Flags: overwritereadonly uninsremovereadonly Source: "icons\toolbar\32x32\*.png"; DestDir: "{app}\icons\toolbar\32x32" Source: "icons\tree\*.png"; DestDir: "{app}\icons\tree" Source: "templates\exports\*.*"; DestDir: "{app}\templates\exports" Source: "templates\*en_*.trln"; DestDir: "{app}\templates"; Attribs: readonly; \ Flags: overwritereadonly uninsremovereadonly Source: "templates\*.trln"; DestDir: "{app}\templates"; Attribs: readonly; \ Tasks: "translate"; Flags: overwritereadonly uninsremovereadonly Source: "translations\*.qm"; DestDir: "{app}\translations"; Tasks: "translate" Source: "source\*.py"; DestDir: "{app}\source"; Tasks: "source" Source: "source\treeline.pro"; DestDir: "{app}\source"; Tasks: "source" Source: "source\treeline.spec"; DestDir: "{app}\source"; Tasks: "source" Source: "treeline.ico"; DestDir: "{app}"; Tasks: "source" Source: "*.iss"; DestDir: "{app}"; Tasks: "source" [Icons] Name: "{commonstartmenu}\TreeLine 3"; Filename: "{app}\treeline.exe"; \ WorkingDir: "{app}"; Tasks: "startmenu" Name: "{group}\TreeLine 3"; Filename: "{app}\treeline.exe"; \ WorkingDir: "{app}"; Tasks: "startmenu" Name: "{group}\Uninstall"; Filename: "{uninstallexe}"; Tasks: "startmenu" Name: "{commondesktop}\TreeLine 3"; Filename: "{app}\treeline.exe"; \ WorkingDir: "{app}"; Tasks: "deskicon" [Registry] Root: HKCR; Subkey: ".trln"; ValueType: string; \ ValueName: ""; ValueData: "TreeLineFile"; Flags: uninsdeletevalue; \ Tasks: "fileassoc" Root: HKCR; Subkey: "TreeLineFile"; ValueType: \ string; ValueName: ""; ValueData: "TreeLine File"; \ Flags: uninsdeletekey; Tasks: "fileassoc" Root: HKCR; Subkey: "TreeLineFile\DefaultIcon"; \ ValueType: string; ValueName: ""; ValueData: "{app}\treeline.exe,0"; \ Tasks: "fileassoc" Root: HKCR; Subkey: "TreeLineFile\shell\open\command"; \ ValueType: string; ValueName: ""; \ ValueData: """{app}\treeline.exe"" ""%1"""; Tasks: "fileassoc" TreeLine-3.2.1/win/treeline-user.iss000066400000000000000000000103431506556630100173340ustar00rootroot00000000000000; treeline-user.iss ; Inno Setup installer script for Treeline, an information storage program. ; This will install for a single user, no admin rights are required. [Setup] AppName=TreeLine AppVersion=3.2.1 ChangesAssociations=yes DefaultDirName={userappdata}\TreeLine-3 DefaultGroupName=TreeLine DisableProgramGroupPage=yes OutputDir=. OutputBaseFilename=treeline-3.2.1-install-user PrivilegesRequired=lowest SetupIconFile=treeline.ico Uninstallable=WizardIsTaskSelected('adduninstall') UninstallDisplayIcon={app}\treeline.exe,0 [Tasks] Name: "fileassoc"; Description: "Add *.trln file association" Name: "startmenu"; Description: "Add start menu shortcuts" Name: "deskicon"; Description: "Add a desktop shortcut" Name: "adduninstall"; Description: "Create an uninstaller" Name: "translate"; Description: "Include language translations" Name: "source"; Description: "Include source code" [InstallDelete] Type: files; Name: "{app}\library.zip" Type: files; Name: "{app}\python*.zip" Type: files; Name: "{app}\*.pyd" Type: files; Name: "{app}\*.dll" Type: files; Name: "{app}\doc\documentation.trl" Type: filesandordirs; Name: "{app}\lib" Type: filesandordirs; Name: "{app}\imageformats" Type: filesandordirs; Name: "{app}\platforms" Type: dirifempty; Name: "{app}\plugins" Type: files; Name: "{app}\samples\*.trl" Type: files; Name: "{app}\source\*.py" Type: files; Name: "{app}\templates\*.trl" Type: files; Name: "{app}\translations\*.qm" [Files] Source: "treeline.exe"; DestDir: "{app}" Source: "base_library.zip"; DestDir: "{app}" Source: "*.dll"; DestDir: "{app}" Source: "*.pyd"; DestDir: "{app}" Source: "PyQt6\*"; DestDir: "{app}\PyQt6"; Flags: recursesubdirs Source: "doc\LICENSE"; DestDir: "{app}\doc" Source: "doc\basichelp.html"; DestDir: "{app}\doc" Source: "doc\documentation.trln"; DestDir: "{app}\doc"; Attribs: readonly; \ Flags: overwritereadonly uninsremovereadonly Source: "doc\*.html"; DestDir: "{app}\doc"; Tasks: "translate" Source: "doc\*.trln"; DestDir: "{app}\doc"; Attribs: readonly; \ Tasks: "translate"; Flags: overwritereadonly uninsremovereadonly Source: "samples\*.trln"; DestDir: "{app}\samples"; Attribs: readonly; \ Flags: overwritereadonly uninsremovereadonly Source: "icons\toolbar\32x32\*.png"; DestDir: "{app}\icons\toolbar\32x32" Source: "icons\tree\*.png"; DestDir: "{app}\icons\tree" Source: "templates\exports\*.*"; DestDir: "{app}\templates\exports" Source: "templates\*en_*.trln"; DestDir: "{app}\templates"; Attribs: readonly; \ Flags: overwritereadonly uninsremovereadonly Source: "templates\*.trln"; DestDir: "{app}\templates"; Attribs: readonly; \ Tasks: "translate"; Flags: overwritereadonly uninsremovereadonly Source: "translations\*.qm"; DestDir: "{app}\translations"; Tasks: "translate" Source: "source\*.py"; DestDir: "{app}\source"; Tasks: "source" Source: "source\treeline.pro"; DestDir: "{app}\source"; Tasks: "source" Source: "source\treeline.spec"; DestDir: "{app}\source"; Tasks: "source" Source: "treeline.ico"; DestDir: "{app}"; Tasks: "source" Source: "*.iss"; DestDir: "{app}"; Tasks: "source" [Icons] Name: "{userstartmenu}\TreeLine 3"; Filename: "{app}\treeline.exe"; \ WorkingDir: "{app}"; Tasks: "startmenu" Name: "{group}\TreeLine 3"; Filename: "{app}\treeline.exe"; \ WorkingDir: "{app}"; Tasks: "startmenu" Name: "{group}\Uninstall"; Filename: "{uninstallexe}"; Tasks: "startmenu" Name: "{userdesktop}\TreeLine 3"; Filename: "{app}\treeline.exe"; \ WorkingDir: "{app}"; Tasks: "deskicon" [Registry] Root: HKCU; Subkey: "Software\Classes\.trln"; ValueType: string; \ ValueName: ""; ValueData: "TreeLineFile"; Flags: uninsdeletevalue; \ Tasks: "fileassoc" Root: HKCU; Subkey: "Software\Classes\TreeLineFile"; ValueType: \ string; ValueName: ""; ValueData: "TreeLine File"; \ Flags: uninsdeletekey; Tasks: "fileassoc" Root: HKCU; Subkey: "Software\Classes\TreeLineFile\DefaultIcon"; \ ValueType: string; ValueName: ""; ValueData: "{app}\treeline.exe,0"; \ Tasks: "fileassoc" Root: HKCU; Subkey: "Software\Classes\TreeLineFile\shell\open\command"; \ ValueType: string; ValueName: ""; \ ValueData: """{app}\treeline.exe"" ""%1"""; Tasks: "fileassoc" TreeLine-3.2.1/win/treeline.ico000066400000000000000000000353561506556630100163470ustar00rootroot00000000000000 h6  ¨ž00 ¨%F(  ÿòäÿêâ“ÿëáäïÞÙÿìÝ×ÿÿëáÿÿëáÿÿëáÿÿëáÿúæßÿêÛ×ÿüêàäÿìá’ÿñãÿòäÿëàÙÿëáÿÿëáÿøæÝÿm}˜ÿ@pÿº·¾ÿbs’ÿ$Esÿ?pÿ[o�ÿ©©¶ÿùçÞÿÿëáØÿñãÿêâ”ÿëáÿÿëáÿÿëáÿÿëáÿå×Ôÿ;lÿ±±ºÿIa…ÿSi‹ÿ÷åÝÿÿëáÿÿëáÿÿëáÿÿëáÿÿìá’ÿëáæÿëáÿÿëáÿÿëáÿÿëáÿæØÔÿ;lÿ±±ºÿH`†ÿas‘ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáäÿëáþÿëáÿ§Ñ­ÿæäÒÿÿëáÿå×Ôÿ;lÿ±±ºÿH`†ÿbs’ÿÿëáÿ½×ºÿÞâÎÿÿëáÿÿëáÿÿëáþÿëáÿÍÜÄÿ¡Mÿ”Ë¢ÿÿëáÿä×Óÿ;lÿ±±ºÿH`†ÿbs’ÿÿëáÿM·xÿ £QÿÄÚ¾ÿÿëáÿÿëáÿÿëáÿlÀŠÿ&«bÿýêàÿÿëáÿãÕÓÿ;lÿ°°¹ÿG`…ÿct’ÿÿëáÿùéÞÿ?²pÿEµtÿÿëáÿÿëáÿÿëáÿl¥�ÿp¢“ÿÿëáÿÿëáÿâÕÓÿ;lÿ°¯¹ÿG`…ÿ\o�ÿÿëáÿÿëáÿ‘¸¤ÿQ—�ÿÿëáÿÿëáÿÿëáÿcu’ÿ&GtÿÐÈÊÿÿëáÿáÕÒÿ;lÿ°¯¹ÿ� °ÿ‹“§ÿñàÚÿ÷åÝÿIb…ÿ2Qzÿÿëáÿÿëáÿÿëáÿn}˜ÿ;lÿ;lÿ Bqÿ$Fsÿ;lÿ Bqÿ&Gtÿ&Gtÿ&Gtÿ=mÿ;lÿ²pÿ Kÿ KÿŸÏ¨ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ¶Ö¶ÿ Kÿ KÿwÑÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÅÀÄÿ;lÿ;lÿcu’ÿÿëáÿy…�ÿ:lÿ:lÿ°¯¹ÿÿëáÿÿëáÿÿëáÿÿëáÿÏÝÅÿ Kÿ KÿXºÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿžÏ¨ÿ Kÿ Kÿ£Ð«ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÅ¿Äÿ;lÿ;lÿbt’ÿÿëáÿy…�ÿ:lÿ:lÿ¯®¸ÿÿëáÿÿëáÿÿëáÿÿëáÿþëàÿ ¢Pÿ Kÿ6°kÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ ¯¯ÿAd€ÿBd€ÿ³¹¹ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿľÄÿ;lÿ;lÿbt’ÿÿëáÿx…�ÿ:lÿ:lÿšž®ÿÿëáÿÿëáÿÿëáÿÿëáÿüéßÿCg€ÿ=c~ÿWzŠÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ©ª¶ÿ;lÿ;lÿYm�ÿýéàÿÿëáÿÿëáÿÿëáÿÿëáÿ¼Âÿ;lÿ;lÿat‘ÿÿëáÿx…�ÿ:lÿ:lÿ7S}ÿÖÌÌÿÿëáÿÿëáÿÿëáÿÊÃÇÿ;lÿ;lÿJc†ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ´²¼ÿ;lÿ;lÿ;lÿew”ÿÚÏÏÿÿëáÿÿëáÿÿëáÿÁ¼Âÿ;lÿ;lÿat‘ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÝÒÐÿ@Z‚ÿ;lÿ;lÿTj‹ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ¿ºÁÿ;lÿ;lÿ;lÿ;lÿ;lÿBqÿ5R|ÿ5R|ÿ-Lwÿ;lÿ;lÿ Bqÿ5R|ÿ5R|ÿ5R|ÿ5R|ÿ5R|ÿ5R|ÿ5R|ÿ,Kwÿ;lÿ;lÿ;lÿ;lÿ^r‘ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÉÃÆÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿhy•ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÔÙÉÿ+�jÿ �cÿa ŠÿÁ¼ÂÿÁ¼ÂÿÁ¼ÂÿÁ¼ÂÿÁ¼ÂÿÁ¼ÂÿÁ¼ÂÿÁ¼ÂÿÁ¼ÂÿÁ¼ÂÿÏÇÉÿÐÈÊÿÐÈÊÿÐÈÊÿÐÈÊÿÐÈÊÿÐÈÊÿÐÈÊÿµÀºÿ-˜jÿ-˜jÿyµ•ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿïæØÿ Kÿ KÿEµtÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ½×ºÿ Kÿ KÿÅ–ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ'¬bÿ Kÿ¢PÿçäÓÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ‹É�ÿ Kÿ Kÿ¡Ïªÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáúÿëáÿÿëáÿ€Æ–ÿ Kÿ Kÿ<±nÿØßÊÿÿëáÿÿëáÿÜáÌÿƒÇ˜ÿ'¬bÿáâÐÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ?²pÿ Kÿ KÿàáÏÿÿëáÿÿëáÿÿëáÿÿëáúÿëáäÿëáÿÿëáÿîæ×ÿª]ÿ Kÿ Kÿ Kÿ¤Sÿ £Rÿ Kÿ Kÿ KÿwÑÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÉÛÁÿ Kÿ Kÿ0®gÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáâÿëáµÿëáÿÿëáÿÿëáÿÔÞÈÿ ©^ÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ £RÿÝáÍÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿòçÚÿ-­fÿ Kÿ Kÿ¢Ïªÿÿëáÿÿëáÿÿëáÿÿëáÿÿëá´ÿëáeÿëáÿÿëáÿÿëáÿÿëáÿõèÛÿ—̤ÿXºÿ3¯iÿ3¯iÿT¸|ÿK¶wÿ Kÿ Kÿ)¬cÿäãÑÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿåãÒÿ:±mÿ Kÿ Kÿ;±nÿüêßÿÿëáÿÿëáÿÿëáÿÿëáÿÿêàcÿßßÿëáâÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿõèÛÿ1®hÿ Kÿ Kÿ¦Xÿ’Ë¡ÿÞâÎÿîæ×ÿÑÞÆÿ{Ä”ÿ¥Tÿ Kÿ Kÿ§ZÿÝáÍÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáäÿãã ÿëáMÿëáýÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿäãÑÿ+­dÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ$ª`ÿ×ßÊÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáýÿëàKÿêámÿëáýÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿïæØÿc½…ÿ¡Mÿ Kÿ Kÿ Kÿ Kÿ Kÿ ¢PÿpÁ�ÿóèÚÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáýÿìàlÿëáMÿëáâÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÚàËÿ�ÊŸÿZ»€ÿU¹}ÿe¾†ÿœÎ§ÿêåÔÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëâáÿêàJÿãã ÿëáeÿëáµÿëáäÿëáúÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáúÿëáäÿëáµÿëàdÿßßü?ðàÀ€€€€Ààðü?(0` $ÿèã-ÿêâ{ÿëá¾ÿëàÙÿëáõÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáõÿëàÙÿëá¾ÿêâzÿîâ,ÿìã7ÿëáÁÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëàÈÿêâ>ÿßßÿìáŸÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ×ÌÍÿ¥§´ÿÇÁÅÿäÖÔÿúæßÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿïÞÙÿÓÊËÿ·´¼ÿ±°ºÿ²±»ÿÒÉËÿþêàÿÿëáÿÿëáÿÿëáÿÿëáÿÿìàžÿßßÿéÞÿëàÈÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿº·¿ÿ-Lwÿ;lÿ;lÿ)Ivÿ;XÿMdˆÿ_r‘ÿÿëáÿÿëáÿÕËËÿ{†žÿhy•ÿSi‹ÿ@Z‚ÿ-Kwÿ>nÿ:lÿ:lÿ:lÿ:lÿ:lÿ:lÿ3Pzÿ¤¦³ÿþêàÿÿëáÿÿëáÿÿëáÿÿêâÇÿèÜÿßßÿêâÇÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿïÞÙÿOf‰ÿ;lÿ;lÿ;lÿ;lÿ;lÿÿëáÿÿëáÿ°°¹ÿ:lÿ:lÿ:lÿ:lÿ:lÿ:lÿ:lÿ:lÿ:lÿnÿöäÜÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ¥¨µÿ;lÿ;lÿ;lÿ;lÿùçÞÿÿëáÿ©©¶ÿ:lÿ:lÿ:lÿ:lÿÖÌÌÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ�•¨ÿ;lÿ;lÿ;lÿXlŽÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿðàÚÿ;lÿ;lÿ;lÿ;lÿ¤¦³ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ¥§´ÿ;lÿ;lÿ;lÿ;lÿùçÞÿÿëáÿ©©¶ÿ:lÿ:lÿ:lÿ:lÿiy•ÿýéàÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿVlŒÿ;lÿ;lÿ;lÿbt’ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿûèßÿ;lÿ;lÿ;lÿ;lÿ&GtÿØÍÍÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ¤¦³ÿ;lÿ;lÿ;lÿ;lÿúæßÿÿëáÿÑÈÊÿƒ�£ÿƒ�£ÿƒ�£ÿƒ�£ÿƒ�£ÿ°°¹ÿûèßÿÿëáÿÿëáÿÿëáÿÿëáÿÐÈÊÿ=mÿ;lÿ;lÿ;lÿk{—ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ@pÿ;lÿ;lÿ;lÿ;lÿ$Fsÿ“™«ÿå×Ôÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ¢¥²ÿ;lÿ;lÿ;lÿ;lÿúçßÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿúæßÿ·´¼ÿ1Pyÿ;lÿ;lÿ;lÿ;lÿuƒœÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ(Hvÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ(Hvÿ5R|ÿA[�ÿE^ƒÿE^ƒÿ1Pyÿ;lÿ;lÿ;lÿ;lÿ7T}ÿE^ƒÿE^ƒÿE^ƒÿE^ƒÿE^ƒÿE^ƒÿE^ƒÿE^ƒÿQh‰ÿLc‡ÿ@Z‚ÿ?oÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿŠ ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ3Qzÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ‰’¦ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ>Z€ÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ;lÿ“™«ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ[™‡ÿ2„pÿ,‚mÿ(‚jÿ|¡›ÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿ±±ºÿV–…ÿ4Œqÿ:�tÿ@�wÿ¢À­ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿR¹{ÿ Kÿ Kÿ KÿŠÈœÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ1®hÿ Kÿ Kÿ Kÿ¬Ó°ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿpÁ�ÿ Kÿ Kÿ KÿW¹~ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ§Xÿ Kÿ Kÿ KÿÅÚ¿ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ«Ó°ÿ Kÿ Kÿ Kÿ¥UÿóèÚÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿââÐÿ Kÿ Kÿ Kÿ KÿããÐÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿìåÖÿ¢Nÿ Kÿ Kÿ KÿwÑÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿËÜÂÿÊÛÂÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ¡Ïªÿ Kÿ Kÿ Kÿ ©^ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáôÿëáÿÿëáÿÿëáÿÿëáÿ`¼„ÿ Kÿ Kÿ Kÿ KÿlÀŠÿããÐÿÿëáÿÿëáÿþëàÿÛáÌÿŽÊžÿ,­eÿ Kÿ<±nÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿG´uÿ Kÿ Kÿ Kÿa¼„ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáôÿëáÜÿëáÿÿëáÿÿëáÿÿëáÿÜáÌÿ £Rÿ Kÿ Kÿ Kÿ Kÿ Kÿ§Xÿ¥Wÿ £Qÿ Kÿ Kÿ Kÿ Kÿ KÿÎÝÄÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÓÞÇÿ Lÿ Kÿ Kÿ Kÿ­Ò±ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÚÿëàÀÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ§Ñ­ÿ¡Lÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ KÿYº€ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿýêàÿ>²pÿ Kÿ Kÿ Kÿ!©^ÿüêßÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëá¾ÿëá~ÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ­Ò±ÿ ¤Rÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ±Ô³ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÅ–ÿ Kÿ Kÿ Kÿ Kÿ�Ë ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿêà|ÿéÞ/ÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿéåÔÿtÂ�ÿ©\ÿ Kÿ Kÿ Kÿ Kÿ Lÿ$ª`ÿ¦Vÿ Kÿ Kÿ Kÿ ¤RÿÌÜÃÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿþëàÿƒÇ˜ÿ Kÿ Kÿ Kÿ Kÿ/®fÿùéÞÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿîâ,ÿêâÇÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿããÐÿÌÜÃÿÌÜÃÿÎÝÄÿñçÙÿÿëáÿªÒ¯ÿ Kÿ Kÿ Kÿ Kÿ £Rÿ­Ò±ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÜáÌÿHµvÿ Kÿ Kÿ Kÿ Kÿ¢NÿÐÝÆÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿìáÅÿêâ=ÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿmÀ‹ÿ Kÿ Kÿ Kÿ Kÿ Kÿ@³pÿ«Ó°ÿââÐÿïæØÿããÐÿ©Ò®ÿV¹~ÿ¡Mÿ Kÿ Kÿ Kÿ Kÿ¡Mÿ§Ñ­ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëß@ÿêá¡ÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿüêßÿS¸|ÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ¢Nÿ£Ð«ÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿìáŸÿßßÿëàÈÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿýêàÿqÁŽÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ%«aÿÉÛÁÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÌÿãã ÿéÞÿëáÉÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿ¸×·ÿ.­fÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ Kÿ¦Xÿ†ÇšÿôèÚÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëàÈÿéÞÿßßÿêá¡ÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿýêàÿªÒ¯ÿS¸|ÿ¨[ÿ Kÿ Kÿ Kÿ§XÿXºÿ¤Ð¬ÿõèÛÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿêá ÿßßÿíß8ÿëáÂÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿôèÚÿîæ×ÿ÷éÜÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÉÿëß@ÿéã.ÿëà}ÿëàÀÿëáÛÿëáõÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáÿÿëáõÿëáÚÿëâ¿ÿêà|ÿèã-ÿÀÿþøðàÀÀ€€€€€€ÀÀàðøþÿÀÿTreeLine-3.2.1/working/000077500000000000000000000000001506556630100147135ustar00rootroot00000000000000TreeLine-3.2.1/working/translations/000077500000000000000000000000001506556630100174345ustar00rootroot00000000000000TreeLine-3.2.1/working/translations/gettrans.py000077500000000000000000000241631506556630100216460ustar00rootroot00000000000000#!/usr/bin/env python3 #****************************************************************************** # gettrans.py, updates Qt-style translation files from PyQt source # uses gettext-style markings and filenames as contexts # # Copyright (C) 2020, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, either Version 2 or any later # version. This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY. See the included LICENSE file for details. #****************************************************************************** import argparse import pathlib import ast import collections import copy import xml.etree.ElementTree as ET from xml.sax.saxutils import escape class TransItem: """Class to hold data for and output a single translation string. """ def __init__(self, contextName, lineNum, srcText, comment=''): """Initialize the tramslation string item. Arguments: contextName -- a string containing the filename-based context lineNum -- the line of the first occurrence in the source code srcText -- the untranslated source text string comment -- optional comment from source as a guide to translation """ self.contextName = contextName self.lineNum = lineNum self.srcText = srcText self.comment = comment self.transType = 'unfinished' self.transText = '' def xmlLines(self): """Return a list of XML output lines for this item. """ lines = [' ', f' ', f' {escape(self.srcText)}'] if self.comment: lines.append(f' {self.comment}') transType = f' type="{self.transType}"' if self.transType else '' lines.extend([f' ' f'{escape(self.transText)}', ' ']) return lines def readSource(path, sourceDict): """Read strings to be translated from the a single source file path. Updates the give source dict with any results from this context. Arguments: path -- the source file path to read sourceDict -- the dictionary to add a context dict to with results """ with path.open(encoding='utf-8') as f: src = f.read() tree = ast.parse(src) contextDict = collections.OrderedDict() for node in ast.walk(tree): if (isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and (node.func.id == '_' or node.func.id == 'N_')): try: text = node.args[0].value text.replace # throw exception if not a string comment = node.args[1].value if len(node.args) > 1 else '' except AttributeError: continue # skip if no string is present item = TransItem(path.stem, node.lineno, text, comment) contextDict.setdefault((text, comment), item) if contextDict: # only add the context dictionary if there are results sourceDict[path.stem] = contextDict if verbose: print('Read', len(contextDict), 'items from', path.name) def readXml(root, sourceDict, keepObsolete=True): """Read the XML for a language file starting from an elemant tree root. Returns tuple of an outputDict with results by context and a globalDict with all translations to search for matches. Arguments: root -- the ET root to read sourceDict -- the dict with source strings for comparison keepObsolete -- save obsolete strings (no longer in source) if True """ outputDict = collections.OrderedDict() globalDict = {} for contextNode in root.findall('context'): contextName = contextNode.find('name').text currentDict = collections.OrderedDict() numObsolete = 0 for msgNode in contextNode.findall('message'): try: lineNum = int(msgNode.find('location').attrib['line']) except AttributeError: # .ts files converted from .qm files have no locations and # line numbers lineNum = 0 srcText = msgNode.find('source').text commentNode = msgNode.find('comment') comment = commentNode.text if commentNode is not None else '' item = TransItem(contextName, lineNum, srcText, comment) transNode = msgNode.find('translation') item.transType = transNode.attrib.get('type', '') item.transText = transNode.text if transNode.text else '' try: sourceItem = sourceDict[contextName][(srcText, comment)] except KeyError: # string wasn't found in source dict if item.transType != 'obsolete': item.transType = 'obsolete' numObsolete += 1 else: item.lineNum = sourceItem.lineNum if item.transType == 'obsolete': item.transType = 'unfinished' if keepObsolete or item.transType != 'obsolete': currentDict[(srcText, comment)] = item if item.transText: globalDict[(srcText, comment)] = item outputDict[contextName] = currentDict if verbose and numObsolete: print(f' {numObsolete} newly obsolete strings in ' f'{contextName}.py') return (outputDict, globalDict) def addMissingItems(sourceDict, outputDict): """Add items from source dict that are missing from output dict. Arguments: sourceDict -- the source translations to add from outputDict -- the result dict to modify """ for contextName, sourceItems in sourceDict.items(): numNew = 0 currentDict = outputDict.get(contextName, {}) if not currentDict: outputDict[contextName] = currentDict for sourceItem in sourceItems.values(): if (verbose and (sourceItem.srcText, sourceItem.comment) not in currentDict): numNew += 1 currentDict.setdefault((sourceItem.srcText, sourceItem.comment), copy.copy(sourceItem)) if verbose and numNew: print(f' {numNew} new strings added from {contextName}.py') def updateFromGlobal(outputDict, globalDict): """Search strings from all contexts and add translations if they match. Arguments: outputDict -- the result dict to modify globalDict -- the overall dict to search """ for contextName, currentDict in outputDict.items(): numUpdates = 0 for item in currentDict.values(): if not item.transText: match = globalDict.get((item.srcText, item.comment)) if match: item.transText = match.transText numUpdates += 1 if verbose and numUpdates: print(f' {numUpdates} translations in {contextName} copied ' 'from other strings') def outputXml(outputDict, path, lang): """Return a list of output lines for a language file. Arguments: outputDict -- the result strings to output path -- the translation file path to write the file lang -- the language code for the file header """ outputLines = ['', f''] for contextName, currentDict in outputDict.items(): outputLines.extend(['', f' {contextName}']) for item in currentDict.values(): outputLines.extend(item.xmlLines()) outputLines.append('') outputLines.append('') with open(path, 'w', encoding='utf-8') as f: f.write('\n'.join(outputLines)) verbose = False def main(): """Main program entry function. """ parser = argparse.ArgumentParser() parser.add_argument('sourceDir', type=pathlib.Path, help='directory of input source files read with *.py') parser.add_argument('translateDir', type=pathlib.Path, help='directory of *.ts translation files to update') parser.add_argument('--no-obsolete', action='store_true', help='drop all obsolete strings') parser.add_argument('-R', '--recursive', action='store_true', help='recursively scan the directories') parser.add_argument('-v', '--verbose', action='store_true', help='increase output messages') args = parser.parse_args() global verbose verbose = args.verbose sourceDict = collections.OrderedDict() pyGlob = '**/*.py' if args.recursive else '*.py' for sourcePath in sorted(args.sourceDir.glob(pyGlob)): readSource(sourcePath, sourceDict) if verbose: print('-----------------------------------------') tsGlob = '**/*.ts' if args.recursive else '*.ts' for transPath in sorted(args.translateDir.glob(tsGlob)): try: root = ET.parse(transPath).getroot() except ET.ParseError: print('Warning: nothing read from', transPath) root = ET.ElementTree(ET.Element('TS')).getroot() lang = root.attrib.get('language') if not lang: # get from filename if not in header pathParts = transPath.stem.split('_') if len(pathParts) > 1: lang = pathParts[-1] if not lang: lang = 'xx' if verbose: print(f'For language code "{lang}":') outputDict, globalDict = readXml(root, sourceDict, not args.no_obsolete) addMissingItems(sourceDict, outputDict) updateFromGlobal(outputDict, globalDict) outputXml(outputDict, transPath, lang) if __name__ == '__main__': """Main program entry point. """ main() TreeLine-3.2.1/working/translations/treeline_de.ts000066400000000000000000005713401506556630100222750ustar00rootroot00000000000000 conditional starts with beginnt mit ends with endet mit contains enthält True Wahr False Falsch and und or oder [All Types] [Alle Typen] Node Type Knotentyp &Add New Rule &Regel hinzufügen &Remove Rule &Regel löschen &OK &OK &Cancel &Abbrechen Find &Previous Suche &Vorherigen Find &Next Suche &Nächsten &Filter &Filter &End Filter Filter &beenden &Close &Schließen No conditional matches were found Keine Übereinstimmungen gefunden Rule {0} Regel {0} Saved Rules Gespeicherte Regeln Name: Name: &Load &Laden &Save S&peichern &Delete &Löschen configdialog Configure Data Types Datentypen konfigurieren T&ype List &Typliste Field &List &Feldliste &Field Config Feld &konfigurieren &Show Advanced Erweitert &anzeigen &OK &OK &Apply &Anwenden &Reset &Zurücksetzen &Cancel &Abbrechen Add or Remove Data Types Datentypen hinzufügen oder löschen &New Type... &Neuer Typ... Co&py Type... Typ &kopieren... &Delete Type Typ &löschen Add Type Typ hinzufügen Enter new type name: Gib den Namen des neuen Typs ein: Rename Type Typ umbenennen Cannot delete data type being used by nodes Kann keinen Datentyp löschen, der noch in Benutzung ist &Data Type &Datentyp Icon Icon Change &Icon &Icon ändern Derived from &Generic Type Abgeleitet von &Basistyp Automatic Types Automatische Typen Modify Co&nditional Types &Bedingte Typen ändern Create Co&nditional Types &Bedingte Typen anlegen Set Types Conditionally Typ durch Bedingung setzen Name Name Type Typ Move &Up Nach &oben verschieben Move Do&wn Nach &unten verschieben &New Field... &Neues Feld... Add Field Feld hinzufügen Enter new field name: Name des neuen Feldes eingeben: Rename Field Feld umbenennen F&ield &Feld Format &Help Hilfe zum &Format Extra Text Zusatztext &Prefix &Präfix Suffi&x &Suffix Editor Height Editorhöhe Num&ber of text lines &Anzahl der Textzeilen File Info Reference Dateiinfo-Verweis Parent Reference Vater-Verweis Child Reference Kind-Verweis Child Count Anzahl Kinder F&ield List &Feldliste Other Field References Verweise zu anderen Feldern Copy Type Typ kopieren Set Data Type Icon Datentyp Icon zuweisen Clear &Select Auswahl &zurücksetzen Typ&e Config Typ &Konfiguration O&utput &Ausgabe &Hide Advanced Erweitert &ausblenden Error - circular reference in math field equations Fehler - Zirkulärer Verweis im berechnetem Feld Rena&me Type... Typ &umbenennen... &Derive from original Von &Original ableiten Rename from {} to: Umbenennen von {} nach: [None] no type set [Leer] Default Child &Type Standard Kind &Typ Output Options Ausgabeoptionen Add &blank lines between nodes &Leere Zeilen zwischen Knotenhinzufügen Allow &HTML rich text in format &HTML Text im Format erlauben Add text bullet&s &Aufzählungspunkte hinzufügen Use a table for field &data Eine Tabelle für &Feldwerte verwenden Combination && Child List Output &Separator Ausgabe &Trenner für Kombination && Kindliste None Leer Modify &Field List &Feldliste bearbeiten Sort Key Sortierfeld Move U&p Nach &oben verschieben Rena&me Field... Feld &umbenennen... Dele&te Field Feld &löschen Sort &Keys... &Sortierfelder... fwd >> rev << &Field Type &Feldtyp Outpu&t Format &Ausgabeformat Default &Value for New Nodes &Standardwert für neue Knoten Math Equation Mathematischer Ausdruck Define Equation Ausdruck definieren &Title Format &Überschrift Format Out&put Format &Ausgabeformat Reference Le&vel Verweis&stufe Refere&nce Type Verweis&typ The name cannot be empty Der Name kann nicht leer sein The name must start with a letter Der Name muss mit einem Buchstaben beginnen The name cannot start with "xml" Der Name kann nicht mit "xml" beginnen The name cannot contain spaces Der Name darf keine Leerzeichen enthalten The following characters are not allowed: {} Die folgenden Zeichen sind nicht erlaubt: {} The name was already used Der Name ist bereits in Verwendung forward vorwärts reverse rückwärts Sort Key Fields Sortierfelder Available &Fields Verfügbare &Felder &Sort Criteria &Sortierbedingung Field Feld Direction Richtung &Move Down Nach &unten Flip &Direction Richtung &umkehren Self Reference Verweis auf sich selbst Root Reference Verweis auf Wurzel Date Result Datum Time Result Uhrzeit add hinzufügen subtract abziehen multiply multiplizieren divide dividieren floor divide dividieren mit runden modulus modulo power exponieren sum of items summieren maximum Maximum minimum Minimum average Durchschnitt absolute value Absolutwert square root Quadratwurzel natural logarithm Natürlicher Logarithmus base-10 logarithm Logarithmus Basis 10 factorial Fakultät round to num digits Runden auf n Stellen lower integer Niedrigere Ganzzahl higher integer Höhere Ganzzahl truncated integer Abgeschnittene Ganzzahl floating point Fliesskommazahl sine of radians Sinus Bogenmaß cosine of radians Cosinus Bogenmaß tangent of radians Tangens Bogenmaß arc sine Arcus Sinus arc cosine Arcus Cosinus arc tangent Arcus Tangens radians to degrees Bogenmaß nach Grad degrees to radians Grad nach Bogenmaß pi constant PI natural log constant Eulersche Zahl Define Math Field Equation Mathematischen Ausdruck definieren Field References Feldverweis Reference &Level Verweis &Stufe Reference &Type Verweis &Typ Available &Field List Verfügbare &Feldliste &Result Type &Ergebnistyp Description Beschreibung &Equation &Gleichung Equation error: {} Fehler in Gleichung: {} Boolean Result Bool'sches Ergebnis Text Result Text Ergebnis Arithmetic Operators Arithmetische Operatoren Comparison Operators Vergleichsoperatoren Text Operators Text Operatoren equal to Ist gleich less than Ist kleiner greater than Ist größer less than or equal to Ist kleiner oder gleich greater than or equal to Ist größer oder gleich not equal to Ist nicht gleich true value, condition, false value Wahrer Wert, Bedingung, Falscher Wert true if 1st text arg starts with 2nd arg Wahr, wenn 1. Argument mit 2. Argument beginnt true if 1st text arg ends with 2nd arg Wahr, wenn 1. Argument mit 2. Argument endet true if 1st text arg contains 2nd arg Wahr, wenn 1.Argument 2.Argument enthält concatenate text Text aneinanderhängen join text using 1st arg as separator Text verbinden mit 1. Argument als Trenner convert text to upper case Text in Großbuchstaben konvertieren convert text to lower case Text in Kleinbuchsrtaben konvertieren in 1st arg, replace 2nd arg with 3rd arg Ersetze in 1. Argument das 2. Argument durch das 3. Argument Operations Operationen O&perator Type Typ des O&perators Oper&ator List Liste der Oper&atoren logical and Logisches Und logical or Logisches Oder Output HTML HTML Ausgabe Evaluate &HTML tags Bewerte HTML Tags Child Type Limits Kind Typ Grenzen [All Types Available] [Alle Typen verfügbar] &Select All &Alles auswählen Select &None Nichts auswählen Number Result Anzahl Ergebnis Count Zählen Number of Children Anzahl der Kinder dataeditors Today's &Date Heutiges &Datum &Open Link &Verweis öffnen Open &Folder &Verzeichnis öffnen External Link Externer Verweis Scheme Schema &Browse for File Datei &suchen File Path Type Verzeichnis Angabe Absolute Absolut Relative Relativ Address Adresse Display Name Anzeigename &OK &OK &Cancel &Abbrechen TreeLine - External Link File Verweis zu externer TreeLine Datei &Go to Target &Gehe zu Ziel Internal Link Interner Verweis &Open Picture &Öffne Bild Picture Link Verweis auf Bild TreeLine - Picture File TreeLine Bilddatei Set to &Now Auf &heute setzen Clear &Link Verweis löschen (Click link target in tree) Klicke Verweis Ziel im Baum link Verweis dataeditview exports Bookmarks Lesezeichen TreeLine - Export HTML TreeLine - Exportiere HTML TreeLine - Export Text Titles TreeLine - Exportiere Textüberschriften TreeLine - Export Plain Text TreeLine - Exportiere Text TreeLine - Export Text Tables TreeLine - Exportiere Text Tabelle TreeLine - Export Generic XML TreeLine - Exportiere Generisches XML TreeLine - Export TreeLine Subtree TreeLine - Exportiere TreeLine Teilbaum TreeLine - Export ODF Text TreeLine - Exportiere ODF Text TreeLine - Export HTML Bookmarks TreeLine - Exportiere HTML Lesezeichen TreeLine - Export XBEL Bookmarks TreeLine - Exportiere XBEL Lesezeichen &HTML &HTML &Text &Text &ODF Outline &ODF Struktur Book&marks &Lesezeichen &Single HTML page &Einzelne HTML Seite Single &HTML page with navigation pane Einzelne &HTML Seite mit Navigationsleiste Multiple HTML &pages with navigation pane Mehrere HTML &Seiten mit Navigationsleiste Multiple HTML &data tables Mehrere HTML &Datentabellen &Tabbed title text &Titelzeile mit Tabulator &Unformatted output of all text &Unformatierte Ausgabe des gesamten Textes &HTML format bookmarks &HTML formatierte Lesezeichen &XBEL format bookmarks &XBEL formatierte Lesezeichen File Export Datei Export Choose export format type Ausgabeformat wählen Choose export format subtype Ausgabe Unterformat wählen Choose export options Ausgabeoptionen wählen What to Export Was wird exportiert &Entire tree &Gesamter Baum Selected &branches &Ausgewählte Teilbäume Selected &nodes Ausgewählte &Knoten Other Options Andere Optionen &Only open node children &Nur geöffnete Kindknoten Include &print header && footer &Kopf- und Fußzeile einschließen &Columns &Spalten Navigation pane &levels &Stufen der Navigationsleiste Error - export template files not found. Check your TreeLine installation. Fehler - Export Vorlage nicht gefunden. Überprüfe deine TreeLine Installation. Error - cannot link to unsaved TreeLine file. Save the file and retry. Fehler - Kann nicht auf nicht gespeicherte TreeLine Datei verweisen. Speichere die Datei und versuche es erneut. Warning - no relative path from "{0}" to "{1}". Continue with absolute path? Warnung - kein relativer Pfad von "{0}" nach "{1}". Weitermachen mit absolutem Pfad? Parent Eltern Tree&Line Tree&Line &XML (generic) &XML (generisch) Live tree view, linked to TreeLine file (for web server) Live Baum Ansicht, verlinkt mit der TreeLine Datei (für Web Server) Live tree view, single file (embedded data) Live Baum Ansicht, eine Datei (Daten eingeschlossen) &Comma delimited (CSV) table of descendants (level numbers) &Komma-getrennte Tabelle (CSV) der Nachkommen (Nummern Grad) Comma &delimited (CSV) table of children (single level) Komma-&getrennte Tabelle (CSV) der Kinder (einzelner Grad) Tab &delimited table of children (&single level) Tab-&getrennte Tabelle der Kinder (&einzelner Grad) &Old TreeLine (2.0.x) Altes TreeLine Format (2.0.x) &TreeLine Subtree TreeLine Teilbaum &Include root nodes einschließlich Wurzel Knoten Must select nodes prior to export Sie müssen Knoten vor dem Export auswählen. fieldformat yes/no ja/nein true/false wahr/falsch T/F W/F Y/N J/N Text Text HtmlText HtmlText OneLineText Einzeiler SpacedText Text, Leerzeichen getrennt Number Nummer Math Mathematisch Numbering Nummer Boolean Boolean Date Datum Time Zeit Choice Auswahlfeld AutoChoice Auto Auswahlfeld Combination Kombinationsfeld AutoCombination Auto-Kombinationsfeld ExternalLink Externer Verweis InternalLink Interner Verweis Picture Bild RegularExpression Regulärer Ausdruck Now Heute Optional Digit # Optionale Ziffer # Required Digit 0 Erforderliche Ziffer 0 Digit or Space (external) <space> Ziffer oder Leertaste (Extern) <space> Decimal Point . Dezimalpunkt . Decimal Comma , Dezimalkomma , Space Separator (internal) <space> Leertaste Trenner (Intern) <space> Optional Sign - Optionales Vorzeichen - Required Sign + Erforderliches Vorzeichen + Exponent (capital) E Exponent (Groß) E Exponent (small) e Exponent (Klein) e Number 1 Ziffer 1 Capital Letter A Großbuchstabe A Small Letter a Kleinbuchstabe a Capital Roman Numeral I Große römische Ziffer I Small Roman Numeral i Kleine römische Ziffer i Level Separator / Stufentrenner / Section Separator . Sektionstrenner . "/" Character // "/" Zeichen // "." Character .. "." Zeichen .. Outline Example I../A../1../a)/i) Gliederungsbeispiel I../A../1../a)/i) Section Example 1.1.1.1 Überschrift Beispiel 1.1.1.1 Separator / Trenner / Example 1/2/3/4 Beispiel 1/2/3/4 Any Character . Beliebiges Zeichen . End of Text $ Texteende $ 0 Or More Repetitions * 0 oder mehr Wiederholungen * 1 Or More Repetitions + 1 oder mehr Wiederholungen + 0 Or 1 Repetitions ? 0 oder 1 Wiederholung ? Set of Numbers [0-9] Menge von Ziffern [0-9] Lower Case Letters [a-z] Kleinbuchstabe [a-z] Upper Case Letters [A-Z] Großbuchstabe [A-Z] Not a Number [^0-9] Keine Ziffer [^0-9] Or | Oder | Escape a Special Character \ Escape für Sonderzeichen \ DateTime Datum/Zeit Day (1 or 2 digits) %-d Tag (1 oder 2 Ziffern) Day (2 digits) %d Tag (2 Ziffern) Weekday Abbreviation %a Wochentag Abkürzung Weekday Name %A Wochentag Name Month (1 or 2 digits) %-m Monat (1 oder 2 Ziffern) Month (2 digits) %m Monat (2 Ziffern) Month Abbreviation %b Monat Abkürzung Month Name %B Monat Name Year (2 digits) %y Jahr (2 Ziffern) Year (4 digits) %Y Jahr (4 Ziffern) Week Number (0 to 53) %-U Wochennummer (0 bis 53) Day of year (1 to 366) %-j Tag des Jahres (1 bis 366) Hour (0-23, 1 or 2 digits) %-H Stunde (0-23, 1 oder 2 Ziffern) Hour (00-23, 2 digits) %H Stunde (00-23, 2 Ziffern) Hour (1-12, 1 or 2 digits) %-I Stunde (1-12, 1 oder 2 Ziffern) Hour (01-12, 2 digits) %I Stunde (01-12, 2 Ziffern) Minute (1 or 2 digits) %-M Minute (1 oder 2 Ziffern) Minute (2 digits) %M Minute (2 Ziffern) Second (1 or 2 digits) %-S Sekunde (1 oder 2 Ziffern) Second (2 digits) %S Sekunde (2 Ziffern) Microseconds (6 digits) %f Microsekunde (6 Ziffern) AM/PM %p AM/PM Comma Separator \, Komma Trenner \, Dot Separator \. Punkt Trenner \. DescendantCount Anzahl der Nachkommen genboolean true wahr false falsch yes ja no nein globalref TreeLine Files TreeLine Dateien TreeLine Files - Compressed TreeLine Dateien (komprimiert) TreeLine Files - Encrypted TreeLine Dateien (verschlüsselt) All Files Alle Dateien HTML Files HTML Dateien Text Files Text Dateien XML Files XML Dateien ODF Text Files ODF Dateien Treepad Files Treepad Dateien PDF Files PDF Dateien CSV (Comma Delimited) Files CSV Datei (Komma-getrennt) All TreeLine Files Alle Treeline Dateien Old TreeLine Files Alte Treeline Dateien helpview &Back &Zurück &Forward &Vorwärts &Home &Eigenes Verzeichnis Find: Suchen: Find &Previous &Rückwärts Suchen Find &Next &Vorwärts Suchen Text string not found Text nicht gefunden Tools Werkzeuge imports &Tab indented text, one node per line &Mit Tabulator eingerückter Text, Knoten je Zeile Tab delimited text table with header &row Tabulator getrennter Text mit Kopfzeile Plain text &paragraphs (blank line delimited) Text &Blöcke (Beendet mit Leerzeile) Treepad &file (text nodes only) Treepad &Datei (nur Text) &Generic XML (non-TreeLine file) Generisches &XML (Keine TreeLine Datei) Open &Document (ODF) outline Open &Document (ODF) Gliederung &HTML bookmarks (Mozilla Format) &HTML Lesezeichen (Mozilla Format) &XML bookmarks (XBEL format) &XML Lesezeichendatei (XBEL-Format) FOLDER VERZEICHNIS BOOKMARK LESEZEICHEN SEPARATOR TRENNER Link Verweis Text Text Import File Import Datei Choose Import Method Import Methode auswählen Invalid File Ungültige Datei "{0}" is not a valid TreeLine file. Use an import filter? "{0}" ist keine TreeLine Datei. Importfilter verwenden? TreeLine - Import File TreeLine - Import Datei Error - could not read file {0} Fehler - Kann Datei {0} nicht lesen Error - improper format in {0} Fehler - ungültiges Format in {0} TABLE TABELLE Bookmarks Lesezeichen Too many entries on Line {0} Zu viele Einträge in der Zeile {0} Plain text, one &node per line (CR delimited) Nur Text, ein &Knoten pro Zeile (CR getrennt) Bad CSV format on Line {0} Fehler im CSV Format bei Zeile {0} Co&mma delimited (CSV) text table with level column && header row Ko&mma-getrennter (CSV) Text Tabelle mit Stufe Spalte && Kopfzeile Reihe Comma delimited (CSV) text table &with header row Ko&mma-getrennter (CSV) Text Tabelle mit Kopfzeile Other Andere Old Tree&Line File (1.x or 2.x) Alte Tree&Line Datei (1.x oder 2.x) Invalid level number on line {0} Falsche Ebene Nummer on line {0} Invalid level structure Fehlerhafte Ebenen Struktur No headings found matheval Illegal "{}" characters Ungültige Zeichen "{}" Child references must be combined in a function Verweise auf Kinder müssen in einer Funktion kombiniert werden Illegal syntax in equation Ungültige Syntax in Ausdruck Illegal function present: {0} Ungültige Funktion: {0} Illegal object type or operator: {0} Ungültiger Objekttyp oder Operator: {0} Invalid field modifiers miscdialogs &OK &OK &Cancel &Abbrechen Fields Felder File Properties Datei Eigenschaften File Storage Datei Speicherung &Use file compression Datei&komprimierung verwenden Use file &encryption Datei&verschlüsselung verwenden Spell Check Rechtschreibprüfung Language code or dictionary (optional) Sprachcode oder Wörterbuch (optional) Math Fields Mathematisches Feld &Treat blank fields as zeros &Leere Felder als Null behandeln Encrypted File Password Passwort der verschlüsselten Datei Type Password for "{0}": Passwort für {0} eingeben: Type Password: Passwort eingeben: Re-Type Password: Passwort wiederholen: Remember password during this session Passwort für diese Sitzung merken Zero-length passwords are not permitted Leere Passwörter sind nicht erlaubt Re-typed password did not match Passworte stimmen nicht überein Default - Single Line Text Standard - Einzeiliger Text &Search Text &Suchtext What to Search Nach was wird gesucht Full &data Gesamte &Daten &Titles only Nur &Titel How to Search Wie wird gesucht &Key words &Schlüsselworte Key full &words &Ganze Worte F&ull phrase Ganzer &Satz &Regular expression &Regulärer Ausdruck Find Suchen Find &Previous Suche &Vorherige Find &Next Suche &Nächster Filter Filter &Filter &Filter &End Filter Filter &Ende &Close &Schließen Error - invalid regular expression Fehler - Ungültiger regulärer Ausdruck Search string "{0}" not found Suchtext "{0}" nicht gefunden Find and Replace Suchen und Ersetzen Replacement &Text Ersetzungs&text Any &match Jedes &Vorkommen Full &words Ganze &Worte Re&gular expression Regulärer &Ausdruck &Node Type &Knotentyp N&ode Fields &Felder &Find Next Suche &Nächster &Replace &Ersetzen Replace &All &Alle Ersetzen [All Types] [Alle Typen] [All Fields] [Alle Felder] Search text "{0}" not found Suchtext "{0}" nicht gefunden Error - replacement failed Fehler - Ersetzung nicht möglich Replaced {0} matches {0} Stellen ersetzt Sort Nodes Konten sortieren What to Sort Was wird sortiert &Entire tree &Gesamter Baum Selected &branches Ausgewählte &Teilbäume Selection's childre&n &Kinder der ausgewählten Teilbäume Selection's &siblings &Geschwister der ausgewählten Telibäume Sort Method Sortiermethode &Predefined Key Fields &Vordefinierte Schlüsselfelder Node &Titles Knoten&titel Sort Direction Sortierrichtung &Forward &Vorwärts &Reverse &Rückwärts &Apply &Anwenden Update Node Numbering Nummerierung erneuern What to Update Was soll erneuert werden &Selection's children &Kinder der Auswahl Root Node Wurzelelement Include top-level nodes Knoten der ersten Ebene einschliessen Handling Nodes without Numbering Fields Behandlung von Knoten ohne Nummerierungsfelder &Ignore and skip &Ignorieren &Restart numbers for next siblings &Nummerierung für nächste Geschwister neu starten Reserve &numbers Nummerierung &umkehren TreeLine Numbering TreeLine Nummerierung No numbering fields were found in data types Keine Nummerierungsfelder gefunden File Menu Datei Menü File Datei Edit Menu Bearbeiten Menü Edit Bearbeiten Node Menu Knoten Menü Node Knoten Data Menu Daten Menü Data Daten Tools Menu Werkzeug Menü Tools Werkzeug View Menu Ansicht Menü View Ansicht Window Menu Fenster Menü Window Fenster Help Menu Hilfe Menü Help Hilfe Keyboard Shortcuts Tastaturkürzel &Restore Defaults &Standard wiederherstellen Key {0} is already used Taste {0} bereits belegt Clear &Key Lösche &Taste --Separator-- --Trenner-- Customize Toolbars Symbolleisten konfigurieren Toolbar &Size Symbolleisten&größe Small Icons Kleine Icons Large Icons Große Icons Toolbar Quantity Anzahl Symbolleisten &Toolbars &Symbolleisten A&vailable Commands &Verfügbare Funktionen Tool&bar Commands &Symbolleisten Funktionen Move &Up Nach &oben verschieben Move &Down Nach &unten verschieben Tree View Font Schriftart für Baumanzeige Output View Font Schriftart für Ausgabe Editor View Font Schriftart für Editor No menu Kein Menü TreeLine - Serious Error TreeLine - Schwerer Fehler A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. Ein schwerer Fehler ist aufgetreten. TreeLine kann sich in einem instabilen Zustand befinden. Empfehlung, die Datei unter einem anderen Namen zu speichern und TreeLine neu zu starten. Das Debug Info unterhalb kann kopiert werden und per Mail an doug101@bellz.org geschickt werden zusammen mit Erläuterungen, unter welchen Umständen, der Fehler auftrat. Format Menu Format Menü Format Format Customize Fonts Schriftarten Anpassen &Use system default font &System Schriftart verwenden App Default Font Standardschriftart &Use app default font &Standard Schriftart verwenden Externally Modified File &Overwrite File &Cancel Save File was externally modified at {} nodeformat Name Name optiondefaults Monday Montag Tuesday Dienstag Wednesday Mittwoch Thursday Donnerstag Friday Freitag Saturday Samstag Sunday Sonntag Startup Condition Programmstart Automatically open last file used Die zuletzt benutzte Datei automatisch öffnen Show descendants in output view Unterknoten in der Ansicht anzeigen Restore tree view states of recent files Baumansicht von kürzlich geöffneten Dateien wierherstellen Restore previous window geometry Fenstereinteilung wiederherstellen Features Available Verfügbare Funktionen Open files in new windows Öffne Dateien in neuem Fenster Click node to rename Klick auf Knoten zum Umbenennen Rename new nodes when created Neue Knoten nach dem Anlegen umbenennen Tree drag && drop available Verschieben von Bäumen mit der Maus erlauben Show icons in the tree view Icons in der Baumansicht anzeigen Show math fields in the Data Edit view Mathematische Felder im Bearbeiten Fenster anzeigen Show numbering fields in the Data Edit view Nummerierungsfelder im Bearbeiten Fenster anzeigen Undo Memory Speicher für Wiederherstellungen Number of undo levels Anzahl der möglichen Wiederherstellungen Auto Save Automatisches Speichern Minutes between saves (set to 0 to disable) Minuten zwischen Speichervorgängen (0 für Abschalten) Recent Files Zuletzt geöffnete Dateien Number of recent files in the file menu Anzahl zuletzt geöffneter Dateien Data Editor Formats Formate im Bearbeitungsfenster Times Zeitdarstellung Dates Datumsdarstellung First day of week Erster Wochentag Appearance Aussehen Child indent offset (in font height units) Einrückung für Kinder (In Schriftart Einheiten) Show breadcrumb ancestor view Zeige Breadcrumb Vorfahren Ansicht Show child pane in right hand views Zeige Kind Ausschnitt in der rechten Ansicht Remove inaccessible recent file entries Lösche alle nicht vorhandenen aktuellen Datei-Einträge Activate data editors on mouse hover Aktiviere den Daten Editor bei schwebender Maus Minimize application to system tray Minimiere Programm in die Systemleiste Indent (pretty print) TreeLine JSON files Druckoptimierte TreeLine JSON Dateien mit Einrückung Limit data editor height to window size Begrenzung der Höhe des Dateneditors auf die Fenstergröße options Choose configuration file location Ablage Konfigurationsfile User's home directory (recommended) Benutzerverzeichnis (empfohlen) Program directory (for portable use) Programmverzeichnis (für portablen Einsatz) &OK &OK &Cancel &Abbrechen printdata Error initializing printer Fehler beim Initialisieren des Druckers TreeLine - Export PDF TreeLine - PDF Exportieren Warning: Page size and margin settings unsupported on current printer. Save page adjustments? Warnung: Seitengröße und Randeinstellung werden vom derzeitigen Drucker nicht unterstützt. Sollen die Einstellungen berichtigt werden? Warning: Page size setting unsupported on current printer. Save adjustment? Warnung: Seitengröße werden vom derzeitigen Drucker nicht unterstützt. Sollen die Einstellungen berichtigt werden? Warning: Margin settings unsupported on current printer. Save adjustments? Warnung: Randeinstellung werden vom derzeitigen Drucker nicht unterstützt. Sollen die Einstellungen berichtigt werden? printdialogs Print Preview Druckvorschau &Print... &Drucken... &General Options Allgemeine &Einstellungen &Font Selection Schrift&auswahl &Header/Footer &Kopf-/Fußzeile Print Pre&view... Druck&vorschau... &OK &OK &Cancel &Abbrechen What to print Was wird gedruckt &Entire tree Gesamter Baum Selected &branches Ausgewählte Teilbäume Selected &nodes Ausgewählte Knoten Features Eigenschaften &Include root node Wurzelelement hinzunehmen &Keep first child with parent Das erste Unterelement mit dem Elternelement zusammen anzeigen Letter (8.5 x 11 in.) Letter (8.5 × 11 Inch) Legal (8.5 x 14 in.) Legal (8.5 × 14 Inch) Tabloid (11 x 17 in.) Tabloid (11 × 17 Inch) A3 (279 x 420 mm) A3 (279 × 420 mm) A4 (210 x 297 mm) A4 (210 × 297 mm) A5 (148 x 210 mm) A5 (148 × 210 mm) Paper &Size Papiergröße Orientation Orientierung &Units &Einheiten Columns Spalten &Number of columns Spaltenanzahl Default Font standard Schriftart Select Font Schriftart auswählen &Font &Schriftart Font st&yle Schrifts&til Sample Beispiel &Header Left Kopfzeile &Links Header C&enter Kopfzeile Mitt&e Footer &Left &Fußzeile Links Footer Ce&nter Fußzeile M&itte Fiel&ds Felder Header and Footer Kopf- und Fußzeile Extra Text Extratext &Prefix Präfi&x Format &Help &Hilfe zu den Formaten Fit Width Breite anpassen Fit Page Seite anpassen Zoom In Vergrößern Zoom Out Verkleinern Previous Page Vorherige Seite Next Page Nächste Seite Single Page Einzelne Seite Facing Pages Gegenüberliegende Seiten Print Setup Druckeinstellungen Print Drucken Printing Setup Druckeinstellungen Page &Setup Seiteneinstellungen Included Nodes Berücksichtigte Knoten Onl&y open node children Nur Kinder von geöffneten Knoten &Draw lines to children Linien zu den Kindern zeichnen Indent Einrücken Indent Offse&t (line height units) Abstand beim Einrücken (Einheit Zeilenhöhe) Custom Size Benutzerdefinierte Größe Inches (in) Inch (in) Millimeters (mm) Millimeter (mm) Centimeters (cm) Zentimeter (cm) &Width: &Breite: Height: &Höhe: Portra&it &Hochformat Lan&dscape &Querformat Margins Ränder &Left: &Links: &Top: &Oben: &Right: &Rechts: &Bottom: &Unten: He&ader: &Kopfzeile: Foot&er: &Fußzeile: Space between colu&mns Abstand zwischen &Spalten &Use TreeLine output view font &TreeLine Ausgabe Schriftart verwenden Si&ze &Größe AaBbCcDdEeFfGg...TtUuVvWvXxYyZz AaBbCcDcEeFfGg...TtUuVvWwXxYyZz Header &Right Kopfzeile &Rechts Footer Righ&t Fusszeile &Rechts Field For&mat Feldf&ormat Field Format for "{0}" Feldformat für "{0}" Output &Format Ausgabeformat &Suffix &Suffix Error: Page size or margins are invalid Fehler: Seitengröße oder Seitenränder sind ungültig TreeLine PDF Printer TreeLine PDF Drucker Select &Printer Wähle &Drucker recentfiles spellcheck Could not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? Kann weder aspell.exe, ispell.exe oder hunspell.exe finden. Speicherort suchen? Spell Check Error Fehler in der Rechtschreibprüfung Locate aspell.exe, ipsell.exe or hunspell.exe Suche aspell.exe, ispell.exe oder hunspell.exe Program (*.exe) Programm (*.exe) TreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed Fehler bei der Rechtschreibprüfung. Stellen Sie sicher, dass aspell, ispell oder hunspell installiert ist TreeLine Spell Check TreeLine Rechtschreibprüfung Finished spell checking Rechtschreibprüfung beendet Spell Check Rechtschreibprüfung Not in Dictionary Nicht im Wörterbuch Word: Wort: Context: Kontext: Suggestions Vorschläge Ignor&e &Ignorieren &Ignore All &Alles Ignorieren &Add &Hinzufügen Add &Lowercase Hinzufügen in &Kleinbuchstaben &Replace &Ersetzen Re&place All Alles E&rsetzen &Cancel &Abbrechen Finished checking the branch Continue from the top? Rechtschreibprüfung für den Zweig beendet. Wieder von oben anfangen? titlelistview Select in Tree Auswahl im Baum treeformats DEFAULT STANDARD FILE DATEI TYPE TYP FIELD FELD FieldType FELDTYP TitleFormat Titelformat OutputFormat Ausgabeformat SpaceBetween Zwischenraum FormatHtml HTML-Format Bullets Kugeln Table Tabelle ChildType KinderTyp Icon Icon">Icon GenericType GenerischerTyp ConditionalRule Bedingungen ListSeparator ListenTrennzeichen ChildTypeLimit unfinished Format Format">Format Prefix Prefix Suffix Suffix InitialValue Anfangswert NumLines Zeilennummerierung SortKeyNum Sortierschlüssel SortForward AufwärtsSortierten EvalHtml unfinished treelocalcontrol Error - could not delete backup file {} Fehler: Kann Sicherheitskopie {0} nicht löschen Save changes to {}? Änderungen an {0} abspeichern? Save changes? Änderungen abspeichern? &Save S&peichern Save File Datei speichern Save the current file Aktuelle Datei speichern Save &As... Speichern &unter... Save the file with a new name Die Datei unter einem neuen Namen speichern &Export... &Exportieren... Export the file in various other formats Die Datei in unterschiedlichen Formaten exportieren Prop&erties... &Eigenschaften... Set file parameters like compression and encryption Datei Eigenschaften wie Komprimierung oder Verschlüsselung setzen P&rint Setup... &Drucken einrichten... Set margins, page size and other printing options Ränder, Seitengröße und andere Druckeinstellungen Print Pre&view... Druck&vorschau... Show a preview of printing results Vorschau der Druckergebnisse anzeigen &Print... &Drucken... Print tree output based on current options Baum basierend auf aktuellen Einstellungen drucken Print &to PDF... Nach &PDF drucken... Export to PDF with current printing options Nach PDF mit aktuellen Druckoptionen exportieren &Undo &Rückgängig Undo the previous action Die letzte Aktion rückgängig machen &Redo W&iederherstellen Redo the previous undo Die letzte Aktion wiederherstellen Cu&t &Ausschneiden Cut the branch or text to the clipboard Den Teilbaum oder Text ausschneiden und in die Zwischenablage legen &Copy &Kopieren Copy the branch or text to the clipboard Den Teilbaum oder den Text in die Zwischenablage kopieren &Paste Ein&fügen Paste nodes or text from the clipboard Knoten oder Text von der Zwischenablage einfügen Paste non-formatted text from the clipboard Unformatierten Text von der Zwischenablage einfügen &Bold Font &Fettschrift Set the current or selected font to bold Die aktuelle oder ausgewählte Schriftart auf "fett" setzen &Italic Font &Kursivschrift Set the current or selected font to italic Die aktuelle oder ausgewählte Schriftart auf "kursiv" setzen U&nderline Font &Unterstreichen Set the current or selected font to underline Die aktuelle oder ausgewählte Schriftart auf "unterstreichen" setzen &Font Size &Schriftart Größe Set size of the current or selected text Die Größe der aktuellen oder selektierten Schriftart setzen Small Klein Default Standard Large Groß Larger Größer Largest Am Größten Set Font Size Schriftart Größe setzen Font C&olor... Schriftart &Farbe... Set the color of the current or selected text Die Farbe der aktuellen oder ausgewählten Schriftart setzen &External Link... &Externer Verweis... Add or modify an extrnal web link Einen externen Verweis hinzufügen oder ändern Internal &Link... &Interner Verweis... Add or modify an internal node link Internen Verweis ändern oder hinzufügen Clear For&matting &Formatierung entfernen Clear current or selected text formatting Die Formatierung am aktuellen oder selektierten Text entfernen &Rename &Umbenennen Rename the current tree entry title Den Titel des aktuellen Knotens ändern Insert Sibling &Before &Vor ausgewähltem Element einfügen Insert new sibling before selection Ein neues Element vor dem ausgewählten Element einfügen Insert Sibling &After &Nach ausgewähltem Element einfügen Insert new sibling after selection Ein neues Element nach dem ausgewählten Element einfügen Add &Child &Kind hinzufügen Add new child to selected parent Neues Kind zu aktuellem Knoten hinzufügen &Delete Node Knoten &löschen Delete the selected nodes Die ausgewählten Knoten löschen &Indent Node Knoten &einrücken Indent the selected nodes Die ausgewählten Knoten einrücken &Unindent Node Knoten &ausrücken Unindent the selected nodes Die ausgewählten Knoten "ausrücken" (um eine Ebene nach links verschieben) &Move Up Nach &oben verschieben Move the selected nodes up Die ausgewählten Knoten nach oben verschieben M&ove Down Nach &unten verschieben Move the selected nodes down Die ausgewählten Knoten nach unten verschieben Move &First Zum Anfang verschieben Move the selected nodes to be the first children Das ausgewählte Knoten als erstes Unterelement setzen Move &Last Zum Ende verschieben Move the selected nodes to be the last children Das ausgewählte Knoten als letztes Unterelement setzen &Set Node Type Knoten&typ zuweisen Set the node type for selected nodes Den Typ für den ausgewählten Knoten setzen Set Node Type Knotentyp zuweisen Copy Types from &File... Typen aus &Datei kopieren... Copy the configuration from another TreeLine file Konfiguration aus einer anderen TreeLine-Datei übernehmen Flatten &by Category &Abflachen nach Kategorie Collapse descendants by merging fields Kinder zusammenfassen und Felder vereinen Add Category &Level... Kategorie &Hierarchieebene einfügen... Insert category nodes above children Kategorieebene oberhalb der Unterknoten einfügen &Spell Check... &Rechtschreibprüfung... &New Window &Neues Fenster Open a new window for the same file Neues Fenster für die gleiche Datei öffnen Error - could not write to {} Fehler - konnte nicht nach {0} schreiben TreeLine - Save As TreeLine - Speichern unter Error - could not write to file Fehler - konnte nicht auf Datei schreiben TreeLine - Open Configuration File TreeLine - Konfigurationsdatei schreiben Error - could not read file {0} Fehler - Konnte Datei {0} nicht lesen Cannot expand without common fields Ohne gemeinsame Felder kann der Baum nicht expandiert werden Category Fields Kategoriefelder Select fields for new level Felder für die neue Ebene auswählen File saved Datei gespeichert Pa&ste Plain Text Nu&r Text einfügen Paste C&hild Kind Knoten einfügen Paste a child node from the clipboard Kind Knoten von der Zwischenablage einfügen Paste Sibling &Before Füge Geschwister Knoten &davor Paste a sibling before selection Füge Geschwister Knoten vor Auswahl ein Paste Sibling &After Füge Geschwister Knoten d&ahinter Paste a sibling after selection Füge Geschwister Knoten hinter Auswahl ein Paste Cl&oned Child Füge geklonten Kind Knoten ein Paste a child clone from the clipboard Füge geklonten Kind Knoten von der Zwischenablage ein Paste Clo&ned Sibling Before Füge geklo&nten Geschwwister Knoten davor ein Paste a sibling clone before selection Füge Geschwister Knoten Klon vor der Auswahl ein Paste Clone&d Sibling After Füge geklonten Geschwister Knoten &danach ein Paste a sibling clone after selection Füge Geschwister Knoten Klon nach der Auswahl ein Clone All &Matched Nodes Klone alle &passenden Knoten Convert all matching nodes into clones Konvertiere alle passenden Knoten in Klone &Detach Clones Trenne Klone Detach all cloned nodes in current branches Trenne alle Klone Knoten im aktuellen Zweig S&wap Category Levels Tausche Kategorie Ebene Swap child and grandchild category nodes Tausche Kind und Enkel Kategorie Knoten Converted {0} branches into clones {0} Zweige in Klone konvertiert No identical nodes found Keine identischen Knoten gefunden Warning - file corruption! Skipped bad child references in the following nodes: Warnung - Datei Fehler! Überspringe fehlerhafte Kind Verweise in den folgenden Knoten: Spell check the tree's text data Rechtschreibprüfung für Text &Regenerate References Erstelle Verweise neu Force update of all conditional types & math fields Erzwinge Aktualisierung alle konditonalen Bedingungen & Mathematischen Feldern Insert &Date &Datum einfügen Insert current date as text Aktuelles Datum als Text einfügen St&rikethrough Font Set the current or selected font to strikethough treemaincontrol Warning: Could not create local socket Warnung - Socket kann nicht geöffnet werden Error - could not write config file to {} Fehler - Kann Konfigurationsdatei nicht auf {} schreiben Error - could not read file {0} Fehler - Kann Datei {0} nicht lesen Backup file "{}" exists. A previous session may have crashed Sicherheitskopie {} existiert. Eine vorherige Sitzung ist möglicherweise abgestürzt &Restore Backup Sicherungskopie &wiederherstellen &Delete Backup Sicherungskopie &löschen &Cancel File Open Datei öffnen &abbrechen Error - could not rename "{0}" to "{1}" Fehler - Kann {0} nicht nach {1} umbenennen Error - could not remove backup file {} Fehler - Kann Sicherheitskopie {} nicht entfernen &New... &Neu... New File Neue Datei Start a new file Eine neue Datei öffnen &Open... &Öffnen... Open File Datei öffnen Open a file from disk Datei von Datenträger öffnen Open Sa&mple... &Beispiele... Open Sample Beispiel öffnen Open a sample file Eine Beispieldatei öffnen &Import... &Importieren... Open a non-TreeLine file Eine nicht TreeLine Datei laden &Quit &Beenden Exit the application Die Anwendung beenden &Select All &Alles auswählen Select all text in an editor Gesamten Text im Editor auswählen &Configure Data Types... &Datentypen konfigurieren... Modify data types, fields & output lines Konfiguriere Datentypen, Felder und Ausgabezeilen Sor&t Nodes... Knoten&sortierung... Define node sort operations Knotensortierung definieren Update &Numbering... &Nummerierung anpassen... Update node numbering fields Die Nummerierung anpassen &Find Text... &Suche Text... Find text in node titles & data Text in Knoten suchen &Conditional Find... &Bedingtes Suchen... Use field conditions to find nodes Feldbasierte Bedingungen verwenden um Knoten zu finden Find and &Replace... Suchen und &Ersetzen... Replace text strings in node data Text in Knoten ersetzen &Text Filter... &Textfilter... Filter nodes to only show text matches Knoten filtern auf übereinstimmenden Text C&onditional Filter... &Bedingter Filter... Use field conditions to filter nodes Feldbasierte Bedingungen verwenden &General Options... Allgemeine &Einstellungen... Set user preferences for all files Benutzereinstellungen für alle Dateien Set &Keyboard Shortcuts... &Tastaturkürzel konfigurieren... Customize keyboard commands Tastaturkürzel anpassen C&ustomize Toolbars... &Symbolleiste anpassen... Customize toolbar buttons Symbolleiste Aktionen anpassen Customize Fo&nts... &Schriftarten anpassen... Customize fonts in various views Schriftarten der Ansichten anpassen &Basic Usage... &Grundlegende Verwendung... Display basic usage instructions Grundlegende Anleitungen anzeigen &Full Documentation... &Umfassende Dokumentation... Open a TreeLine file with full documentation TreeLine Datei mit umfassender Dokumentation anzeigen &About TreeLine... Über &TreeLine... Display version info about this program Versionsinformationen zum Programm anzeigen &Select Template &Vorlagenauswahl TreeLine - Open File TreeLine - Datei Öffnen Open Sample File Beispieldatei öffnen &Select Sample &Beispiel auswählen Conditional Find Bedingtes suchen Conditional Filter Bedingter Filter General Options Allgemeine Einstellungen Error - basic help file not found Fehler - Grundlegende Hilfedatei nicht gefunden TreeLine Basic Usage TreeLine grundlegende Verwendung Error - documentation file not found Fehler - Dokumentation nicht gefunden Error - invalid TreeLine file {0} Fehler - ungültige TreeLine Datei {0} TreeLine version {0} TreeLine Version {0} written by {0} geschrieben von {0} Library versions: Bibliothek Versionen: missing directory fehlendes Verzeichnis Show C&onfiguration Structure... Zeige Struktur der Konfiguration Show read-only visualization of type structure Zeige nur-lesende Visualisierung der Typ Struktur Custo&mize Colors... Farben anpassen Customize GUI colors and themes GUI Farben und Thema anpassen treemodel treenode New Neu treeopener treestructure Main Hauptprogramm treeview Filtering by "{0}", found {1} nodes Filtern nach {0}, {1} Knoten gefunden Conditional filtering, found {0} nodes Bedingtes Filter hat {0} Knoten gefunden Search for: Suche nach: Search for: {0} Suche nach: {0} Search for: {0} (not found) Suche nach: {0} (nicht gefunden) Next: {0} Nächste: {0} Next: {0} (not found) Nächste: {0} (nicht gefunden) treewindow Data Output Datenansicht Data Edit Datenbearbeitung Title List Überschriftsliste &Expand Full Branch Teilbaum vollständig &expandieren Expand all children of the selected nodes Alle Kinder der selektierten Knoten expandieren &Collapse Full Branch Teilbaum vollständig &einklappen Collapse all children of the selected nodes Alle Kinder der selektierten Knoten einklappen &Previous Selection &Vorherige Auswahl Return to the previous tree selection Zu der vorherigen Selektion zurückkehren &Next Selection &Nachfolgende Auswahl Go to the next tree selection in history Die folgende Selektion wieder aktivieren Show Data &Output &Ansicht anzeigen Show data output in right view Die Daten-Ansicht in der rechten Fensterhälfte anzeigen Show Data &Editor Edit&or anzeigen Show data editor in right view Den Editor in der rechten Fensterhälfte anzeigen Show &Title List &Überschriftsliste anzeigen Show title list in right view Die Überschriften-Liste in der rechten Fensterhälfte anzeigen &Show Child Pane &Kinder mit anzeigen Toggle showing right-hand child views Die Kinder in der Ausgabeansicht mit anzeigen Toggle showing output view indented descendants Die Kunde in der Ausgabeansicht eingerückt anzeigen &Close Window Fenster &schließen Close this window Dieses Fenster schließen &File &Datei &Edit &Bearbeiten &Node &Knoten &Data Da&ten &Tools &Extras &View &Ansicht &Window &Fenster &Help &Hilfe Start Incremental Search Starte inkrementelle Suche Next Incremental Search Nächste inkrementelle Suche Previous Incremental Search Vorherige inkrementelle Suche Show &Breadcrumb View Zeige &Breadcrumb Ansicht Toggle showing breadcrumb ancestor view Umschalten zu Breadcrumb Vorfahren Ansicht Show Output &Descendants Kinder in der Ausgabe mit anzeigen Fo&rmat Fo&rmat colorset Dialog background color Dialog für Hintergrundfarbe Dialog text color Dialog für Textfarbe Text widget background color Hintergrundfarbe für Textfelder Text widget foreground color Vordergrundfarbe für Textfelder Selected item background color Hintergrundfarbe des Eintrags Selected item text color Vordergrundfarbe des Eintragstextes Link text color Textfarbe von Links Tool tip background color Hintergrundfarbe für Tooltips Tool tip foreground color Vordergrundfarbe für Tooltips Button background color Button Hintergrundfarbe Button text color Button Textfarbe Disabled text foreground color Textfarbe deaktivieren Disabled button text color Farbe für nicht verfügbare Funktionen Color Settings Farbeinstellungen Color Theme unfinished">Farbschema Default system theme (Voreingestelltes) Systemthema Dark theme Dunkles Thema Custom theme Anwender-definiertes Thema &OK &OK &Cancel &Abbrechen Custom Colors Anwender-definierte Farben Theme Colors Farben des Themas Select {0} color {0} Farben auswählen TreeLine-3.2.1/working/translations/treeline_es.ts000066400000000000000000005732611506556630100223200ustar00rootroot00000000000000 conditional starts with comienza con ends with termina con contains contiene True Verdadero False Falso and y or o [All Types] [Todos los tipos] Node Type Tipo de nodo &Add New Rule Añadir &Nueva Regla &Remove Rule &Eliminar Regla &OK &OK &Cancel &Cancelar Find &Previous B&uscar Anterior Find &Next Buscar &Siguiente &Filter &Filtro &End Filter &Terminar filtro &Close &Cerrar No conditional matches were found Coincidencias condicionales no encontradas Rule {0} Regla {0} Saved Rules Reglas Guardadas Name: Nombre: &Load Car&gar &Save Guar&dar &Delete &Borrar configdialog Configure Data Types Configurar Tipos de Datos T&ype List Lista de &Tipos Field &List Lista de &Campos &Field Config Configuración de &Campos &Show Advanced &Mostrar Avanzado &OK &OK &Apply &Aplicar &Reset &Reiniciar &Cancel &Cancelar Add or Remove Data Types Añadir o Quitar Datos de Tipos &New Type... &Nuevo Tipo... Co&py Type... Co&piar Tipo... &Delete Type &Eliminar tipo Add Type Añadir tipo Enter new type name: Establecer nombre del nuevo tipo: Rename Type Renombrar tipo Cannot delete data type being used by nodes No se puede eliminar un tipo de datos que esté siendo usado por algún nodo &Data Type Tipo de &Datos Icon Icono Change &Icon Cambiar &Icono Derived from &Generic Type Derivado del Tipo &Genérico Automatic Types Tipos Automáticos Modify Co&nditional Types Modificar Tipos Co&ndicionales Create Co&nditional Types Crear Tipos Co&ndicionales Set Types Conditionally Configurar Tipos Condicionalmente Name Nombre Type Tipo Move &Up Mover A&rriba Move Do&wn Mover Aba&jo &New Field... &Nuevo Campo... Add Field Añadir Campo Enter new field name: Introduzca el nombre del nuevo campo: Rename Field Renombrar Campo F&ield Cam&po Format &Help Ayuda sobre &Formato Extra Text Texto Adicional &Prefix P&refijo Suffi&x Sufi&jo Editor Height Altura del editor Num&ber of text lines Número de líneas de te&xto File Info Reference Referencia de información de archivo Parent Reference Referencia Padre Child Reference Referencia Hija Child Count Recuento de Hijos F&ield List &Lista de Campos Other Field References Otras Referencias de Campos Copy Type Copiar Tipo Set Data Type Icon Establecer el Icono del Tipo de Datos Clear &Select Borrar &Selección Typ&e Config Configurar &Tipo O&utput &Salida de Datos &Hide Advanced &Ocultar Avanzado Error - circular reference in math field equations Error - referencia circular en ecuaciones de campo matemático Rena&me Type... Renom&brar Tipo... &Derive from original &Derivado del original Rename from {} to: Renombrar de {} a: [None] no type set [Nada] Default Child &Type Tipo Hi&jo por Defecto Output Options Opciones de Salida Add &blank lines between nodes Agregar línea en &blanco entre nodos Allow &HTML rich text in format Permitir &HTML con formato de texto enriquecido Add text bullet&s Agregar &viñetas al texto Use a table for field &data Mostrar datos de campo en tab&la Combination && Child List Output &Separator Combinación && &separador lista de hijos de Salida None Nada Modify &Field List Modificar &Lista de Campos Sort Key Clave de Clasificación Move U&p Mo&ver Arriba Rena&me Field... Renombrar Cam&po... Dele&te Field &Borrar Campo Sort &Keys... Ord&enar Claves... fwd Adelante rev Atrás &Field Type Tip&o de Campo Outpu&t Format Formato de Sa&lida Default &Value for New Nodes &Valor por Defecto para Nuevos Nodos Math Equation Ecuación matemática Define Equation Definir Ecuación &Title Format &Formato de Título Out&put Format &Formato de Salida Reference Le&vel Niv&el de Referencia Refere&nce Type Tipo de Refere&ncia The name cannot be empty El nombre no puede estar vacío The name must start with a letter El nombre debe comenzar con una letra The name cannot start with "xml" El nombre no puede comenzar con "xml" The name cannot contain spaces El nombre no puede contener espacios The following characters are not allowed: {} Los siguientes caracteres no están permitidos: {} The name was already used El nombre ya está en uso forward adelante reverse atrás Sort Key Fields Ordenar Campos Clave Available &Fields Campos &Disponibles &Sort Criteria C&riterio de Ordenación Field Campo Direction Dirección &Move Down Mover Aba&jo Flip &Direction Cam&biar Dirección Self Reference Autoreferencia Root Reference Referencia Raíz Date Result Resultado de Fecha Time Result Resultado de Tiempo add sumar subtract restar multiply multiplicar divide dividir floor divide división por redondeo modulus módulo power potencia sum of items suma de ítems maximum máximo minimum mínimo average promedio absolute value valor absoluto square root raíz cuadrada natural logarithm logaritmo natural base-10 logarithm logaritmo en base 10 factorial factorial round to num digits redondear a número de dígitos lower integer entero menor higher integer entero mayor truncated integer entero truncado floating point punto flotante sine of radians seno de radián cosine of radians coseno de radián tangent of radians Tangente de Radián arc sine arcoseno arc cosine arcocoseno arc tangent arcotangente radians to degrees radianes a grados degrees to radians grados a radianes pi constant número pi (constante) natural log constant constante logaritmo natural Define Math Field Equation Definir el Campo de Ecuación Matemática Field References Referencias de Campo Reference &Level Referencia de &Nivel Reference &Type Referencia de &Tipo Available &Field List Lista de &Campos Disponible &Result Type &Resultado Tipo Description Descripción &Equation &Ecuación Equation error: {} Erron en ecuación: {} Boolean Result Resultado Booleano Text Result Texto Resultante Arithmetic Operators Operadores Aritméticos Comparison Operators Operadores Comparativos Text Operators Operadores de Texto equal to igual a less than menor que greater than mayor que less than or equal to menor o igual que greater than or equal to mayor o igual que not equal to distinto a true value, condition, false value valor verdadero, condición, valor falso true if 1st text arg starts with 2nd arg verdadero si el argumentdo del primer texto comienza con un segundo argumento true if 1st text arg ends with 2nd arg verdadero si el argumentdo del primer texto termina con un segundo argumento true if 1st text arg contains 2nd arg verdadero si el argumentdo del primer texto contiene un segundo argumento concatenate text concatenar texto join text using 1st arg as separator unir texto usando como primer argumento un separador convert text to upper case convertir texto a mayúsculas convert text to lower case convertir texto a minúsculas in 1st arg, replace 2nd arg with 3rd arg en primer argumento, reemplazar segundo argumento con tercer argumento Operations Operaciones O&perator Type Tipo de O&perador Oper&ator List Lista de Oper&adores logical and lógico y logical or lógico o Output HTML Salida HTML Evaluate &HTML tags Evaluar etiquetas &HTML Child Type Limits Límites de los Tipos Hijo [All Types Available] [Todos los Tipos Disponibles] &Select All &Seleccionar Todo Select &None Seleccionar &Ninguno Number Result Resultado Numérico Count Number of Children dataeditors Today's &Date Fecha de &Hoy &Open Link &Abrir Enlace Open &Folder Abrir &Carpeta External Link Enlace Externo Scheme Esquema &Browse for File &Seleccionar Archivo File Path Type Tipo de ruta de archivo Absolute Absoluta Relative Relativa Address Dirección Display Name Mostrar Nombre &OK &OK &Cancel &Cancelar TreeLine - External Link File TreeLine - Enlace a archivo externo &Go to Target &Ir al Destino Internal Link Enlace Interno &Open Picture &Abrir Imagen Picture Link Enlace de Imagen TreeLine - Picture File TreeLine - Archivo de Imagen Set to &Now Establecer A&hora Clear &Link Borrar En&lace (Click link target in tree) (Clicar objeto a enlazar en el árbol) link enlace exports Bookmarks Favoritos TreeLine - Export HTML TreeLine - Exportar HTML TreeLine - Export Text Titles TreeLine - Exportar Textos de Títulos TreeLine - Export Plain Text TreeLine - Exportar Texto Plano TreeLine - Export Text Tables TreeLine - Exportar Tablas de Texto TreeLine - Export Generic XML TreeLine - Exportar XML Genérico TreeLine - Export TreeLine Subtree TreeLine - Exportar Subárbol TreeLine TreeLine - Export ODF Text Exportar Texto ODF TreeLine - Export HTML Bookmarks TreeLine - Exportar Favoritos HTML TreeLine - Export XBEL Bookmarks TreeLine - Exportar Favoritos XBEL &HTML &HTML &Text &Texto &ODF Outline &ODF Texto (esquema) Book&marks &Favoritos &Single HTML page Página HTML &Simple Single &HTML page with navigation pane &Página HTML simple con panel de navegación Multiple HTML &pages with navigation pane &Multiples páginas HTML con panel de navegación Multiple HTML &data tables Múltiples tablas de datos &HTML &Tabbed title text &Texto con tabulación por títulos &Unformatted output of all text &Salida sin formato para todo el texto &HTML format bookmarks Formato &HTML de favoritos &XBEL format bookmarks Formato &XBEL de favoritos File Export Exportar Archivo Choose export format type Seleccionar tipo de formato para exportar Choose export format subtype Seleccionar subtipo de formato para exportar Choose export options Seleccionar opciones para exportar What to Export Qué exportar &Entire tree &Todo el Ã�rbol Selected &branches &Ramas Seleccionadas Selected &nodes &Nodos Seleccionados Other Options Otras Opciones &Only open node children Abrir s&olo nodos hijos Include &print header && footer Incluir im&presión de encabezado y pie &Columns &Columnas Navigation pane &levels Nive&les del Panel de Navegación Error - export template files not found. Check your TreeLine installation. Error - Exportar archivos de plantilla no encontrados. Verifique la instalación de su TreeLine. Error - cannot link to unsaved TreeLine file. Save the file and retry. Error: No se puede vincular al archivo TreeLine no guardado. Guarde el archivo y vuelva a intentarlo. Warning - no relative path from "{0}" to "{1}". Continue with absolute path? Advertencia: no hay una ruta relativa entre "{0}" y "{1}". Continuar con la ruta absoluta? Parent Padre Tree&Line Tree&Line &XML (generic) &XML (genérico) Live tree view, linked to TreeLine file (for web server) Vista de árbol en tiempo real, vinculada al archivo TreeLine (para servidor web) Live tree view, single file (embedded data) Vista de árbol en tiempo real, archivo único (datos incrustados) &Comma delimited (CSV) table of descendants (level numbers) Tabla &de descendientes delimitada por comas (CSV) (número de niveles) Comma &delimited (CSV) table of children (single level) T&abla de hijos delimitada por comas (CSV) (nivel único) Tab &delimited table of children (&single level) Ta&bla delimitada por tabulaciones según nodos hijos (nivel único) &Old TreeLine (2.0.x) &Antiguos TreeLine (2.0.x) &TreeLine Subtree &Subárbol TreeLine &Include root nodes &Incluir noddos principales Must select nodes prior to export Debe seleccionar nodos antes de exportar fieldformat yes/no sí/no true/false verdadero/falso T/F V/F Y/N S/N Text Texto HtmlText Texto Html OneLineText Texto de una línea SpacedText Texto espaciado Number Número Math Matemáticas Numbering Numeración Boolean Booleano Date Fecha Time Hora Choice Elección AutoChoice AutoElección Combination Combinación AutoCombination AutoCombinación ExternalLink Enlace Externo InternalLink EnlaceInterno Picture Imagen RegularExpression Expresión regular Now Ahora Optional Digit # Dígito Opcional # Required Digit 0 Dígito Requerido 0 Digit or Space (external) <space> Dígito o Espacio (externo) <space> Decimal Point . Punto Decimal . Decimal Comma , Coma Decimal , Space Separator (internal) <space> Separador Espacio (interno) <space> Optional Sign - Signo Opcional - Required Sign + Signo Requerido + Exponent (capital) E Exponente (mayúscula) E Exponent (small) e Exponente (minúscula) e Number 1 Número 1 Capital Letter A Mayúsculas A Small Letter a Minúsculas a Capital Roman Numeral I Números Romanos (mayúsculas) I Small Roman Numeral i Números romanos (minúsculas) i Level Separator / Separador de nivel / Section Separator . Separador de sección . "/" Character // "/" Carácter // "." Character .. "." Carácter .. Outline Example I../A../1../a)/i) Ejemplo de esquema I../A../1../a)/i) Section Example 1.1.1.1 Ejemplo de sección 1.1.1.1 Separator / Separador / Example 1/2/3/4 Ejemplo 1/2/3/4 Any Character . Cualquier Carácter . End of Text $ Final del Texto $ 0 Or More Repetitions * 0 o más repeticiones * 1 Or More Repetitions + 1 o más repeticiones + 0 Or 1 Repetitions ? 0 ó 1 Repeticiones ? Set of Numbers [0-9] Conjunto de Números [0-9] Lower Case Letters [a-z] Minúsculas [a-z] Upper Case Letters [A-Z] Mayúsculas [A-Z] Not a Number [^0-9] No es un número [^0-9] Or | O | Escape a Special Character \ Escape carácter especial \ DateTime Fecha y hora Day (1 or 2 digits) %-d Día (1 ó 2 dígitos) %-d Day (2 digits) %d Día (2 dígitos) %d Weekday Abbreviation %a Día de la semana (abreviado) %a Weekday Name %A Día de la semana %A Month (1 or 2 digits) %-m Mes (1 o 2 dígitos) %-m Month (2 digits) %m Mes (2 dígitos) %m Month Abbreviation %b Mes (abreviado) %b Month Name %B Mes (nombre completo) %B Year (2 digits) %y Año (2 dígitos) %y Year (4 digits) %Y Año (4 dígitos) %Y Week Number (0 to 53) %-U Semana (0 a 53) %-U Day of year (1 to 366) %-j Día del año (1 a 366) %-j Hour (0-23, 1 or 2 digits) %-H Hora (0-23, 1 ó 2 dígitos) %-H Hour (00-23, 2 digits) %H Hora (00-23, 2 dígitos) %H Hour (1-12, 1 or 2 digits) %-I Hora (1-12, 1 ó 2 dígitos) %-I Hour (01-12, 2 digits) %I Hora (01-12, 2 dígitos) %I Minute (1 or 2 digits) %-M Minutos (1 ó 2 dígitos) %-M Minute (2 digits) %M Minutos (2 dígitos) %M Second (1 or 2 digits) %-S Segundos (1 ó 2 dígitos) %-S Second (2 digits) %S Segundos (2 dígitos) %S Microseconds (6 digits) %f Microsegundos (6 dígitos) %f AM/PM %p AM/PM %p Comma Separator \, Separador Coma \, Dot Separator \. Separador Punto \. DescendantCount Cuenta Descendiente genboolean true verdadero false falso yes sí no no globalref TreeLine Files Archivos TreeLine TreeLine Files - Compressed Archivos TreeLine - Comprimido TreeLine Files - Encrypted Archivos TreeLine - Encriptado All Files Todos los Archivos HTML Files Archivos HTML Text Files Archivos de Texto XML Files Archivos XML ODF Text Files Archivos de Texto ODF Treepad Files Archivos de Treepad PDF Files Archivos PDF CSV (Comma Delimited) Files Archivos CSV (Delimitado por Comas) All TreeLine Files Todos los Archivos TreeLine Old TreeLine Files Archivos TreeLine Antiguos helpview &Back &Volver &Forward &Siguiente &Home &Inicio Find: Buscar: Find &Previous Buscar &Anterior Find &Next &Buscar Siguiente Text string not found Cadena de texto no encontrada Tools Herramientas imports &Tab indented text, one node per line &Sangrado de texto por tabulaciones, un nodo por línea Tab delimited text table with header &row Tabl&a de texto delimitada por tabulaciones con fila de encabezado Plain text &paragraphs (blank line delimited) Texto &plano en párrafos (delimitado por línea en blanco) Treepad &file (text nodes only) &Archivo Treepad (únicamente nodos de texto) &Generic XML (non-TreeLine file) XML &genérico (No es un archivo TreeLine) Open &Document (ODF) outline Open &Document (ODF) &HTML bookmarks (Mozilla Format) &HTML favoritos (Formato Mozilla) &XML bookmarks (XBEL format) Favoritos en &XML (Formato XBEL) FOLDER CARPETA BOOKMARK FAVORITO SEPARATOR SEPARADOR Link Enlace Text Texto Import File Importar Archivo Choose Import Method Escoger Método de Importación Invalid File Archivo no Válido "{0}" is not a valid TreeLine file. Use an import filter? "{0}" no es un archivo válido TreeLine. ¿Usar filtro de importación de archivo? TreeLine - Import File TreeLine - Importar archivo Error - could not read file {0} Error-no se puede leer archivo {0} Error - improper format in {0} Error - formato incorrecto en {0} TABLE TABLA Bookmarks Favoritos Too many entries on Line {0} Demasiadas entradas en la Línea {0} Plain text, one &node per line (CR delimited) Text&o plano, un &nodo por línea (delimitado por retorno de carro -CR-) Bad CSV format on Line {0} Formato CSV.erróneo en Línea {0} Co&mma delimited (CSV) text table with level column && header row T&exto delimitado por comas (CSV) tabla de texto con nivel de columna y fila de encabezado Comma delimited (CSV) text table &with header row Texto &delimitado por comas (CSV) tabla con fila de encabezado Other Otro Old Tree&Line File (1.x or 2.x) Archivo Antiguo de Tree&Line (1.x o 2.x) Invalid level number on line {0} Número de nivel no válido en la línea {0} Invalid level structure Estructura de nivel no válida No headings found matheval Illegal "{}" characters Caracteres "{}" no permitidos Child references must be combined in a function Las referencias secundarias deben combinarse en una función Illegal syntax in equation Sintaxis ilegar en la ecuación Illegal function present: {0} Función ilegal presente: {0} Illegal object type or operator: {0} Tipo de objeto u operador no permitido: {0} Invalid field modifiers miscdialogs &OK &OK &Cancel &Cancelar Fields Campos File Properties Propiedades de Archivo File Storage Almacenamiento de Archivos &Use file compression &Comprimir Archivo Use file &encryption &Encriptar Archivo Spell Check Comprobación de la ortografía Language code or dictionary (optional) Código de idioma o diccionario (opcional) Math Fields Campos Matemáticos &Treat blank fields as zeros Considerar los espacios en blanco como ceros (&0) Encrypted File Password Contraseña del Archivo Encriptado Type Password for "{0}": Escriba la Contraseña para "{0}": Type Password: Escriba la Contraseña: Re-Type Password: Escriba de nuevo la contraseña: Remember password during this session Recordar la contraseña durante esta sesión Zero-length passwords are not permitted No se permiten contraseñas de longitud cero Re-typed password did not match La contraseña reescrita no coincide Default - Single Line Text Predeterminado - Texto Simple &Search Text &Buscar texto What to Search Dónde Buscar Full &data En to&do &Titles only Sólo en &títulos How to Search Cómo Buscar &Key words &Contiene Key full &words Texto E&xacto F&ull phrase Frase co&mpleta &Regular expression Exp&resión regular Find Buscar Find &Previous Buscar &Anterior Find &Next Buscar &Siguiente Filter Filtro &Filter &Filtro &End Filter C&errar Filtro &Close &Cerrar Error - invalid regular expression Error - Expresión regular no válida Search string "{0}" not found Buscar cadena "{0}". No encontrada Find and Replace Buscar y reemplazar Replacement &Text Reemplazar &Texto Any &match Co&ntiene Full &words Coinci&de Re&gular expression Expresión re&gular &Node Type Tipo de &Nodo N&ode Fields Campos de N&odo &Find Next &Buscar Siguiente &Replace &Reemplazar Replace &All Reemplaz&ar Todo [All Types] [Todos los tipos] [All Fields] [Todos los campos] Search text "{0}" not found Búsqueda del texto "{0}" no encontrado Error - replacement failed Error - reemplazo fallido Replaced {0} matches Reemplazadas {0} coincidencias Sort Nodes Ordenar Nodos What to Sort Qué ordenar &Entire tree Ã�rbol compl&eto Selected &branches Ramas &Seleccionadas Selection's childre&n &Hijos seleccionados Selection's &siblings Her&manos seleccionados Sort Method Método de ordenado &Predefined Key Fields Nombres de Campos &Predefinidos Node &Titles &Títulos de Nodos Sort Direction Dirección de Ordenado &Forward &Adelante &Reverse At&rás &Apply A&plicar Update Node Numbering Actualizar Numeración de Nodo What to Update Qué Actualizar &Selection's children &Selección de Hijos Root Node Nodo Principal Include top-level nodes Incluir nodos de nivel superior Handling Nodes without Numbering Fields Manejar nodos sin Campos de Numeración &Ignore and skip &Ignorar y omitir &Restart numbers for next siblings &Reiniciar números para los siguientes hermanos Reserve &numbers Reserva &números TreeLine Numbering Numeración TreeLine No numbering fields were found in data types No se encontraron campos de numeración en los tipos de datos File Menu Menú de Archivo File Archivo Edit Menu Menú Edición Edit Editar Node Menu Menú de Nodo Node Nodo Data Menu Menú de datos Data Datos Tools Menu Menú de Herramientas Tools Herramientas View Menu Menú Ver View Ver Window Menu Menú Ventana Window Ventana Help Menu Menú Ayuda Help Ayuda Keyboard Shortcuts Atajos de Teclado &Restore Defaults &Restaurar Valores por &Defecto Key {0} is already used Clave {0} ya está en uso Clear &Key Borrar Cla&ve --Separator-- --Separador-- Customize Toolbars Personalizar Barra de Herramientas Toolbar &Size Tamaño Barra de Herramienta&s Small Icons Iconos Pequeños Large Icons Iconos Grandes Toolbar Quantity Cantidad de barras de herramientas &Toolbars Barras de herramien&tas A&vailable Commands Comandos Dis&ponibles Tool&bar Commands Comandos de la &barra de herramientas Move &Up Mover &Arriba Move &Down Mover Aba&jo Tree View Font Fuente del Ã�rbol Output View Font Fuente de Salida Editor View Font Fuente del Editor No menu No.menu TreeLine - Serious Error TreeLine - Error Grave A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. Se ha producido un error grave. TreeLine podría estar en un estado inestable. Se recomienda guardar cualquier cambio de archivo con otro nombre de archivo y reiniciar TreeLine. La información de depuración que se muestra a continuación se puede copiar y enviar por correo electrónico a doug101@bellz.org junto con una explicación de las circunstancias del error. Format Menu Menú Formato Format Formato Customize Fonts Personalizar Fuentes &Use system default font &Usar fuente por defecto del sistema App Default Font Fuente por defecto de la aplicación &Use app default font &Usar la fuente predeterminada de la aplicación Externally Modified File &Overwrite File &Cancel Save File was externally modified at {} nodeformat Name Nombre optiondefaults Monday Lunes Tuesday Martes Wednesday Miércoles Thursday Jueves Friday Viernes Saturday Sábado Sunday Domingo Startup Condition Condición de Inicio Automatically open last file used Abrir automáticamente el último archivo usado Show descendants in output view Mostrar hijos en la vista de salida Restore tree view states of recent files Restaurar estados de vista en árbol de archivos recientes Restore previous window geometry Restaurar la geometría de la ventana anterior Features Available Funcionalidades disponibles Open files in new windows Abrir archivos en una nueva ventana Click node to rename Clicar en nodo para renombrar Rename new nodes when created Renombrar los nodos nuevos cuando sean creados Tree drag && drop available Disponible la opción de pulsar y arrastrar en el árbol Show icons in the tree view Mostrar iconos en la vista de árbol Show math fields in the Data Edit view Mostrar campos matemáticos en la vista de Edición de Datos Show numbering fields in the Data Edit view Mostrar campos de numeración en la vista de Edición de Datos Undo Memory Memoria usada por la opción "deshacer" Number of undo levels Número de niveles de deshacer Auto Save Grabación automática Minutes between saves (set to 0 to disable) Minutos entre respaldos (seleccione 0 para desactivar) Recent Files Archivos recientes Number of recent files in the file menu Cantidad de archivos recientes en el menú de archivo Data Editor Formats Formatos del editor de datos Times Horas Dates Fechas First day of week Primer día de la semana Appearance Apariencia Child indent offset (in font height units) Corrección de sangrado de hijos (en unidades de altura de fuente) Show breadcrumb ancestor view Mostrar panel de navegación Show child pane in right hand views Motrar paneles hijos en la vista derecha Remove inaccessible recent file entries Eliminar archivos inaccesibles en la vista de archivos recientes Activate data editors on mouse hover Activar editores de datos cuando el puntero del ratón esté encima Minimize application to system tray Minimiza aplicación a la bandeja del sistema Indent (pretty print) TreeLine JSON files Sangrado (mejor impresión) Archivos TreeLine JSON Limit data editor height to window size options Choose configuration file location Elija la ubicación del archivo de configuración User's home directory (recommended) Directorio de inicio de usuario (recomendado) Program directory (for portable use) Carpeta del programa (para uso portable) &OK &Aceptar &Cancel &Cancelar printdata Error initializing printer Error inicializando la impresora TreeLine - Export PDF TreeLine - Exportar a PDF Warning: Page size and margin settings unsupported on current printer. Save page adjustments? Advertencia: configuración de tamaño de página y margen no admitida en la impresora actual. ¿Guardar los ajustes de página? Warning: Page size setting unsupported on current printer. Save adjustment? Advertencia: configuración de tamaño de página no admitida en la impresora actual. ¿Guardar ajustes? Warning: Margin settings unsupported on current printer. Save adjustments? Advertencia: configuración de margen no compatible en la impresora actual. ¿Guardar los ajustes? printdialogs Print Preview Vista Previa de Impresión &Print... &Imprimir... &General Options Opciones &Generales &Font Selection Selección de &Fuente &Header/Footer &Encabezado y pie Print Pre&view... &Vista Previa... &OK &OK &Cancel &Cancelar What to print Qué imprimir &Entire tree &Ã�rbol completo Selected &branches &Ramas seleccionadas Selected &nodes &Nodos seleccionados Features Características &Include root node Incluir el nodo rai&z &Keep first child with parent &Mantener el primer nodo hijo con el padre Letter (8.5 x 11 in.) Carta (8.5 x 11 in.) Legal (8.5 x 14 in.) Legal (8.5 x 14 in.) Tabloid (11 x 17 in.) Tabloide (11 x 17 in.) A3 (279 x 420 mm) A3 (279 x 420 mm) A4 (210 x 297 mm) A4 (210 x 297 mm) A5 (148 x 210 mm) A5 (148 x 210 mm) Paper &Size Tamaño del Pape&l Orientation Orientación &Units &Unidades Columns Columnas &Number of columns &Número de columnas Default Font Fuente predeterminada Select Font Seleccionar Fuente &Font &Fuente Font st&yle E&stilo de fuente Sample Ejemplo &Header Left Encabezado I&zquierdo Header C&enter Encabezado cen&trado Footer &Left Pie Iz&quierdo Footer Ce&nter Pie ce&ntrado Fiel&ds Campo&s Header and Footer Encabezado y pie de página Extra Text Texto adicional &Prefix &Prefijo Format &Help A&yuda de Formato Fit Width Ajuste de ancho Fit Page Ajuste de página Zoom In Zoom Aumentar Zoom Out Zorrm Reducir Previous Page Página anterior Next Page Página Siguiente Single Page Página sencilla Facing Pages Páginas enfrentadas Print Setup Configuración de Impresión Print Imprimir Printing Setup Configuración de Impresión Page &Setup Configuración de &Página Included Nodes Nodos Incluídos Onl&y open node children Incluir solo nodos &hijos &Draw lines to children &Dibujar líneas para los nodos hijos Indent Sangrar Indent Offse&t (line height units) Sangrado de &Salida (unidades de altura de línea) Custom Size Tamaño Personalizado Inches (in) Pulgadas (in) Millimeters (mm) Milímetros (mm) Centimeters (cm) Centímetros (cm) &Width: A&nchura: Height: Altura: Portra&it Retra&to Lan&dscape Paisa&je Margins Márgenes &Left: Iz&quierda: &Top: A&rriba: &Right: Derec&ha: &Bottom: A&bajo: He&ader: Encabe&zado: Foot&er: &Pie: Space between colu&mns Espacio entre colu&mnas &Use TreeLine output view font &Usar la misma que haya configurada en "Salida de Datos" de TreeLine Si&ze &Tamaño AaBbCcDdEeFfGg...TtUuVvWvXxYyZz AaBbCcDdEeFfGg...TtUuVvWvXxYyZz Header &Right Encabezado &Derecho Footer Righ&t Pie De&recho Field For&mat For&mato de Campo Field Format for "{0}" Formato de Campo para "{0}" Output &Format Salida &Formato &Suffix &Sufijo Error: Page size or margins are invalid Error: Tamaño de página o márgenes inválidos TreeLine PDF Printer TreeLine Impresora PDF Select &Printer Seleccionar Im&presora recentfiles spellcheck Could not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? No se pudo encontrar aspell.exe, ispell.exe o hunspell.exe ¿Buscar la ubicación? Spell Check Error Error ortográfico Locate aspell.exe, ipsell.exe or hunspell.exe Ubique aspell.exe, ipsell.exe o hunspell.exe Program (*.exe) Programa (*.exe) TreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed Error de comprobación ortográfica TreeLine Comprobar que esté instalado aspell, ispell o hunspell TreeLine Spell Check Comprobación ortográfica de TreeLIne Finished spell checking Comprobación ortográfica finalizada Spell Check Comprobación de la ortografía Not in Dictionary No está en el diccionario Word: Palabra: Context: Contexto: Suggestions Sugerencias Ignor&e Ignor&ar &Ignore All &Ignorar todo &Add &Añadir Add &Lowercase Añadir &minúscula &Replace &Reemplazar Re&place All Reem&plazar todo &Cancel &Cancelar Finished checking the branch Continue from the top? Terminada revisión de la rama Continuar desde la parte superior? titlelistview Select in Tree Seleccionar en Ã�rbol treeformats DEFAULT PREDETERMINADO FILE ARCHIVO TYPE TIPO FIELD CAMPO FieldType TipoCampo TitleFormat OutputFormat SpaceBetween FormatHtml Bullets Table ChildType Icon Icono GenericType ConditionalRule ListSeparator ChildTypeLimit Format Formato Prefix Suffix InitialValue NumLines SortKeyNum SortForward EvalHtml treelocalcontrol Error - could not delete backup file {} Error - No se puede borrar el archivo de respaldo {} Save changes to {}? ¿Guardar cambios en {}? Save changes? ¿Guardar cambios? &Save &Guardar Save File Guardar archivo Save the current file Guardar el archivo actual Save &As... Guardar &Como... Save the file with a new name Guardar el archivo con un nombre nuevo &Export... &Exportar... Export the file in various other formats Exportar el archivo en varios formatos Prop&erties... &Propiedades... Set file parameters like compression and encryption Establecer parámetros de archivo como compresión y encriptación P&rint Setup... Config&uración de Impresión... Set margins, page size and other printing options Establecer márgenes, tamaño de página y otras opciones de impresión Print Pre&view... &Vista Previa de Impresión... Show a preview of printing results Vista previa de los resultados de impresión &Print... &Imprimir... Print tree output based on current options Imprimir salida de árbol en base a las opciones actuales Print &to PDF... Imprimir a PD&F... Export to PDF with current printing options Exportar a PDF con las opciones de impresión actuales &Undo &Deshacer Undo the previous action Deshacer la acción anterior &Redo &Rehacer Redo the previous undo Rehacer la última acción sobre la que se ha aplicado deshacer Cu&t Cor&tar Cut the branch or text to the clipboard Cortar la rama o el texto al portapapeles &Copy &Copiar Copy the branch or text to the clipboard Copiar la rama o texto al portapapeles &Paste &Pegar Paste nodes or text from the clipboard Pegar nodos o texto desde el portapapeles Paste non-formatted text from the clipboard Pegar texto sin formato del portapapeles &Bold Font &Negrita Set the current or selected font to bold Establecer la fuente actual o seleccionada en negrita &Italic Font &Cursiva Set the current or selected font to italic Establecer la fuente actual o seleccionada en cursiva U&nderline Font &Subrayado Set the current or selected font to underline Establecer la fuente actual o seleccionada para subrayar &Font Size &Tamaño de Fuente Set size of the current or selected text Establecer el tamaño del texto actual o seleccionado Small Pequeño Default Predeterminado Large Grande Larger Más grande Largest El más grande Set Font Size Definir tamaño de fuente Font C&olor... Color de &Fuente... Set the color of the current or selected text Establecer el color del texto actual o seleccionado &External Link... Enlace &Externo... Add or modify an extrnal web link Añadir o modificar un enlace web externo Internal &Link... Enlace &Interno... Add or modify an internal node link Añadir o modificar un enlace interno a nodo Clear For&matting &Borrar Formato Clear current or selected text formatting Borrar actual o seleccionado formato de texto &Rename &Renombrar Rename the current tree entry title Renombrar título completo del árbol en uso Insert Sibling &Before Añadir &Hermano Antes Insert new sibling before selection Añadir nuevo hermano antes de la selección Insert Sibling &After Añadir Hermano &Después Insert new sibling after selection Añadir nuevo hermano despues de la selección Add &Child &Añadir Hijo Add new child to selected parent Añadir nuevo hijo al padre seleccionado &Delete Node &Eliminar Nodo Delete the selected nodes Eliminar los nodos seleccionados &Indent Node &Sangrar Nodos Indent the selected nodes Sangrar los nodos seleccionados &Unindent Node Deshacer Sangrado de &Nodo Unindent the selected nodes Eliminar sangrado de los nodos seleccionados &Move Up Mover A&rriba Move the selected nodes up Desplazar hacia arriba los nodos seleccionados M&ove Down Mover Aba&jo Move the selected nodes down Desplazar hacia abajo los nodos seleccionados Move &First Mover al &Principio Move the selected nodes to be the first children Mover nodos seleccionados para ser los primeros hijos Move &Last Mover al &Final Move the selected nodes to be the last children Mover nodos seleccionados para ser los últimos hijos &Set Node Type &Establecer Tipo de Nodo Set the node type for selected nodes Establecer tipo de nodo para los nodos seleccionados Set Node Type Establecer tipo de nodo Copy Types from &File... &Copiar Tipos desde Archivo... Copy the configuration from another TreeLine file Copiar la configuración desde otro archivo de TreeLine Flatten &by Category &Acoplar por Categoría Collapse descendants by merging fields Contraer descendientes cuando se fusionen campos Add Category &Level... Añadir Ni&vel de Categoría... Insert category nodes above children Añadir los nodos con las categorías por encima de los hijos &Spell Check... Corrector &Ortográfico... &New Window &Nueva Ventana Open a new window for the same file Abrir nueva ventana para el mismo archivo Error - could not write to {} Error - No se pudo escribir en {} TreeLine - Save As TreeLine - Guardar como Error - could not write to file Error - no se pudo escribir en el archivo TreeLine - Open Configuration File TreeLine - Abrir archivo de configuración Error - could not read file {0} Error: no se pudo leer el archivo {0} Cannot expand without common fields No es posible expandir sin campos comunes Category Fields Campos de las categorías Select fields for new level Seleccionar campos para nuevo nivel File saved Archivo guardado Pa&ste Plain Text Pegar Texto sin &Formato Paste C&hild Pegar &Hijo Paste a child node from the clipboard Pegar un nodo hijo desde el portapapeles Paste Sibling &Before Pegar Hermano &Antes Paste a sibling before selection Pegar hermano antes de la selección Paste Sibling &After Pegar Hermano Despué&s Paste a sibling after selection Pegar un hermano después de la selección Paste Cl&oned Child Pegar Hijo C&lonado Paste a child clone from the clipboard Pegar hijo clonado desde el portapapeles Paste Clo&ned Sibling Before Pegar Hermano Clo&nado Antes Paste a sibling clone before selection Pegar un clon hermano antes de la selección Paste Clone&d Sibling After Pegar Hermano Clonad&o Después Paste a sibling clone after selection Pegar un clon hermano después de la selección Clone All &Matched Nodes Clonar &Todos los Nodos Emparejados Convert all matching nodes into clones Convertir todos los nodos coincidentes en clones &Detach Clones &Separar Clones Detach all cloned nodes in current branches Separar todos los nodos clonados en las ramas actuales S&wap Category Levels &Intercambiar Niveles de Categoría Swap child and grandchild category nodes Intercambiar categoría nodos hijos y nietos Converted {0} branches into clones Convierte ramas {0} en clones No identical nodes found No existen nodos idénticos Warning - file corruption! Skipped bad child references in the following nodes: Advertencia: ¡archivo corrupto! Se omitieron referencias de elementos secundarios incorrectos en los siguientes nodos: Spell check the tree's text data Revisar los datos de texto del árbol &Regenerate References Re&generar Referencias Force update of all conditional types & math fields Forzar actualización de todos los tipos condicionales y campos matemáticos Insert &Date Insert current date as text St&rikethrough Font Set the current or selected font to strikethough treemaincontrol Warning: Could not create local socket Advertencia: no se pudo crear el socket local Error - could not write config file to {} Error - no se pudo escribir el archivo de configuración en {} Error - could not read file {0} Error: no se pudo leer el archivo {0} Backup file "{}" exists. A previous session may have crashed Existe un archivo de respaldo: "{}". Una sesión anterior puede haberse bloqueado &Restore Backup &Restaurar copia de seguridad &Delete Backup Eliminar copia de segurida&d &Cancel File Open &Cancelar archivo abierto Error - could not rename "{0}" to "{1}" Error: - no se pudo cambiar el nombre de "{0}" a "{1}" Error - could not remove backup file {} Error - no se pudo eliminar el archivo de copia de seguridad {} &New... &Nuevo... New File Archivo nuevo Start a new file Comenzar un archivo nuevo &Open... &Abrir... Open File Abrir archivo Open a file from disk Abrir un archivo desde el disco Open Sa&mple... Abrir Archivo de Eje&mplo... Open Sample Abrir ejemplo Open a sample file Abrir un archivo de ejemplo &Import... Importa&r... Open a non-TreeLine file Abriri un arhchivo no-TreeLine &Quit &Salir Exit the application Salir de la aplicación &Select All Seleccionar T&odo Select all text in an editor Seleccionar todo el texto en un editor &Configure Data Types... Configurar Tipos de &Datos... Modify data types, fields & output lines Modificar tipos de datos, campos y líneas de salida Sor&t Nodes... &Ordenar Nodos... Define node sort operations Definir operaciones de ordenación de nodos Update &Numbering... Actualizar &Numeración... Update node numbering fields Actualizar campos de numeración de nodos &Find Text... &Buscar Texto... Find text in node titles & data Buscar texto en títulos y datos de nodo &Conditional Find... Búsqueda &Condicional... Use field conditions to find nodes Use condiciones de campo para encontrar nodos Find and &Replace... Buscar y &Reemplazar... Replace text strings in node data Reemplazar cadenas de texto en datos de nodo &Text Filter... Filtro de &Texto... Filter nodes to only show text matches Filtrar nodos para mostrar solo coincidencias de texto C&onditional Filter... &Filtro Condicional... Use field conditions to filter nodes Usar condiciones de campo para filtrar nodos &General Options... Opciones &Generales... Set user preferences for all files Configurar las preferencias para todos los archivos Set &Keyboard Shortcuts... Establecer &Atajos de Teclado... Customize keyboard commands Personalizar comandos de teclado C&ustomize Toolbars... Personalizar Barras de &Herramientas... Customize toolbar buttons Personalizar botones de la barra de herramientas Customize Fo&nts... &Personalizar Fuentes... Customize fonts in various views Personalizar fuentes en varias vistas &Basic Usage... Uso &Básico... Display basic usage instructions Mostrar instrucciones de uso básico &Full Documentation... &Documentación completa... Open a TreeLine file with full documentation Abrir un archivo TreeLine con documentación completa &About TreeLine... &Acerca de TreeLine... Display version info about this program Mostrar información de versión de esta aplicación &Select Template &Seleccionar Plantilla TreeLine - Open File TreeLine - Abrir Archivo Open Sample File Abrir archivo de ejemplo &Select Sample &Seleccionar Ejemplo Conditional Find Búsqueda Condicional Conditional Filter Filtro Condicional General Options Opciones generales Error - basic help file not found Error - archivo de ayuda básica no encontrado TreeLine Basic Usage TreeLine Uso Básico Error - documentation file not found Error - archivo de documentación no encontrado Error - invalid TreeLine file {0} Error - archivo TreeLine no válido {0} TreeLine version {0} TreeLine version {0} written by {0} escrito por {} Library versions: Versiones de la biblioteca: missing directory Directorio no encontrado Show C&onfiguration Structure... Mostrar Confi&guración de Estructura... Show read-only visualization of type structure Mostrar visualización de solo lectura del tipo de estructura Custo&mize Colors... Customize GUI colors and themes treemodel treenode New Nuevo treestructure Main Principal treeview Filtering by "{0}", found {1} nodes Filtrando por "{0}", encontrados.{1} nodos Conditional filtering, found {0} nodes Filtrado condicional, encontrados {0} nodos Search for: Buscar: Search for: {0} Buscar {0} Search for: {0} (not found) Buscar {0} (no encontrado) Next: {0} Siguiente: {0} Next: {0} (not found) Siguiente: {0} (no encontrado) treewindow Data Output Salida de Datos Data Edit Editor de Datos Title List Lista de Títulos &Expand Full Branch &Expandir Toda la Rama Expand all children of the selected nodes Expandir todos los hijos de los nodos seleccionados &Collapse Full Branch &Reducir Toda la Rama Collapse all children of the selected nodes Reducir todos los hijos de los nodos seleccionados &Previous Selection Selección &Previa Return to the previous tree selection Volver a la selección de árbol anterior &Next Selection Selección &Siguiente Go to the next tree selection in history Ir a la siguiente selección de árbol en el historial Show Data &Output &Mostrar Salida de Datos Show data output in right view Mostrar la salida de datos en la vista derecha Show Data &Editor Mostrar Editor de &Datos Show data editor in right view Mostrar el editor de datos en la vista de la derecha Show &Title List Mostrar &Lista de Títulos Show title list in right view Mostrar la lista de títulos en la vista de la derecha &Show Child Pane Mostrar Panel &Hijo Toggle showing right-hand child views Alternar mostrando resultados Toggle showing output view indented descendants Alternar mostrando la vista de salida sangría de descendients &Close Window &Cerrar Ventana Close this window Cerrar esta ventana &File &Archivo &Edit &Editar &Node &Nodo &Data &Datos &Tools &Herramientas &View &Ver &Window Ven&tana &Help A&yuda Start Incremental Search Iniciar búsqueda incremental Next Incremental Search Búsqueda incremental siguiente Previous Incremental Search Búsqueda incremental anterior Show &Breadcrumb View Mostrar &vista panel de navegación Toggle showing breadcrumb ancestor view Alternar mostrando vista anterior de navegación Show Output &Descendants Mostrar Salida de Datos y Des&cendientes Fo&rmat &Formato colorset Dialog background color Dialog text color Text widget background color Text widget foreground color Selected item background color Selected item text color Link text color Tool tip background color Tool tip foreground color Button background color Button text color Disabled text foreground color Disabled button text color Color Settings Color Theme Color de Tema Default system theme Dark theme Custom theme &OK &OK &Cancel &Cancelar Custom Colors Theme Colors Select {0} color TreeLine-3.2.1/working/translations/treeline_fr.ts000066400000000000000000005666041506556630100223230ustar00rootroot00000000000000 conditional starts with commence avec ends with se termine par contains contient True Vrai False Faux and et or ou [All Types] Node Type &Add New Rule &Ajouter Nouvelle Règle &Remove Rule &Supprimer Règle &OK &OK &Cancel &Annuler Find &Previous Chercher &Précédent Find &Next Chercher &Suivant &Filter &End Filter &Close &Fermer No conditional matches were found Rule {0} Saved Rules Name: &Load &Save &Enregistrer &Delete configdialog Configure Data Types Paramètres du Type de Données T&ype List Liste des t&ypes Field &List &Liste des champs &Field Config Con&figuration des champs &Show Advanced Avancé&s &OK &OK &Apply &Appliquer &Reset &Réinitialiser &Cancel &Annuler Add or Remove Data Types Ajouter ou supprimer des Types de Données &New Type... &Nouveau Type... Co&py Type... Co&pier le type… &Delete Type &Supprimer Type Add Type Ajouter Type Enter new type name: Entrer un nouveau nom de type: Rename Type Renommer Type Cannot delete data type being used by nodes Impossible de supprimer un type de données qui est en cours d'utilisation par des nÅ“uds &Data Type T&ype de Données Icon Icône Change &Icon Modifier l'&Icône Derived from &Generic Type Dérivé d'un Type &Générique Automatic Types Types Automatiques Modify Co&nditional Types Modifier un Type co&nditionnel Create Co&nditional Types Créer un Type Co&nditionnel Set Types Conditionally Configurer Types Sous Conditons Name Nom Type Type Move &Up Déplacer vers le &haut Move Do&wn Déplacer vers le &bas &New Field... &Nouveau Champ... Add Field Ajouter un champ Enter new field name: Entrer le nouveau nom du champ : Rename Field Renommer le champ F&ield C&hamp Format &Help Aide & formatage Extra Text Texte Supplémentaire &Prefix &Préfixe Suffi&x Suffi&xe Editor Height Hauteur de l'Editeur Num&ber of text lines Nom&bre de lignes de texte File Info Reference Références du Fichier Parent Reference Référence du Parent Child Reference Réference du Fils Child Count Nombre d'enfant F&ield List L&iste des champs Other Field References Références à d'autres champs Copy Type Copier Type Set Data Type Icon Configurer Icône Type de Données Clear &Select Effacer &Sélection Typ&e Config O&utput &Hide Advanced Error - circular reference in math field equations Rena&me Type... &Derive from original Rename from {} to: [None] no type set [Aucun] Default Child &Type Output Options Add &blank lines between nodes Allow &HTML rich text in format Add text bullet&s Use a table for field &data Combination && Child List Output &Separator None Aucun Modify &Field List Sort Key Move U&p Rena&me Field... Dele&te Field Sort &Keys... fwd rev &Field Type Outpu&t Format Default &Value for New Nodes Math Equation Define Equation &Title Format Out&put Format Reference Le&vel Refere&nce Type The name cannot be empty The name must start with a letter The name cannot start with "xml" The name cannot contain spaces The following characters are not allowed: {} The name was already used forward reverse Sort Key Fields Available &Fields &Sort Criteria Field Direction Direction &Move Down Flip &Direction Self Reference Root Reference Date Result Time Result add ajouter subtract multiply divide floor divide modulus power sum of items maximum minimum average absolute value square root natural logarithm base-10 logarithm factorial round to num digits lower integer higher integer truncated integer floating point sine of radians cosine of radians tangent of radians arc sine arc cosine arc tangent radians to degrees degrees to radians pi constant natural log constant Define Math Field Equation Field References Reference &Level Reference &Type Available &Field List &Result Type Description &Equation Equation error: {} Boolean Result Text Result Arithmetic Operators Comparison Operators Text Operators equal to less than greater than less than or equal to greater than or equal to not equal to true value, condition, false value true if 1st text arg starts with 2nd arg true if 1st text arg ends with 2nd arg true if 1st text arg contains 2nd arg concatenate text join text using 1st arg as separator convert text to upper case convert text to lower case in 1st arg, replace 2nd arg with 3rd arg Operations O&perator Type Oper&ator List logical and logical or Output HTML Evaluate &HTML tags Child Type Limits [All Types Available] &Select All Select &None Number Result Count Number of Children dataeditors Today's &Date &Open Link Open &Folder External Link Scheme &Browse for File File Path Type Absolute Relative Address Display Name &OK &OK &Cancel &Annuler TreeLine - External Link File &Go to Target Internal Link &Open Picture Picture Link TreeLine - Picture File Set to &Now Clear &Link (Click link target in tree) link exports Bookmarks Favoris TreeLine - Export HTML TreeLine - Export Text Titles TreeLine - Export Plain Text TreeLine - Export Text Tables TreeLine - Export Generic XML TreeLine - Export TreeLine Subtree TreeLine - Export ODF Text TreeLine - Export HTML Bookmarks TreeLine - Export XBEL Bookmarks &HTML &Text &ODF Outline Book&marks &Single HTML page Single &HTML page with navigation pane Multiple HTML &pages with navigation pane Multiple HTML &data tables &Tabbed title text &Texte des titres tabulés &Unformatted output of all text &HTML format bookmarks &XBEL format bookmarks File Export Choose export format type Choose export format subtype Choose export options What to Export Que faut−il exporter &Entire tree Arbre &Entier Selected &branches &Branches sélectionnées Selected &nodes &NÅ“uds sélectionnés Other Options &Only open node children Include &print header && footer &Columns Navigation pane &levels Error - export template files not found. Check your TreeLine installation. Error - cannot link to unsaved TreeLine file. Save the file and retry. Warning - no relative path from "{0}" to "{1}". Continue with absolute path? Parent Tree&Line &XML (generic) Live tree view, linked to TreeLine file (for web server) Live tree view, single file (embedded data) &Comma delimited (CSV) table of descendants (level numbers) Comma &delimited (CSV) table of children (single level) Tab &delimited table of children (&single level) &Old TreeLine (2.0.x) &TreeLine Subtree &Include root nodes Must select nodes prior to export fieldformat yes/no oui/non true/false vrai/faux T/F V/F Y/N O/N Text Texte HtmlText OneLineText SpacedText Number Nombre Math Numbering Boolean Booléen Date Date Time Heure Choice Choix AutoChoice ChoixAuto Combination Combinaison AutoCombination ExternalLink InternalLink LienInterne Picture Image RegularExpression Now Maintenant Optional Digit # Required Digit 0 Digit or Space (external) <space> Decimal Point . Decimal Comma , Space Separator (internal) <space> Optional Sign - Required Sign + Exponent (capital) E Exponent (small) e Number 1 Capital Letter A Small Letter a Capital Roman Numeral I Small Roman Numeral i Level Separator / Section Separator . "/" Character // "." Character .. Outline Example I../A../1../a)/i) Section Example 1.1.1.1 Separator / Example 1/2/3/4 Any Character . End of Text $ 0 Or More Repetitions * 1 Or More Repetitions + 0 Or 1 Repetitions ? Set of Numbers [0-9] Lower Case Letters [a-z] Upper Case Letters [A-Z] Not a Number [^0-9] Or | Escape a Special Character \ DateTime Day (1 or 2 digits) %-d Day (2 digits) %d Weekday Abbreviation %a Weekday Name %A Month (1 or 2 digits) %-m Month (2 digits) %m Month Abbreviation %b Month Name %B Year (2 digits) %y Year (4 digits) %Y Week Number (0 to 53) %-U Day of year (1 to 366) %-j Hour (0-23, 1 or 2 digits) %-H Hour (00-23, 2 digits) %H Hour (1-12, 1 or 2 digits) %-I Hour (01-12, 2 digits) %I Minute (1 or 2 digits) %-M Minute (2 digits) %M Second (1 or 2 digits) %-S Second (2 digits) %S Microseconds (6 digits) %f AM/PM %p Comma Separator \, Dot Separator \. DescendantCount genboolean true vrai false faux yes oui no non globalref TreeLine Files Fichiers TreeLine TreeLine Files - Compressed Fichiers TreeLine - Compressé TreeLine Files - Encrypted Fichiers TreeLine - Encrypté All Files HTML Files Text Files Fichiers Texte XML Files Fichiers XML ODF Text Files Fichier Texte ODF Treepad Files Fichiers Treepad PDF Files CSV (Comma Delimited) Files All TreeLine Files Old TreeLine Files helpview &Back &Précédent &Forward &Suivant &Home &Accueil Find: Chercher: Find &Previous Chercher &Précédent Find &Next Chercher &Suivant Text string not found Chaîne de caractères non trouvée Tools imports &Tab indented text, one node per line Tab delimited text table with header &row Plain text &paragraphs (blank line delimited) Treepad &file (text nodes only) &Fichier Treepad (noeuds texte seulement) &Generic XML (non-TreeLine file) Open &Document (ODF) outline &HTML bookmarks (Mozilla Format) &XML bookmarks (XBEL format) &XML favoris (format XBEL) FOLDER REPERTOIRE BOOKMARK FAVORIS SEPARATOR SEPARATEUR Link Lien Text Texte Import File Choose Import Method Invalid File "{0}" is not a valid TreeLine file. Use an import filter? TreeLine - Import File Error - could not read file {0} Error - improper format in {0} TABLE Bookmarks Favoris Too many entries on Line {0} Plain text, one &node per line (CR delimited) Bad CSV format on Line {0} Co&mma delimited (CSV) text table with level column && header row Comma delimited (CSV) text table &with header row Other Old Tree&Line File (1.x or 2.x) Invalid level number on line {0} Invalid level structure No headings found matheval Illegal "{}" characters Child references must be combined in a function Illegal syntax in equation Illegal function present: {0} Illegal object type or operator: {0} Invalid field modifiers miscdialogs &OK &OK &Cancel &Annuler Fields Champs File Properties File Storage Fichier &Use file compression Use file &encryption Spell Check Vérification orthographique Language code or dictionary (optional) Math Fields &Treat blank fields as zeros Encrypted File Password Mot de passe encrypté Type Password for "{0}": Type Password: Entrer le mot de passe: Re-Type Password: Entrer à nouveau le mot de passe: Remember password during this session Se souvenir du mot de passe pendant cette session Zero-length passwords are not permitted Les mots de passe de longueur zéro ne sont pas autorisés Re-typed password did not match Le mot de passe entré la deuxième fois ne correspond pas Default - Single Line Text &Search Text What to Search Full &data &Titles only How to Search &Key words Key full &words F&ull phrase &Regular expression Find Chercher Find &Previous Chercher &Précédent Find &Next Chercher &Suivant Filter &Filter &End Filter &Close &Fermer Error - invalid regular expression Search string "{0}" not found Find and Replace Replacement &Text Any &match Full &words Re&gular expression &Node Type N&ode Fields &Find Next &Replace &Remplacer Replace &All [All Types] [All Fields] Search text "{0}" not found Error - replacement failed Replaced {0} matches Sort Nodes What to Sort Que trie−t−on &Entire tree Arbre &Entier Selected &branches &Branches sélectionnées Selection's childre&n Les e&nfants de la sélection Selection's &siblings Les frères de la &sélection Sort Method Méthode de tri &Predefined Key Fields Node &Titles Sort Direction &Forward &Suivant &Reverse &Apply &Appliquer Update Node Numbering What to Update &Selection's children Root Node Noeud Racine Include top-level nodes Handling Nodes without Numbering Fields &Ignore and skip &Restart numbers for next siblings Reserve &numbers TreeLine Numbering No numbering fields were found in data types File Menu File Edit Menu Edit Node Menu Node Data Menu Data Tools Menu Tools View Menu View Window Menu Window Help Menu Help Keyboard Shortcuts Raccourcis clavier &Restore Defaults Key {0} is already used Clear &Key --Separator-- −Séparateur− Customize Toolbars Personnaliser les barres d''outils Toolbar &Size &Taille des barres d'outils Small Icons Petites icônes Large Icons Grandes icônes Toolbar Quantity Nombre de barres d'outls &Toolbars &Barre d'Outils A&vailable Commands Comma&ndes disponibles Tool&bar Commands Commandes des &barres d'outils Move &Up Déplacer vers le &haut Move &Down &Descendre Tree View Font Output View Font Editor View Font No menu TreeLine - Serious Error A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. Format Menu Format Customize Fonts &Use system default font App Default Font &Use app default font Externally Modified File &Overwrite File &Cancel Save File was externally modified at {} nodeformat Name Nom optiondefaults Monday Lundi Tuesday Mardi Wednesday Mercredi Thursday Jeudi Friday Vendredi Saturday Samedi Sunday Dimanche Startup Condition Au Démarrage Automatically open last file used Ouvrir automatiquement le dernier fichier utilisé Show descendants in output view Montrer descendants dans l'aperçu sortie Restore tree view states of recent files Restore previous window geometry Features Available Fonctionnalités disponibles Open files in new windows Ouverture des fichiers dans de nouvelles fenetres Click node to rename Rename new nodes when created Renommer les nouveaux noeuds quand ils sont créés Tree drag && drop available Glisser && déposer l'arborescence disponible dans le volet d'exploration Show icons in the tree view Afficher les icônes dans le volet d'exploration Show math fields in the Data Edit view Show numbering fields in the Data Edit view Undo Memory Mémoire utilisée pour la fonctionnalité "Annuler" Number of undo levels Nombre de niveaux d'annulation Auto Save Sauvegarde automatique Minutes between saves (set to 0 to disable) Recent Files Fichiers récents Number of recent files in the file menu Data Editor Formats Formats de l'Editeur de Données Times Heures Dates Dates First day of week Appearance Apparence Child indent offset (in font height units) Show breadcrumb ancestor view Show child pane in right hand views Remove inaccessible recent file entries Activate data editors on mouse hover Minimize application to system tray Indent (pretty print) TreeLine JSON files Limit data editor height to window size options Choose configuration file location User's home directory (recommended) Program directory (for portable use) &OK &OK &Cancel &Annuler printdata Error initializing printer Erreur à l'initialisation de l'imprimante TreeLine - Export PDF Warning: Page size and margin settings unsupported on current printer. Save page adjustments? Warning: Page size setting unsupported on current printer. Save adjustment? Warning: Margin settings unsupported on current printer. Save adjustments? printdialogs Print Preview AperçuAvantImpression &Print... &Imprimer.... &General Options Options &Générales &Font Selection &Sélection Police &Header/Footer &En−tête/PiedDePage Print Pre&view... Aperçu a&vant impression... &OK &OK &Cancel &Annuler What to print Qu'imprimer  &Entire tree Arbre &Entier Selected &branches &Branches sélectionnées Selected &nodes &NÅ“uds sélectionnés Features Fonctionnalités &Include root node &Inclure le nÅ“ud racine &Keep first child with parent &Garder le premier enfant avec le parent Letter (8.5 x 11 in.) Lettre (8.5 × 11 pouces)  Legal (8.5 x 14 in.) Légal (8.5 × 14 pouces) Tabloid (11 x 17 in.) Tabloïde (11 × 17 pouces) A3 (279 x 420 mm) A3 (279 × 420 mm) A4 (210 x 297 mm) A4 (210 × 297 mm) A5 (148 x 210 mm) A5 (148 × 210 mm) Paper &Size &Taille papier Orientation Orientation &Units &Unités Columns Colonnes &Number of columns &Nombre de colonnes Default Font Police par défaut Select Font Sélectionner police &Font &Police Font st&yle St&yle de police Sample Exemple &Header Left &En-tête gauche Header C&enter En-tête C&entré Footer &Left Pied de page &Gauche Footer Ce&nter Pied de page Ce&ntré Fiel&ds Cham&ps Header and Footer En-tête et Pied de pages Extra Text Texte Supplémentaire &Prefix &Préfixe Format &Help Format de &l'Aide Fit Width Fit Page Zoom In Zoom Out Previous Page Next Page Single Page Facing Pages Print Setup Print Printing Setup Page &Setup Included Nodes Onl&y open node children &Draw lines to children Indent Indent Offse&t (line height units) Custom Size Inches (in) Millimeters (mm) Centimeters (cm) &Width: Height: Portra&it Lan&dscape Margins &Left: &Top: &Right: &Bottom: He&ader: Foot&er: Space between colu&mns &Use TreeLine output view font Si&ze AaBbCcDdEeFfGg...TtUuVvWvXxYyZz Header &Right Footer Righ&t Field For&mat Field Format for "{0}" Output &Format &Suffix Error: Page size or margins are invalid TreeLine PDF Printer Select &Printer recentfiles spellcheck Could not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? Spell Check Error Erreur Correction Orthographe Locate aspell.exe, ipsell.exe or hunspell.exe Program (*.exe) Programme (*.exe) TreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed TreeLine Spell Check Vérification Orthographique TreeLIne Finished spell checking Spell Check Vérification orthographique Not in Dictionary Pas dans le dictionnaire Word: Mot: Context: Contexte: Suggestions Suggestions Ignor&e Ignor&er &Ignore All &Ignorer Tout &Add &Ajouter Add &Lowercase Ajouter &Minuscule &Replace &Remplacer Re&place All Rem&placer Tout &Cancel &Annuler Finished checking the branch Continue from the top? titlelistview Select in Tree treeformats DEFAULT DEFAUT FILE TYPE FIELD FieldType TitleFormat OutputFormat SpaceBetween FormatHtml Bullets Table ChildType Icon Icône GenericType ConditionalRule ListSeparator ChildTypeLimit Format Prefix Suffix InitialValue NumLines SortKeyNum SortForward EvalHtml treelocalcontrol Error - could not delete backup file {} Save changes to {}? Save changes? Enregistrer les changements? &Save &Enregistrer Save File Enregistrer Fichier Save the current file Save &As... Enregistrer &Sous... Save the file with a new name Enregistrer le fichier sous un nouveau nom &Export... &Exporter... Export the file in various other formats Prop&erties... Set file parameters like compression and encryption P&rint Setup... Set margins, page size and other printing options Print Pre&view... Aperçu a&vant impression... Show a preview of printing results Montrer l'aperçu de l'impression &Print... &Imprimer.... Print tree output based on current options Print &to PDF... Export to PDF with current printing options &Undo &Annuler Undo the previous action Annuler l'action précédente &Redo &Rétablir Redo the previous undo Rétablir l'annulation précédente Cu&t Co&uper Cut the branch or text to the clipboard Couper la branche ou le texte dans le presse-papier &Copy &Copier Copy the branch or text to the clipboard Copier la branche ou le texte dans le presse-papier &Paste C&oller Paste nodes or text from the clipboard Coller les noeuds ou le texte dans le presse-papier Paste non-formatted text from the clipboard &Bold Font Set the current or selected font to bold &Italic Font Set the current or selected font to italic U&nderline Font Set the current or selected font to underline &Font Size Set size of the current or selected text Small Default Large Larger Largest Set Font Size Font C&olor... Set the color of the current or selected text &External Link... Add or modify an extrnal web link Internal &Link... Add or modify an internal node link Clear For&matting Clear current or selected text formatting &Rename Rename the current tree entry title Insert Sibling &Before Insérer Frère A&vant Insert new sibling before selection Insérer le nouveau frère avant la sélection Insert Sibling &After Insérer Frère Apr&ès Insert new sibling after selection Insérer le nouveau frère après la sélection Add &Child Add new child to selected parent &Delete Node &Supprimer Noeud Delete the selected nodes Supprimer les noeuds sélectionnés &Indent Node Inden&ter Noeud Indent the selected nodes Indenter les noeuds sélectionnés &Unindent Node Unindent the selected nodes Désindenter les noeuds sélectionnés &Move Up &Déplacer En &haut Move the selected nodes up Déplacer les noeuds sélectionnés vers le haut M&ove Down D&éplacer En bas Move the selected nodes down Déplacer les noeuds sélectionnés vers le bas Move &First Déplacer &premier Move the selected nodes to be the first children Déplacer les nÅ“uds sélectionnés comme premier enfant Move &Last Déplacer &dernier Move the selected nodes to be the last children Déplacer les nÅ“uds sélectionnés comme dernier enfant &Set Node Type Set the node type for selected nodes Set Node Type Copy Types from &File... Copy the configuration from another TreeLine file Copier la configuration à partir d'un autre fichier TreeLine Flatten &by Category Collapse descendants by merging fields Add Category &Level... Insert category nodes above children Insérer les noeuds du classement au-dessus des fils &Spell Check... &New Window j&Nouvelle Fenetre Open a new window for the same file Error - could not write to {} TreeLine - Save As Error - could not write to file TreeLine - Open Configuration File Error - could not read file {0} Cannot expand without common fields Impossible de développer sans champs communs Category Fields Champ du Classement Select fields for new level Sélection des champs pour le nouveau niveau File saved Pa&ste Plain Text Paste C&hild Paste a child node from the clipboard Paste Sibling &Before Paste a sibling before selection Paste Sibling &After Paste a sibling after selection Paste Cl&oned Child Paste a child clone from the clipboard Paste Clo&ned Sibling Before Paste a sibling clone before selection Paste Clone&d Sibling After Paste a sibling clone after selection Clone All &Matched Nodes Convert all matching nodes into clones &Detach Clones Detach all cloned nodes in current branches S&wap Category Levels Swap child and grandchild category nodes Converted {0} branches into clones No identical nodes found Warning - file corruption! Skipped bad child references in the following nodes: Spell check the tree's text data &Regenerate References Force update of all conditional types & math fields Insert &Date Insert current date as text St&rikethrough Font Set the current or selected font to strikethough treemaincontrol Warning: Could not create local socket Error - could not write config file to {} Error - could not read file {0} Backup file "{}" exists. A previous session may have crashed &Restore Backup &Restaure Sauvegarde &Delete Backup &Supprime Sauvegarde &Cancel File Open &Annule Fichier Ouvert Error - could not rename "{0}" to "{1}" Error - could not remove backup file {} &New... &Nouveau… New File Nouveau Fichier Start a new file Commencer un nouveau fichier &Open... &Ouvir... Open File Ouvrir Fichier Open a file from disk Ouvrir un ficier à partir du disque Open Sa&mple... Ouvrir Exa&mple... Open Sample Open a sample file &Import... Open a non-TreeLine file &Quit &Quitter Exit the application Quitter l'application &Select All Select all text in an editor &Configure Data Types... &Paramètres du Type de Données... Modify data types, fields & output lines Modifier les types de données, les champs & les lignes en sortie Sor&t Nodes... Define node sort operations Update &Numbering... Update node numbering fields &Find Text... Find text in node titles & data &Conditional Find... Use field conditions to find nodes Find and &Replace... Replace text strings in node data &Text Filter... Filter nodes to only show text matches C&onditional Filter... Use field conditions to filter nodes &General Options... &Options Générales... Set user preferences for all files Configurer les préférences utilisateur pour tous les fichiers Set &Keyboard Shortcuts... Fixe les raccourcis &claviers... Customize keyboard commands Personnalise les commandes au clavier C&ustomize Toolbars... Customize toolbar buttons Personnalise les boutons des barres d'outils Customize Fo&nts... Customize fonts in various views &Basic Usage... Display basic usage instructions &Full Documentation... Open a TreeLine file with full documentation &About TreeLine... Display version info about this program &Select Template &Sélectionner un modèle TreeLine - Open File Open Sample File &Select Sample Conditional Find Conditional Filter Filtre conditionnel General Options Options Générales Error - basic help file not found TreeLine Basic Usage Error - documentation file not found Error - invalid TreeLine file {0} TreeLine version {0} written by {0} Library versions: missing directory Show C&onfiguration Structure... Show read-only visualization of type structure Custo&mize Colors... Customize GUI colors and themes treemodel treenode New Nouveau treestructure Main Base treeview Filtering by "{0}", found {1} nodes Conditional filtering, found {0} nodes Search for: Search for: {0} Search for: {0} (not found) Next: {0} Next: {0} (not found) treewindow Data Output Sortie des données Data Edit Title List Liste des titres &Expand Full Branch &Développer Toute la Branche Expand all children of the selected nodes &Collapse Full Branch &Réduire Toute la Branche Collapse all children of the selected nodes &Previous Selection Sélection &Précédente Return to the previous tree selection &Next Selection &Sélection suivante Go to the next tree selection in history Show Data &Output Montrer une &sortie des données Show data output in right view Afficher le volet de données dans la vue de droite Show Data &Editor Afficher l'&Editeur de Données Show data editor in right view Afficher l'éditeur de données dans la vue de droite Show &Title List Show title list in right view Afficher la liste des titres dans la vue de droite &Show Child Pane Toggle showing right-hand child views Toggle showing output view indented descendants &Close Window &Fermer la fenetre Close this window &File &Fichier &Edit &Editer &Node &Data &Données &Tools &Outils &View &Affichage &Window &Fenetre &Help A&ide Start Incremental Search Next Incremental Search Previous Incremental Search Show &Breadcrumb View Toggle showing breadcrumb ancestor view Show Output &Descendants Fo&rmat colorset Dialog background color Dialog text color Text widget background color Text widget foreground color Selected item background color Selected item text color Link text color Tool tip background color Tool tip foreground color Button background color Button text color Disabled text foreground color Disabled button text color Color Settings Color Theme Default system theme Dark theme Custom theme &OK &OK &Cancel &Annuler Custom Colors Theme Colors Select {0} color TreeLine-3.2.1/working/translations/treeline_it.ts000066400000000000000000005544431506556630100223260ustar00rootroot00000000000000 conditional starts with ends with contains True False and or [All Types] Node Type &Add New Rule &Remove Rule &OK &Cancel Find &Previous Find &Next &Filter &End Filter &Close No conditional matches were found Rule {0} Saved Rules Name: &Load &Save &Delete configdialog Configure Data Types T&ype List Typ&e Config Field &List &Field Config O&utput &Show Advanced &OK &Apply &Reset &Cancel &Hide Advanced Error - circular reference in math field equations Add or Remove Data Types &New Type... Co&py Type... Rena&me Type... &Delete Type Add Type Enter new type name: Copy Type &Derive from original Rename Type Rename from {} to: Cannot delete data type being used by nodes [None] no type set &Data Type Default Child &Type Icon Change &Icon Output Options Add &blank lines between nodes Allow &HTML rich text in format Add text bullet&s Use a table for field &data Combination && Child List Output &Separator Derived from &Generic Type Automatic Types None Modify Co&nditional Types Create Co&nditional Types Set Types Conditionally Modify &Field List Name Type Sort Key Move U&p Move Do&wn &New Field... Rena&me Field... Dele&te Field Sort &Keys... fwd rev Add Field Enter new field name: Rename Field File Info Reference F&ield &Field Type Outpu&t Format Format &Help Extra Text &Prefix Suffi&x Default &Value for New Nodes Editor Height Num&ber of text lines Math Equation Define Equation F&ield List &Title Format Out&put Format Other Field References Reference Le&vel Refere&nce Type The name cannot be empty The name must start with a letter The name cannot start with "xml" The name cannot contain spaces The following characters are not allowed: {} The name was already used Set Data Type Icon Clear &Select forward reverse Sort Key Fields Available &Fields &Sort Criteria Field Direction Move &Up &Move Down Flip &Direction Self Reference Parent Reference Root Reference Child Reference Child Count Date Result Time Result Boolean Result Text Result Arithmetic Operators Comparison Operators Text Operators add subtract multiply divide floor divide modulus power sum of items maximum minimum average absolute value square root natural logarithm base-10 logarithm factorial round to num digits lower integer higher integer truncated integer floating point sine of radians cosine of radians tangent of radians arc sine arc cosine arc tangent radians to degrees degrees to radians pi constant natural log constant equal to less than greater than less than or equal to greater than or equal to not equal to true value, condition, false value logical and logical or true if 1st text arg starts with 2nd arg true if 1st text arg ends with 2nd arg true if 1st text arg contains 2nd arg concatenate text join text using 1st arg as separator convert text to upper case convert text to lower case in 1st arg, replace 2nd arg with 3rd arg Define Math Field Equation Field References Reference &Level Reference &Type Available &Field List &Result Type Operations O&perator Type Oper&ator List Description &Equation Equation error: {} Output HTML Evaluate &HTML tags Child Type Limits [All Types Available] &Select All Select &None Number Result Count Number of Children dataeditors Today's &Date &Open Link Open &Folder External Link Scheme &Browse for File File Path Type Absolute Relative Address Display Name &OK &Cancel TreeLine - External Link File &Go to Target Internal Link &Open Picture Picture Link TreeLine - Picture File Set to &Now Clear &Link (Click link target in tree) link exports Bookmarks TreeLine - Export HTML TreeLine - Export Text Titles TreeLine - Export Plain Text TreeLine - Export Text Tables TreeLine - Export Generic XML TreeLine - Export TreeLine Subtree TreeLine - Export ODF Text TreeLine - Export HTML Bookmarks TreeLine - Export XBEL Bookmarks &HTML &Text &ODF Outline Book&marks &Single HTML page Single &HTML page with navigation pane Multiple HTML &pages with navigation pane Multiple HTML &data tables &Tabbed title text &Unformatted output of all text &HTML format bookmarks &XBEL format bookmarks File Export Choose export format type Choose export format subtype Choose export options What to Export &Entire tree Selected &branches Selected &nodes Other Options &Only open node children Include &print header && footer &Columns Navigation pane &levels Error - export template files not found. Check your TreeLine installation. Error - cannot link to unsaved TreeLine file. Save the file and retry. Warning - no relative path from "{0}" to "{1}". Continue with absolute path? Parent Tree&Line &XML (generic) Live tree view, linked to TreeLine file (for web server) Live tree view, single file (embedded data) &Comma delimited (CSV) table of descendants (level numbers) Comma &delimited (CSV) table of children (single level) Tab &delimited table of children (&single level) &Old TreeLine (2.0.x) &TreeLine Subtree &Include root nodes Must select nodes prior to export fieldformat Text HtmlText OneLineText SpacedText Number Math Numbering Boolean Date Time Choice AutoChoice Combination AutoCombination ExternalLink InternalLink Picture RegularExpression Now Optional Digit # Required Digit 0 Digit or Space (external) <space> Decimal Point . Decimal Comma , Space Separator (internal) <space> Optional Sign - Required Sign + Exponent (capital) E Exponent (small) e Number 1 Capital Letter A Small Letter a Capital Roman Numeral I Small Roman Numeral i Level Separator / Section Separator . "/" Character // "." Character .. Outline Example I../A../1../a)/i) Section Example 1.1.1.1 Separator / Example 1/2/3/4 yes/no true/false T/F Y/N Any Character . End of Text $ 0 Or More Repetitions * 1 Or More Repetitions + 0 Or 1 Repetitions ? Set of Numbers [0-9] Lower Case Letters [a-z] Upper Case Letters [A-Z] Not a Number [^0-9] Or | Escape a Special Character \ DateTime Day (1 or 2 digits) %-d Day (2 digits) %d Weekday Abbreviation %a Weekday Name %A Month (1 or 2 digits) %-m Month (2 digits) %m Month Abbreviation %b Month Name %B Year (2 digits) %y Year (4 digits) %Y Week Number (0 to 53) %-U Day of year (1 to 366) %-j Hour (0-23, 1 or 2 digits) %-H Hour (00-23, 2 digits) %H Hour (1-12, 1 or 2 digits) %-I Hour (01-12, 2 digits) %I Minute (1 or 2 digits) %-M Minute (2 digits) %M Second (1 or 2 digits) %-S Second (2 digits) %S Microseconds (6 digits) %f AM/PM %p Comma Separator \, Dot Separator \. DescendantCount genboolean true false yes no globalref TreeLine Files TreeLine Files - Compressed TreeLine Files - Encrypted All Files HTML Files Text Files XML Files ODF Text Files Treepad Files PDF Files CSV (Comma Delimited) Files All TreeLine Files Old TreeLine Files helpview Tools &Back &Forward &Home Find: Find &Previous Find &Next Text string not found imports &Tab indented text, one node per line Tab delimited text table with header &row Plain text &paragraphs (blank line delimited) Treepad &file (text nodes only) &Generic XML (non-TreeLine file) Open &Document (ODF) outline &HTML bookmarks (Mozilla Format) &XML bookmarks (XBEL format) FOLDER BOOKMARK SEPARATOR Link Text Import File Choose Import Method Invalid File "{0}" is not a valid TreeLine file. Use an import filter? TreeLine - Import File Error - could not read file {0} Error - improper format in {0} TABLE Bookmarks Too many entries on Line {0} Plain text, one &node per line (CR delimited) Bad CSV format on Line {0} Co&mma delimited (CSV) text table with level column && header row Comma delimited (CSV) text table &with header row Other Old Tree&Line File (1.x or 2.x) Invalid level number on line {0} Invalid level structure No headings found matheval Illegal "{}" characters Child references must be combined in a function Illegal syntax in equation Illegal function present: {0} Illegal object type or operator: {0} Invalid field modifiers miscdialogs &OK &Cancel Fields File Properties File Storage &Use file compression Use file &encryption Spell Check Language code or dictionary (optional) Math Fields &Treat blank fields as zeros Encrypted File Password Type Password for "{0}": Type Password: Re-Type Password: Remember password during this session Zero-length passwords are not permitted Re-typed password did not match Default - Single Line Text &Search Text What to Search Full &data &Titles only How to Search &Key words Key full &words F&ull phrase &Regular expression Find Find &Previous Find &Next Filter &Filter &End Filter &Close Error - invalid regular expression Search string "{0}" not found Find and Replace Replacement &Text Any &match Full &words Re&gular expression &Node Type N&ode Fields &Find Next &Replace Replace &All [All Types] [All Fields] Search text "{0}" not found Error - replacement failed Replaced {0} matches Sort Nodes What to Sort &Entire tree Selected &branches Selection's childre&n Selection's &siblings Sort Method &Predefined Key Fields Node &Titles Sort Direction &Forward &Reverse &Apply Update Node Numbering What to Update &Selection's children Root Node Include top-level nodes Handling Nodes without Numbering Fields &Ignore and skip &Restart numbers for next siblings Reserve &numbers TreeLine Numbering No numbering fields were found in data types File Menu File Edit Menu Edit Node Menu Node Data Menu Data Tools Menu Tools View Menu View Window Menu Window Help Menu Help Keyboard Shortcuts &Restore Defaults Key {0} is already used Clear &Key --Separator-- Customize Toolbars Toolbar &Size Small Icons Large Icons Toolbar Quantity &Toolbars A&vailable Commands Tool&bar Commands Move &Up Move &Down Tree View Font Output View Font Editor View Font No menu TreeLine - Serious Error A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. Format Menu Format Customize Fonts &Use system default font App Default Font &Use app default font Externally Modified File &Overwrite File &Cancel Save File was externally modified at {} nodeformat Name optiondefaults Monday Tuesday Wednesday Thursday Friday Saturday Sunday Startup Condition Automatically open last file used Show descendants in output view Restore tree view states of recent files Restore previous window geometry Features Available Open files in new windows Click node to rename Rename new nodes when created Tree drag && drop available Show icons in the tree view Show math fields in the Data Edit view Show numbering fields in the Data Edit view Undo Memory Number of undo levels Auto Save Minutes between saves (set to 0 to disable) Recent Files Number of recent files in the file menu Data Editor Formats Times Dates First day of week Appearance Child indent offset (in font height units) Show breadcrumb ancestor view Show child pane in right hand views Remove inaccessible recent file entries Activate data editors on mouse hover Minimize application to system tray Indent (pretty print) TreeLine JSON files Limit data editor height to window size options Choose configuration file location User's home directory (recommended) Program directory (for portable use) &OK &Cancel printdata Error initializing printer TreeLine - Export PDF Warning: Page size and margin settings unsupported on current printer. Save page adjustments? Warning: Page size setting unsupported on current printer. Save adjustment? Warning: Margin settings unsupported on current printer. Save adjustments? printdialogs Print Preview Fit Width Fit Page Zoom In Zoom Out Previous Page Next Page Single Page Facing Pages Print Setup Print Printing Setup &General Options Page &Setup &Font Selection &Header/Footer Print Pre&view... &Print... &OK &Cancel What to print &Entire tree Selected &branches Selected &nodes Included Nodes &Include root node Onl&y open node children Features &Draw lines to children &Keep first child with parent Indent Indent Offse&t (line height units) Letter (8.5 x 11 in.) Legal (8.5 x 14 in.) Tabloid (11 x 17 in.) A3 (279 x 420 mm) A4 (210 x 297 mm) A5 (148 x 210 mm) Custom Size Inches (in) Millimeters (mm) Centimeters (cm) &Units Paper &Size &Width: Height: Orientation Portra&it Lan&dscape Margins &Left: &Top: &Right: &Bottom: He&ader: Foot&er: Columns &Number of columns Space between colu&mns Default Font &Use TreeLine output view font Select Font &Font Font st&yle Si&ze Sample AaBbCcDdEeFfGg...TtUuVvWvXxYyZz &Header Left Header C&enter Header &Right Footer &Left Footer Ce&nter Footer Righ&t Fiel&ds Field For&mat Header and Footer Field Format for "{0}" Output &Format Format &Help Extra Text &Prefix &Suffix Error: Page size or margins are invalid TreeLine PDF Printer Select &Printer spellcheck Could not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? Spell Check Error Locate aspell.exe, ipsell.exe or hunspell.exe Program (*.exe) TreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed TreeLine Spell Check Finished spell checking Spell Check Not in Dictionary Word: Context: Suggestions Ignor&e &Ignore All &Add Add &Lowercase &Replace Re&place All &Cancel Finished checking the branch Continue from the top? titlelistview Select in Tree treeformats DEFAULT FILE TYPE FIELD FieldType TitleFormat OutputFormat SpaceBetween FormatHtml Bullets Table ChildType Icon GenericType ConditionalRule ListSeparator ChildTypeLimit Format Prefix Suffix InitialValue NumLines SortKeyNum SortForward EvalHtml treelocalcontrol Error - could not delete backup file {} Save changes to {}? Save changes? &Save Save File Save the current file Save &As... Save the file with a new name &Export... Export the file in various other formats Prop&erties... Set file parameters like compression and encryption P&rint Setup... Set margins, page size and other printing options Print Pre&view... Show a preview of printing results &Print... Print tree output based on current options Print &to PDF... Export to PDF with current printing options &Undo Undo the previous action &Redo Redo the previous undo Cu&t Cut the branch or text to the clipboard &Copy Copy the branch or text to the clipboard &Paste Paste nodes or text from the clipboard Paste non-formatted text from the clipboard &Bold Font Set the current or selected font to bold &Italic Font Set the current or selected font to italic U&nderline Font Set the current or selected font to underline &Font Size Set size of the current or selected text Small Default Large Larger Largest Set Font Size Font C&olor... Set the color of the current or selected text &External Link... Add or modify an extrnal web link Internal &Link... Add or modify an internal node link Clear For&matting Clear current or selected text formatting &Rename Rename the current tree entry title Insert Sibling &Before Insert new sibling before selection Insert Sibling &After Insert new sibling after selection Add &Child Add new child to selected parent &Delete Node Delete the selected nodes &Indent Node Indent the selected nodes &Unindent Node Unindent the selected nodes &Move Up Move the selected nodes up M&ove Down Move the selected nodes down Move &First Move the selected nodes to be the first children Move &Last Move the selected nodes to be the last children &Set Node Type Set the node type for selected nodes Set Node Type Copy Types from &File... Copy the configuration from another TreeLine file Flatten &by Category Collapse descendants by merging fields Add Category &Level... Insert category nodes above children &Spell Check... &New Window Open a new window for the same file Error - could not write to {} File saved TreeLine - Save As Error - could not write to file TreeLine - Open Configuration File Error - could not read file {0} Cannot expand without common fields Category Fields Select fields for new level Pa&ste Plain Text Paste C&hild Paste a child node from the clipboard Paste Sibling &Before Paste a sibling before selection Paste Sibling &After Paste a sibling after selection Paste Cl&oned Child Paste a child clone from the clipboard Paste Clo&ned Sibling Before Paste a sibling clone before selection Paste Clone&d Sibling After Paste a sibling clone after selection Clone All &Matched Nodes Convert all matching nodes into clones &Detach Clones Detach all cloned nodes in current branches S&wap Category Levels Swap child and grandchild category nodes Converted {0} branches into clones No identical nodes found Warning - file corruption! Skipped bad child references in the following nodes: Spell check the tree's text data &Regenerate References Force update of all conditional types & math fields Insert &Date Insert current date as text St&rikethrough Font Set the current or selected font to strikethough treemaincontrol Warning: Could not create local socket Error - could not write config file to {} Error - could not read file {0} Backup file "{}" exists. A previous session may have crashed &Restore Backup &Delete Backup &Cancel File Open Error - could not rename "{0}" to "{1}" Error - could not remove backup file {} &New... New File Start a new file &Open... Open File Open a file from disk Open Sa&mple... Open Sample Open a sample file &Import... Open a non-TreeLine file &Quit Exit the application &Select All Select all text in an editor &Configure Data Types... Modify data types, fields & output lines Sor&t Nodes... Define node sort operations Update &Numbering... Update node numbering fields &Find Text... Find text in node titles & data &Conditional Find... Use field conditions to find nodes Find and &Replace... Replace text strings in node data &Text Filter... Filter nodes to only show text matches C&onditional Filter... Use field conditions to filter nodes &General Options... Set user preferences for all files Set &Keyboard Shortcuts... Customize keyboard commands C&ustomize Toolbars... Customize toolbar buttons Customize Fo&nts... Customize fonts in various views &Basic Usage... Display basic usage instructions &Full Documentation... Open a TreeLine file with full documentation &About TreeLine... Display version info about this program &Select Template TreeLine - Open File Open Sample File &Select Sample Conditional Find Conditional Filter General Options Error - basic help file not found TreeLine Basic Usage Error - documentation file not found Error - invalid TreeLine file {0} TreeLine version {0} written by {0} Library versions: missing directory Show C&onfiguration Structure... Show read-only visualization of type structure Custo&mize Colors... Customize GUI colors and themes treenode New treestructure Main treeview Filtering by "{0}", found {1} nodes Conditional filtering, found {0} nodes Search for: Search for: {0} Search for: {0} (not found) Next: {0} Next: {0} (not found) treewindow Data Output Data Edit Title List &Expand Full Branch Expand all children of the selected nodes &Collapse Full Branch Collapse all children of the selected nodes &Previous Selection Return to the previous tree selection &Next Selection Go to the next tree selection in history Show Data &Output Show data output in right view Show Data &Editor Show data editor in right view Show &Title List Show title list in right view &Show Child Pane Toggle showing right-hand child views Toggle showing output view indented descendants &Close Window Close this window &File &Edit &Node &Data &Tools &View &Window &Help Start Incremental Search Next Incremental Search Previous Incremental Search Show &Breadcrumb View Toggle showing breadcrumb ancestor view Show Output &Descendants Fo&rmat colorset Dialog background color Dialog text color Text widget background color Text widget foreground color Selected item background color Selected item text color Link text color Tool tip background color Tool tip foreground color Button background color Button text color Disabled text foreground color Disabled button text color Color Settings Color Theme Default system theme Dark theme Custom theme &OK &Cancel Custom Colors Theme Colors Select {0} color TreeLine-3.2.1/working/translations/treeline_pt.ts000066400000000000000000005675531506556630100223430ustar00rootroot00000000000000 conditional starts with começa com ends with acaba com contains contém True Verdadeiro False Falso and e or ou Node Type Tipo de ramo &Add New Rule Adicionar &Nova Regra &Remove Rule &Eliminar Regra &OK &OK &Cancel &Cancelar Find &Previous Encontrar &Anterior Find &Next Encontrar &Seguinte &Filter F&iltrar &End Filter &Terminar Filtragem &Close &Fechar No conditional matches were found Nenhum resultado satisfaz as condições Rule {0} Regra {0} [All Types] [Todos os Tipos] Saved Rules Name: &Load &Save &Guardar &Delete configdialog Configure Data Types Configurar Tipos de Dados T&ype List &Lista de Tipos Typ&e Config Configuração de &Tipos Field &List Lista de &Campos &Field Config C&onfiguração de Campos O&utput &Apresentação &Show Advanced &Mostrar Avançadas &OK &OK &Apply &Aplicar &Reset &Repor &Cancel &Cancelar &Hide Advanced &Ocultar Avançadas Error - circular reference in math field equations Erro - referência cíclica em equações de campos matemáticos Add or Remove Data Types Adicionar ou Remover Tipos de Dados &New Type... &Novo Tipo... Co&py Type... Co&piar Tipo... Rena&me Type... &Mudar o Nome... &Delete Type &Eliminar Tipo Add Type Adicionar Tipo Enter new type name: Introduza novo nome para o tipo: Copy Type Copiar Tipo &Derive from original &Derivadar de Original Rename Type Mudar Nome a Tipo Rename from {} to: Mudar nome de {} para: Cannot delete data type being used by nodes Não é possivel apagar tipo de dados em utilização por ramos [None] no type set [Nenhum] &Data Type Tipo de &Dados Default Child &Type Tipo de &descendente pré definido Icon Ã�cone Change &Icon Mudar &Ã�cone Output Options Opções de apresentação Add &blank lines between nodes Adicionar linhas &vazias entre ramos Allow &HTML rich text in format Permitir texto formatado em &HTML Add text bullet&s Adicionar &pontos de tópico Use a table for field &data &Utilizar uma tabela para dados dos campos Combination && Child List Output &Separator Carácter de &Separação de Combinações e Lista de Descendentes Derived from &Generic Type &Derivado de Tipo Genérico Automatic Types Tipos Automáticos None Nenhum Modify Co&nditional Types &Modificar Tipos Condicionais Create Co&nditional Types &Criar Tipos Condicionais Set Types Conditionally Definir tipos condicionalmente Modify &Field List &Modificar Lista de Campos Name Nome Type Tipo Sort Key Prioridade de Ordenamento Move U&p Mover para &cima Move Do&wn Mover para &Baixo &New Field... &Novo Campo... Rena&me Field... M&udar Nome... Dele&te Field &Eliminar Campo Sort &Keys... &Prioridade de Ordenamento... fwd Descendente rev Ascendente Add Field Adicionar Campo Enter new field name: Introduza o nome do novo campo: Rename Field Mudar Nome File Info Reference Informação sobre o ficheiro F&ield Ca&mpo &Field Type T&ipo de Campo Outpu&t Format &Formato de Apresentação Format &Help &Ajuda de Formato Extra Text Texto adicional &Prefix &Prefixo Suffi&x &Sufixo Default &Value for New Nodes Valor pré &definido para novos ramos Editor Height Altura da Caixa de Introdução Num&ber of text lines &Número de linhas de texto Math Equation Equação Matemática Define Equation Definir Equação F&ield List Li&sta de Campos &Title Format &Formatação do Título Out&put Format &Formatação de Apresentação Other Field References Referências a outros campo Reference Le&vel &Nível de Referência Refere&nce Type &Tipo de Referência The name cannot be empty O nome não pode ser vazio The name must start with a letter O nome deve começar com uma letra The name cannot start with "xml" O nome não pode começar com "xml" The name cannot contain spaces O nome não pode conter espaços The following characters are not allowed: {} Os seguintes carácteres não são permitidos: {} The name was already used Nome já em utilização Set Data Type Icon Definir Ã�cone do Tipo de Dados Clear &Select &Limpar Selecção forward Descendente reverse Ascendente Sort Key Fields Campos de Ordenamento Available &Fields Campos &Disponíveis &Sort Criteria &Critério de Ordenamento Field Campo Direction Direcção Move &Up Mover para &Cima &Move Down Mover para &Baixo Flip &Direction &Inverter Direcção Self Reference Auto Referência Parent Reference Referência a Ascendentes Child Reference Referência a Descendentes Child Count Número de Descendentes add adicionar subtract subtrair multiply multiplicar divide dividir floor divide Divisão arredondada modulus resto power potência sum of items sumatório maximum máximo minimum mínimo average média absolute value valor absoluto square root raiz quadrada natural logarithm logarítmo natural base-10 logarithm logarítmo de base 10 factorial factorial round to num digits arredondar para x dígitos lower integer inteiro inferior higher integer inteiro superior truncated integer inteiro truncado floating point ponto flutuante sine of radians seno de radianos cosine of radians coseno de radianos tangent of radians tangente de radianos arc sine arco seno arc cosine arco coseno arc tangent arco tangente radians to degrees radianos para graus degrees to radians graus para radianos pi constant constante pi natural log constant constante logarítmo natural Define Math Field Equation Definir equação do campo matemático Field References Referências a Campos Reference &Level &Nível de Referência Reference &Type &Tipo de Referência Description Descrição &Equation &Equação Equation error: {} Erro na equação: {} Root Reference Referência à Raiz Date Result Resultado de Data Time Result Resultado de Tempo Available &Field List Lista de &Campos Disponíveis &Result Type &Tipo de Resultados Boolean Result Resultado Boleano Text Result Resultado Textual Arithmetic Operators Operadores Aritméticos Comparison Operators Operadores de Comparação Text Operators Operadores de Texto equal to igual a less than menor que greater than maior que less than or equal to menor ou igual a greater than or equal to maior ou igual not equal to diferente de true value, condition, false value valor verdadeiro, condição, valor falso true if 1st text arg starts with 2nd arg verdadeiro se o 1º argumento de texto começar com o 2º argumento true if 1st text arg ends with 2nd arg verdadeiro se o 1º argumento de texto terminar com o 2º argumento true if 1st text arg contains 2nd arg verdadeiro se o 1º argumento de texto contiver o 2º argumento concatenate text concatenar texto join text using 1st arg as separator juntar texto utilizando o primeiro argumento como separador convert text to upper case converter texto para maiúsculas convert text to lower case converter texto para minúsculas in 1st arg, replace 2nd arg with 3rd arg no 1º argumento, substituir o 2º argumento pelo 3º argumento Operations Operações O&perator Type &Tipo de Operador Oper&ator List &Lista de Operadores logical and e lógico logical or ou lógico Output HTML Evaluate &HTML tags Child Type Limits [All Types Available] &Select All &Seleccionar Tudo Select &None Number Result Count Number of Children dataeditors Today's &Date Data de &Hoje &Open Link &Abrir Ligação External Link Ligação Externa Scheme Protocolo &Browse for File Procurar &Ficheiro File Path Type Tipo de Caminho para o Ficheiro Absolute Absoluto Relative Relativo Address Endereço Display Name Texto de Apresentação &OK &OK &Cancel &Cancelar TreeLine - External Link File TreeLine - Ligação para Ficheiro Externo &Go to Target &Ir para Destino Internal Link Ligação Interna &Open Picture &Abrir Imagem Picture Link Ligação para imagem TreeLine - Picture File TreeLine - Ficheiro de Imagem Open &Folder Abrir &Pasta Set to &Now Clear &Link (Click link target in tree) link dataeditview exports Bookmarks Favoritos TreeLine - Export HTML TreeLine - Exportar HTML TreeLine - Export Text Titles TreeLine - Exportar Texto de Títulos TreeLine - Export Plain Text TreeLine - Exportar Texto Simples TreeLine - Export Text Tables TreeLine - Exportar Tabelas de Texto TreeLine - Export Generic XML TreeLine - Exportar XML Genérico TreeLine - Export TreeLine Subtree TreeLine - Exportar Sub Ã�rvore TreeLine TreeLine - Export ODF Text TreeLine - Exportar Texto ODF TreeLine - Export HTML Bookmarks TreeLine - Exportar Favoritos em HTML TreeLine - Export XBEL Bookmarks TreeLine - Exportar Favoritos em XBEL &HTML &HTML &Text &Texto &ODF Outline Ã�ndice &ODF Book&marks &Favoritos &Single HTML page HTML Página &Única Single &HTML page with navigation pane HTML página única com barra de &navegação Multiple HTML &pages with navigation pane &Multiplas páginas HTML com barra de navegação Multiple HTML &data tables Multiplas páginas HTML com &tabelas de informação &Tabbed title text &Títulos separados por tabulação &Unformatted output of all text Conteúdo não &formatado para todos os textos &HTML format bookmarks Favoritos em formato &HTML &XBEL format bookmarks Favoritos em formato &XBEL File Export Exportação de ficheiros Choose export format type Escolha o formato de exportação Choose export format subtype Escolha o subtipo do formato de exportação Choose export options Escolha as opções de exportação What to Export O que exportar &Entire tree Ã�rvore &Inteira Selected &branches &Subramos Seleccionados Selected &nodes &Ramos Seleccionados Other Options Outras Opções &Only open node children &Apenas descendentes expandidos Include &print header && footer Incluir &cabeçalho e rodapé de impressão &Columns &Colunas Navigation pane &levels &Níveis da barra de navegação Error - export template files not found. Check your TreeLine installation. Error - cannot link to unsaved TreeLine file. Save the file and retry. Warning - no relative path from "{0}" to "{1}". Continue with absolute path? Parent Tree&Line &XML (generic) Live tree view, linked to TreeLine file (for web server) Live tree view, single file (embedded data) &Comma delimited (CSV) table of descendants (level numbers) Comma &delimited (CSV) table of children (single level) Tab &delimited table of children (&single level) &Old TreeLine (2.0.x) &TreeLine Subtree &Include root nodes Must select nodes prior to export fieldformat Text Texto HtmlText TextoHTML SpacedText TextoEspaçado Number Número Math Matemática Numbering Numeração Boolean Boleano Date Data Time Tempo Choice Escolha AutoChoice AutoEscolha Combination Combinação AutoCombination AutoCombinação ExternalLink LigaçãoExterna InternalLink LigaçãoInterna Picture Imagem RegularExpression ExpressãoRegular Now Agora Optional Digit # Dígito Opcional # Required Digit 0 Dígito Obrigatório 0 Digit or Space (external) <space> Dígito ou espaço (externo) <space> Decimal Point . Ponto Decimal . Decimal Comma , Vírgula Decimal , Space Separator (internal) <space> Espaço de Separação (interno) <space> Optional Sign - Sinal Opcional - Required Sign + Sinal Obrigatório + Exponent (capital) E Exponente (maiúscula) E Exponent (small) e Exponente (minúscula) e Number 1 Número 1 Capital Letter A Letra Maiúscula A Small Letter a Letra Minúscula a Capital Roman Numeral I Numeral Romano Maiúsculo I Small Roman Numeral i Numeral Romano Minúsculo i Level Separator / Separador de Nível / Section Separator . Separador de Secção . "/" Character // Carácter "/" // "." Character .. Carácter "." .. Outline Example I../A../1../a)/i) Exemplo de Ã�ndice I../A../1../a)/i) Section Example 1.1.1.1 Exemplo de Secção 1.1.1.1 Separator / Separador / Example 1/2/3/4 Exemplo 1/2/3/4 yes/no sim/não true/false verdadeiro/falso T/F V/F Y/N S/N Any Character . Qualquer carácter . End of Text $ Fim de texto $ 0 Or More Repetitions * 0 ou Mais Repetições * 1 Or More Repetitions + 1 Ou Mais Repetições + 0 Or 1 Repetitions ? 0 Ou 1 Repetições ? Set of Numbers [0-9] Conjunto de Números [0-9] Lower Case Letters [a-z] Letras Minúsculas [a-z] Upper Case Letters [A-Z] Letras Maiúsculas [A-Z] Not a Number [^0-9] Carácter não numérico [^0-9] Or | Ou | Escape a Special Character \ Terminar Carácter Especial \ OneLineText TextoLinhaUnica DateTime Day (1 or 2 digits) %-d Day (2 digits) %d Weekday Abbreviation %a Weekday Name %A Month (1 or 2 digits) %-m Month (2 digits) %m Month Abbreviation %b Month Name %B Year (2 digits) %y Year (4 digits) %Y Week Number (0 to 53) %-U Day of year (1 to 366) %-j Hour (0-23, 1 or 2 digits) %-H Hour (00-23, 2 digits) %H Hour (1-12, 1 or 2 digits) %-I Hour (01-12, 2 digits) %I Minute (1 or 2 digits) %-M Minute (2 digits) %M Second (1 or 2 digits) %-S Second (2 digits) %S Microseconds (6 digits) %f AM/PM %p Comma Separator \, Dot Separator \. DescendantCount genboolean true verdadeiro false falso yes sim no não globalref TreeLine Files Ficheiros TreeLine TreeLine Files - Compressed Ficheiros TreeLine - Comprimidos TreeLine Files - Encrypted Ficheiros TreeLine - Encriptados All Files Todos os Ficheiros HTML Files Ficheiros HTML Text Files Ficheiros de Texto XML Files Ficheiros XML ODF Text Files Ficheiros ODF Treepad Files Ficheiros Treepad PDF Files Ficheiros PDF CSV (Comma Delimited) Files All TreeLine Files Old TreeLine Files helpview Tools Ferramentas &Back &Retroceder &Forward &Avançar &Home &Início Find: Encontrar: Find &Previous Encontrar &Anterior Find &Next Encontrar &Seguinte Text string not found Texto não encontrado imports &Tab indented text, one node per line &Texto recuado por tabulação, um ramo por linha Tab delimited text table with header &row Tabela de texto delimitada por tabulação com &cabeçalhos e colunas Plain text &paragraphs (blank line delimited) &Parágrafos de texto simples (delimitados por linha em branco) Treepad &file (text nodes only) &Ficheiro Treepad (ramos de texto apenas) &Generic XML (non-TreeLine file) &XML Genérico (ficheiro não específico do TreeLine) Open &Document (ODF) outline Ã�ndice &Open Document (ODF) &HTML bookmarks (Mozilla Format) Favoritos em &HTML (Formato Mozilla) &XML bookmarks (XBEL format) &Favoritos XML (Formato XBEL) FOLDER PASTA BOOKMARK FAVORITO SEPARATOR SEPARADOR Link Ligação Text Texto Import File Importar Ficheiro Choose Import Method Escolher Método de Importação Invalid File Ficheiro Inválido "{0}" is not a valid TreeLine file. Use an import filter? "{0}" não é um ficheiro TreeLine válido. Utilizar um filtro de importação? TreeLine - Import File TreeLine - Importar Ficheiro Error - could not read file {0} Erro - não foi possível ler o ficheiro {0} Error - improper format in {0} Erro - formato de ficheiro impróprio {0} TABLE TABELA Bookmarks Favoritos Too many entries on Line {0} Plain text, one &node per line (CR delimited) Bad CSV format on Line {0} Co&mma delimited (CSV) text table with level column && header row Comma delimited (CSV) text table &with header row Other Old Tree&Line File (1.x or 2.x) Invalid level number on line {0} Invalid level structure No headings found matheval Illegal "{}" characters Carácteres "{0}" ilegais Child references must be combined in a function Referências a descendentes devem ser combinadas numa função Illegal syntax in equation Sintaxe ilegal na equação Illegal function present: {0} Função ilegal presente: {0} Illegal object type or operator: {0} Operador ou tipo de objecto ilegal: {0} Invalid field modifiers miscdialogs &OK &OK &Cancel &Cancelar Fields Campos File Properties Propriedades do Ficheiro File Storage Armazenamento do Ficheiro &Use file compression Utilizar &compressão de ficheiro Use file &encryption Utilizar &encriptação de ficheiro Spell Check Verificar Ortografia Language code or dictionary (optional) Código de linguagem ou dicionário (opcional) Math Fields Campos Matemáticos &Treat blank fields as zeros &Tratar campos vazios como zeros Encrypted File Password Palavra Passe de Ficheiro Encriptado Type Password for "{0}": Introduza a palavra passe para "{0}": Type Password: Introduza a Palavra Passe: Re-Type Password: Re-Introduza a Palavra Passe: Remember password during this session Lembrar a palavra passe durante esta sessão Zero-length passwords are not permitted Palavras passe vazias não são permitidas Re-typed password did not match Palavras passe introduzidas são diferentes Default - Single Line Text Pré definido - Texto em linha única &Search Text &Pesquisar Texto What to Search Onde pesquisar Full &data Toda a &informação &Titles only Apenas &Títulos How to Search Como pesquisar &Key words &Palavras chave parciais Key full &words Palavras chave &completas F&ull phrase &Frase completa &Regular expression &Expressão regular Find Encontrar Find &Previous Encontrar &Anterior Find &Next Encontrar &Seguinte Filter Filtrar &Filter &Filtrar &End Filter &Terminar Filtro &Close &Fechar Error - invalid regular expression Erro - Expressão Regular inválida Search string "{0}" not found Termos de pesquisa "{0}" não encontrados Find and Replace Encontrar e Substituir Replacement &Text Texto de &Substituição Any &match &Qualquer ocorrência Full &words Palavras &Completas Re&gular expression &Expressão regular &Node Type &Tipo de ramo N&ode Fields &Campos dos Ramos &Find Next Encontrar &Seguinte &Replace &Substituir Replace &All Substituir &Todos [All Types] [Todos os Tipos] [All Fields] [Todos os Campos] Search text "{0}" not found Termo de pesquisa "{0}" não encontrado Error - replacement failed Erro - substituição falhou Replaced {0} matches Foram substituidas {0} ocorrências Sort Nodes Ordenar Ramos What to Sort O que Ordenar &Entire tree &Toda a árvore Selected &branches Ramos &Seleccionados Selection's childre&n &Descendentes da selecção Selection's &siblings &Irmãos da selecção Sort Method Método de Ordenamento &Predefined Key Fields &Campos de ordenamento pré definidos Node &Titles Títulos dos &Ramos Sort Direction Direcção de Ordenamento &Forward &Ascendente &Reverse &Descendente &Apply &Aplicar Update Node Numbering Actualizar Numeração dos Ramos What to Update O que Actualizar &Selection's children &Descendentes da Selecção Root Node Raiz Include top-level nodes Icluir ramos dos níveis superiores Handling Nodes without Numbering Fields Critério para Ramos sem Campos de Numeração &Ignore and skip &Ignorar e saltar &Restart numbers for next siblings &Reiniciar contagem para próximos irmãos Reserve &numbers &Reservar números TreeLine Numbering Numeração TreeLine No numbering fields were found in data types Não foram encontrados campos de numeração nos tipos de dados File Menu Menu Ficheiro File Ficheiro Edit Menu Menu Editar Edit Editar Node Menu Menu Ramo Node Ramo Data Menu Menu Informação Data Informação Tools Menu Menu Ferramentas Tools Ferramentas View Menu Menu Ver View Ver Window Menu Menu Janela Window Janela Help Menu Menu Ajuda Help Ajuda Keyboard Shortcuts Atalhos de Teclado &Restore Defaults &Restaurar pré definições Key {0} is already used Tecla {0} já em utilização Clear &Key &Remover Atalho --Separator-- --Separador-- Customize Toolbars Personalizar Barra de Ferramentas Toolbar &Size &Tamanho da Barra de Ferramentas Small Icons Ã�cones Pequenos Large Icons Ã�cones Grandes Toolbar Quantity Número de Barras de Ferramentas &Toolbars &Barras de Ferramentas A&vailable Commands Comandos &Disponíveis Tool&bar Commands Comandos da &Barra de Ferramentas Move &Up Mover para &Cima Move &Down Mover para &Baixo Tree View Font Tipo de Letra da Ã�rvore Output View Font Tipo de Letra de Apresentação Editor View Font Tipo de Letra da Vista de Edição No menu TreeLine - Serious Error A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. Format Menu Format Customize Fonts &Use system default font Utilizar fonte pré definida do &sistema App Default Font &Use app default font Externally Modified File &Overwrite File &Cancel Save File was externally modified at {} nodeformat Name Nome optiondefaults Monday Segunda-Feira Tuesday Terça-Feira Wednesday Quarta-Feira Thursday Quinta-Feira Friday Sexta-Feira Saturday Sábado Sunday Domingo Startup Condition Opções de Arranque Automatically open last file used Abrir automaticamente último ficheiro utilizado Show descendants in output view Mostrar descendentes na vista de apresentação Restore tree view states of recent files Restaurar o estado de visualização dos ficheiros recentes Restore previous window geometry Repor a anterior disposição de janelas Features Available Funcionalidades Disponíveis Open files in new windows Abrir ficheiros em novas janelas Click node to rename Clicar nos ramos para alterar nome Rename new nodes when created Editar nome de ramos após criação Tree drag && drop available Permitir arrastar e largar na vista da árvore Show icons in the tree view Mostrar ícones na vista em árvore Show math fields in the Data Edit view Mostrar campos matemáticos na Vista de Edição Show numbering fields in the Data Edit view Mostrar campos de numeração na Vista de Edição Undo Memory Memória de operações Number of undo levels Número de passos a desfazer Auto Save Gravação Automática Minutes between saves (set to 0 to disable) Minutos entre gravações (0 desactiva) Recent Files Ficheiros Recentes Number of recent files in the file menu Número de ficheiros recentes no menu ficheiro Data Editor Formats Formatos do Editor de Dados Times Tempo Dates Datas First day of week Primeiro dia da semana Appearance Aparência Child indent offset (in font height units) Recuo dos descendentes (em unidades de altura da fonte) Show breadcrumb ancestor view Show child pane in right hand views Remove inaccessible recent file entries Activate data editors on mouse hover Minimize application to system tray Indent (pretty print) TreeLine JSON files Limit data editor height to window size options Choose configuration file location Escolher localização do ficheiro de configuração User's home directory (recommended) Pasta do utilizador (recomendado) Program directory (for portable use) Pasta do programa (para utilização portátil) &OK &OK &Cancel &Cancelar printdata Error initializing printer Erro ao iniciar a impressora TreeLine - Export PDF TreeLine - Exportar PDF Warning: Page size and margin settings unsupported on current printer. Save page adjustments? Warning: Page size setting unsupported on current printer. Save adjustment? Warning: Margin settings unsupported on current printer. Save adjustments? printdialogs Print Preview Previsualização de Impressão Fit Width Ajustar à Largura Fit Page Ajustar à Página Zoom In Aproximar Zoom Out Afastar Previous Page Página Anterior Next Page Página Seguinte Single Page Página única Facing Pages Páginas Consecutivas Print Setup Definições de Impressão Print Imprimir Printing Setup Opções de impressão &General Options &Opções Gerais Page &Setup Configuração de &Página &Font Selection Selecção de &Fonte &Header/Footer &Cabeçalho/Rodapé Print Pre&view... &Previsualização de Impressão... &Print... &Imprimir... &OK &OK &Cancel &Cancelar What to print O que imprimir &Entire tree &Ã�rvore completa Selected &branches &Ramos e descendentes seleccionados Selected &nodes Ramos &Seleccioandos Included Nodes Ramos Incluídos &Include root node &Incluir Raiz Onl&y open node children Apenas descendentes de ramos &expandidos Features Opções &Draw lines to children &Desenhar linhas até descendentes &Keep first child with parent &Manter primeiro descendente com o ascendente Indent Avanço Indent Offse&t (line height units) &Distancia do Avanço (em unidades de altura de linha) Letter (8.5 x 11 in.) Carta (8.5 x 11 pol.) Legal (8.5 x 14 in.) Legal (8.5 x 14 pol.) Tabloid (11 x 17 in.) Tablóide (11 x 17 pol.) A3 (279 x 420 mm) A3 (279 x 420 mm) A4 (210 x 297 mm) A4 (210 x 297 mm) A5 (148 x 210 mm) A5 (148 x 210 mm) Custom Size Tamanho personalizado Inches (in) Polegadas (pol) Millimeters (mm) Milímetros (mm) Centimeters (cm) Centímetros (cm) &Units &Unidades Paper &Size &Tamanho do Papel &Width: &Largura: Height: Altura: Orientation Orientação Portra&it Ao &baixo Lan&dscape Ao &alto Margins Margens &Left: &Esquerda: &Top: &Topo: &Right: &Direita: &Bottom: &Base: He&ader: &Cabeçalho: Foot&er: &Rodapé: Columns Colunas &Number of columns &Número de colunas Space between colu&mns &Espaçamento entre colunas Default Font Fonte Pré Definida &Use TreeLine output view font Utilizar a fonte de apresentação do &TreeLine Select Font Seleccionar Fonte &Font &Fonte Font st&yle &Estilo de Fonte Si&ze &Tamanho Sample Amostra AaBbCcDdEeFfGg...TtUuVvWvXxYyZz AaBbCcDdEeFfGg...TtUuVvWvXxYyZz &Header Left &Esquerda do Cabeçalho Header C&enter &Centro do Cabeçalho Header &Right &Direita do Cabeçalho Footer &Left E&squerda do Rodapé Footer Ce&nter Ce&ntro do Rodapé Footer Righ&t Direi&ta do Rodapé Fiel&ds &Campos Field For&mat &Formato dos Campos Header and Footer Cabeçalho e Rodapé Field Format for "{0}" Formato de campo para "{0}" Output &Format Formato de &Apresentação Format &Help &Ajuda de Formato Extra Text Texto Extra &Prefix &Prefixo &Suffix &Sufixo Error: Page size or margins are invalid TreeLine PDF Printer Select &Printer recentfiles spellcheck Could not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? Não foi possível encontrar aspell.exe, ispell.exe ou hunspell.exe Procurar localização? Spell Check Error Erro de Verificação Ortográfica Locate aspell.exe, ipsell.exe or hunspell.exe Localizar aspell.exe, ispell.exe ou hunspell.exe Program (*.exe) Programa (*.exe) TreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed Erro de verificação Ortográfica do TreeLine Cerifique-se que aspell, ispell ou hunspell estão instalados TreeLine Spell Check Verificação Ortográfica TreeLine Finished spell checking Terminada verificação ortográfica Spell Check Verificação Ortográfica Not in Dictionary Ausente no Dicionário Word: Palavra: Context: Contexto: Suggestions Sugestões Ignor&e &Ignorar &Ignore All Ignorar &Todas &Add &Adicionar Add &Lowercase Adicionar em &Minúsculas &Replace &Substituir Re&place All S&ubstituir Todas &Cancel &Cancelar Finished checking the branch Continue from the top? titlelistview Select in Tree treeformats DEFAULT PRÉ DEFINIDO FILE TYPE FIELD FieldType TitleFormat OutputFormat SpaceBetween FormatHtml Bullets Table ChildType Icon Ã�cone GenericType ConditionalRule ListSeparator ChildTypeLimit Format Prefix Suffix InitialValue NumLines SortKeyNum SortForward EvalHtml treelocalcontrol Error - could not delete backup file {} Erro - não foi possível apagar cópia de segurança {} Save changes to {}? Guardar alterações em {}? Save changes? Guardar alterações? &Save &Guardar Save File Guardar Ficheiro Save the current file Guardar o ficheiro actual Save &As... Guardar &Como... Save the file with a new name Guardar o ficheiro com um novo nome &Export... &Exportar... Export the file in various other formats Exportar o ficheiro em diversos outros formatos Prop&erties... &Propriedades... Set file parameters like compression and encryption Definir parâmetros do ficheiro como compressão e encriptação P&rint Setup... &Definições de Impressão... Set margins, page size and other printing options Definir margens, tamanho de papel e outras opções de impressão Print Pre&view... Pré &visualizar impressão... Show a preview of printing results Mostrar uma pré visualização do resultado da impressão &Print... &Imprimir... Print tree output based on current options Imprimir apresentação da árvore baseada nas opções actuais Print &to PDF... Imprimir para &PDF... Export to PDF with current printing options Exportar para PDF com as actuais opções de impressão &Undo &Desfazer Undo the previous action Reverte a última acção &Redo &Refazer Redo the previous undo Repõe a última acção desfeita Cu&t Cor&tar Cut the branch or text to the clipboard Cortar o ramo ou texto para a memória de trabalho &Copy &Copiar Copy the branch or text to the clipboard Copiar o ramo ou texto para a memória de trabalho &Paste C&olar Paste nodes or text from the clipboard Colar ramos ou texto da memória de trabalho Paste non-formatted text from the clipboard Colar texto sem formatação da memória de trabalho &Bold Font &Negrito Set the current or selected font to bold Definir o texto actual ou seleccionado como negrito &Italic Font &Itálico Set the current or selected font to italic Definir o texto actual ou seleccionado como itálico U&nderline Font &Sublinhado Set the current or selected font to underline Definir o texto actual ou seleccionado como sublinhado &Font Size &Tamanho do texto Set size of the current or selected text Definir o tamanho do texto actual ou seleccionado Small Pequeno Default Normal Large Grande Larger Maior Largest Muito Grande Set Font Size Definir tamanho do texto Font C&olor... Co&r do Texto... Set the color of the current or selected text Definir a cor do texto actual ou seleccionado &External Link... &Ligação Externa... Add or modify an extrnal web link Adicionar ou modificar uma ligação externa para a internet Internal &Link... Ligação &Interna... Add or modify an internal node link Adicionar ou modificar uma ligação interna para outro ramo Clear current or selected text formatting Remover a formatação do texto actual ou seleccionado &Rename &Mudar Nome Rename the current tree entry title Alterar o nome da entrada actual na árvore Insert Sibling &Before Inserir Irmão &Antes Insert new sibling before selection Inserir novo ramo acima da selecção Insert Sibling &After Inserir Irmão &Depois Insert new sibling after selection Inserir novo ramo abaixo da selecção Add &Child Adicionar De&scendente Add new child to selected parent Adicionar sub ramo ao ramo seleccionado &Delete Node &Eliminar Ramo Delete the selected nodes Eliminar os ramos seleccionados &Indent Node &Recuar Ramo Indent the selected nodes Avançar os ramos seleccionados &Unindent Node A&vançar Ramo Unindent the selected nodes Recuar os ramos seleccionados &Move Up Mover para &Cima Move the selected nodes up Mover para cima os ramos seleccionados M&ove Down Mover para &Baixo Move the selected nodes down Mover para baixo os ramos seleccionados Move &First Colocar em &Primeiro Move the selected nodes to be the first children Mover os ramos seleccionados para que sejam os primeiros descendentes Move &Last Colocar em &Último Move the selected nodes to be the last children Mover os ramos seleccionados para que sejam os últimos descendentes &Set Node Type Definir &Tipo de Ramo Set the node type for selected nodes Definir o tipo de dados para os ramos seleccionados Set Node Type Definir Tipo de Ramo Copy Types from &File... Copiar Tipos de Outro &Ficheiro... Copy the configuration from another TreeLine file Copiar configuração de outro ficheiro TreeLine Flatten &by Category &Nivelar por categoria Collapse descendants by merging fields Colapsar descendentes juntando campos Add Category &Level... &Adicionar Nível por Categoria... Insert category nodes above children Insere ramos sobre descendentes classificanado segundo um campo &Spell Check... &Verificar Ortografia... &New Window &Nova Janela Open a new window for the same file Abrir nova vista do mesmo ficheiro Error - could not write to {} Erro - não é possível escrever para {} TreeLine - Save As TreeLine - Guardar Como Error - could not write to file Erro - não foi possível escrever para o ficheiro TreeLine - Open Configuration File TreeLine - Abrir Ficheiro de Configuração Error - could not read file {0} Erro - não foi possível ler o ficheiro {0} Cannot expand without common fields Não é possível expandir sem campos em comum Category Fields Campos de Categorias Select fields for new level Seleccione campo para novo nível Clear For&matting Limpar &Formatação File saved Ficheiro gravado Pa&ste Plain Text Paste C&hild Paste a child node from the clipboard Paste Sibling &Before Paste a sibling before selection Paste Sibling &After Paste a sibling after selection Paste Cl&oned Child Paste a child clone from the clipboard Paste Clo&ned Sibling Before Paste a sibling clone before selection Paste Clone&d Sibling After Paste a sibling clone after selection Clone All &Matched Nodes Convert all matching nodes into clones &Detach Clones Detach all cloned nodes in current branches S&wap Category Levels Swap child and grandchild category nodes Converted {0} branches into clones No identical nodes found Warning - file corruption! Skipped bad child references in the following nodes: Spell check the tree's text data &Regenerate References Force update of all conditional types & math fields Insert &Date Insert current date as text St&rikethrough Font Set the current or selected font to strikethough treemaincontrol Warning: Could not create local socket Aviso: Não foi possível criar ligação local Error - could not write config file to {} Erro - não foi possível gravar configuração no ficheiro {0} Error - could not read file {0} Erro - não foi possível ler o ficheiro {0} Backup file "{}" exists. A previous session may have crashed Cópia de segurança {0} existente. Uma sessão anterior pode ter terminado inesperadamente &Restore Backup &Restaurar Cópia de Segurança &Delete Backup &Apagar Cópia de Segurança &Cancel File Open &Cancelar Abertura de Ficheiro Error - could not rename "{0}" to "{1}" Erro - não foi possível alterar o nome de "{0}" para"{1}" Error - could not remove backup file {} Erro - não foi possível remover a cópia de segurança {} &New... &Novo... New File Novo Ficheiro Start a new file Criar um novo ficheiro &Open... &Abrir... Open File Abrir um Ficheiro Open a file from disk Abrir um ficheiro do disco Open Sa&mple... A&brir Exemplo... Open Sample Abrir um Exemplo Open a sample file Abrir um ficheiro de exemplo &Import... &Importar... Open a non-TreeLine file Abrir um ficheiro alheio ao TreeLine &Quit &Sair Exit the application Sair da aplicação &Configure Data Types... &Configurar Tipos de Dados... Modify data types, fields & output lines Modificar tipos de dados, campos e opções de apresentação Sor&t Nodes... &Ordenar Ramos... Define node sort operations Definir operações de ordenamento Update &Numbering... &Actualizar Numeração... Update node numbering fields Actualizar os campos de numeração &Find Text... &Encontrar Texto... Find text in node titles & data Encontrar texto nos títulos e conteúdo dos ramos &Conditional Find... &Procura Condicional... Use field conditions to find nodes Utilizar condições para encontrar ramos Find and &Replace... Encontar e &Substituir... Replace text strings in node data Substituir texto no conteúdo dos ramos &Text Filter... Filtro de &Texto... Filter nodes to only show text matches Filtrar ramos para mostrar apenas textos correspondentes C&onditional Filter... Filtro &Condicional... Use field conditions to filter nodes Utilizar condições para filtrar ramos &General Options... &Opções Gerais... Set user preferences for all files Definir opções do utilizador para todos os ficheiros Set &Keyboard Shortcuts... Definir &Atalhos de Teclado... Customize keyboard commands Personalizar comandos de teclado C&ustomize Toolbars... Personalizar &Barras de Ferramentas... Customize toolbar buttons Personalizar os botões das barras de ferramentas Customize Fo&nts... Personalizar &Fontes... Customize fonts in various views Personalizar as fontes utilizadas nas diversas vistas &Basic Usage... Utilização &Básica... Display basic usage instructions Mostrar instruções de utilização básica &Full Documentation... &Documentação Completa... Open a TreeLine file with full documentation Abrir um ficheiro TreeLine com a documentação completa &About TreeLine... &Acerca do TreeLine... Display version info about this program Mostrar informção sobre a versão deste programa &Select Template Seleccionar &Modelo TreeLine - Open File TreeLine -Abrir Ficheiro Open Sample File Abrir Ficheiro de Exemplo &Select Sample &Seleccione um exemplo Conditional Find Procura Condicional Conditional Filter Filtro Condicional General Options Opções Gerais Error - basic help file not found Erro -Ficheiro de ajuda básica não encontrado TreeLine Basic Usage Utilização Básica TreeLine Error - documentation file not found Erro - Ficheiro de documentação não encontrado &Select All &Seleccionar Tudo Select all text in an editor Seleccionar todo o texto num editor Error - invalid TreeLine file {0} TreeLine version {0} written by {0} Library versions: missing directory Show C&onfiguration Structure... Show read-only visualization of type structure Custo&mize Colors... Customize GUI colors and themes treemodel treenode New Novo treeopener treestructure Main Principal treeview Filtering by "{0}", found {1} nodes Filtragem por "{0}", encontrados {1} ramos Conditional filtering, found {0} nodes Filtragem condicional, encontrados {0} ramos Search for: Search for: {0} Search for: {0} (not found) Next: {0} Next: {0} (not found) treewindow Data Output Apresentação de Informação Data Edit Edição de Informação Title List Lista de Títulos &Expand Full Branch &Expandir Ramo Completo Expand all children of the selected nodes Expandir todos os descendentes dos ramos seleccionados &Collapse Full Branch &Colapsar Ramo Completo Collapse all children of the selected nodes Colapsar todos os descendentos dos ramos seleccionados &Previous Selection Selecção &Anterior Return to the previous tree selection Repor a anterior selecção da árvore &Next Selection Selecção &Seguinte Go to the next tree selection in history Ir para a selecção da árvore seguinte no histórico Show Data &Output M&ostrar Apresentação de Informação Show data output in right view Mostrar Apresentação de Dados na vista direita Show Data &Editor Mostrar Editor de &Informação Show data editor in right view Mostrar o editor de informação na vista direita Show &Title List Mostrar &Lista de Títulos Show title list in right view Mostra lista de títulos na vista direita &Show Child Pane Mostrar Painel dos &Descendentes Toggle showing right-hand child views Alternar mostrar vista de descendentes na vista direita Toggle showing output view indented descendants Alternar mostrar a apresentação de descendentes &Close Window &Fechar Janela Close this window Fechar esta janela &File &Ficheiro &Edit &Editar &Node &Ramo &Data &Informação &Tools Fe&rramentas &View &Ver &Window &Janela &Help &Ajuda Start Incremental Search Next Incremental Search Previous Incremental Search Show &Breadcrumb View Toggle showing breadcrumb ancestor view Show Output &Descendants Fo&rmat colorset Dialog background color Dialog text color Text widget background color Text widget foreground color Selected item background color Selected item text color Link text color Tool tip background color Tool tip foreground color Button background color Button text color Disabled text foreground color Disabled button text color Color Settings Color Theme Default system theme Dark theme Custom theme &OK &OK &Cancel &Cancelar Custom Colors Theme Colors Select {0} color TreeLine-3.2.1/working/translations/treeline_ru.ts000066400000000000000000006445321506556630100223370ustar00rootroot00000000000000 genboolean true иÑ�тина false ложь no нет yes да conditional starts with начинаетÑ�Ñ� Ñ� True ИÑ�тина False Ложь contains Ñ�одержит ends with оканчиваетÑ�Ñ� на or или and и [All Types] [Ð’Ñ�е Типы] Node Type Тип Узла &Add New Rule &Добавить Ð�овое Правило &Remove Rule &Удалить Правило &OK &OK &Cancel &Отмена Saved Rules Сохраненные Правила Name: ИмÑ�: &Load &Загрузить &Save &Сохранить &Delete &Удалить Find &Previous Ð�айти &Предыдущий Find &Next Ð�айти &Следующий &Filter От&фильтровать &End Filter Прекратить &Фильтрацию &Close &Закрыть No conditional matches were found УдовлетворÑ�ющие уÑ�ловию Ñ�овпадениÑ� не найдены Rule {0} Правило {0} colorset Dialog background color Цвет фона интерфейÑ�а Dialog text color Цвет шрифта интерфейÑ�а Text widget background color Цвет фона Ñ�лементов интерфейÑ�а Text widget foreground color Цвет фона Ñ�имволов Ñ�лементов интерфейÑ�а Selected item background color Цвет фона выбранного пункта меню Selected item text color Цвет шрифта выбранного пункта меню Link text color Цвет шрифта гиперÑ�Ñ�ылки Tool tip background color Цвет фона вÑ�плывающей подÑ�казки Tool tip foreground color Цвет фона Ñ�имволов вÑ�плывающей подÑ�казки Button background color Цвет фона кнопки Button text color Цвет шрифта кнопки Disabled text foreground color Цвет шрифта неактивного текÑ�та Disabled button text color Цвет шрифта неактивной кнопки Color Settings Ð�аÑ�тройка Цветов Color Theme ЦветоваÑ� Тема Default system theme Тема Ñ�иÑ�темы по умолчанию Dark theme ТемнаÑ� тема Custom theme Тема пользователÑ� &OK &OK &Cancel &Отмена Custom Colors Цвета ПользователÑ� Theme Colors Цвета Темы Select {0} color Вабрать {0} цвет configdialog [None] [Ð�и один] Configure Data Types Ð�аÑ�тройка Типов Данных T&ype List СпиÑ�ок &Типов Typ&e Config Ð�аÑ�тройка &Типа Field &List СпиÑ�ок &Полей &Field Config Ð�аÑ�тройка &ПолÑ� O&utput &Вывод &Show Advanced Показать &Дополнительные Ð�аÑ�тройки &OK &OK &Apply &Применить &Reset &СброÑ�ить &Cancel &Отмена &Hide Advanced &Скрыть Дополнительные Ð�аÑ�тройки Error - circular reference in math field equations Ошибка — цикличеÑ�каÑ� Ñ�Ñ�ылка в выражениÑ�Ñ… математичеÑ�кого полÑ� Add or Remove Data Types Добавить или Удалить Типы Данных &New Type... &Ð�овый Тип... Co&py Type... С&копировать Тип... Rena&me Type... &Переименовать Тип... &Delete Type &Удалить Тип Add Type Добавить Тип Enter new type name: Введите имÑ� нового типа: Copy Type Копировать Тип &Derive from original Ð�аÑ�ледовать от &иÑ�точника Rename Type Переименовать Тип Rename from {} to: Переименовать из {} в: Cannot delete data type being used by nodes Ð�евозможно удалить тип, в узлах которого Ñ�одержатÑ�Ñ� данные [None] тип не задан [Ð�и один] &Data Type Тип &Данных Default Child &Type Тип &Дочернего Узла по Умолчанию Icon Значок Change &Icon Сменить &Значок Output Options Опции Вывода Add &blank lines between nodes Добавить &пуÑ�тые Ñ�троки между узлами Allow &HTML rich text in format Учитывать при форматировании &HTML-разметку Add text bullet&s Добавить &маркеры текÑ�та Use a table for field &data ИÑ�пользовать таблицу длÑ� &данных полÑ� Combination && Child List Output &Separator &Разделитель Значений Типа КомбинациÑ� && СпиÑ�ков Дочерних Узлов Derived from &Generic Type Сделать Производным от &Общего Типа Automatic Types Ð�втоматичеÑ�кие Типы Child Type Limits ОграничениÑ� Типа Дочернего Узла None Ð�и один Modify Co&nditional Types Изменить &УÑ�ловные Типы Create Co&nditional Types Создать У&Ñ�ловные Типы Set Types Conditionally Ð�азначить Типы в завиÑ�имоÑ�ти от УÑ�ловий Modify &Field List Изменить СпиÑ�ок &Полей Name ИмÑ� Type Тип Sort Key Ключ Сортировки Move U&p ПеремеÑ�тить Ð’&верх Move Do&wn ПеремеÑ�тить Ð’&низ &New Field... &Ð�овое Поле... Rena&me Field... Пе&реименовать Поле... Dele&te Field &Удалить Поле Sort &Keys... Ключи &Сортировки... fwd >> rev << Enter new field name: Введите имÑ� нового полÑ�: Add Field Добавить Поле Rename Field Переименовать Поле File Info Reference СÑ�ылка на Информацию о Файле F&ield &Поле &Field Type Тип &ПолÑ� Outpu&t Format Формат &Вывода Format &Help Справка по &Форматированию Extra Text Дополнительный ТекÑ�Ñ‚ &Prefix &ПриÑ�тавка Suffi&x &Окончание Default &Value for New Nodes Значение по &Умолчанию длÑ� Ð�овых Узлов Editor Height Ð’Ñ‹Ñ�ота ПолÑ� Редактора Num&ber of text lines &ЧиÑ�ло Ñ�трок текÑ�та Math Equation МатематичеÑ�кое Выражение Define Equation Задать Выражение Output HTML Вывод в HTML Evaluate &HTML tags ОпределÑ�ть теги &HTML F&ield List СпиÑ�ок &Полей &Title Format Формат &Заголовка Out&put Format Формат &Вывода Other Field References СÑ�ылки на Другие ПолÑ� Reference Le&vel &Уровень СÑ�ылки Refere&nce Type Тип &СÑ�ылки [All Types Available] [Ð’Ñ�е Типы ДопуÑ�тимы] &Select All Выбрать &Ð’Ñ�е Select &None Ð�е Выбрать &Ð�ичего The name cannot be empty ИмÑ� не может быть пуÑ�тым The name must start with a letter ИмÑ� должно начинатьÑ�Ñ� Ñ� буквы The name cannot start with "xml" ИмÑ� не может начинатьÑ�Ñ� Ñ� "xml" The name cannot contain spaces ИмÑ� не может Ñ�одержать пробелы The following characters are not allowed: {} Следующие Ñ�имволы недопуÑ�тимы: {} The name was already used ИмÑ� уже иÑ�пользовано Set Data Type Icon Ð�азначить Значок Типа Данных Clear &Select ОчиÑ�тить &Выбор reverse Ñ�менить направление на обратное forward вперед Sort Key Fields ПолÑ� Ключа Сортировки Available &Fields ДопуÑ�тимые &ПолÑ� &Sort Criteria Критерии &Сортировки Field Поле Direction Ð�аправление Move &Up ПеремеÑ�тить &Вверх &Move Down ПеремеÑ�тить Ð’&низ Flip &Direction Сменить &Ð�аправление Parent Reference СÑ�ылка на ПолÑ� РодительÑ�кого Узла Self Reference СÑ�ылка на ПолÑ� Своего Узла Child Count ЧиÑ�ло ПодÑ�читанных Дочерних Узлов Root Reference СÑ�ылка на Поле Корневого Узла Child Reference СÑ�ылка на Поле Дочернего Узла Number Result Итоговое ЧиÑ�ло Date Result ИтоговаÑ� Дата Time Result Итоговое ВремÑ� Boolean Result Итоговое Значение ЛогичеÑ�кого Типа Text Result Итоговый ТекÑ�Ñ‚ Comparison Operators Операторы СравнениÑ� Arithmetic Operators Ð�рифметичеÑ�кие Операторы Text Operators ТекÑ�товые Операторы add Ñ�ложить subtract вычеÑ�ть multiply умножить divide разделить floor divide целочиÑ�ленное деление modulus модуль power возвеÑ�ти в Ñ�тепень sum of items Ñ�умма Ñ�лементов maximum макÑ�имум minimum минимум average Ñ�реднее absolute value абÑ�олютное значение square root квадратный корень natural logarithm натуральный логарифм base-10 logarithm деÑ�Ñ�тичный логарифм factorial факториал round to num digits округлить до чиÑ�ла разрÑ�дов lower integer меньшее целое чиÑ�ло higher integer большее целое чиÑ�ло truncated integer уÑ�еченное целое чиÑ�ло floating point плавающаÑ� точка sine of radians Ñ�инуÑ� в радианах cosine of radians коÑ�инуÑ� в радианах tangent of radians тангенÑ� в радианах arc sine аркÑ�инуÑ� arc cosine арккоÑ�инуÑ� arc tangent арктангенÑ� radians to degrees радианы в градуÑ�Ñ‹ degrees to radians градуÑ�Ñ‹ в радианы pi constant чиÑ�ло пи natural log constant оÑ�нование натурального логарифма equal to равно less than меньше чем greater than больше чем less than or equal to меньше или равно greater than or equal to больше или равно not equal to не равно true value, condition, false value иÑ�тинное значение, уÑ�ловие, ложное значение logical and логичеÑ�кое И logical or логичеÑ�кое ИЛИ true if 1st text arg starts with 2nd arg иÑ�тина, еÑ�ли 1-й аргумент начинаетÑ�Ñ� Ñ�о 2-го аргумента true if 1st text arg ends with 2nd arg иÑ�тина, еÑ�ли 1-й текÑ�товый аргумент оканчиваетÑ�Ñ� 2-м аргументом true if 1st text arg contains 2nd arg иÑ�тина, еÑ�ли 1-й текÑ�товый аргумент Ñ�одержит 2-й аргумент concatenate text Ñ�цепить текÑ�товые Ñ�троки join text using 1st arg as separator приÑ�оединить текÑ�Ñ‚, иÑ�пользуÑ� значение 1-го аргумента в качеÑ�тве разделителÑ� convert text to upper case преобразовать текÑ�Ñ‚ в верхний региÑ�тр convert text to lower case преобразовать текÑ�Ñ‚ в нижний региÑ�тр in 1st arg, replace 2nd arg with 3rd arg заменить в 1-м аргументе 2-й аргумент 3-м аргументом Define Math Field Equation Задать Выражение МатематичеÑ�кого ПолÑ� Field References СÑ�ылки на Поле Reference &Level &Уровень СÑ�ылки Reference &Type &Тип СÑ�ылки Available &Field List СпиÑ�ок ДопуÑ�тимых &Полей &Result Type &Тип Результата Operations Операции O&perator Type Тип &Оператора Oper&ator List СпиÑ�ок &Операторов Description ОпиÑ�ание &Equation &Выражение Count ПодÑ�читать Number of Children ЧиÑ�ло Дочерних Узлов Equation error: {} Ошибка в выражении: {} [None] no type set dataeditors Today's &Date СегоднÑ�шнÑ�Ñ� &Дата Set to &Now УÑ�тановить &СегоднÑ�шнюю Дату &Open Link &Открыть ГиперÑ�Ñ�ылку Open &Folder Открыть &Папку External Link ВнешнÑ�Ñ� ГиперÑ�Ñ�ылка Scheme Структура &Browse for File &ПоиÑ�к Файла File Path Type Задать Тип Пути к Файлу Absolute Ð�бÑ�олютный Relative ОтноÑ�ительный Address Ð�дреÑ� Display Name Показать ИмÑ� TreeLine - External Link File TreeLine — ГиперÑ�Ñ�ылка на Внешний Файл &Go to Target &Перейти к Цели Clear &Link ОчиÑ�тить &ГиперÑ�Ñ�ылку (Click link target in tree) Кликните на целевую гиперÑ�Ñ�ылку в дереве Internal Link ВнутреннÑ�Ñ� ГиперÑ�Ñ�ылка &OK &OK &Cancel &Отмена link гиперÑ�Ñ�ылка &Open Picture &Открыть Изображение Picture Link ГиперÑ�Ñ�ылка на Изображение TreeLine - Picture File TreeLine — Файл Ñ� Изображением miscdialogs &OK &OK &Cancel &Отмена Fields ПолÑ� File Properties СвойÑ�тва Файла File Storage Файловое Хранилище &Use file compression Применить Ñ�&жатие файлов Use file &encryption Применить &шифрование файлов Spell Check Проверка ПравопиÑ�аниÑ� Language code or dictionary (optional) Код Ñ�зыка или Ñ�ловарь (по желанию) Math Fields МатематичеÑ�кие ПолÑ� &Treat blank fields as zeros &Обрабатывать пуÑ�тые полÑ� как нули Encrypted File Password Пароль к Зашифрованному Файлу Type Password for "{0}": Введите Пароль длÑ� "{0}": Type Password: Введите Пароль: Re-Type Password: Введите Пароль Заново: Remember password during this session Запомнить пароль текущей Ñ�еÑ�Ñ�ии Zero-length passwords are not permitted Пароли нулевой длины не допуÑ�тимы Re-typed password did not match Вновь набранный пароль не подходит Default - Single Line Text По Умолчанию — ОдноÑ�трочный ТекÑ�Ñ‚ TreeLine - Serious Error TreeLine — СерьезнаÑ� Ошибка A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. Возникла Ñ�ерьезнаÑ� ошибка. TreeLine может находитьÑ�Ñ� в неÑ�табильном Ñ�оÑ�тоÑ�нии. РекомендуетÑ�Ñ� Ñ�охранить файл Ñ� внеÑ�енными изменениÑ�ми под другим именем и перезапуÑ�тить TreeLine. Отладочную информацию, приведенную ниже, Ð’Ñ‹ можете Ñ�копировать и отправить Ñ�лектронной почтой на e-mail: doug101@bellz.org Ñ� опиÑ�анием обÑ�тоÑ�тельÑ�тв возникновениÑ� ошибки. &Close &Закрыть &Search Text &ИÑ�комый ТекÑ�Ñ‚ What to Search Ð’ Чем ИÑ�кать Full &data Во вÑ�ех &данных &Titles only Только в &заголовках How to Search Как ИÑ�кать &Key words &Ключевые Ñ�лова Key full &words Полные ключевые &Ñ�лова F&ull phrase Полное &выражение &Regular expression &РегулÑ�рное выражение Find ПоиÑ�к Find &Next Ð�айти &Следующий Filter Фильтровать &Filter &Фильтровать &End Filter &Прекратить Фильтрацию Search string "{0}" not found ИÑ�комаÑ� Ñ�трока "{0}" не найдена Find and Replace ПоиÑ�к и Замена Replacement &Text ЗаменÑ�ющий &ТекÑ�Ñ‚ Any &match Любое &Ñ�овпадение Full &words Целые &Ñ�лова Re&gular expression Ре&гулÑ�рное выражение &Node Type Тип &Узла N&ode Fields ПолÑ� &Узлов Find &Previous Ð�айти &Предыдущий &Find Next Ð�айти &Следующий &Replace &Заменить Replace &All Заменить &Ð’Ñ�е [All Types] [Ð’Ñ�е Типы] [All Fields] [Ð’Ñ�е ПолÑ�] Error - invalid regular expression Ошибка — неверное регулÑ�рное выражение Search text "{0}" not found ИÑ�комый текÑ�Ñ‚ "{0}" не найден Error - replacement failed Ошибка — замена невозможна Replaced {0} matches Заменено {0} Ñ�овпадений Sort Nodes СортироватьУзлы What to Sort Что Сортировать &Entire tree Ð’Ñ�е &дерево Selected &branches Выбранные &ветви Selection's childre&n &Дочерние узлы в выбранном Selection's &siblings &СеÑ�тринÑ�кие узлы в выбранном Sort Method СпоÑ�об Сортировки &Predefined Key Fields &Предопределенные Ключевые ПолÑ� Node &Titles &Заголовки Узлов Sort Direction Ð�аправление Сортировки &Forward &Вперед &Reverse &Сменить направление &Apply &Применить Update Node Numbering Обновить Ð�умерацию Узлов What to Update Что ОбновлÑ�ть &Selection's children &Дочерние узлы в выбранном Root Node Корневой Узел Include top-level nodes Включить узлы верхних уровней Handling Nodes without Numbering Fields Обработка Узлов без Полей Ð�умерации &Ignore and skip &Игнорировать и пропуÑ�тить &Restart numbers for next siblings &ПерезапуÑ�тить нумерацию Ñ� начала длÑ� Ñ�ледующих Ñ�еÑ�тринÑ�ких узлов Reserve &numbers За&резервировать номера TreeLine Numbering Ð�умерациÑ� TreeLine No numbering fields were found in data types ПолÑ� нумерации в типах данных не найдены File Файл File Menu Меню Файл Edit Редактировать Edit Menu Меню Правка Node Узел Node Menu Меню Узел Data Данные Data Menu Меню Данные Tools ИнÑ�трументы Tools Menu Меню ИнÑ�трументы Format Форматировать Format Menu Меню Формат View Вид View Menu Меню Вид Window Окно Window Menu Меню Окно Help Справка Help Menu Меню Справки Keyboard Shortcuts ГорÑ�чие Клавиши No menu Меню отÑ�утÑ�твует &Restore Defaults ВоÑ�Ñ�тановить ЗначениÑ� по &Умолчанию Key {0} is already used Ключ {0} уже иÑ�пользуетÑ�Ñ� Clear &Key ОчиÑ�тить &Ключ --Separator-- --Разделитель-- Customize Toolbars Ð�аÑ�троить Панели ИнÑ�трументов Toolbar &Size &Размер Панели ИнÑ�трументов Large Icons Большие Значки Small Icons Маленькие Значки Toolbar Quantity КоличеÑ�тво Панелей ИнÑ�трументов &Toolbars &Панели ИнÑ�трументов A&vailable Commands До&пуÑ�тимые Команды Tool&bar Commands Команды &Панели ИнÑ�трументов Move &Up ПеремеÑ�тить &Вверх Move &Down ПеремеÑ�тить &Вниз Customize Fonts Ð�аÑ�троить Шрифты &Use system default font ИÑ�пользовать &Ñ�иÑ�темный шрифт по умолчанию App Default Font Шрифт ПриложениÑ� по Умолчанию &Use app default font &ИÑ�пользовать шрифт приложениÑ� по умолчанию Tree View Font Шифт длÑ� ПроÑ�мотра Дерева Output View Font Шрифт в Форме Вывода Editor View Font Шрифт Редактора Language code or dictionary (optional) Externally Modified File &Overwrite File &Cancel Save A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. File was externally modified at {} options Choose configuration file location Выберите раÑ�положение файла конфигурации User's home directory (recommended) ДомашнÑ�Ñ� директориÑ� пользователÑ� (рекомендуетÑ�Ñ�) Program directory (for portable use) ДиректориÑ� программы (длÑ� портативного иÑ�пользованиÑ�) &OK &OK &Cancel &Отмена printdialogs Print Preview Предварительный ПроÑ�мотр Печати Fit Width Заполнить по Ширине Fit Page Страница Целиком Zoom In Увеличить Zoom Out Уменьшить Previous Page ПредыдущаÑ� Страница Next Page СледующаÑ� Страница Single Page ОдниночнаÑ� Страница Facing Pages Страницы в Развороте Print Setup Ð�аÑ�тройка Печати Print Печать Printing Setup Ð�аÑ�тройка Печати &General Options &Общие Ð�аÑ�тройки Page &Setup &Параметры Страницы &Font Selection &Выбор Шрифта &Header/Footer &Верхний/Ð�ижний Колонтитул Print Pre&view... Предварительный Про&Ñ�мотр Печати... &Print... &Печать... &OK &OK &Cancel &Отмена Error: Page size or margins are invalid Ошибка: Размер или полÑ� Ñ�траницы неверны TreeLine PDF Printer PDF Принтер TreeLine What to print Что печатать &Entire tree &Ð’Ñ�е Дерево Selected &branches Выбранные &ветви Selected &nodes Выбранные &узлы Included Nodes Включенные Узлы &Include root node &Включить корневой узел Onl&y open node children То&лько открытые дочерние узлы Select &Printer Выберите &Принтер Features СвойÑ�тва &Draw lines to children &Отображать пути к дочерним узлам &Keep first child with parent По&казывать первый дочерний узел Ñ� родителем Indent ОтÑ�туп Indent Offse&t (line height units) О&Ñ‚Ñ�тупить при Печати (на количеÑ�тво Ñ�трок) Letter (8.5 x 11 in.) Letter (8.5 × 11 Inch) Legal (8.5 x 14 in.) Legal (8.5 × 14 Inch) Tabloid (11 x 17 in.) Tabloid (11 × 17 Inch) A3 (279 x 420 mm) A3 (279 × 420 мм) A4 (210 x 297 mm) A4 (210 × 297 мм) A5 (148 x 210 mm) A5 (148 × 210 мм) Custom Size Заданный Размер Inches (in) Дюймы (in.) Millimeters (mm) Миллиметры (мм) Centimeters (cm) Сантиметры (Ñ�м) &Units &Единицы ИзмерениÑ� Paper &Size &Размер Бумаги &Width: &Ширина: Height: Ð’Ñ‹Ñ�ота: Orientation ОриентациÑ� Portra&it &КнижнаÑ� Lan&dscape &Ð�льбомнаÑ� Margins ПолÑ� &Left: С&лева: &Top: &Сверху: &Right: С&права: &Bottom: &Снизу: He&ader: &Верхний Колонтитул: Foot&er: Ð�ижний &Колонтитул: Columns Столбцы &Number of columns &ЧиÑ�ло Ñ�толбцов Space between colu&mns РаÑ�Ñ�тоÑ�ние между Ñ�&толбцами Default Font Шрифт по Умолчанию &Use TreeLine output view font &ИÑ�пользовать шрифт формы вывода TreeLine Select Font Выберите Шрифт &Font &Шрифт Font st&yle &Ð�ачертание Шрифта Si&ze Р&азмер Sample Пример AaBbCcDdEeFfGg...TtUuVvWvXxYyZz Ð�аБбВвГгДдЕеЖж...ЦцШшЩщЬьЭÑ�ЮюЯÑ� Header &Right Верхний С&права Header C&enter Верхний по &Центру &Header Left Верхний С&лева Footer &Left Ð�ижний &Слева Footer Righ&t Ð�ижний С&права Footer Ce&nter Ð�ижний по &Центру Fiel&ds По&лÑ� Field For&mat &Поле Формата Header and Footer Верхний и Ð�ижний Колонтитулы Field Format for "{0}" Формат полÑ� длÑ� "{0}" Output &Format &Формат Вывода Format &Help &Справка по Форматированию Extra Text Дополнительный текÑ�Ñ‚ &Prefix &ПриÑ�тавка &Suffix &Окончание Indent Offse&t (line height units) treenode New Ð�овый fieldformat Text ТекÑ�Ñ‚ OneLineText ОдноÑ�трочный ТекÑ�Ñ‚ SpacedText ТекÑ�Ñ‚ Ñ� МеждуÑ�трочными Интервалами HtmlText ТекÑ�Ñ‚ Ñ� разметкой HTML Math МатематичеÑ�кое Поле Numbering Ð�умерациÑ� Number ЧиÑ�ло Date Дата Time ВремÑ� DateTime Дата и ВремÑ� Boolean ЛогичеÑ�кий Тип Combination КомбинациÑ� AutoChoice Ð�втоВыбор Choice Выбор ExternalLink ВнешнÑ�Ñ� ГиперÑ�Ñ�ылка InternalLink ВнутреннÑ�Ñ� ГиперÑ�Ñ�ылка AutoCombination Ð�втоКомбинациÑ� Picture Изображение RegularExpression РегулÑ�рное Выражение Now СегоднÑ� и СейчаÑ� Optional Digit # Ð�еобÑ�зательнаÑ� Цифра # Required Digit 0 ОбÑ�зательнаÑ� Цифра 0 Digit or Space (external) <space> Цифра или Пробел (внешний) <space> Decimal Point . ДеÑ�Ñ�тичнаÑ� Точка . Decimal Comma , ДеÑ�Ñ�тичнаÑ� ЗапÑ�таÑ� , Comma Separator \, Разделитель ЗапÑ�таÑ� \, Dot Separator \. Разделитель в виде Точки \. Space Separator (internal) <space> Пробельный Разделитель (внутренний) <space> Optional Sign - Ð�еобÑ�зательный Знак - Required Sign + Ð�еобходимый Знак + Exponent (capital) E ОÑ�нование Ñ�тепени (большое) E Exponent (small) e ОÑ�нование Ñ�тепени (малое) e Number 1 Ð�омер 1 Capital Letter A ЗаглавнаÑ� Буква A Small Letter a СтрочнаÑ� буква a Capital Roman Numeral I ЗаглавнаÑ� РимÑ�каÑ� Цифра I Small Roman Numeral i СтрочнаÑ� РимÑ�каÑ� Цифра i Level Separator / Разделитель Уровней / Section Separator . Разделитель Разделов . "/" Character // "/" Символ // "." Character .. "." Символ .. Outline Example I../A../1../a)/i) Образец Макета I../A../1../a)/i) Section Example 1.1.1.1 Образец Раздела 1.1.1.1 Day (1 or 2 digits) %-d День (1 или 2 цифры) %-d Day (2 digits) %d День (2 цифры) %d Weekday Abbreviation %a Сокращенное Ð�азвание ДнÑ� Ð�едели %a Weekday Name %A День Ð�едели %A Month (1 or 2 digits) %-m МеÑ�Ñ�ц (1 или 2 цифры) %-m Month (2 digits) %m МеÑ�Ñ�ц (2 цифры) %m Month Abbreviation %b Сокращенное Ð�азвание МеÑ�Ñ�ца %b Month Name %B Ð�азвание МеÑ�Ñ�ца %B Year (2 digits) %y Год (2 цифры) %y Year (4 digits) %Y Год (4 цифры) %Y Week Number (0 to 53) %-U Ð�омер Ð�едели (от 0 до 53) %-U Day of year (1 to 366) %-j День Года (от 1 до 366) %-j Hour (0-23, 1 or 2 digits) %-H ЧаÑ� (0-23, 1 или 2 цифры) %H Hour (00-23, 2 digits) %H ЧаÑ� (00-23, 2 цифры) %H Hour (1-12, 1 or 2 digits) %-I ЧаÑ� (1-12, 1 или 2 цифры) %-I Hour (01-12, 2 digits) %I ЧаÑ� (01-12, 2 цифры) %I Minute (1 or 2 digits) %-M Минута (1 или 2 цифры) %-M Minute (2 digits) %M Минута (2 цифры) %M Second (1 or 2 digits) %-S Секунда (1 или 2 цифры) %-S Second (2 digits) %S Секундa (2 цифры) %S Microseconds (6 digits) %f МикроÑ�екунда (6 цифр) %f AM/PM %p AM/PM Separator / Разделитель / Example 1/2/3/4 Образец 1/2/3/4 yes/no да/нет true/false иÑ�тина/ложь T/F И/Л Y/N Д/Ð� Any Character . Любой Символ . End of Text $ Конец Строки $ 0 Or More Repetitions * 0 Или Более Повторов * 1 Or More Repetitions + 1 Или Более Повторов + 0 Or 1 Repetitions ? 0 Или 1 Повтор ? Set of Numbers [0-9] Ð�абор Цифр [0-9] Lower Case Letters [a-z] Буквы в Ð�ижнем РегиÑ�тре [а-Ñ�] Upper Case Letters [A-Z] Буквы в Верхнем РегиÑ�тре [Ð�-Я] Not a Number [^0-9] Ð�е Цифра [^0-9] Or | ИЛИ | Escape a Special Character \ Экранирование Специального Символа \ DescendantCount ПодÑ�чет Потомков spellcheck Could not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? Ð�евозможно найти ни aspell.exe, ни ispell.exe или hunspell.exe Выбрать меÑ�тораÑ�положение? Spell Check Error Ошибка Проверки ПравопиÑ�аниÑ� Locate aspell.exe, ipsell.exe or hunspell.exe Укажите меÑ�тораÑ�положение aspell.exe, ispell.exe или hunspell.exe Program (*.exe) Программа (*.exe) TreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed Ошибка Проверки ПравопиÑ�аниÑ� TreeLine УдоÑ�товерьтеÑ�ÑŒ, что aspell, ispell или hunspell уÑ�тановлен Finished checking the branch Continue from the top? Проверка правопиÑ�аниÑ� в ветви окончена Продолжить Ñ�верху? TreeLine Spell Check Проверка ПравопиÑ�аниÑ� TreeLine Finished spell checking Проверка правопиÑ�аниÑ� окончена Spell Check Проверка ПравопиÑ�аниÑ� Not in Dictionary Ð�ет в Словаре Word: Слово: Context: КонтекÑ�Ñ‚: Suggestions ПредложениÑ� Ignor&e &Игнорировать &Ignore All Игнорировать &Ð’Ñ�е &Add &Добавить Add &Lowercase Добавить в &Ð�ижнем региÑ�тре &Replace &Заменить Re&place All Заменить &Ð’Ñ�е &Cancel &Отмена treelocalcontrol Warning - file corruption! Skipped bad child references in the following nodes: Внимание — файл поврежден! Пропущены неверные Ñ�Ñ�ылки на дочерние узлы в Ñ�ледующих узлах: Save changes to {}? Сохранить изменениÑ� в {0}? Save changes? Сохранить изменениÑ�? Error - could not delete backup file {} Ошибка — невозможно удалить резервную копию файла {0} &Save &Сохранить Save File Сохранить Файл Save the current file Сохранить текущий файл Save &As... Сохранить &Как... Save the file with a new name Сохранить файл под новым именем &Export... &ЭкÑ�портировать... Export the file in various other formats ЭкÑ�портировать файл в Ñ€Ñ�д других форматов Prop&erties... &СвойÑ�тва... Set file parameters like compression and encryption Ð�азначить такие параметры, как компреÑ�Ñ�иÑ� и шифрование P&rint Setup... Ð�аÑ�тройка &Печати... Set margins, page size and other printing options Ð�аÑ�троить полÑ�, размер Ñ�траницы и уÑ�тановить другие наÑ�тройки печати Print Pre&view... Предварительный Про&Ñ�мотр Печати... Show a preview of printing results Показать предварительный проÑ�мотр результатов печати &Print... &Печать... Print tree output based on current options РаÑ�печатать вид дерева на выходе в Ñ�оответÑ�твии Ñ� текущими наÑ�тройками Print &to PDF... Печать в &PDF... Export to PDF with current printing options ЭкÑ�порт в PDF Ñ� текущими наÑ�тройками печати &Undo &Отмена Undo the previous action Отменить предыдущее дейÑ�твие &Redo &Повтор Redo the previous undo Повторить предшеÑ�твующую отмену Cu&t Ð’Ñ‹&резать Cut the branch or text to the clipboard Вырезать ветвь или текÑ�Ñ‚ и помеÑ�тить в буфер обмена &Copy &Копировать Copy the branch or text to the clipboard Копировать ветвь или текÑ�Ñ‚ в буфер обмена &Paste &Ð’Ñ�тавить Paste nodes or text from the clipboard Ð’Ñ�тавить узлы или текÑ�Ñ‚ из буфера обмена Pa&ste Plain Text &Ð’Ñ�тавить ПроÑ�той ТекÑ�Ñ‚ Paste non-formatted text from the clipboard Ð’Ñ�тавить неформатированный текÑ�Ñ‚ из буфера обмена Paste C&hild Ð’Ñ�тавить &Дочерний Узел Paste a child node from the clipboard Ð’Ñ�тавить дочерний узел из буфера обмена Paste Sibling &Before Ð’Ñ�тавить СеÑ�тринÑ�кий Узел &Перед Paste a sibling before selection Ð’Ñ�тавить Ñ�еÑ�тринÑ�кий узел перед выбранным Paste Sibling &After Ð’Ñ�тавить СеÑ�тринÑ�кий Узел &ПоÑ�ле Paste a sibling after selection Ð’Ñ�тавить Ñ�еÑ�тринÑ�кий узел поÑ�ле выбранного Paste Cl&oned Child Ð’Ñ�тавить К&лонированный Дочерний Узел Paste a child clone from the clipboard Ð’Ñ�тавить клон дочернего узла из буфера обмена Paste Clo&ned Sibling Before Ð’Ñ�тавить К&лонированный СеÑ�тринÑ�кий Узел Перед Paste a sibling clone before selection Ð’Ñ�тавить клон Ñ�еÑ�тринÑ�кого узла перед выбранным Paste Clone&d Sibling After Ð’Ñ�тавить К&лонированный СеÑ�тринÑ�кий Узел ПоÑ�ле Paste a sibling clone after selection Ð’Ñ�тавить клон Ñ�еÑ�тринÑ�кого узла поÑ�ле выбранного &Rename &Переименовать Rename the current tree entry title Переименовать заголовок текущего Ñ�лемента дерева Add &Child Добавить &Дочерний Узел Add new child to selected parent Добавить новый дочерний узел к выбранному родителю Insert Sibling &Before Создать СеÑ�тринÑ�кий Узел П&еред Insert new sibling before selection Создать новый Ñ�еÑ�тринÑ�кий узел перед выбранным Insert Sibling &After Создать СеÑ�тринÑ�кий Узел &ПоÑ�ле Insert new sibling after selection Создать новый Ñ�еÑ�тринÑ�кий узел поÑ�ле выбранного &Delete Node &Удалить Узел Delete the selected nodes Удалить выбранные узлы &Indent Node &Вдвинуть Узел Indent the selected nodes Вдвинуть выбранные узлы &Unindent Node Ð’&ыдвинуть Узел Unindent the selected nodes Выдвинуть выбранные узлы &Move Up &ПеремеÑ�тить Вверх Move the selected nodes up ПеремеÑ�тить выбранные узлы вверх M&ove Down Пе&ремеÑ�тить Вниз Move the selected nodes down ПеремеÑ�тить выбранные узлы вниз Move &First ПеремеÑ�тить в &Ð�ачало [внутри родителÑ�] Move the selected nodes to be the first children ПеремеÑ�тить выбранные узлы на меÑ�то первых дочерних Move &Last ПеремеÑ�тить в &Конец [внутри родителÑ�] Move the selected nodes to be the last children ПеремеÑ�тить выбранные узлы на меÑ�то поÑ�ледних дочерних &Set Node Type &Ð�азначить Тип Узла Set the node type for selected nodes Ð�азначить тип узла длÑ� выбранных узлов Set Node Type Ð�азначить Тип Узла Copy Types from &File... Копировать Типы из &Файла... Copy the configuration from another TreeLine file Скопировать конфигурацию из другого файла Treeline &Regenerate References &Обновить СÑ�ылки Force update of all conditional types & math fields Принудительное обновление вÑ�ех уÑ�ловных типов & полей математичеÑ�ких полей Clone All &Matched Nodes Клонировать Ð’Ñ�е &Подошедшие Узлы Convert all matching nodes into clones Конвертировать вÑ�е подошедшие узлы в клоны &Detach Clones &Отделить Клоны Detach all cloned nodes in current branches Отделить вÑ�е клонированные узлы в текущих ветвÑ�Ñ… Flatten &by Category СвеÑ�ти на Один Уровень &по Категории Collapse descendants by merging fields Объединить потомков Ñ�лиÑ�нием полей Add Category &Level... Добавить &Уровень Категории... Insert category nodes above children Создать узлы категорий над дочерними узлами S&wap Category Levels П&оменÑ�ть МеÑ�тами Уровни Категории Swap child and grandchild category nodes ПоменÑ�ть узлы дочерней и внучатой категорий &Spell Check... &Проверка ПравопиÑ�аниÑ�... Spell check the tree's text data Проверить правопиÑ�ание текÑ�та в дереве &Bold Font &Жирный Шрифт Set the current or selected font to bold Сделать текущий или выбранный шрифт жирным &Italic Font &Ð�аклонный Шрифт Set the current or selected font to italic Сделать текущий или выбранный шрифт наклонным U&nderline Font Под&черкнутый Шрифт Set the current or selected font to underline Сделать текущий или выбранный текÑ�Ñ‚ подчеркнутым St&rikethrough Font &Зачеркнутый Шрифт Set the current or selected font to strikethough Сделать текущий или выбранный текÑ�Ñ‚ зачеркнутым &Font Size &Размер Шрифта Set size of the current or selected text Ð�азначить размер текущего или выбранного текÑ�та Large Большой Small Маленький Larger Больший Default По Умолчанию Largest Ð�аибольший Set Font Size УÑ�тановить Размер Шрифта Font C&olor... Ц&вет Шрифта... Set the color of the current or selected text Ð�азначить цвет текущего или выбранного текÑ�та &External Link... &ВнешнÑ�Ñ� ГиперÑ�Ñ�ылка... Add or modify an extrnal web link Добавить или изменить внешннюю гиперÑ�Ñ�ылку на web-Ñ�траницу Internal &Link... &ВнутренÑ�Ñ� ГиперÑ�Ñ�ылка... Add or modify an internal node link Добавить или изменить внутреннюю гиперÑ�Ñ�ылку на узел Insert &Date Ð’Ñ�тавить &Дату Insert current date as text Ð’Ñ�тавить текущую дату как текÑ�Ñ‚ Clear For&matting ОчиÑ�тить Фо&рматирование Clear current or selected text formatting ОчиÑ�тить наÑ�тройки формата текущего или выбранного текÑ�та &New Window &Ð�овое Окно Open a new window for the same file Открыть Ñ�тот же файл в новом окне Error - could not write to {} Ошибка — не могу запиÑ�ать в {} File saved Файл Ñ�охранен TreeLine - Save As TreeLine — Сохранить Как Error - could not write to file Ошибка — невозможно запиÑ�ать файл TreeLine - Open Configuration File TreeLine — Открыть Файл Конфигурации Error - could not read file {0} Ошибка — не могу прочитать файл {0} Converted {0} branches into clones Конвертировано {0} ветвей в клоны No identical nodes found Идентичные узлы не найдены Cannot expand without common fields Ð�евозможно раÑ�ширить без общих полей Category Fields ПолÑ� Категории Select fields for new level Выберите полÑ� длÑ� нового уровнÑ� Warning - file corruption! Skipped bad child references in the following nodes: treeformats DEFAULT ПО УМОЛЧÐ�Ð�ИЮ FILE ФÐ�ЙЛ TYPE ТИП TitleFormat ФорматЗаголовка OutputFormat ФорматВывода SpaceBetween ПробелМежду FormatHtml ФорматироватьHTML Bullets Маркеры Table Таблица ChildType ДочернийТип Icon Значок GenericType ОбщийТип ConditionalRule УÑ�ловноеПравило ListSeparator РазделительЭлементовСпиÑ�ка ChildTypeLimit ОграничениеДочернегоТипа FIELD ПОЛЕ FieldType Тип ПолÑ� Format Формат Prefix ПриÑ�тавка Suffix Окончание InitialValue Ð�ачальноеЗначение NumLines Ð�умСтроки SortKeyNum Ð�омСортКл SortForward СортВперед EvalHtml ОпредHTML imports &Tab indented text, one node per line ТекÑ�Ñ‚ Ñ� &Tab-отÑ�тупами, один узел на Ñ�троку Co&mma delimited (CSV) text table with level column && header row ТекÑ�товаÑ� таблица, размеченнаÑ� за&пÑ�тыми (CSV), Ñ�о Ñ�толбцом уровней && Ñ�трокой заголовка Comma delimited (CSV) text table &with header row ТекÑ�товаÑ� таблица, размеченнаÑ� за&пÑ�тыми (CSV) Ñ�о Ñ�трокой заголовка Tab delimited text table with header &row ТекÑ�товаÑ� таблица, размеченнаÑ� Tab, Ñ�о Ñ�Ñ‚&рокой заголовка Plain text, one &node per line (CR delimited) ПроÑ�той текÑ�Ñ‚, один &узел на Ñ�троку (ограниченный переноÑ�ом Ñ�троки) Plain text &paragraphs (blank line delimited) &ПроÑ�той текÑ�Ñ‚ Ñ� абзацами (разграничены пуÑ�тыми Ñ�троками) &HTML bookmarks (Mozilla Format) Закладки &HTML (в формате Mozilla) &XML bookmarks (XBEL format) Закладки &XML (в формате XBEL) Other Другие Old Tree&Line File (1.x or 2.x) Файл Tree&Line Старой ВерÑ�ии (1.x или 2.x) Treepad &file (text nodes only) &Файл Treepad (только текÑ�товые узлы) &Generic XML (non-TreeLine file) XML &Общего Вида (не файл Treeline) Open &Document (ODF) outline Открыть Структуру &Документа (ODF) FOLDER ПÐ�ПКÐ� BOOKMARK ЗÐ�КЛÐ�ДКÐ� SEPARATOR РÐ�ЗДЕЛИТЕЛЬ Link ГиперÑ�Ñ�ылка Text ТекÑ�Ñ‚ Import File Импортировать Файл Choose Import Method Выберите СпоÑ�об ИмпортированиÑ� Invalid File Ð�еверный Файл "{0}" is not a valid TreeLine file. Use an import filter? "{0}" не Ñ�влÑ�влÑ�етÑ�Ñ� файлом, подходÑ�щим длÑ� Treeline. Применить фильтр длÑ� импорта? TreeLine - Import File TreeLine — Импортировать Файл Error - could not read file {0} Ошибка — невозможно прочитать файл {0} Error - improper format in {0} Ошибка — неверный формат в {0} TABLE ТÐ�БЛИЦÐ� Invalid level number on line {0} Ð�еверный номер уровнÑ� в Ñ�троке {0} Bad CSV format on Line {0} Ð�еверный формат CSV в Ñ�троке {0} Invalid level structure Ð�евернаÑ� Ñ�труктура уровнÑ� Too many entries on Line {0} Слишком много Ñ�лементов в Строке {0} Bookmarks Закладки No headings found treestructure Main Главный nodeformat Name ИмÑ� treemaincontrol Warning: Could not create local socket Внимание: Ð�евозможно Ñ�оздать локальный Ñ�окет missing directory отÑ�утÑ�твующаÑ� директориÑ� Error - could not write config file to {} Ошибка — не могу запиÑ�ать файл конфигурации в {} Error - could not read file {0} Ошибка — невозможно прочитать файл {0} Error - invalid TreeLine file {0} Ошибка — неверный файл файл Treeline {0} Backup file "{}" exists. A previous session may have crashed ИмеетÑ�Ñ� резервнаÑ� копиÑ� файла {}. Возможно предыдущаÑ� Ñ�еÑ�Ñ�иÑ� была аварийно завершена &Restore Backup &ВоÑ�Ñ�тановить из резервной копии файла &Delete Backup Удалить файл &Резервной Копии &Cancel File Open &Отмена ОткрытиÑ� Файла Error - could not rename "{0}" to "{1}" Ошибка — невозможно переименовать {0} в {1} Error - could not remove backup file {} Ошибка — невозможно удалить резервную копию файла &New... &Ð�овый... New File Ð�овый Файл Start a new file Создать новый файл &Open... &Открыть... Open File Открыть Файл Open a file from disk Открыть файл Ñ� диÑ�ка Open Sa&mple... Открыть П&ример... Open Sample Открыть Пример Open a sample file Открыть файл примера &Import... &Импортировать... Open a non-TreeLine file Открыть не-Treeline файл &Quit &Выход Exit the application Выйти из приложениÑ� &Configure Data Types... &Ð�аÑ�троить Типы Данных... Modify data types, fields & output lines Изменить типы данных, полÑ� & Ñ�троки вывода Show C&onfiguration Structure... Показать С&конфигурированную Структуру... Show read-only visualization of type structure Показать доÑ�тупное только длÑ� чтениÑ� предÑ�тавление Ñ�труктуры типов Sor&t Nodes... &Сортировать Узлы... Define node sort operations Задать параметры Ñ�ортировки узлов Update &Numbering... Обновить &Ð�умерацию... Update node numbering fields Обновить полÑ� нумерации &Find Text... &ПоиÑ�к ТекÑ�та... Find text in node titles & data Ð�айти текÑ�Ñ‚ в заголовках узлов & данных &Conditional Find... &УÑ�ловный ПоиÑ�к... Use field conditions to find nodes ИÑ�пользовать уÑ�ловиÑ� выбора полей длÑ� фильтрации узлов Find and &Replace... ПоиÑ�к и &Замена... Replace text strings in node data Заменить текÑ�товые Ñ�троки в узлах &Text Filter... &ТекÑ�товый Фильтр... Filter nodes to only show text matches Фильтровать узлы, показав только Ñ�овпадениÑ� текÑ�та C&onditional Filter... &УÑ�ловный Фильтр... Use field conditions to filter nodes ИÑ�пользовать уÑ�ловиÑ� выбора полей длÑ� фильтрации узлов &General Options... &Общие Параметры... Set user preferences for all files Ð�азначить уÑ�тановки пользователÑ� длÑ� вÑ�ех файлов Set &Keyboard Shortcuts... &Ð�азначить ГорÑ�чие Клавиши... Customize keyboard commands Ð�аÑ�троить команды клавиатуры C&ustomize Toolbars... &Ð�аÑ�троить Панели инÑ�трументов... Customize toolbar buttons Ð�аÑ�троить кнопки на панели инÑ�трументов Customize Fo&nts... Ð�аÑ�троить Ш&рифты... Customize fonts in various views Ð�аÑ�троить шрифты длÑ� разных форм проÑ�мотра Custo&mize Colors... Ð�аÑ�троить &Цвета... Customize GUI colors and themes Ð�аÑ�троить цвета и темы GUI &Select All &Выбрать вÑ�е Select all text in an editor Выбрать веÑ�ÑŒ текÑ�Ñ‚ в редакторе &Basic Usage... &ОÑ�новы... Display basic usage instructions Показать оÑ�новные иÑ�пользуемые инÑ�трукции &Full Documentation... &ПолнаÑ� ДокументациÑ�... Open a TreeLine file with full documentation Открыть файл Treeline, Ñ�одержащий полную документацию &About TreeLine... &О TreeLine... Display version info about this program Показать Ñ�ведениÑ� о верÑ�ии программы &Select Template &Выбрать Шаблон TreeLine - Open File TreeLine — Открыть Файл Open Sample File Открыть Файл Примера &Select Sample &Выбрать Пример Conditional Find УÑ�ловный ПоиÑ�к Conditional Filter УÑ�ловный Фильтр General Options Общие Параметры Error - basic help file not found Ошибка — файл Ñ�правки по оÑ�новам иÑ�пользованиÑ� не найден TreeLine Basic Usage ОÑ�новы иÑ�пользованиÑ� TreeLine Error - documentation file not found Ошибка — файл документации не найден TreeLine version {0} ВерÑ�иÑ� TreeLine {0} written by {0} автор {0} Library versions: ВерÑ�ии библиотек: helpview Tools ИнÑ�трументы &Back &Ð�азад &Forward &Вперед &Home &К Ð�ачалу Find: Ð�айти: Find &Previous Ð�айти &Предыдущий Find &Next &Ð�айти Следующий Text string not found ТекÑ�товаÑ� Ñ�трока не найдена treewindow Data Output Вывод Данных Data Edit Редактор Данных Title List СпиÑ�ок Заголовков &Expand Full Branch &Развернуть Ð’Ñ�ÑŽ Ветвь Expand all children of the selected nodes РаÑ�крыть вÑ�е дочерние узлы выбранных узлов &Collapse Full Branch &Свернуть Ð’Ñ�ÑŽ Ветвь Collapse all children of the selected nodes Свернуть вÑ�е дочерние узлы выбранных узлов &Previous Selection &Предыдущий Выбор Return to the previous tree selection ВернутьÑ�Ñ� к предыдущему выбору в дереве &Next Selection &Следующий Выбор Go to the next tree selection in history Перейти к Ñ�ледующему выбору в иÑ�тории Show Data &Output Показать &Вывод Данных Show data output in right view Показать вывод данных в форме Ñ�права Show Data &Editor Показать &Редактор Данных Show data editor in right view Показать редактор данных в форме Ñ�права Show &Title List Показать СпиÑ�ок &Заголовков Show title list in right view Показать Ñ�пиÑ�ок заголовков в форме Ñ�права Show &Breadcrumb View Показать &Ð�авигационную цепочку Toggle showing breadcrumb ancestor view Переключить на показ навигационной цепочки к предку &Show Child Pane &Показать Панель Дочернего Узла Toggle showing right-hand child views Переключить на показ дочерних узлов в форме Ñ�права Show Output &Descendants Показать Вывод &Потомков Toggle showing output view indented descendants Переключить показ потомков Ñ� отÑ�тупами &Close Window &Закрыть Окно Close this window Закрыть Ñ�то окно Start Incremental Search Ð�ачать Пошаговый ПоиÑ�к Next Incremental Search Пошагово ИÑ�кать Следующий Previous Incremental Search Пошагово ИÑ�кать Предыдущий &File &Файл &Edit &Правка &Node &Узел &Data &Данные &Tools &ИнÑ�трументы Fo&rmat &Формат &View &Вид &Window &Окно &Help &Справка exports Bookmarks Закладки TreeLine - Export HTML TreeLine — ЭкÑ�порт в HTML Error - export template files not found. Check your TreeLine installation. Ошибка — файлы шаблона длÑ� Ñ�кÑ�порта не найдены. Проверьте вашу уÑ�тановку Treeline. Error - cannot link to unsaved TreeLine file. Save the file and retry. Ошибка — невозможно уÑ�тановить Ñ�Ñ�ылку на неÑ�охраненный файл Treeline. Сохраните файл и попробуйте Ñ�нова. Warning - no relative path from "{0}" to "{1}". Continue with absolute path? Внимание — отÑ�утÑ�твует отноÑ�ительный путь от{0} к {1}. Продолжить, иÑ�пользуÑ� абÑ�олютный путь? TreeLine - Export Text Titles TreeLine — ЭкÑ�порт Заголовков ТекÑ�та TreeLine - Export Plain Text TreeLine — ЭкÑ�порт в ПроÑ�той ТекÑ�Ñ‚ TreeLine - Export Text Tables TreeLine — ЭкÑ�порт в ТекÑ�товые Таблицы TreeLine - Export TreeLine Subtree TreeLine — ЭкÑ�порт в Поддерево Treeline TreeLine - Export Generic XML TreeLine — ЭкÑ�порт в XML Общего Вида TreeLine - Export ODF Text TreeLine — ЭкÑ�порт в ODF ТекÑ�Ñ‚ TreeLine - Export HTML Bookmarks TreeLine — ЭкÑ�порт в Закладки HTML TreeLine - Export XBEL Bookmarks TreeLine — ЭкÑ�порт в Закладки XBEL Parent Родитель &HTML &HTML &Text &ТекÑ�Ñ‚ Tree&Line Tree&Line &ODF Outline Структура &ODF &XML (generic) &XML (общего вида) Book&marks За&кладки &Single HTML page ОдиночнаÑ� Ñ�траница &HTML Single &HTML page with navigation pane ОдиночнаÑ� Ñ�траница &HTML Ñ� панелью навигации Multiple HTML &pages with navigation pane МногоÑ�траничный &HTML Ñ� панелью навигации Multiple HTML &data tables МногоÑ�траничный HTML Ñ� таблицами &данных Live tree view, linked to TreeLine file (for web server) Интерактивный проÑ�мотр дерева, привÑ�занного к файлу Treeline (длÑ� веб-Ñ�ервера) Live tree view, single file (embedded data) Интерактивный проÑ�мотр дерева, одиночный файл (вÑ�троенные данные) &Tabbed title text &Табулированный текÑ�Ñ‚ заголовков &Unformatted output of all text &Ð�еформатированный вывод вÑ�его текÑ�та &Comma delimited (CSV) table of descendants (level numbers) Таблица потомков (номера уровней), размеченнаÑ� &запÑ�тыми (CSV) Comma &delimited (CSV) table of children (single level) Таблица дочерних узлов, размеченнаÑ� &запÑ�тыми (CSV) (единÑ�твенный уровень) Tab &delimited table of children (&single level) Таблица дочерних узлов, размеченнаÑ� Tab (&единÑ�твенный уровень) &Old TreeLine (2.0.x) &СтараÑ� верÑ�иÑ� Treeline (2.0.x) &TreeLine Subtree Поддерево &TreeLine &HTML format bookmarks Закладки в формате &HTML &XBEL format bookmarks Закладки в формате &XBEL File Export ЭкÑ�порт Файла Choose export format type Выберите тип формата длÑ� Ñ�кÑ�порта Choose export format subtype Выберите подтип формата длÑ� Ñ�кÑ�порта Choose export options Выберите наÑ�тройки Ñ�кÑ�порта What to Export Что ЭкÑ�портировать &Entire tree &Ð’Ñ�е Дерево Selected &branches Выбранные &ветви Selected &nodes Выбранные &узлы Other Options Другие Ð�аÑ�тройки &Include root nodes &Включить корневые узлы &Only open node children &Только открытые дочерние узлы Include &print header && footer &Включить верхний && нижний колонтитулы &Columns &Столбцы Navigation pane &levels &Уровни навигационной панели Must select nodes prior to export Перед Ñ�кÑ�портом должны быть выбраны узлы Error - export template files not found. Check your TreeLine installation. optiondefaults Monday Понедельник Wednesday Среда Tuesday Вторник Thursday Четверг Friday ПÑ�тница Sunday ВоÑ�креÑ�енье Saturday Суббота Startup Condition УÑ�ловиÑ� ЗапуÑ�ка Программы Automatically open last file used Ð�втоматичеÑ�ки открывать поÑ�ледний файл Show breadcrumb ancestor view Включить проÑ�мотр навигационной цепочки к предку Show child pane in right hand views Показывать панель дочернего узла в форме Ñ�права Show descendants in output view Показывать потомков в окне вывода Restore tree view states of recent files ВоÑ�Ñ�танавливать Ñ�оÑ�тоÑ�ние поÑ�леднего файла Remove inaccessible recent file entries УдалÑ�ть недоÑ�тупные данные, вошедшие в поÑ�ледний файл Restore previous window geometry ВоÑ�Ñ�танавливать уÑ�тановки окна при запуÑ�ке Features Available ДоÑ�тупные Функции Open files in new windows Открывать файлы в новых окнах Minimize application to system tray Сворачивать приложение в Ñ�иÑ�темный лоток Activate data editors on mouse hover Ð�ктивировать полÑ� редактора данных при наведении мышью Limit data editor height to window size Ограничить выÑ�оту редактора данных размером окна Click node to rename Переименовывать узлы по щелчку мыши Rename new nodes when created Редактировать имена новых узлов при Ñ�оздании Tree drag && drop available Разрешить перетаÑ�кивание Ñ�лементов дерева мышью Indent (pretty print) TreeLine JSON files Смещать вправо (длÑ� краÑ�ивой печати) JSON файлы Treeline Show icons in the tree view Показывать значки в дереве Show math fields in the Data Edit view Показывать математичеÑ�кие полÑ� в Редакторе Данных Show numbering fields in the Data Edit view Показывать полÑ� нумерации в Редакторе Данных Undo Memory СохранÑ�ть длÑ� ВоÑ�Ñ�тановлениÑ� Number of undo levels ЧиÑ�ло возможных отмен дейÑ�твий Auto Save Ð�втоСохранение Minutes between saves (set to 0 to disable) КоличеÑ�тво минут между Ñ�охранениÑ�ми (уÑ�тановите 0 длÑ� отключениÑ�) Recent Files ПоÑ�ледние Файлы Number of recent files in the file menu ЧиÑ�ло поÑ�ледних файлов в файловом меню Times ВремÑ� Data Editor Formats Форматы Редактора Данных Dates Дата First day of week Первый день недели Appearance Вид Child indent offset (in font height units) Величина Ñ�двига дочерних узлов (в единицах размера шрифта) First day of week Child indent offset (in font height units) globalref All TreeLine Files Ð’Ñ�е Файлы Treeline TreeLine Files Файлы TreeLine TreeLine Files - Compressed Файлы TreeLine — Сжаты TreeLine Files - Encrypted Файлы TreeLine — Зашифрованы Old TreeLine Files Файлы Старой ВерÑ�ии TreeLine All Files Ð’Ñ�е Файлы HTML Files Файлы HTML Text Files ТекÑ�товые Файлы XML Files Файлы XML CSV (Comma Delimited) Files Файлы CSV (Размечены ЗапÑ�тыми) ODF Text Files Файлы ODF Treepad Files Файлы Treepad PDF Files Файлы PDF treeview Search for: Ð�айти: Search for: {0} Ð�айти: {0} Search for: {0} (not found) Ð�айти: {0} (не найдено) Next: {0} Следующий: {0} Next: {0} (not found) Следующий: {0} (не найдено) Filtering by "{0}", found {1} nodes Отфильтровано по "{0}", узлов найдено {0} Conditional filtering, found {0} nodes УÑ�ловнаÑ� фильтрациÑ�, узлов найдено {0} titlelistview Select in Tree Выбрать в Дереве matheval Illegal "{}" characters Ð�едопуÑ�тимые "{}" Ñ�имволы Invalid field modifiers Ð�еверные модификаторы полÑ� Child references must be combined in a function СÑ�ылки на дочерние узлы должны быть включены в функцию Illegal syntax in equation Ð�едопуÑ�тимый Ñ�интакÑ�иÑ� в выражении Illegal function present: {0} Ð�едопуÑ�тимаÑ� функциÑ�: {0} Illegal object type or operator: {0} Ð�едопуÑ�тимый тип объекта или оператор: {0} printdata Warning: Page size and margin settings unsupported on current printer. Save page adjustments? Внимание: Выбранный размер и полÑ� Ñ�траницы не поддерживаетÑ�Ñ� данным принтером. Сохранить наÑ�тройки Ñ�траницы? Warning: Page size setting unsupported on current printer. Save adjustment? Внимание: Выбранный размер Ñ�траницы не поддерживаетÑ�Ñ� данным принтером. Сохранить наÑ�тройки? Warning: Margin settings unsupported on current printer. Save adjustments? Внимание: Ð�аÑ�тройки полей не поддерживаютÑ�Ñ� данным принтером. Сохранить наÑ�тройки? Error initializing printer Ошибка инициализации принтера TreeLine - Export PDF TreeLine — ЭкÑ�порт в PDF Warning: Page size and margin settings unsupported on current printer. Save page adjustments? Warning: Page size setting unsupported on current printer. Save adjustment? Warning: Margin settings unsupported on current printer. Save adjustments? TreeLine-3.2.1/working/translations/treeline_xx.ts000066400000000000000000005544431506556630100223510ustar00rootroot00000000000000 conditional starts with ends with contains True False and or [All Types] Node Type &Add New Rule &Remove Rule &OK &Cancel Find &Previous Find &Next &Filter &End Filter &Close No conditional matches were found Rule {0} Saved Rules Name: &Load &Save &Delete configdialog Configure Data Types T&ype List Typ&e Config Field &List &Field Config O&utput &Show Advanced &OK &Apply &Reset &Cancel &Hide Advanced Error - circular reference in math field equations Add or Remove Data Types &New Type... Co&py Type... Rena&me Type... &Delete Type Add Type Enter new type name: Copy Type &Derive from original Rename Type Rename from {} to: Cannot delete data type being used by nodes [None] no type set &Data Type Default Child &Type Icon Change &Icon Output Options Add &blank lines between nodes Allow &HTML rich text in format Add text bullet&s Use a table for field &data Combination && Child List Output &Separator Derived from &Generic Type Automatic Types None Modify Co&nditional Types Create Co&nditional Types Set Types Conditionally Modify &Field List Name Type Sort Key Move U&p Move Do&wn &New Field... Rena&me Field... Dele&te Field Sort &Keys... fwd rev Add Field Enter new field name: Rename Field File Info Reference F&ield &Field Type Outpu&t Format Format &Help Extra Text &Prefix Suffi&x Default &Value for New Nodes Editor Height Num&ber of text lines Math Equation Define Equation F&ield List &Title Format Out&put Format Other Field References Reference Le&vel Refere&nce Type The name cannot be empty The name must start with a letter The name cannot start with "xml" The name cannot contain spaces The following characters are not allowed: {} The name was already used Set Data Type Icon Clear &Select forward reverse Sort Key Fields Available &Fields &Sort Criteria Field Direction Move &Up &Move Down Flip &Direction Self Reference Parent Reference Root Reference Child Reference Child Count Date Result Time Result add subtract multiply divide floor divide modulus power sum of items maximum minimum average absolute value square root natural logarithm base-10 logarithm factorial round to num digits lower integer higher integer truncated integer floating point sine of radians cosine of radians tangent of radians arc sine arc cosine arc tangent radians to degrees degrees to radians pi constant natural log constant Define Math Field Equation Field References Reference &Level Reference &Type Available &Field List &Result Type Description &Equation Equation error: {} Boolean Result Text Result Arithmetic Operators Comparison Operators Text Operators equal to less than greater than less than or equal to greater than or equal to not equal to true value, condition, false value true if 1st text arg starts with 2nd arg true if 1st text arg ends with 2nd arg true if 1st text arg contains 2nd arg concatenate text join text using 1st arg as separator convert text to upper case convert text to lower case in 1st arg, replace 2nd arg with 3rd arg Operations O&perator Type Oper&ator List logical and logical or Output HTML Evaluate &HTML tags Child Type Limits [All Types Available] &Select All Select &None Number Result Count Number of Children dataeditors Today's &Date &Open Link Open &Folder External Link Scheme &Browse for File File Path Type Absolute Relative Address Display Name &OK &Cancel TreeLine - External Link File &Go to Target Internal Link &Open Picture Picture Link TreeLine - Picture File Set to &Now Clear &Link (Click link target in tree) link exports Bookmarks TreeLine - Export HTML TreeLine - Export Text Titles TreeLine - Export Plain Text TreeLine - Export Text Tables TreeLine - Export Generic XML TreeLine - Export TreeLine Subtree TreeLine - Export ODF Text TreeLine - Export HTML Bookmarks TreeLine - Export XBEL Bookmarks &HTML &Text &ODF Outline Book&marks &Single HTML page Single &HTML page with navigation pane Multiple HTML &pages with navigation pane Multiple HTML &data tables &Tabbed title text &Unformatted output of all text &HTML format bookmarks &XBEL format bookmarks File Export Choose export format type Choose export format subtype Choose export options What to Export &Entire tree Selected &branches Selected &nodes Other Options &Only open node children Include &print header && footer &Columns Navigation pane &levels Error - export template files not found. Check your TreeLine installation. Error - cannot link to unsaved TreeLine file. Save the file and retry. Warning - no relative path from "{0}" to "{1}". Continue with absolute path? Parent Tree&Line &XML (generic) Live tree view, linked to TreeLine file (for web server) Live tree view, single file (embedded data) &Comma delimited (CSV) table of descendants (level numbers) Comma &delimited (CSV) table of children (single level) Tab &delimited table of children (&single level) &Old TreeLine (2.0.x) &TreeLine Subtree &Include root nodes Must select nodes prior to export fieldformat Text HtmlText OneLineText SpacedText Number Math Numbering Boolean Date Time Choice AutoChoice Combination AutoCombination ExternalLink InternalLink Picture RegularExpression Now Optional Digit # Required Digit 0 Digit or Space (external) <space> Decimal Point . Decimal Comma , Space Separator (internal) <space> Optional Sign - Required Sign + Exponent (capital) E Exponent (small) e Number 1 Capital Letter A Small Letter a Capital Roman Numeral I Small Roman Numeral i Level Separator / Section Separator . "/" Character // "." Character .. Outline Example I../A../1../a)/i) Section Example 1.1.1.1 Separator / Example 1/2/3/4 yes/no true/false T/F Y/N Any Character . End of Text $ 0 Or More Repetitions * 1 Or More Repetitions + 0 Or 1 Repetitions ? Set of Numbers [0-9] Lower Case Letters [a-z] Upper Case Letters [A-Z] Not a Number [^0-9] Or | Escape a Special Character \ DateTime Day (1 or 2 digits) %-d Day (2 digits) %d Weekday Abbreviation %a Weekday Name %A Month (1 or 2 digits) %-m Month (2 digits) %m Month Abbreviation %b Month Name %B Year (2 digits) %y Year (4 digits) %Y Week Number (0 to 53) %-U Day of year (1 to 366) %-j Hour (0-23, 1 or 2 digits) %-H Hour (00-23, 2 digits) %H Hour (1-12, 1 or 2 digits) %-I Hour (01-12, 2 digits) %I Minute (1 or 2 digits) %-M Minute (2 digits) %M Second (1 or 2 digits) %-S Second (2 digits) %S Microseconds (6 digits) %f AM/PM %p Comma Separator \, Dot Separator \. DescendantCount genboolean true false yes no globalref TreeLine Files TreeLine Files - Compressed TreeLine Files - Encrypted All Files HTML Files Text Files XML Files ODF Text Files Treepad Files PDF Files CSV (Comma Delimited) Files All TreeLine Files Old TreeLine Files helpview Tools &Back &Forward &Home Find: Find &Previous Find &Next Text string not found imports &Tab indented text, one node per line Tab delimited text table with header &row Plain text &paragraphs (blank line delimited) Treepad &file (text nodes only) &Generic XML (non-TreeLine file) Open &Document (ODF) outline &HTML bookmarks (Mozilla Format) &XML bookmarks (XBEL format) FOLDER BOOKMARK SEPARATOR Link Text Import File Choose Import Method Invalid File "{0}" is not a valid TreeLine file. Use an import filter? TreeLine - Import File Error - could not read file {0} Error - improper format in {0} TABLE Bookmarks Too many entries on Line {0} Plain text, one &node per line (CR delimited) Bad CSV format on Line {0} Co&mma delimited (CSV) text table with level column && header row Comma delimited (CSV) text table &with header row Other Old Tree&Line File (1.x or 2.x) Invalid level number on line {0} Invalid level structure No headings found matheval Illegal "{}" characters Child references must be combined in a function Illegal syntax in equation Illegal function present: {0} Illegal object type or operator: {0} Invalid field modifiers miscdialogs &OK &Cancel Fields File Properties File Storage &Use file compression Use file &encryption Spell Check Language code or dictionary (optional) Math Fields &Treat blank fields as zeros Encrypted File Password Type Password for "{0}": Type Password: Re-Type Password: Remember password during this session Zero-length passwords are not permitted Re-typed password did not match Default - Single Line Text &Search Text What to Search Full &data &Titles only How to Search &Key words Key full &words F&ull phrase &Regular expression Find Find &Previous Find &Next Filter &Filter &End Filter &Close Error - invalid regular expression Search string "{0}" not found Find and Replace Replacement &Text Any &match Full &words Re&gular expression &Node Type N&ode Fields &Find Next &Replace Replace &All [All Types] [All Fields] Search text "{0}" not found Error - replacement failed Replaced {0} matches Sort Nodes What to Sort &Entire tree Selected &branches Selection's childre&n Selection's &siblings Sort Method &Predefined Key Fields Node &Titles Sort Direction &Forward &Reverse &Apply Update Node Numbering What to Update &Selection's children Root Node Include top-level nodes Handling Nodes without Numbering Fields &Ignore and skip &Restart numbers for next siblings Reserve &numbers TreeLine Numbering No numbering fields were found in data types File Menu File Edit Menu Edit Node Menu Node Data Menu Data Tools Menu Tools View Menu View Window Menu Window Help Menu Help Keyboard Shortcuts &Restore Defaults Key {0} is already used Clear &Key --Separator-- Customize Toolbars Toolbar &Size Small Icons Large Icons Toolbar Quantity &Toolbars A&vailable Commands Tool&bar Commands Move &Up Move &Down Tree View Font Output View Font Editor View Font No menu TreeLine - Serious Error A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. Format Menu Format Customize Fonts &Use system default font App Default Font &Use app default font Externally Modified File &Overwrite File &Cancel Save File was externally modified at {} nodeformat Name optiondefaults Monday Tuesday Wednesday Thursday Friday Saturday Sunday Startup Condition Automatically open last file used Show descendants in output view Restore tree view states of recent files Restore previous window geometry Features Available Open files in new windows Click node to rename Rename new nodes when created Tree drag && drop available Show icons in the tree view Show math fields in the Data Edit view Show numbering fields in the Data Edit view Undo Memory Number of undo levels Auto Save Minutes between saves (set to 0 to disable) Recent Files Number of recent files in the file menu Data Editor Formats Times Dates First day of week Appearance Child indent offset (in font height units) Show breadcrumb ancestor view Show child pane in right hand views Remove inaccessible recent file entries Activate data editors on mouse hover Minimize application to system tray Indent (pretty print) TreeLine JSON files Limit data editor height to window size options Choose configuration file location User's home directory (recommended) Program directory (for portable use) &OK &Cancel printdata Error initializing printer TreeLine - Export PDF Warning: Page size and margin settings unsupported on current printer. Save page adjustments? Warning: Page size setting unsupported on current printer. Save adjustment? Warning: Margin settings unsupported on current printer. Save adjustments? printdialogs Print Preview Fit Width Fit Page Zoom In Zoom Out Previous Page Next Page Single Page Facing Pages Print Setup Print Printing Setup &General Options Page &Setup &Font Selection &Header/Footer Print Pre&view... &Print... &OK &Cancel What to print &Entire tree Selected &branches Selected &nodes Included Nodes &Include root node Onl&y open node children Features &Draw lines to children &Keep first child with parent Indent Indent Offse&t (line height units) Letter (8.5 x 11 in.) Legal (8.5 x 14 in.) Tabloid (11 x 17 in.) A3 (279 x 420 mm) A4 (210 x 297 mm) A5 (148 x 210 mm) Custom Size Inches (in) Millimeters (mm) Centimeters (cm) &Units Paper &Size &Width: Height: Orientation Portra&it Lan&dscape Margins &Left: &Top: &Right: &Bottom: He&ader: Foot&er: Columns &Number of columns Space between colu&mns Default Font &Use TreeLine output view font Select Font &Font Font st&yle Si&ze Sample AaBbCcDdEeFfGg...TtUuVvWvXxYyZz &Header Left Header C&enter Header &Right Footer &Left Footer Ce&nter Footer Righ&t Fiel&ds Field For&mat Header and Footer Field Format for "{0}" Output &Format Format &Help Extra Text &Prefix &Suffix Error: Page size or margins are invalid TreeLine PDF Printer Select &Printer spellcheck Could not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? Spell Check Error Locate aspell.exe, ipsell.exe or hunspell.exe Program (*.exe) TreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed TreeLine Spell Check Finished spell checking Spell Check Not in Dictionary Word: Context: Suggestions Ignor&e &Ignore All &Add Add &Lowercase &Replace Re&place All &Cancel Finished checking the branch Continue from the top? titlelistview Select in Tree treeformats DEFAULT FILE TYPE FIELD FieldType TitleFormat OutputFormat SpaceBetween FormatHtml Bullets Table ChildType Icon GenericType ConditionalRule ListSeparator ChildTypeLimit Format Prefix Suffix InitialValue NumLines SortKeyNum SortForward EvalHtml treelocalcontrol Error - could not delete backup file {} Save changes to {}? Save changes? &Save Save File Save the current file Save &As... Save the file with a new name &Export... Export the file in various other formats Prop&erties... Set file parameters like compression and encryption P&rint Setup... Set margins, page size and other printing options Print Pre&view... Show a preview of printing results &Print... Print tree output based on current options Print &to PDF... Export to PDF with current printing options &Undo Undo the previous action &Redo Redo the previous undo Cu&t Cut the branch or text to the clipboard &Copy Copy the branch or text to the clipboard &Paste Paste nodes or text from the clipboard Paste non-formatted text from the clipboard &Bold Font Set the current or selected font to bold &Italic Font Set the current or selected font to italic U&nderline Font Set the current or selected font to underline &Font Size Set size of the current or selected text Small Default Large Larger Largest Set Font Size Font C&olor... Set the color of the current or selected text &External Link... Add or modify an extrnal web link Internal &Link... Add or modify an internal node link Clear For&matting Clear current or selected text formatting &Rename Rename the current tree entry title Insert Sibling &Before Insert new sibling before selection Insert Sibling &After Insert new sibling after selection Add &Child Add new child to selected parent &Delete Node Delete the selected nodes &Indent Node Indent the selected nodes &Unindent Node Unindent the selected nodes &Move Up Move the selected nodes up M&ove Down Move the selected nodes down Move &First Move the selected nodes to be the first children Move &Last Move the selected nodes to be the last children &Set Node Type Set the node type for selected nodes Set Node Type Copy Types from &File... Copy the configuration from another TreeLine file Flatten &by Category Collapse descendants by merging fields Add Category &Level... Insert category nodes above children &Spell Check... &New Window Open a new window for the same file Error - could not write to {} TreeLine - Save As Error - could not write to file TreeLine - Open Configuration File Error - could not read file {0} Cannot expand without common fields Category Fields Select fields for new level File saved Pa&ste Plain Text Paste C&hild Paste a child node from the clipboard Paste Sibling &Before Paste a sibling before selection Paste Sibling &After Paste a sibling after selection Paste Cl&oned Child Paste a child clone from the clipboard Paste Clo&ned Sibling Before Paste a sibling clone before selection Paste Clone&d Sibling After Paste a sibling clone after selection Clone All &Matched Nodes Convert all matching nodes into clones &Detach Clones Detach all cloned nodes in current branches S&wap Category Levels Swap child and grandchild category nodes Converted {0} branches into clones No identical nodes found Warning - file corruption! Skipped bad child references in the following nodes: Spell check the tree's text data &Regenerate References Force update of all conditional types & math fields Insert &Date Insert current date as text St&rikethrough Font Set the current or selected font to strikethough treemaincontrol Warning: Could not create local socket Error - could not write config file to {} Error - could not read file {0} Backup file "{}" exists. A previous session may have crashed &Restore Backup &Delete Backup &Cancel File Open Error - could not rename "{0}" to "{1}" Error - could not remove backup file {} &New... New File Start a new file &Open... Open File Open a file from disk Open Sa&mple... Open Sample Open a sample file &Import... Open a non-TreeLine file &Quit Exit the application &Select All Select all text in an editor &Configure Data Types... Modify data types, fields & output lines Sor&t Nodes... Define node sort operations Update &Numbering... Update node numbering fields &Find Text... Find text in node titles & data &Conditional Find... Use field conditions to find nodes Find and &Replace... Replace text strings in node data &Text Filter... Filter nodes to only show text matches C&onditional Filter... Use field conditions to filter nodes &General Options... Set user preferences for all files Set &Keyboard Shortcuts... Customize keyboard commands C&ustomize Toolbars... Customize toolbar buttons Customize Fo&nts... Customize fonts in various views &Basic Usage... Display basic usage instructions &Full Documentation... Open a TreeLine file with full documentation &About TreeLine... Display version info about this program &Select Template TreeLine - Open File Open Sample File &Select Sample Conditional Find Conditional Filter General Options Error - basic help file not found TreeLine Basic Usage Error - documentation file not found Error - invalid TreeLine file {0} TreeLine version {0} written by {0} Library versions: missing directory Show C&onfiguration Structure... Show read-only visualization of type structure Custo&mize Colors... Customize GUI colors and themes treenode New treestructure Main treeview Filtering by "{0}", found {1} nodes Conditional filtering, found {0} nodes Search for: Search for: {0} Search for: {0} (not found) Next: {0} Next: {0} (not found) treewindow Data Output Data Edit Title List &Expand Full Branch Expand all children of the selected nodes &Collapse Full Branch Collapse all children of the selected nodes &Previous Selection Return to the previous tree selection &Next Selection Go to the next tree selection in history Show Data &Output Show data output in right view Show Data &Editor Show data editor in right view Show &Title List Show title list in right view &Show Child Pane Toggle showing right-hand child views Toggle showing output view indented descendants &Close Window Close this window &File &Edit &Node &Data &Tools &View &Window &Help Start Incremental Search Next Incremental Search Previous Incremental Search Show &Breadcrumb View Toggle showing breadcrumb ancestor view Show Output &Descendants Fo&rmat colorset Dialog background color Dialog text color Text widget background color Text widget foreground color Selected item background color Selected item text color Link text color Tool tip background color Tool tip foreground color Button background color Button text color Disabled text foreground color Disabled button text color Color Settings Color Theme Default system theme Dark theme Custom theme &OK &Cancel Custom Colors Theme Colors Select {0} color TreeLine-3.2.1/working/translations/treeline_zh.ts000066400000000000000000005613031506556630100223240ustar00rootroot00000000000000 conditional starts with 以...开始 ends with 以...结尾 contains 包å�« True 真 False å�‡ and 与 or 或 [All Types] [所有类型] Node Type 节点类型 &Add New Rule 添加新规则(&A) &Remove Rule 删除规则(&R) &OK 确认(&O) &Cancel å�–消(&C) Find &Previous 查找上一个(&P) Find &Next 查找下一个(&N) &Filter 过滤(&F) &End Filter 结æ�Ÿè¿‡æ»¤(&E) &Close 关闭(&C) No conditional matches were found 没有找到æ�¡ä»¶åŒ¹é…� Rule {0} 规则{0} Saved Rules ä¿�存规则 Name: å��å­—: &Load 载入(&L) &Save ä¿�å­˜(&S) &Delete 删除(&D) configdialog Configure Data Types é…�置数æ�®ç±»åž‹ T&ype List 类型列表(&y) Typ&e Config 类型é…�ç½®(&e) Field &List 字段列表(&L) &Field Config 字段é…�ç½®(&F) O&utput 输出(&u) &Show Advanced 显示高级(&S) &OK 确认(&O) &Apply 应用(&A) &Reset é‡�ç½®(&R) &Cancel å�–消(&C) &Hide Advanced éš�è—�高级(&H) Error - circular reference in math field equations 错误 - 数学场方程中的循环引用 Add or Remove Data Types 添加或删除数æ�®ç±»åž‹ &New Type... 新类型(&N)... Co&py Type... æ‹·è´�类型(&p)... Rena&me Type... é‡�命å��类型(&m)... &Delete Type 删除类型(&D) Add Type 添加类型 Enter new type name: 输入新类型的å��å­—: Copy Type å¤�制类型 &Derive from original 从原æ�¥ç±»åž‹è¡�生(&D) Rename Type é‡�命å��类型 Rename from {} to: 从{}é‡�命å��为: Cannot delete data type being used by nodes 无法删除节点使用的数æ�®ç±»åž‹ [None] no type set [æ— ] &Data Type æ•°æ�®ç±»åž‹(&D) Default Child &Type 默认å­�节点类型(&T) Icon 图标 Change &Icon 改å�˜å›¾æ ‡(&I) Output Options 输出选项 Add &blank lines between nodes 在节点之间添加空行(&b) Allow &HTML rich text in format å…�许&HTML多格å¼�文本 Add text bullet&s 添加文本项目符å�·(&s) Use a table for field &data 为字段数æ�®ä½¿ç”¨è¡¨æ ¼(&d) Combination && Child List Output &Separator 组å�ˆ&&å­�列表输出分隔符(&S) Derived from &Generic Type 从通用类型è¡�生(&G) Automatic Types 自动类型 None æ—  Modify Co&nditional Types 修改æ�¡ä»¶ç±»åž‹(&n) Create Co&nditional Types 创建æ�¡ä»¶ç±»åž‹(&n) Set Types Conditionally 有æ�¡ä»¶åœ°è®¾ç½®ç±»åž‹ Modify &Field List 修改字段列表(&F) Name å��å­— Type 类型 Sort Key 排åº�é”® Move U&p 上移(&p) Move Do&wn 下移(&w) &New Field... 新字段(&N)... Rena&me Field... é‡�命å��字段(&m)... Dele&te Field 删除字段(&t) Sort &Keys... 排åº�é”®(&K)... fwd æ­£å�‘ rev 逆å�‘ Add Field 添加字段 Enter new field name: 输入新的字段å��ç§°: Rename Field é‡�命å��字段 File Info Reference 文件信æ�¯å�‚考 F&ield 字段(&i) &Field Type 字段类型(&F) Outpu&t Format 输出格å¼�(&t) Format &Help æ ¼å¼�帮助(&H) Extra Text é¢�外文字 &Prefix å‰�ç¼€(&P) Suffi&x å�Žç¼€(&x) Default &Value for New Nodes 新节点的缺çœ�值(&V) Editor Height 编辑器高度 Num&ber of text lines 文本行数(&b) Math Equation 数学方程å¼� Define Equation 定义方程å¼� F&ield List 字段列表(&i) &Title Format 标题格å¼�(&T) Out&put Format 输出格å¼�(&p) Other Field References 其他字段å�‚考 Reference Le&vel å�‚考级别(&v) Refere&nce Type å�‚考类型(&n) The name cannot be empty å��ç§°ä¸�能为空 The name must start with a letter å��称必须以字æ¯�开头 The name cannot start with "xml" å��ç§°ä¸�能以“xmlâ€�开头 The name cannot contain spaces å��ç§°ä¸�能包å�«ç©ºæ ¼ The following characters are not allowed: {} ä¸�å…�许使用以下字符:{} The name was already used 该å��称已被使用 Set Data Type Icon 设置数æ�®ç±»åž‹å›¾æ ‡ Clear &Select 清除选择(&S) forward æ­£å�‘ reverse 逆å�‘ Sort Key Fields 排åº�关键字段 Available &Fields å�¯ç”¨å­—段(&F) &Sort Criteria 排åº�标准(&S) Field 字段 Direction æ–¹å�‘ Move &Up 上移(&U) &Move Down 下移(&M) Flip &Direction 翻转方å�‘(&D) Self Reference 自引用 Parent Reference 父引用 Root Reference 根引用 Child Reference å­�引用 Child Count å­�计数 Date Result 日期结果 Time Result 时间结果 add 加 subtract å‡� multiply 乘 divide 除 floor divide å�‘下å�–整除 modulus 系数 power 乘方 sum of items 项目总和 maximum 最大 minimum 最å°� average å¹³å�‡ absolute value ç»�对值 square root 平方根 natural logarithm 自然对数 base-10 logarithm 以10为底的对数 factorial 阶乘 round to num digits å››èˆ�五入 lower integer 较低的整数(lower integer) higher integer 更高的整数(higher integer) truncated integer 截断的整数(truncated integer) floating point 浮点 sine of radians 正弦 cosine of radians 余弦 tangent of radians 切线(tangent of radians) arc sine 正弦波 arc cosine å��余弦 arc tangent å��正切 radians to degrees 弧度到度 degrees to radians 度数到弧度 pi constant π常数 natural log constant 自然对数常数 Define Math Field Equation 定义数学字段方程 Field References 字段引用 Reference &Level 引用级别(&L) Reference &Type 引用类型(&T) Available &Field List å�¯ç”¨å­—段列表(&F) &Result Type 结果类型(&R) Description æ��è¿° &Equation 方程å¼�(&E) Equation error: {} 方程å¼�错误:{} Boolean Result 布尔结果 Text Result 文本结果 Arithmetic Operators 算术è¿�算符 Comparison Operators 比较è¿�算符 Text Operators 文本è¿�算符 equal to 等于 less than å°�于 greater than 大于 less than or equal to å°�于等于 greater than or equal to 大于等于 not equal to ä¸�ç­‰ true value, condition, false value 真值, æ�¡ä»¶, å�‡å€¼ true if 1st text arg starts with 2nd arg 如果第一个文本å�‚数以第二个å�‚数开头,则为真 true if 1st text arg ends with 2nd arg 如果第一个文本å�‚数以第二个å�‚数结尾,则为真 true if 1st text arg contains 2nd arg 如果第一个文本å�‚数包å�«ç¬¬äºŒä¸ªå�‚数,则为真 concatenate text 连接文本 join text using 1st arg as separator 使用第一个å�‚数作为分隔符连接文本 convert text to upper case 将文本转æ�¢ä¸ºå¤§å†™ convert text to lower case 将文本转æ�¢ä¸ºå°�写 in 1st arg, replace 2nd arg with 3rd arg 在第一个å�‚数中,将第二个å�‚数替æ�¢ä¸ºç¬¬ä¸‰ä¸ªå�‚æ•° Operations è¿�ç®— O&perator Type è¿�算类型(&p) Oper&ator List è¿�算列表(&a) logical and 逻辑与 logical or 逻辑或 Output HTML 输出HTML Evaluate &HTML tags 评估&HTML标记 Child Type Limits å­�类型é™�制 [All Types Available] [所有å�¯ç”¨ç±»åž‹] &Select All 选择所有(&S) Select &None 都ä¸�选(&N) Number Result 数字结果 Count 计数 Number of Children å­�节点数é‡� dataeditors Today's &Date 当å‰�日期(&D) &Open Link 打开链接(&O) Open &Folder 打开文件夹(&F) External Link 外部链接 Scheme 方案 &Browse for File æµ�览文件(&B) File Path Type 文件路径类型 Absolute ç»�对 Relative 相对 Address 地å�€ Display Name 显示å��ç§° &OK 确认(&O) &Cancel å�–消(&C) TreeLine - External Link File TreeLine - 外部链接文件 &Go to Target 转到目标(&G) Internal Link 内部链接 &Open Picture 打开图片(&O) Picture Link 图片链接 TreeLine - Picture File TreeLine - 图片文件 Set to &Now 设置为当å‰�æ—¶é—´(&N) Clear &Link 清除链接(&L) (Click link target in tree) (在树中点击链接目标) link 链接 exports Bookmarks 书签 TreeLine - Export HTML TreeLine - 导出HTML TreeLine - Export Text Titles TreeLine - 导出文本标题 TreeLine - Export Plain Text TreeLine - 导出纯文本 TreeLine - Export Text Tables TreeLine - 导出文本表格 TreeLine - Export Generic XML TreeLine - 导出通用XML TreeLine - Export TreeLine Subtree TreeLine - 导出TreeLineå­�æ ‘ TreeLine - Export ODF Text TreeLine - 导出ODF文本 TreeLine - Export HTML Bookmarks TreeLine - 导出HTML书签 TreeLine - Export XBEL Bookmarks TreeLine - 导出XBEL书签 &HTML &HTML &Text 文本(&T) &ODF Outline &ODF大纲 Book&marks 书签(&m) &Single HTML page å�•个HTML页é�¢(&S) Single &HTML page with navigation pane 带有导航窗格的å�•个&HTML页é�¢ Multiple HTML &pages with navigation pane 带导航窗格的多个HTML页é�¢(&p) Multiple HTML &data tables 多个HTML和数æ�®è¡¨(&d) &Tabbed title text 标签标题文字(&T) &Unformatted output of all text 未格å¼�化的所有文本输出(&U) &HTML format bookmarks &HTMLæ ¼å¼�的书签 &XBEL format bookmarks &XBELæ ¼å¼�的书签 File Export 文件导出 Choose export format type 选择导出格å¼�类型 Choose export format subtype 选择导出格å¼�å­�类型 Choose export options 选择导出选项 What to Export 导出什么 &Entire tree 整棵树(&E) Selected &branches 选定的分支(&b) Selected &nodes 选定的节点(&n) Other Options 其他选项 &Only open node children å�ªæœ‰æ‰“开节点的å­�节点(&O) Include &print header && footer 包括打å�°æ ‡é¢˜å’Œé¡µè„š(&p) &Columns 列(&C) Navigation pane &levels 导航窗格级别(&l) Error - export template files not found. Check your TreeLine installation. 错误 - 未找到导出模æ�¿æ–‡ä»¶ã€‚ 检查TreeLine安装。 Error - cannot link to unsaved TreeLine file. Save the file and retry. 错误 - 无法链接到未ä¿�存的TreeLine文件。 ä¿�存文件并é‡�试。 Warning - no relative path from "{0}" to "{1}". Continue with absolute path? 警告 - 没有从“{0}â€�到“{1}â€�的相对路径。 ç»§ç»­ç»�对路径? Parent 父 Tree&Line Tree&Line &XML (generic) &XML (通用) Live tree view, linked to TreeLine file (for web server) 实时树视图,链接到TreeLine文件(用于Webæœ�务器) Live tree view, single file (embedded data) 实时树视图,å�•个文件(嵌入数æ�®) &Comma delimited (CSV) table of descendants (level numbers) 逗å�·åˆ†éš”(CSV)å�Žä»£è¡¨æ ¼(级别编å�·)(&C) Comma &delimited (CSV) table of children (single level) 逗å�·åˆ†éš”(CSV)å­�表格(å�•级)(&d) Tab &delimited table of children (&single level) 制表符分隔(CSV)å­�表格(å�•级)(&d) &Old TreeLine (2.0.x) è€�版本TreeLine (2.0.x)(&O) &TreeLine Subtree TreeLineå­�æ ‘(&T) &Include root nodes 包括根节点(&I) Must select nodes prior to export 必须在导出之å‰�选择节点 fieldformat Text 文本 HtmlText Html文本 OneLineText å�•行文本 SpacedText 间隔文本 Number æ•°å­— Math æ•°å­¦ Numbering ç¼–å�· Boolean 布尔 Date 日期 Time æ—¶é—´ Choice 选择 AutoChoice 自动选择 Combination 组å�ˆ AutoCombination 自动组å�ˆ ExternalLink 外部链接 InternalLink 内部链接 Picture 图片 RegularExpression 正则表达å¼� Now 现在 Optional Digit # å�¯é€‰æ•°å­— # Required Digit 0 必需数字 0 Digit or Space (external) <space> 数字或空格(外部) <space> Decimal Point . å°�数点 . Decimal Comma , å��进制逗å�· , Space Separator (internal) <space> 空格分隔符 (内部) <space> Optional Sign - å�¯é€‰æ ‡å¿— - Required Sign + 必需的标志 + Exponent (capital) E 指数 (大写) E Exponent (small) e 指数(å°�写) e Number 1 æ•° 1 Capital Letter A 大写字æ¯� A Small Letter a å°�写字æ¯� a Capital Roman Numeral I 大写罗马数字 I Small Roman Numeral i å°�写罗马数字 i Level Separator / 级分隔符 / Section Separator . 段è�½åˆ†éš”符 . "/" Character // "/" 字符 // "." Character .. "." 字符 .. Outline Example I../A../1../a)/i) 大纲例å­� I../A../1../a)/i) Section Example 1.1.1.1 段è�½ä¾‹å­� 1.1.1.1 Separator / 分隔符 / Example 1/2/3/4 例å­� 1/2/3/4 yes/no yes/no true/false true/false T/F T/F Y/N Y/N Any Character . ä»»æ„�字符 . End of Text $ 文本结尾 $ 0 Or More Repetitions * é‡�å¤�0或多次 * 1 Or More Repetitions + é‡�å¤�1或多次 + 0 Or 1 Repetitions ? é‡�å¤�0或1次 ? Set of Numbers [0-9] æ•°å­— [0-9] Lower Case Letters [a-z] å°�写字æ¯� [a-z] Upper Case Letters [A-Z] 大写字æ¯� [A-Z] Not a Number [^0-9] é�žæ•°å­— [^0-9] Or | 或 | Escape a Special Character \ 特殊字符转义 \ DateTime 日期时间 Day (1 or 2 digits) %-d æ—¥ (1或2ä½�) %-d Day (2 digits) %d æ—¥ (2ä½�) %d Weekday Abbreviation %a 星期缩写 %a Weekday Name %A 星期å��å­— %A Month (1 or 2 digits) %-m 月 (1 or 2 digits) %-m Month (2 digits) %m 月 (2 digits) %m Month Abbreviation %b 月缩写 %b Month Name %B 月å��å­— %B Year (2 digits) %y å¹´ (2 digits) %y Year (4 digits) %Y å¹´ (4 digits) %Y Week Number (0 to 53) %-U 星期数字 (0 to 53) %-U Day of year (1 to 366) %-j 年内第几日 (1 to 366) %-j Hour (0-23, 1 or 2 digits) %-H å°�æ—¶(0-23, 1 or 2 digits) %-H Hour (00-23, 2 digits) %H å°�æ—¶(00-23, 2 digits) %H Hour (1-12, 1 or 2 digits) %-I å°�æ—¶ (1-12, 1 or 2 digits) %-I Hour (01-12, 2 digits) %I å°�æ—¶ (01-12, 2 digits) %I Minute (1 or 2 digits) %-M 分 (1 or 2 digits) %-M Minute (2 digits) %M 分 (2 digits) %M Second (1 or 2 digits) %-S ç§’ (1 or 2 digits) %-S Second (2 digits) %S ç§’ (2 digits) %S Microseconds (6 digits) %f 毫秒 (6 digits) %f AM/PM %p AM/PM %p Comma Separator \, 逗å�·åˆ†éš”符 \, Dot Separator \. 点分隔符 \. DescendantCount å�Žä»£æ•° genboolean true 真 false å�‡ yes 是 no å�¦ globalref TreeLine Files TreeLine文件 TreeLine Files - Compressed TreeLine文件 - 压缩 TreeLine Files - Encrypted TreeLine文件 - 加密 All Files 所有文件 HTML Files HTML文件 Text Files 文本文件 XML Files XML文件 ODF Text Files ODF文本文件 Treepad Files Treepad文件 PDF Files PDF文件 CSV (Comma Delimited) Files CSV(逗å�·åˆ†éš”)文件 All TreeLine Files 所有TreeLine文件 Old TreeLine Files è€�TreeLine文件 helpview Tools 工具 &Back 返回(&B) &Forward å‰�è¿›(&F) &Home 主页(&H) Find: 查找: Find &Previous 查找å‰�一个(&P) Find &Next 查找å�Žä¸€ä¸ª(&N) Text string not found 没找到文本串 imports &Tab indented text, one node per line &Tab缩进文本,æ¯�行一个节点 Tab delimited text table with header &row 带标题和行的Tab分隔文本表格(&r) Plain text &paragraphs (blank line delimited) 纯文本与段è�½(空白行分隔)(&p) Treepad &file (text nodes only) Treepad文件(ä»…é™�文本节点)(&f) &Generic XML (non-TreeLine file) 通用XML(é�žTreeLine文件)(&G) Open &Document (ODF) outline Open &Document (ODF)大纲 &HTML bookmarks (Mozilla Format) &HTML书签(Mozillaæ ¼å¼�) &XML bookmarks (XBEL format) &XML书签(XBELæ ¼å¼�) FOLDER 目录 BOOKMARK 书签 SEPARATOR 分隔符 Link 链接 Text 文本 Import File 导入文件 Choose Import Method 选择导入方å¼� Invalid File 无效的文件 "{0}" is not a valid TreeLine file. Use an import filter? "{0}"ä¸�是有效的TreeLine文件。 使用导入过滤器? TreeLine - Import File TreeLine - 导入文件 Error - could not read file {0} 错误 - 无法读å�–文件{0} Error - improper format in {0} 错误 - {0}中的格å¼�ä¸�正确 TABLE 表格 Bookmarks 书签 Too many entries on Line {0} 行{0}上的æ�¡ç›®å¤ªå¤š Plain text, one &node per line (CR delimited) 纯文本,æ¯�行一个节点(回车分隔)(&n) Bad CSV format on Line {0} 行{0}上的错误CSVæ ¼å¼� Co&mma delimited (CSV) text table with level column && header row 带有级别列 && 标题行的逗å�·åˆ†éš”(CSV)文本表格(&m) Comma delimited (CSV) text table &with header row 带有标题行的逗å�·åˆ†éš”(CSV)文本表格(&w) Other å…¶ä»– Old Tree&Line File (1.x or 2.x) è€�版本Tree&Line文件(1.x或2.x) Invalid level number on line {0} 第{0}行上的级别编å�·æ— æ•ˆ Invalid level structure 级别结构无效 No headings found matheval Illegal "{}" characters é�žæ³•çš„"{}"字符 Child references must be combined in a function 必须在函数中组å�ˆå­�引用 Illegal syntax in equation ç­‰å¼�中的é�žæ³•语法 Illegal function present: {0} 存在é�žæ³•函数: {0} Illegal object type or operator: {0} é�žæ³•对象类型或è¿�算符: {0} Invalid field modifiers miscdialogs &OK 确认(&O) &Cancel å�–消(&C) Fields 字段 File Properties 文件属性 File Storage 文件存储 &Use file compression 使用文件压缩(&U) Use file &encryption 使用文件加密(&e) Spell Check 拼写检查 Language code or dictionary (optional) 语言代ç �或 å­—å…¸(å�¯é€‰) Math Fields 数学字段 &Treat blank fields as zeros 将空白字段视为零(&T) Encrypted File Password 加密文件密ç � Type Password for "{0}": 输入“{0}â€�的密ç �: Type Password: 输入密ç �: Re-Type Password: é‡�新输入密ç �: Remember password during this session 在此会è¯�期间记ä½�密ç � Zero-length passwords are not permitted ä¸�å…�许使用零长度密ç � Re-typed password did not match é‡�新输入的密ç �ä¸�匹é…� Default - Single Line Text 默认 - å�•行文字 &Search Text æ�œç´¢æ–‡å­—(&S) What to Search æ�œç´¢å†…容 Full &data 完整数æ�®(&d) &Titles only å�ªæœ‰æ ‡é¢˜(&T) How to Search 如何æ�œç´¢ &Key words 关键è¯�(&K) Key full &words 完整的关键è¯�(&w) F&ull phrase 完整的短语(&u) &Regular expression 正则表达å¼�(&R) Find 查找 Find &Previous 查找上一个(&P) Find &Next 查找下一个(&N) Filter 过滤 &Filter 过滤(&F) &End Filter 结æ�Ÿè¿‡æ»¤(&E) &Close 关闭(&C) Error - invalid regular expression 错误 - 无效的正则表达å¼� Search string "{0}" not found æ�œç´¢å­—符串“{0}â€�未找到 Find and Replace 查找和替æ�¢ Replacement &Text 替æ�¢æ–‡å­—(&T) Any &match ä»»æ„�匹é…�(&m) Full &words 完整的è¯�(&w) Re&gular expression 正则表达å¼�(&g) &Node Type 节点类型(&N) N&ode Fields 节点字段(&o) &Find Next 查找下一个(&F) &Replace 替æ�¢(&R) Replace &All 替æ�¢å…¨éƒ¨(&A) [All Types] [所有类型] [All Fields] [所有字段] Search text "{0}" not found æ�œç´¢æ–‡æœ¬â€œ{0}â€�未找到 Error - replacement failed 错误 - 替æ�¢å¤±è´¥ Replaced {0} matches 替æ�¢äº†{0}个匹é…�项 Sort Nodes 节点排åº� What to Sort 排åº�内容 &Entire tree 整棵树(&E) Selected &branches 选定的分支(&b) Selection's childre&n 选择节点的å­�节点(&n) Selection's &siblings 选择节点的å�Œçº§èŠ‚ç‚¹(&s) Sort Method 排åº�方法 &Predefined Key Fields 预定义的关键字段(&P) Node &Titles 节点标题(&T) Sort Direction 排åº�æ–¹å�‘ &Forward æ­£å�‘(&F) &Reverse å��å�‘(&R) &Apply 应用(&A) Update Node Numbering 更新节点编å�· What to Update 更新的内容 &Selection's children 选择节点的å­�节点(&S) Root Node 根节点 Include top-level nodes 包括顶级节点 Handling Nodes without Numbering Fields 处ç�†æ²¡æœ‰ç¼–å�·å­—段的节点 &Ignore and skip 忽略并跳过(&I) &Restart numbers for next siblings é‡�å�¯ä¸‹ä¸€ä¸ªå�Œçº§èŠ‚ç‚¹çš„ç¼–å�·(&R) Reserve &numbers ä¿�留的编å�·(&n) TreeLine Numbering TreeLineç¼–å�· No numbering fields were found in data types 在数æ�®ç±»åž‹ä¸­æ‰¾ä¸�到编å�·å­—段 File Menu 文件è�œå�• File 文件 Edit Menu 编辑è�œå�• Edit 编辑 Node Menu 节点è�œå�• Node 节点 Data Menu æ•°æ�®è�œå�• Data æ•°æ�® Tools Menu 工具è�œå�• Tools 工具 View Menu 视图è�œå�• View 视图 Window Menu 窗å�£è�œå�• Window 窗å�£ Help Menu 帮助è�œå�• Help 帮助 Keyboard Shortcuts 键盘快æ�·é”® &Restore Defaults æ�¢å¤�默认(&R) Key {0} is already used é”®{0}已被使用 Clear &Key 清除键(&K) --Separator-- - 分隔符 - Customize Toolbars 自定义工具æ � Toolbar &Size 工具æ �尺寸(&S) Small Icons å°�图标 Large Icons 大图标 Toolbar Quantity 工具æ �æ•°é‡� &Toolbars 工具æ �(&T) A&vailable Commands å�¯ç”¨å‘½ä»¤(&v) Tool&bar Commands 工具æ �命令(&b) Move &Up 上移(&U) Move &Down 下移(&D) Tree View Font 树视图字体 Output View Font 输出视图字体 Editor View Font 编辑器视图字体 No menu æ— è�œå�• TreeLine - Serious Error TreeLine - 严é‡�错误 A serious error has occurred. TreeLine could be in an unstable state. Recommend saving any file changes under another filename and restart TreeLine. The debugging info shown below can be copied and emailed to doug101@bellz.org along with an explanation of the circumstances. å�‘生了严é‡�错误。 TreeLineå�¯èƒ½å¤„于ä¸�稳定状æ€�. 建议在å�¦ä¸€ä¸ªæ–‡ä»¶å��下ä¿�存任何文件更改并é‡�æ–°å�¯åЍTreeLine. 下é�¢æ˜¾ç¤ºçš„调试信æ�¯å�¯ä»¥å¤�制并通过电å­�邮件å�‘é€�到doug101@bellz.org 对情况的解释. Format Menu æ ¼å¼�è�œå�• Format æ ¼å¼� Customize Fonts 自定义字体 &Use system default font 使用系统默认字体(&U) App Default Font 应用默认字体 &Use app default font 使用应用默认字体(&U) Externally Modified File &Overwrite File &Cancel Save File was externally modified at {} nodeformat Name å��å­— optiondefaults Monday 星期一 Tuesday 星期二 Wednesday 星期三 Thursday 星期四 Friday 星期五 Saturday 星期六 Sunday 星期日 Startup Condition å�¯åЍæ�¡ä»¶ Automatically open last file used 自动打开上次使用的文件 Show descendants in output view 在输出视图中显示å�Žä»£ Restore tree view states of recent files æ�¢å¤�最近文件的树视图状æ€� Restore previous window geometry æ�¢å¤�上一个窗å�£å‡ ä½• Features Available å�¯ç”¨åŠŸèƒ½ Open files in new windows 在新窗å�£ä¸­æ‰“开文件 Click node to rename å�•击节点é‡�命å�� Rename new nodes when created 创建时é‡�命å��新节点 Tree drag && drop available 树拖放å�¯ç”¨ Show icons in the tree view 在树视图中显示图标 Show math fields in the Data Edit view 在数æ�®ç¼–辑视图中显示数学字段 Show numbering fields in the Data Edit view 在数æ�®ç¼–辑视图中显示编å�·å­—段 Undo Memory 撤消内存 Number of undo levels 撤消级别数 Auto Save 自动ä¿�å­˜ Minutes between saves (set to 0 to disable) ä¿�存之间的分钟数 (设为0表示ç¦�用) Recent Files 最近的文件 Number of recent files in the file menu 最近文件的数é‡� 在文件è�œå�•中 Data Editor Formats æ•°æ�®ç¼–辑器格å¼� Times æ—¶ Dates 日期 First day of week 第一天 æ¯�周 Appearance 呈现 Child indent offset (in font height units) å­�缩进å��ç§» (字体高度å�•ä½�) Show breadcrumb ancestor view 显示é�¢åŒ…屑祖先视图 Show child pane in right hand views 在å�³æ‰‹è§†å›¾ä¸­æ˜¾ç¤ºå­�窗格 Remove inaccessible recent file entries 删除无法访问的最近文件æ�¡ç›® Activate data editors on mouse hover 在鼠标悬å�œæ—¶æ¿€æ´»æ•°æ�®ç¼–辑器 Minimize application to system tray 最å°�化应用程åº�到系统托盘 Indent (pretty print) TreeLine JSON files 缩进(优雅打å�°)TreeLine JSON文件 Limit data editor height to window size options Choose configuration file location 选择é…�置文件ä½�ç½® User's home directory (recommended) 用户的主目录(推è��) Program directory (for portable use) 程åº�目录(便æ�ºå¼�使用) &OK 确认(&O) &Cancel å�–消(&C) printdata Error initializing printer åˆ�始化打å�°æœºæ—¶å‡ºé”™ TreeLine - Export PDF TreeLine - 导出PDF Warning: Page size and margin settings unsupported on current printer. Save page adjustments? 警告:当å‰�打å�°æœºä¸�支æŒ�页é�¢å¤§å°�和边è·�设置。 ä¿�存页é�¢è°ƒæ•´ï¼Ÿ Warning: Page size setting unsupported on current printer. Save adjustment? 警告:当å‰�打å�°æœºä¸�支æŒ�页é�¢å¤§å°�设置。 ä¿�存调整? Warning: Margin settings unsupported on current printer. Save adjustments? 警告:当å‰�打å�°æœºä¸�支æŒ�è¾¹è·�设置。 ä¿�存调整? printdialogs Print Preview 打å�°é¢„览 Fit Width 适å�ˆå®½åº¦ Fit Page 适å�ˆé¡µé�¢ Zoom In 放大 Zoom Out 缩å°� Previous Page å‰�一页 Next Page å�Žä¸€é¡µ Single Page å�•页 Facing Pages é�¢å¯¹é¡µé�¢ Print Setup 打å�°è®¾ç½® Print 打å�° Printing Setup 打å�°è®¾ç½® &General Options 常规选项(&G) Page &Setup 页é�¢è®¾ç½®(&S) &Font Selection 字体选择(&F) &Header/Footer 页眉/页脚(&H) Print Pre&view... 打å�°é¢„览(&v)... &Print... 打å�°(&P)... &OK 确认(&O) &Cancel å�–消(&C) What to print 打å�°ä»€ä¹ˆ &Entire tree 整棵树(&E) Selected &branches 选定的分支(&b) Selected &nodes 选定的节点(&n) Included Nodes 包括的节点 &Include root node 包括根节点(&I) Onl&y open node children å�ªæœ‰æ‰“开节点的å­�节点(&y) Features 特å¾� &Draw lines to children ç»™å­�节点画线(&D) &Keep first child with parent ä¿�æŒ�第一个å­�节点在父节点上(&K) Indent 缩进 Indent Offse&t (line height units) 缩进å��ç§»é‡�(&t) (线高å�•ä½�) Letter (8.5 x 11 in.) 信纸 (8.5 x 11 in.) Legal (8.5 x 14 in.) 法律文书 (8.5 x 14 in.) Tabloid (11 x 17 in.) å°�型报纸 (11 x 17 in.) A3 (279 x 420 mm) A3 (279 x 420 mm) A4 (210 x 297 mm) A4 (210 x 297 mm) A5 (148 x 210 mm) A5 (148 x 210 mm) Custom Size 自定义大å°� Inches (in) 英寸(in) Millimeters (mm) 毫米 (mm) Centimeters (cm) 厘米 (cm) &Units å�•ä½�(&U) Paper &Size 纸张尺寸(&S) &Width: 宽(&W): Height: 高: Orientation æ–¹å�‘ Portra&it ç«–å�‘(&i) Lan&dscape æ°´å¹³(&d) Margins è¾¹è·� &Left: å·¦(&L): &Top: 上(&T): &Right: å�³(&R): &Bottom: 下(&B): He&ader: 页眉(&a): Foot&er: 页脚(&e): Columns 列 &Number of columns 列数(&N) Space between colu&mns 列之间空格(&m) Default Font 默认字体 &Use TreeLine output view font 使用TreeLine输出视图字体(&U) Select Font 选择字体 &Font 字体(&F) Font st&yle 字体样å¼�(&y) Si&ze 尺寸(&z) Sample 示例 AaBbCcDdEeFfGg...TtUuVvWvXxYyZz AaBbCcDdEeFfGg...TtUuVvWvXxYyZz &Header Left 页眉左(&H) Header C&enter 页眉中(&e) Header &Right 页眉å�³(&R) Footer &Left 页脚左(&L) Footer Ce&nter 页脚中(&n) Footer Righ&t 页脚å�³(&t) Fiel&ds 字段(&d) Field For&mat 字段格å¼�(&m) Header and Footer 页眉和页脚 Field Format for "{0}" "{0}"的字段格å¼� Output &Format 输出格å¼�(&F) Format &Help æ ¼å¼�帮助(&H) Extra Text é¢�外文字 &Prefix å‰�ç¼€(&P) &Suffix å�Žç¼€(&S) Error: Page size or margins are invalid 错误:页é�¢å¤§å°�或边è·�无效 TreeLine PDF Printer TreeLine PDF 打å�°æœº Select &Printer 选择打å�°æœº(&P) spellcheck Could not find either aspell.exe, ispell.exe or hunspell.exe Browse for location? 找ä¸�到aspell.exe,ispell.exe或hunspell.exe 指定ä½�置? Spell Check Error 拼写检查错误 Locate aspell.exe, ipsell.exe or hunspell.exe 定ä½�aspell.exe,ipsell.exe或hunspell.exe Program (*.exe) 程åº�(*.exe) TreeLine Spell Check Error Make sure aspell, ispell or hunspell is installed TreeLine拼写检查错误 ç¡®ä¿�安装了aspell,ispell或hunspell TreeLine Spell Check TreeLine拼写检查 Finished spell checking 完æˆ�拼写检查 Spell Check 拼写检查 Not in Dictionary ä¸�在字典中 Word: è¯�: Context: 上下文: Suggestions 建议 Ignor&e 忽略(&e) &Ignore All 忽略全部(&I) &Add 添加(&A) Add &Lowercase 添加å°�写(&L) &Replace 替æ�¢(&R) Re&place All 替æ�¢å…¨éƒ¨(&p) &Cancel å�–消(&C) Finished checking the branch Continue from the top? 完æˆ�检查分支 从顶部继续? titlelistview Select in Tree 在树中选择 treeformats DEFAULT 默认 FILE 文件 TYPE 类型 FIELD 字段 FieldType 字段类型 TitleFormat 标题格å¼� OutputFormat 输出格å¼� SpaceBetween 中间空格 FormatHtml æ ¼å¼�Html Bullets 项目符å�· Table 表格 ChildType å­�类型 Icon 图标 GenericType 一般类型 ConditionalRule æ�¡ä»¶è§„则 ListSeparator 列表分割符 ChildTypeLimit å­�类型é™�制 Format æ ¼å¼� Prefix å‰�ç¼€ Suffix å�Žç¼€ InitialValue åˆ�始值 NumLines 数字线 SortKeyNum 排åº�键编å�· SortForward å�‘å‰�排åº� EvalHtml 评估Html treelocalcontrol Error - could not delete backup file {} 错误 - 无法删除备份文件{} Save changes to {}? 将更改ä¿�存到{}? Save changes? ä¿�存更改? &Save ä¿�å­˜(&S) Save File ä¿�存文件 Save the current file ä¿�存当å‰�文件 Save &As... å�¦å­˜ä¸º(&A)... Save the file with a new name 使用新å��ç§°ä¿�存文件 &Export... 导出(&E)... Export the file in various other formats 以å�„ç§�å…¶ä»–æ ¼å¼�导出文件 Prop&erties... 属性(&e)... Set file parameters like compression and encryption 设置压缩和加密等文件å�‚æ•° P&rint Setup... 打å�°è®¾ç½®(&r)... Set margins, page size and other printing options 设置边è·�,页é�¢å¤§å°�和其他打å�°é€‰é¡¹ Print Pre&view... 打å�°é¢„览(&v)... Show a preview of printing results 显示打å�°ç»“果的预览 &Print... 打å�°(&P)... Print tree output based on current options æ ¹æ�®å½“å‰�选项打å�°æ ‘输出 Print &to PDF... 打å�°åˆ°PDF(&t)... Export to PDF with current printing options 使用当å‰�打å�°é€‰é¡¹å¯¼å‡ºä¸ºPDF &Undo 撤消(&U) Undo the previous action 撤消上一个æ“�作 &Redo é‡�å�š(&R) Redo the previous undo é‡�å�šä¸Šä¸€ä¸ªæ’¤æ¶ˆ Cu&t 剪切(&t) Cut the branch or text to the clipboard 将分支或文本剪切到剪贴æ�¿ &Copy æ‹·è´�(&C) Copy the branch or text to the clipboard 将分支或文本å¤�制到剪贴æ�¿ &Paste 粘贴(&P) Paste nodes or text from the clipboard 粘贴剪贴æ�¿ä¸­çš„节点或文本 Paste non-formatted text from the clipboard 从剪贴æ�¿ç²˜è´´æœªæ ¼å¼�化的文本 &Bold Font 粗体(&B) Set the current or selected font to bold 将当å‰�或选定的字体设置为粗体 &Italic Font 斜体(&I) Set the current or selected font to italic 将当å‰�或选定的字体设置为斜体 U&nderline Font 下划线(&n) Set the current or selected font to underline 将当å‰�或选定的字体设置为下划线 &Font Size 字体大å°�(&F) Set size of the current or selected text 设置当å‰�或所选文本的大å°� Small å°� Default 默认 Large 大 Larger 更大 Largest 最大 Set Font Size 设置字体大å°� Font C&olor... 字体颜色(&o)... Set the color of the current or selected text 设置当å‰�或所选文本的颜色 &External Link... 外部链接(&E)... Add or modify an extrnal web link 添加或修改外部Web链接 Internal &Link... 内部链接(&L)... Add or modify an internal node link 添加或修改内部节点链接 Clear For&matting 清除格å¼�(&m) Clear current or selected text formatting 清除当å‰�或选定的文本格å¼� &Rename é‡�命å��(&R) Rename the current tree entry title é‡�命å��当å‰�æ ‘æ�¡ç›®æ ‡é¢˜ Insert Sibling &Before 之å‰�æ�’å…¥å�Œçº§(&B) Insert new sibling before selection 在选择节点之å‰�æ�’入新的å�Œçº§èŠ‚ç‚¹ Insert Sibling &After 之å�Žæ�’å…¥å�Œçº§(&A) Insert new sibling after selection 在选择节点之å�Žæ�’入新的å�Œçº§èŠ‚ç‚¹ Add &Child 添加å­�节点(&C) Add new child to selected parent 将新å­�项添加到选定的父项 &Delete Node 删除节点(&D) Delete the selected nodes 删除所选节点 &Indent Node 缩进节点(&I) Indent the selected nodes 缩进选定的节点 &Unindent Node å�–消缩进节点(&U) Unindent the selected nodes å�–消缩进选定的节点 &Move Up 上移(&M) Move the selected nodes up 上移选定的节点 M&ove Down 下移(&o) Move the selected nodes down 下移选定的节点 Move &First 移到首ä½�(&F) Move the selected nodes to be the first children 将所选节点移动为第一个å­�节点 Move &Last 移到最å�Ž(&L) Move the selected nodes to be the last children 将所选节点移动为最å�Žä¸€ä¸ªå­�节点 &Set Node Type 设置节点类型(&S) Set the node type for selected nodes 设置所选节点的节点类型 Set Node Type 设置节点类型 Copy Types from &File... 从文件å¤�制类型(&F)... Copy the configuration from another TreeLine file 从å�¦ä¸€ä¸ªTreeLine文件å¤�制é…�ç½® Flatten &by Category 按类别拼å�ˆ(&b) Collapse descendants by merging fields 通过å�ˆå¹¶å­—段折å� å�Žä»£ Add Category &Level... 添加类别级别(&L)... Insert category nodes above children 在å­�项上方æ�’入类别节点 &Spell Check... 拼写检查(&S)... &New Window 新建窗å�£(&N) Open a new window for the same file 打开å�Œä¸€æ–‡ä»¶çš„æ–°çª—å�£ Error - could not write to {} 错误 - 无法写入{} TreeLine - Save As TreeLine - å�¦å­˜ä¸º Error - could not write to file 错误 - 无法写入文件 TreeLine - Open Configuration File TreeLine - 打开é…�置文件 Error - could not read file {0} 错误 - 无法读å�–文件{0} Cannot expand without common fields 没有常è§�字段无法扩展 Category Fields 类别字段 Select fields for new level 选择新级别的字段 File saved 文件已ä¿�å­˜ Pa&ste Plain Text 粘贴纯文本(&s) Paste C&hild 粘贴å­�节点(&h) Paste a child node from the clipboard 从剪贴æ�¿ç²˜è´´å­�节点 Paste Sibling &Before 之å‰�粘贴å�Œçº§(&B) Paste a sibling before selection 在选择节点之å‰�粘贴新的å�Œçº§èŠ‚ç‚¹ Paste Sibling &After 之å�Žç²˜è´´å�Œçº§(&A) Paste a sibling after selection 在选择节点之å�Žç²˜è´´æ–°çš„å�Œçº§èŠ‚ç‚¹ Paste Cl&oned Child 粘贴克隆的å­�节点(&o) Paste a child clone from the clipboard 从剪贴æ�¿ç²˜è´´å…‹éš†çš„å­�节点 Paste Clo&ned Sibling Before 之å‰�粘贴克隆的å�Œçº§(&n) Paste a sibling clone before selection 在选择节点之å‰�粘贴新的å�Œçº§å…‹éš†èŠ‚ç‚¹ Paste Clone&d Sibling After 之å�Žç²˜è´´å…‹éš†çš„å�Œçº§(&d) Paste a sibling clone after selection 在选择节点之å�Žç²˜è´´æ–°çš„å�Œçº§å…‹éš†èŠ‚ç‚¹ Clone All &Matched Nodes 克隆所有匹é…�的节点(&M) Convert all matching nodes into clones 将所有匹é…�的节点转æ�¢ä¸ºå…‹éš† &Detach Clones 分离克隆(&D) Detach all cloned nodes in current branches 分离当å‰�分支中的所有克隆节点 S&wap Category Levels 交æ�¢ç±»åˆ«çº§åˆ«(&w) Swap child and grandchild category nodes 交æ�¢å­�节点和孙节点类节点 Converted {0} branches into clones å°†{0}分支转æ�¢ä¸ºå…‹éš† No identical nodes found 找ä¸�到相å�Œçš„节点 Warning - file corruption! Skipped bad child references in the following nodes: 警告 - 文件æ�Ÿå��ï¼� 在以下节点中跳过了å��å­�引用: Spell check the tree's text data 拼写检查树的文本数æ�® &Regenerate References é‡�新生æˆ�å�‚考(&R) Force update of all conditional types & math fields 强制更新所有æ�¡ä»¶ç±»åž‹å’Œæ•°å­¦å­—段 Insert &Date Insert current date as text St&rikethrough Font Set the current or selected font to strikethough treemaincontrol Warning: Could not create local socket 警告:无法创建本地套接字 Error - could not write config file to {} 错误 - 无法将é…�置文件写入{} Error - could not read file {0} 错误 - 无法读å�–文件{0} Backup file "{}" exists. A previous session may have crashed 备份文件“{}â€�存在。 之å‰�的会è¯�å�¯èƒ½å·²ç»�崩溃 &Restore Backup æ�¢å¤�备份(&R) &Delete Backup 删除备份(&D) &Cancel File Open å�–消文件打开(&C) Error - could not rename "{0}" to "{1}" 错误 - 无法将“{0}â€�é‡�命å��为“{1}â€� Error - could not remove backup file {} 错误 - 无法删除备份文件{} &New... 新建(&N)... New File 新文件 Start a new file 开始一个新文件 &Open... 打开(&O)... Open File 打开文件 Open a file from disk 从ç£�盘上打开文件 Open Sa&mple... 打开示例文件(&m)... Open Sample 打开示例文件 Open a sample file 打开一个示例文件 &Import... 导入(&I)... Open a non-TreeLine file 打开一个é�žTreeLine文件 &Quit 退出(&Q) Exit the application 退出应用 &Select All 选择所有(&S) Select all text in an editor 在编辑器里选择所有 &Configure Data Types... é…�置数æ�®ç±»åž‹(&C)... Modify data types, fields & output lines 编辑数æ�®ç±»åž‹ï¼Œå­—段和输出行 Sor&t Nodes... 节点排åº�(&t)... Define node sort operations 定义节点排åº�æ“�作 Update &Numbering... æ›´æ–°ç¼–å�·(&N)... Update node numbering fields 更新节点数值型字段 &Find Text... 查找文本(&F)... Find text in node titles & data 在标题和数æ�®ä¸­æŸ¥æ‰¾æ–‡æœ¬ &Conditional Find... æ�¡ä»¶æŸ¥æ‰¾(&C)... Use field conditions to find nodes 使用字段æ�¡ä»¶æŸ¥æ‰¾èŠ‚ç‚¹ Find and &Replace... 查找和替æ�¢(&R)... Replace text strings in node data 替æ�¢èŠ‚ç‚¹æ•°æ�®ä¸­çš„æ–‡æœ¬å­—符串 &Text Filter... 文本过滤器(&T)... Filter nodes to only show text matches 过滤节点仅显示匹é…�文本 C&onditional Filter... æ�¡ä»¶è¿‡æ»¤å™¨(&o)... Use field conditions to filter nodes 使用字段æ�¡ä»¶è¿‡æ»¤èŠ‚ç‚¹ &General Options... 常规选项(&G)... Set user preferences for all files 设置所有文件的用户首选项 Set &Keyboard Shortcuts... 设置键盘快æ�·é”®(&K)... Customize keyboard commands 自定义键盘命令 C&ustomize Toolbars... 自定义工具æ �(&u)... Customize toolbar buttons 自定义工具æ �按钮 Customize Fo&nts... 自定义字体(&n)... Customize fonts in various views 在å�„ç§�视图中自定义字体 &Basic Usage... 基本用法(&B)... Display basic usage instructions 显示基本使用说明 &Full Documentation... 完整文档(&F)... Open a TreeLine file with full documentation 使用完整文档打开TreeLine文件 &About TreeLine... 关于TreeLine(&A)... Display version info about this program 显示有关此程åº�的版本信æ�¯ &Select Template 选择模æ�¿(&S) TreeLine - Open File TreeLine - 打开文件 Open Sample File 打开一个示例文件 &Select Sample 选择示例文件(&S) Conditional Find æ�¡ä»¶æŸ¥æ‰¾ Conditional Filter æ�¡ä»¶è¿‡æ»¤å™¨ General Options 常规选项 Error - basic help file not found 错误 - 找ä¸�到基本帮助文件 TreeLine Basic Usage TreeLine基本用法 Error - documentation file not found 错误 - 找ä¸�到文档文件 Error - invalid TreeLine file {0} 错误 - 无效的TreeLine文件{0} TreeLine version {0} TreeLine版本{0} written by {0} ç”±{0}编写 Library versions: 库版本: missing directory 缺少目录 Show C&onfiguration Structure... 显示é…�置结构(&o)... Show read-only visualization of type structure 显示å�ªè¯»çš„类型结构å�¯è§†åŒ– Custo&mize Colors... Customize GUI colors and themes treenode New 新建 treestructure Main 主 treeview Filtering by "{0}", found {1} nodes 按"{0}"过滤,找到{1}个节点 Conditional filtering, found {0} nodes æ�¡ä»¶è¿‡æ»¤ï¼Œæ‰¾åˆ°{0}个节点 Search for: æ�œç´¢: Search for: {0} æ�œç´¢: {0} Search for: {0} (not found) æ�œç´¢: {0} (未找到) Next: {0} 下一个: {0} Next: {0} (not found) 下一个: {0} (未找到) treewindow Data Output æ•°æ�®è¾“出 Data Edit æ•°æ�®ç¼–辑 Title List 标题列表 &Expand Full Branch 展开完整分支(&E) Expand all children of the selected nodes 展开选定节点的所有å­�节点 &Collapse Full Branch 折å� å®Œæ•´åˆ†æ”¯(&C) Collapse all children of the selected nodes 折å� é€‰å®šèŠ‚ç‚¹çš„æ‰€æœ‰å­�节点 &Previous Selection 上一个选则(&P) Return to the previous tree selection 返回上一个树选择 &Next Selection 下一个选择(&N) Go to the next tree selection in history 去到下一个历å�²æ ‘选择 Show Data &Output 显示数æ�®è¾“出(&O) Show data output in right view 在å�³ä¾§è§†å›¾æ˜¾ç¤ºæ•°æ�®è¾“出 Show Data &Editor 显示数æ�®ç¼–辑器(&E) Show data editor in right view 在å�³ä¾§è§†å›¾æ˜¾ç¤ºæ•°æ�®ç¼–辑器 Show &Title List 显示标题列表(&T) Show title list in right view 在å�³ä¾§è§†å›¾æ˜¾ç¤ºæ ‡é¢˜åˆ—表 &Show Child Pane 显示å­�窗格(&S) Toggle showing right-hand child views 切æ�¢æ˜¾ç¤ºå�³ä¾§å­�视图 Toggle showing output view indented descendants 切æ�¢æ˜¾ç¤ºè¾“出视图缩进å�Žä»£ &Close Window 关闭窗å�£(&C) Close this window 关闭这个窗å�£ &File 文件(&F) &Edit 编辑(&E) &Node 节点(&N) &Data æ•°æ�®(&D) &Tools 工具(&T) &View 视图(&V) &Window 窗å�£(&W) &Help 帮助(&H) Start Incremental Search 开始增é‡�æ�œç´¢ Next Incremental Search 下一个增é‡�æ�œç´¢ Previous Incremental Search 上一个增é‡�æ�œç´¢ Show &Breadcrumb View 显示é�¢åŒ…屑视图(&B) Toggle showing breadcrumb ancestor view 切æ�¢æ˜¾ç¤ºé�¢åŒ…屑祖视图 Show Output &Descendants 显示输出å�Žä»£(&D) Fo&rmat æ ¼å¼�(&r) colorset Dialog background color Dialog text color Text widget background color Text widget foreground color Selected item background color Selected item text color Link text color Tool tip background color Tool tip foreground color Button background color Button text color Disabled text foreground color Disabled button text color Color Settings Color Theme 色彩主题 Default system theme Dark theme Custom theme &OK 确认(&O) &Cancel å�–消(&C) Custom Colors Theme Colors Select {0} color