taglog-0.2.6/0000755000175000017500000000000013603645470011462 5ustar johnjohntaglog-0.2.6/LICENSE0000644000175000017500000010450513534701742012472 0ustar johnjohn GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . taglog-0.2.6/.gitignore0000644000175000017500000000004313534701742013445 0ustar johnjohn# files to ignore for git .taglog taglog-0.2.6/COPYING0000644000175000017500000000017613534701742012517 0ustar johnjohnTaglog is Copyright John Lines Nov 1999 and is released under the terms of the GNU Public Licence. taglog-0.2.6/tagtest.html0000644000175000017500000000227513534701742014027 0ustar johnjohn
Tag-test-version
1.0
Description
Test tag file - note that this is in the header

Id
something
Tag
some value
NextTag
next value

Id
nextthing
Description
This is a multiline description
Here is the second line
Priority
50

Id
anotherthing
Description
just a description
URL
http://www.example.com/
Purpose
testing URL display
Priority
20

Id
yetanotherthing
Priority
60

Id
importantthing
Priority
5

taglog-0.2.6/manifest.txt0000644000175000017500000000037313534701742014032 0ustar johnjohncal2.xbm logEdit.tcl mainwin.tcl pkgIndex.tcl smtp.tcl tag.tcl taglog.xbm taglog_action.tcl taglog_contact.tcl taglog_help.tcl taglog_help_en.tag taglog_init.tcl taglog_project.tcl taglog_report.tcl taglog_stack.tcl taglog_util.tcl taglog_widgets.tcl taglog-0.2.6/Makefile0000644000175000017500000000161213534752765013133 0ustar johnjohn# Make file for the taglog program version: src/taglog grep 'set version' src/taglog | cut -d' ' -f 3 > version maketar: version ./sort_taghelp src/taglog_help_en.tag ./sort_taghelp src/taglog_help_de.tag ./sort_taghelp src/taglog_help_fr.tag ./sort_taghelp src/taglog_help_nl.tag # tagextract -m Project -eq taglog <~/diary/actions.tag | tagextract -m Status -eq Pending > doc/taglog_todo.tag cp -a ../taglog ../taglog-$(shell cat version) tar -czv --dereference --exclude ".git" -f ../taglog-$(shell cat version).tar.gz -C .. taglog-$(shell cat version) rm -rf ../taglog-$(shell cat version) pkgindex: taglog pkg_mkIndex src/. src/*.tcl taglog.exe: taglog.vfs cp taglog taglog.tcl sdx wrap taglog -runtime /usr/local/lib/tclkit/tclkit-win32.upx.exe mv taglog taglog.exe mv taglog.tcl taglog rm -r taglog.vfs taglog.vfs: taglog tclsh install.tcl -vfs clean: # Nothing to do for clean taglog-0.2.6/sort_taghelp0000755000175000017500000000245713534701742014111 0ustar johnjohn#!/usr/bin/env tclsh # # This program sorts taglog_help files by Id field, allowing the taghelp # routine to binary search them # # Copyright John Lines (john+taglog@paladyn.org) January 2002 # # This program is released under the terms of the GNU Public Licence # # Version 0.0.2 sorts in a case insensitive manner # set version 0.0.2 global auto_path # tag.tcl should be in a real library directory or in the script dir set scriptdir [file dirname [info script]] lappend auto_path $scriptdir package require tag proc sorthelp { fn } { # # file copy $fn $fn.unsorted set helpentries [tag readfile $fn] #set sortentries [tag sort $helpentries Id -ascii ] set sortentries [tag sort $helpentries Id -dictionary ] # # The header should be entry 0 (becuase it does not have an Id field and # null sorts before everything else # # Put a Sorted-date header entry in there. set header [lindex $sortentries 0] #tag setorreplace header Sorted-date [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S"] tag setorreplace header Sorted-date [clock format [clock scan "next 10 seconds"] -format "%Y-%m-%d %H:%M:%S"] tag setorreplace header Sort-key Id set sortentries [lreplace $sortentries 0 0 $header] tag writefile $fn $sortentries } global argv # only take one argument for now set fn [lindex $argv 0] sorthelp $fn taglog-0.2.6/doc/0000755000175000017500000000000013534701742012225 5ustar johnjohntaglog-0.2.6/doc/tutorial3.html0000644000175000017500000001344413534701742015047 0ustar johnjohn Taglog tutorial - Preferences

Taglog tutorial - Preferences

Taglog comes with a set of defaults for the way it is set up which suit many people, but is intended to accommodate a range of user preferences for the way things look, or the places files are stored. There preferences are saved in a configuration file which is read in when the program is started.

You can edit the preferences settings with the 'File/Preferences' menu item.

You will see a window which will look like this:

The first thing to note about this window is that the window title contains the name of the configuration file. This is the full operating system file name with any "~" expanded so you can find out which preferences file you are using.

Within the window are a number of items you can alter

Documentation Directory
Taglog looks for its online help in this directory. Usually you do not need to change this. As with most labels in taglog you can see the online help by clicking on the label, and then on the Help item in the drop down list.
Data directory root
Taglog will store its data files in this directory and directories which it will create under here.
Language
The text within taglog is passed through the TCL message catalog and the help information is intended to be available in multiple languages. At present the only fully supported languages are English and German. If you wish to help with the translation please see the taglog internationalisation guide and send patches to the author. If you change languages then the help text will be available immediately in the new langage, but you will need to click OK in the preferences window and then restart the program to see all the text in your chosen language.
Hours worked per day
Some of taglog reports can be displayed as time in man days. This is where you can adjust the number of working hours in a day to be right for you.
Date Format
You can let taglog know your preferred date format here. Taglog always stores dates in ISO format (YYYY-MM-DD) in files, but the ability to have dates read and presented in your preferred format is being gradually added.
History and Current Window depths
You can decrease the amount of screen real estate that taglog uses by reducing these sizes.
Number of 'Today' actions
At the top of the main taglog window you can record a number of things you intend to do that day. That way you can remind yourself of your top priority tasks every time you look at taglog. The number of actions defaults to three. You can increase it if you feel very productive, or set it to zero to save screen space if you do not find the facility useful.
Id Prefix
If you are working with a group of people on the same projects then you can set your Id Prefix to your initials. This will distinguish your action aa.testproj.1 (if your Id is aa) from your colleages fb.testproj.1 (if their Id is fb)
Start Procs
Taglog runs a number of subroutines when it starts, to create windows, start timers etc. You can specify additional procedures here to customise the way taglog works for you. In particular if you specify "iconify_mainwin doShowProjects" then taglog will start with the Project Times window open and the main window iconified. You can use the Project Times window as a simple project timer, clicking on the projects to switch which one is active.
SMTP Preferences filename
Taglog uses a mail implementation written in TCL. This has its own configuration file, because it might be used in programs other than taglog. This preferences item tells taglog where to find the SMTP (Simple Mail Transport Protocol) preferences file.
SMTP thishost
Part of the SMTP protocol requires your computer to say what it is called. This allows you to set the name in case taglog has not detected it correctly.
SMTP mailhost
The SMTP implementation in taglog is very primitive. You should enter the name of a Smart Host which will accept mail from your computer, and be responsible for delivering it. For Unix systems localhost should be fine.
SMTP email address
You should enter your Internet style email address here
SMTP port
Leave this at 25 unless you understand what you are doing.

Starting with an alternative preferences file

Taglog normally looks for a preferences file in the following locations
  1. ~/.taglog
  2. ~/taglog.cfg
It will use whichever of these files it finds first as the user's preferences file. You can override this behaviour by starting taglog as
taglog -- -c configuration-file-name
From Unix you could set this up as an alias.

From Windows, if you have set up a shortcut to taglog on your desktop you can right click the icon and select Properties and modify the Target of the Shortcut properties as shown.

You can use this to run taglog with a set of preferences on a network drive. This set of preferences can specify the location of the data root as being on that network drive as well.


Next Previous Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/doc/Taglog_shortcut.jpg0000644000175000017500000000250113534701742016075 0ustar johnjohnJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222HD"3 !1"QAaq#2%4U'1!2q"ARa ?DELH^LFFߡ*>C%P-׿?E{IWj }q:;NbQ>gNȱUT=dž8nGv"Q.d{ jmT~@}MG0ЅdalQDdAd,otfD'*kߝ3%aki`}WU'7گڀ5tGɦ=<'nl aWsf~ȳ႞֣Q,՜ 1;Jc.N|;3ll0Z6^WJ5(ڋzHW#jeaK ,14MF#y=GW~˜ <B{_&Yߍy\Ec ;Sc\ydm8П1VoKzeJfpeIG m1٭]?s12gi͉q@olŨbi7b7T>gU!m@UQˢ03!Ae(j-d;tx_+1NŅn&-v*b,qNq!F"" C'taglog-0.2.6/doc/taglog_prefs.png0000644000175000017500000002104613534701742015412 0ustar johnjohnPNG  IHDR!3 IDATxݿ$u>Y $@#e 3)2dP@bp(؀[CAA 8 9ṔI:軺Uuu1S]];f|?[J>֭H{|ն >L_ɓ'e777৹Z>=Y_ǁq8ϟ?W^'OP ҇{7|{777AyDǿ_q3ek?7 M^DN+Xntr!it#׸K~n?0.~+*݋ZprU3W˗/K?~8\? Rr]rao~1M7w+~L1pHũwX~o}W=%'=ŋ1=~xggpԝnoo\EkomO W/3v|O? |[릥J#ƮSKMJ{1Ս2x=oLoOJ(U?, sVKE NA~j^kSAKO>'4Wr߱~;~\͹ށ&;sL#\&Ä% )2ϖ^s._eU rT?n/n^3.Ž1~RNBa#w]Yu"ow6H Oez-wCdRo00$V3o\uc.s7}12׳ἒ77SAŋ}{![}y $sss3|>T74*u5hҤPmlKf*jZh|^))Y>(<ˏ?x?xgDTN'r_pa(ƗWpC ݄2(U~cM/9S.GOOE;/llҫL܀s\2("~5+*\9Y?KgϞ? Yf%'Ogdgy%h)? J8%涔U:c_j<^E?_ p\׉V pd=~qc6Jl`-!iay睭JN#W` Q -ڨtzh6UӴ/3\rURϿ KTzWW\.eÝNzeiU3p@5ݗe|#X3'I.EyY}sԜ\gQpדӝlr;3(?䱆Ƀދ6t g3Q/*x zQ(#E(uHT +=,ot[ru (9h(P!BUCj~ڵ*y .f>l4c͘dju{ZO> aD%8K?)Pg]gOEɽdcr-$$a|_I9=(aT+fK ƞuU^+zOXQɿ[r~MR?nlѣ<(` AU]Sf" FpeS,nʈJ[ZgunznY@hBs:M+҄g2Lx+o,9}t1˚Lo+gU=.JQZ`1{|GFTZĜ݁1[PB$avU{Fp{چQiI#}"OE_ -D%¼:U1ITBHܣXDwS+'ŜA7}%rKs5`eGI6\f~_*IQl61dTrL #iû-[{\/?RTRs[7~5 % -k$ gk%B_viy%"Vr&wskBR΂z{i +˝|ֹ^gߍ+\q: VOJM^^+۽sGObPˁz$RWLU&d/0}TJvjV/q G]=m5? mt0ϓoqə>9r$L{5 m;6/Pb]#̛'畄璊*?]s)6Dٱ5Rr ;<|u蓵Sw bh'X_kՋ7¦G0ݝӱպuˇ޶yMî5\/+|>Gp ԽmR3ۃÆ: [Z 6 #*',{ nQ } $#8tTB_ -D%¼z2FT:"8B2:p4W:2~ߋ +=&^de;4yjГUMS|Z=*\d+*H]| HKqO[2/<ݚi\^mʂ(WJsa")X̣W/4 (oRp5Zm.{͟&1*Ȕwf,r]Wr*eQ)WWo/hQzQ`1&&]ZZF_iRIhqq6'.W׬KDh :F|8zTߟ7ƳMQ^&OKqNc`#8BT`畎hPk/D#"$2Fps<}%BT` JhT#Q ͐G?e4WBsA7}%.X6H&UmEcrKhkضmuNIg֌&*|eo$ [[8 tJN6W&Ȇw*%&<Ή:w/B_W`~ܝu=Std6|Jk``MgQi5܁E. Q_m@(Az.r:)?Q]{E@/:+MVi%rtsew~ˡl"#4&{In M{c_d0 OTʍ;Y&Wۢ1s@\yk}2`\7J8if^9.SrNa㕭-zy Wj Rk`ǺNИU{ Fphچ Q #8a-OE_ -D%¼ 6'HTB3ONe0$ s{avM_ -D%t6Kl[pufv9!]]sZ[IM 8o!v0fWYݶUFOi*&*Y'4侃w_޹W:V s.Ev;K! ~$oK}ȝ1A ۨ4Dt&՟ |j'm44s]<&t3+ˉ2:-qSFvd7r-0\<˔Op,΁ѷVJC*VW)vn%U8-q6l'|L Z “{%[RT@6䜧'+WpD%t6C+`Q ]`lm ! M0Cd_BT` Q -+a=|i_k*hOWJu{ɠ[Jl11ӤK9tl@H1ٞf\ױ4\[#3F]:y߶X_>a(*ŒoA$x}x<~\gnP{ ƍlX<ن DBy%}B#~qCsK  \()H&29#r)/0W7m{4&7FB[QI]0"Ŕ` .ےdcD"L$JBi=.ݎۓumE%ߜ`t|`0y~` Yٌd 3l|9B*]WJUO%&L>yӟWQ+Sچ3WBXQL LAFpIJDr^0W` Q - )rY|EvgQi_YA JGu67I#p+HƔz#*՘ .u-_tHaM~} Qi3L9-"Fp5f@L䛜vT`N.d=ˀ#iuyh卓Ŕl[Jla^iXCm1d`+[W:.ЯC̺=:窌ӎJDf^sM_ -D%0{#bHauݣ< +dv ;&ErioC6J%X?[8Wg7]&h*R {F' DT BFQPyB=$qž0{)Ɉ)R{~0b($Q(~\043nr\ty7[:V亚6=[Jla^鈎jzA_p!BT:Bcw ʓ~W` Q -D%0M827dcYFpq I}% 3 W` Q -Ҵk2vY܂eZ3L=E&񗩕MYq\NAOQi,v[wW'ʯSxֵʯ682'9⦎ YSo  i^)^9W?Q8A\FS{j2k~/hg4[%2hZ؄;n~35vr:+Ł)(-+iި2d=BD2u _ q'j2"Oa E%67LTXWF$Tԣ?d(vf&;=5s/ ѭLP>@si^n徚6ӼF0# +YPmKkVΚ8STG"ֺQR2BIgZ1AT#fz4 |޺=q̀u~`~ga%1S_ BT${Y70}%t"h:ccl,[Jl!*y% lmD%BBHFp@vJ;tW` Q -%6O>L2x- <5ZK:NcЋEԯy*:& Z:Pq.Ud1׀Sۯ(\~Kryx^@Ϟj& ^ɪ p+M8-z7nP[1er[(+*.[Sh5^p{xu_f͜j>5fV% qJbLf39/q7`.3[<Byɒ/3RZFz}. kOH>\RhϜf&QS9h[5I;^7!BT+$ð<}%BT` Jo4Q st!> vFIwgb,W` Q -&Gb 5'O5Y,8t5+jhh䉤FTĉ!/t9xթ<";,er@%C&6ű5WpH.@(\~K=b^IgX[%g ޽*yFaSt+MSP@$6'JQy}IwaQIb,nۤiwiMN?,`'Qfg[9BdJ'!\;%-q7`$V-;t&&^Rff\cr4,Gb[Jla^ m<ZXD 0! m1,$@sBT` Q -+P'?M@&L`H_㠯Țۋ^O_ -D%t< > >eWnL֖|j*H>f,lRѡ[%2hx}kT3/*r𪫳/%5W/FIUK16% Wv⎘Pf -U21N|N6yaj+W':y%]( QRp,;y^Jad7OmfSGbۧmj䂑P~cESKuWSP (uȻ$O*qC卭V;Y>f-mftFn ^̨JS\b<.v bdWd#"M[zרKWU<.N\:E Nz3WzWXt:n(u'i~m) O<̬Yqz׾{[V>h`ğ|&w %czh7A0q ]^OokVr#0Wz0 wwwzi\3g{2Ɵ|>{+I7sjzA_ t!B_ }@;D%T.,[Jl!*y%ll/mJ|աfAp\$+|Jl!*\gr%Wx Qn!:;Q'M/P-W] VK%vaB!thzkV>`^'qa?k8=Tr!9Gt$bWd"I9Id2?V?.#NU#Q'dm]s!3B),1xf\ @yl1?E=MO?V|s'DX^dVVUD4'}c[aC'+X#Fp0e!=B|1R @_ -D%0'GhTG_ZIDATi?6N֚E_!_[6o|}TZԡ[Jl!*[f6koRmؤ% &3Gij[1$}o˹, v+)0h;Im@hX&JY%ޓdI/MÂ+c!$ {juaY Q Y{ 50dN].[=laaWZ_p'k+OjM>tr9.*0=\ Ldot4 ŷCa !eR.K.aģ W` Q -7Y@_ -D%BT` mfIԀ4.O 1Jsݽ;[Mo'Q|>oJWWWϞ=+ӧ{رaUTnN Ϝl7[Jl!*0 [7a&?m xb_IENDB`taglog-0.2.6/doc/initial.jpg0000644000175000017500000003327213534701742014367 0ustar johnjohnJFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?E/4r# # IX@(1@=iCԵ-Ħ(]FܢkO&4 o19?3jiѝ9);OgNVDdhޛQNW8 ǭxxZhu1*.BNj ?xaI<}I#5mZv"ҷ aPIŽNg)@ѹfA|Oq|;\}˦#ܡ;8<}1^k?#GPN|_G'R>/s?x?*B/s?x?*B/s?x?*B/s?x?*B+{bO*4<[-+¬38 9m<7w ,Yq@LOR1o]u+]_-]v/-ێ  :˥L-s/q <`UhdM {c?ZP-k$3<6{8zwn85e,V$zHW'ןTń^XiH lxĂzWy56;4q)@g`;qx_QMjsk}s=ܖ#YfFGe*e KּA[yeiC0pI ?YkNLF؆Fv(Ǡp `%^ƿi^331Uf!29eӵQhF,洟ϊkyb,cu`Fn ț%eG U6pa *p |B.m$>6]DYD_W 2H56 Qk/;5s)آEb8ʨ % 2vՠYH|ydns7.l$1EM{J4+uCDՀV;ڹsaN_\|$tѧ1k/6)ZvJ90(Xml 44㗳ѴkgRvo,rJ&:N{qgr- {)9T(W`k^ x[ՂynbX")$ GӁG~K+6Oi+*%DA&-5)NDyHLs0Ϳ-e aAZB]vtH mXJ Z7~> nCĄoc9, , k{C-K#Bc3h Pdhzycݷ~-8>&Xi/$zݺBݽer că8UYu5LV1Hp#ӿA' .,u'Y"Y)VO)_3 m%2VVg㨆 [g9!87wЭ4.E ̷m>L_U*cXd_bxT\d7 *xq@Mb-sN[+ è8$dt  25ڽŬHq䑎Yf>?ƀ-U?44jikhSSO_G?ƀ-U?44jikhSSO_G?ƀ-U?44jikhSSO_G?ƀ-U?44jikhSSO_G?ƀ}}LݍI3ӟxsڹk/6W[%y$VSb pAvy(m`$:=wjk)灵2g9m¶|A`I?A@aWT_?#[^Zx& <MQ]S?aWTmyi=({7P/EuOQQ]S?յoO@_?#GEuOVז?ɿ-?baWT_?#[^Zx& <MQ]S?aWTmyi=({7P/EuOQQ]S?յoO@_?#GEuOVז?ɿ-?baWT_?#[^Zx& <MQ]S?aWTmyi=({7P/EuOQQ]S?յoO@-*8T_G,Đ $zZb ) #QEP\?2M]p>05gz֟)i\E-AEPP^^A^?ooK+$rxzP{[hnm09_tK[j 盁m' +0]R6ZaFðjWDeh-$ڣ$S8[Y 56ͦٛ60/Jc'BTxkAH4ؒOFV^@;εa "ui yq d* wm]](ne(H]&%w.##]Fal ((XP:qA)595 .kXUn @΃_/Gtߺ'?ƍI?4C:TU~礟6=$?uRTgA ah@?KQ*_*zI|l?OP΃_/Gtߺ'?ƍI?4C:TU~礟6=$?uRTgA ah@?KQ*_*zI|l?OP΃_/Gtߺ'?ƍI?4C:TU~礟6=$?uRTgA ah@ tX"rr~OZm>VW|p@2 ( |a!#Bj贈S ;8KH֟*ιY4l1v1F{z +:wN.!C#'Tu'm#~kU-cU{Rd| c y$ 6?  |=ZCsn9py|D]Wg@m@)"1d.+m#v2Ǯ&V@X]Ny v.R:s1O-zm3:mNfPېJ>uia:oep-l\!ϫ W m'K%Q,%]'XM.QQf 1$RO{KL7Yߔr+c@=E%iM- -j*P^>?|-A >?~MQ >?~MPzZߕ ?+$I7G$I7@ek~W(T?'E?'EOυ_/O _POğOğ?^>?|-A >?~MQ >?~MPzZߕ ?+$I7G$I7@ek~W(T?'E?'EOυ_/O _POğOğ?^>?|-A >?~MQ >?~MPzZߕ ?+$I7G$I7@ek~W(T?'E?'EjȋDE `S+2OhXIoEdMCm#~kW qWsms Fpq\7?2M@ޟGWP;U·v1?.Z?OsAN;;KkX"2B.P[ŸOJߖQ-$Et 2! C4y6V6M3Gm? j*ϓm? C4ZC4y6V6M3@>M3Gm? j*ϓm? C4ZC4y6V6M3@>M3Gm? S/+|a!#Bj)ʙ~Fܠ1+|a!#BjBgEr 0Rܖ [6?/<@P 'M$LÀX@95uyXjWOya}O"a]94֓cD-^eE\d $Plr3ѼI6g&`i{lHV%Ozu / WN^Jnͪsh6ޛC'mZ>e{n p˳{I Fq7Cp׭PWz\nx|_=a2Crj28g Z^N8< 3Wӧ I-']F#@#߈F&f>.Qce_rIW[I4 *LA+ʄ[$T6Þ}9$gxy7;<'.nbHSN !4ZF or.L7= 29$`fbI$.s#ڳ܂JFGN  T"BA@(614ghZA럳I ˁa}ϭWՕ8%Z8+u<=<}VN9kkHUWiU qqͨ#Ȗ1t-䈹i.Im# :oh$Ay\B]YYJg~v*YXڥS]2&pfv9坋ϵGmp s! _ic|iZ1< D|ϗ xʃϵrZg"?DgI3*D@wH L3EIYHiK4y<8~xl7W"dJ1E~܊rATW%][i,\[[\pIF]ъ`pAdi/泊eu4R`U$1.F1/)“5HI1qHsI#Ԋ--24qkpi<\yi0 bvϚ핅_f@-!Oz f {.g[>Tzٜv9:EՌ6r\j [vW2! f9^9O:f/ :wF7!|͇nnU&Z {2wS" jjZj|OIMG b*.cYd,fqq" `pKaX\Ie.ª *͔ I$mY\3b(?uRTgA ah@?KQ*_*zI|l?OSLyV{ ҥzn7wI'& 'uyhzRkZ3 r# `k-yP6* ΃_/Gtߺ'?ƍI?4C:TU~礟6=$8tw5g *__ z fG!A55`ѣ@ݟMR%qȻ8ظꭣ8T᷒I/^lFGo_1l(Jevr+[~q}Ftȏ4ۅ5x>q=ĚsJKĊߧnslP3'#}?#kZgHOG#:GG֢2?"?Α>Ƶ Ftȏ43ϧDj('#}?#kZgHOG#:GG֢2?"?Α>Ƶ Ftȏ43ϧDj('#}?#kZgHOG#:GG֢2?"?Α>Ƶ Ftȏ43ϧDj('#}?#kZgHOG#:GG֢2?"?Α>Ƶ Ftȏ43ϧDj(Ac[&ȕA qܚa!#Bj)A05!3?OsA [?**??T6o?訩OS3[OS3[ ((((((((((((((((Ey?2M^?"O?&&wiq"y_GEES׭}02u +v +vQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@O=S ЧX?_WC)\GԄ??T6o?訪c8PN!=On!=On0((((((((((((((((IA05ze?Кޟ׭}L֟*^TT?'`?'`QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEI?"O?&B`q^{ qR;8P\ECk:??XZ??@Š(((((((((((((((( 'X?_WC)\GS/+|a!#BjBgz֟*^TU1ZmzQS'P`gтk P`gтhQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE$e?К Ey?2MHLO\ECk?OsA [?**`d 0Vaj 0V ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ($`q^{ qWO=S ZmzQTiq"y_GEEL CBzF ݬ-CBzF ݠaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP/+|a!#Bj)A05!3?OsA [?**??T6o?訩OS3[OS3[ ((((((((((((((((Ey?2M^?"O?&&wiq"y_GEES׭}02u +v +vQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@O=S ЧX?_WC)\GԄ??T6o?訪c8TT{!u\L CBzF ݬK.S췋32ہOj۠aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP/+|a!#Bj)A05!3?OsAJ`Nʱ*Xt"5nxX71h/fl՟/>o].~Go㹭|&o P5c4b>} }hI.|{qwm%JdԿoM0Q\,[G,[@\ꨮW--.uTW+ } }:+{>h{>h UŽ|4Ž|4ΪbϿ>??bϿ>?UEroMoMs_X&X&Q\,[G,[@\ꨮW--.uTW+ } }:+{>h{>h UŽ|4Ž|4ΪbϿ>??bϿ>?UEroMoMs_X&X&O=S :W.yc _Sջ[Btaglog-0.2.6/doc/stack6.png0000644000175000017500000001544713534701742014141 0ustar johnjohnPNG  IHDR)OɓIDATxݿyv Rp):rpAdBWX^* \"_ #* !!0x*v),E7ňggfݽ~@s3u~𻩫h_O]w7/ikht:M]7`ϟ?'~wFMy{/?|?L0Ă&b:cn6<|?} |ứշ㏙` &1_?~Quuueىқ~~eO>{39xŋKFJƞ7I>|C3 Z=7nإsŽj)y^|94͛7}o޼~&tNW]Ч'{+3Lq1\&` 盬hh>n޼it=띛{o~uͯ>Pu=_uʇǏ___痺eN.bN? &`b)Ό7txym]<功9_m͹sǏ͵wwpGϢDtdza@rӌ7=}[o4~Ͻ7}Iie?hzI{\&D?sNtՕ B|cK2Gx`-L#*s^]fNt~{|3e3\&` ':&s{> u;֭[LR{'~R-lh{6]kZp&L0 k }䥷 LvT'ywO n{Rfn83gϞegϞݾ};ӧ]ݾ}ӧ6Ӧ9sͯ7D? g`c푸݉pT S*ɓ''Ozz"sF?5A63mC7_M;pgsfhd &`B8Ẻ,?p^"춋};41L'1NƎynsP0Ƹt\\\L]Db׿Oש+8gk z @wܽ4?S-e9=m6b@Fh#El6|t<T*(7[7H5GX:ūPV֤nu@%oo̭6aPAd |wBa'`fQ{\XveR{!*ÎZ:{3JդwG]|$]!Ϡ&wlɩ_[p',3yx魉whUgˊ~*YWIcik. @dKޒ(GIԔ]4bJy<7*TIUT(;4oci[O7 MNEgZ a5F m+P82៭ԞI}OPvLnnV6|HeFzǽgԀͼyDM`j*xuVދ5d9|T=825$ɗTcB&k2RìeM]:$[:]}_G5qzZhwǽxr{};~ܜsK'}ZA]'ůT\Pb<6~/Z] ˭9JnWz6b@H~nxs:TU~o96{0+SW8[<g-8SWasBb{օkIVʮAFiϾ\LHqY0+i '+`=@wԄ(٩^01,cn-yiHLMl?"8{Tռ޼fYbO{K ӌ7q$pGU4 gtUޥةpNsk& 2,6b@=Gfس*NCFh|*pi50Χ n  2@!O1=np&ʮAƘ[{WRlX=x^,Ӣ^ c {X.=-ygb#B2R,U5",{S;BPĞfHlƋCUh%jֆ3:{@*{A>q1N=ܚ Db|L><`{ڈ=mY8`X0Ğ Vt:M]=m-=Hp8env5s17cRs3pڢ+=#p.ʰ1A *_";J!NF>AҴFX<Ƕ)σ:N׎ /gŢVBSk4YM\4lM=×fE빶 8®i+s&auNOmr™7_̦]0Hլhg5)-}۶5y=mԵut26ӧĞh {S juƞgWZB\nA2h#Q8%s0(,X4CP4yJf<FD H=/sz!_Pty;={ 0< z.!=ma4X3=X1f3+ƨƴ6I36,FQHcTCz&q@ҳD3lQL)#lqRjh{(UԜ躧>=K4:3pfSG 3L`?jJh|u殻WayA`f~htwȦLF=2yG~Q;HhϣJΐ˔` 6wl/]Jܸ,KY.L{=-qwSzxE*Hޤ57谠̈} `%2CdM|hyh;a>›CAcDsh#{ڈ=m6b@Fh#{ڈ=m6b@FhBv&GcN‡áie\n ` ~'r#{NvU `%ƺzTx dG~vHܵ]2ks%CsCP,{P{{'=cM >CPI{za а~@P>Z8F#1QΞn5v<^=~Y֩E?sP `Z{v^w7O c! "R4~h~,7!ym_6\p{&kp"mRonmff\- ;65~Nrm676\pY7ݏ{j6Mu1gY& LVMVV0:3\P$|,IMtm),n;9dfMt6{r&$ o/*ZXO_ j4MZw;s8mM5ɬBV,Co谪E ymR Ty@zHv";Km'a7ӓ&|OXl懻V716[%^M2n]Tpb^NS3Iۃ*4:l{~ hqך_R̲RM9ÚTjh!a}jDGG7OY&tLJE*=7|ϑ)c{ڱu^ݺOZ5qOE敏*[\flDJzf<(IVC"c,M3^a_g\ƞp/J}Ty[p쭪at}tD^Jg2b$իZ%C }9E+xx#fؘm1WJH=BSI=‚6)qljի,[|oi~.Ѐ~9#,e?\J`1gm6hs:Gc]6̰ x3ZKN%f*0J5-[ܫP7&iѳ =e:"<LT aȧMԂ6 7_;~c~ 5]|JƞNg>Л$ЂkVvh'K5KqCegPMµRt6zVc:=j~&6~0 _ia܀{x4`<17PR {5'{j= Eh#{ڈ=m6b@Fh#{ڈ=m6b@Fh#{ڈ=m6b@Fh#{ڈ=m6b@Fh#{|v8Xdgi~tnUD<\\\(1$\9Pk l2W"04*y: +NX.CP'47CP?5CPO{LׇZ|N4ȟ@ް~@P0S.dD=U8v[sj<̽{}M^uwѣGC{nRE?{kXQ8{ڈ=m7:O(GqjVxAMcyoz ʜΠOjj%L}:4~8m+`dEKBC B: J_7ϙwc1:b+āՄB s~##|{vcvG {sN"שF% 0yҭHdgYN׉cS2N1T%u;-e2P9 xeUά90fpq`㸦Xjx,C3YKucPx^gd7jX. g|񝻺?Sh_Y?G"T?">?ƏEȩ4/ϟEO}g|*?Sh_Y?G"T?">?ƏEȩ4/ϟEO}g|*?Sh_Y?G"T}7IAYOy,BA 99z̋g𦄱\<. 1a'z6$#ot+[(|K[WzOn+3>GrOiQEQEr,hikkfw# d1c{>!wU# a:jڼ6!ڊ9  Ϡ%Eautatbenw@ق߈wX%׉-aOhI*%%O׶+袊(((+ڍbVP{˻y< ňxz!7K2izmX7qW*:K2`SUKӮ%3?B *hlQF{^T>g '߻ݏݝ8z:((k濌>zk6\AZ}QEQX#$?^G~ gsןR?oK ݄ߗ^y>mV=R15/ jߛIUeFE;cbO)nD>ZfnG@Xo7ް;[ ʉϱ((((+.SF!2Y&6x C̜=A?vZ[-ҮXv,ʰ, u) ՞-;P )G IU79>kMǿvdfEQEQEVO^b;{}tY\Cm. VATӜOGFV*aRCAZb}+B=HojQѴ\_]isBi#6'#cw۾<'X3,+r_VgEב}n۷8;ZAre{䀫ws֣{cyOl.'bʢbQA=?G{,q5+O4rVU!2!P. =gEQEQEQU5O^MPНc#w`%pښH9_~qϾ1ڳ?Ǡii֪tj-QOΑ0 <)oڒ[$вBvߕWq'd׮mxsAƃmI44;{VQEQEQEdE*Γ!O۷jV{^^O+^jũ_~qϾ1ڲz=E`m3w{7ךk/6M6ey!GbK;77lpjQEQEQEUMSA\j{gTaVg>߱ZLTQǐؠg_9|f?_NYV/h(((+'/]?1Vt xݿWj!\OթˣjޤsZqP,V#nvāzk/ \@ QEQEQEQEdE*Γ!O۷jV{^^O+gM[WJZY=}&zS?U5׿ ׼yo=ibE1ÿ́ nVVmScu⩼;7y\nT>ô sЀT}6o M$Kfd/o)9B񍖻}^Z\Kb)r8(8yuEEQEQEQU5O^M`A!J7^ZrB%CEQEQEQEQY>&zS?U5׿ xG]5kc\Qc`vʭ}x"בOyonb:γ(uH`mfH #f~OoðLK4,\\zQEQEQET?{\A5l*ӿOk>zk/ \@ QEQEQEQEdE*Γ!O۷jV{^^O* K/atDca< V<GxG&mug!,C00cڣV>,[iOU{Qw$t)8}wL}*.vy@$|r2x5EQEQEQU5O^M`A!J7^ZrB%CEQEQEQEQY>&zS?U5׿ ڤo&[};  0sw_i,~g3wMqG;m>L .HmVAxheU8+(((/& uZzw|GX}9e!X((((ȽuY)vM]k Rgռ&XINe۾~yg۞34Eyk=\%ž:$pFG#=j?Y37R}ufs'](((/& uZzw|GX}9e!X((((ȽuY)vM]k yWb-_m]a>R|G˞Euvvf-0yi HnyfV8jFl!].I-!B4b' syKoM+uWOh, 罢(((/& uZzw|GX}9e!X((((ȽuY)vM]k ]?Σ(((* ?#c`iV 3_7|f?_NYV/h(((+'/]?1Vt xݿWj!^A$_7y̖`OS$]]vff|>ҷ3ɂny v=(.R+)bGL@ʹ%@ G7?6D}[YXɸ,DE@> F~^EQEQEQU5O^M`A!J7^ZrB%CEQEQEQEQY>&zK{/d%֛ raq+E$b]QUppBQѴ\_]isBi#6'#cw۾<'XvH܀99:WIm-汓TDkG :Yv_o-%Ogw@ tQsQY-QFx/DΤ, c^x(((* *l;F`;]eւIܢNxQү$f2hӌF;'3,+r_Vw?ƏM?ښ?44jikh/_SO_G?ƏM?ښ?44jikh/_SO_G?ƳsWpHn$vA,!|jPjZIg7;yG=x?ϵmI k,lpgZ)kWw7٧D DO60dLtcf_}GݻnsfKo {݇i5D8uUJ*IHAi~%fddNDj]?44jikh/_SO_G?ƏM?ښ?44jikh/_SO_Uu-JM.ٙpJmRMجQTg 2z֖}mec3y@T޴젖>͉!1H&k#׬־u 1VB /O _G^>?|-zZߕ ?+ek~W(Qυ_/O _G^>?|-zZߕ ?+ek~W(Qυ_/O _G^>®F-n;iN>[QV\?03皌cv#7>T*ؿ*m_G? /ʟ[_QOB(VySЫkb [?!#I\υ_/O _G^>?|-zZߕ ?+ek~W(Qυ_/O _VH~N8ORo'i+9t,k揌>zk6\AZ}QEQEQEy=SO1 ɧߛ|Ic:0_xLM6?mfCW;+|mwd5ψ.㳖YK]^'󭼿2tC+.zA-u^xk{]3ϳ[m2X8gk9(W8U=w~(-uT67p#e+G»u֣xsHґ$ar(((dXnmy07^xz}3G `{fk{h0ŸPzDt/O?l濕[omyyOEygc)8<×Xqҭi:%řT%Oʠ 6ɢ+ic4Q*؀!#[_`?}y\?xQ >s<G.<(DžK Ь"`uF(((7^ZM$VEQEQEQE\+He1g<~G<~UtmFk͉*ElXW>OU/x(Bҏ/x(Bҏ/x(Bҏ/x*P%g Kx3QEQEQES_[} |GX}&?+O(((쟇x_@ӭM 5v6RDk,тN9=8F=ߋ5M]{="MV"x"$0qو*_[]Zm 2n+4q.P,pWgT/1ekΧ][F AO-nYe]Ѫap99Gҏ:?~y{Ώߥt(GJ<QGҏ:?~y{Ώߥt)*`=+>zkO^1˶pIUX/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_]WX5w\@cAֿtaglog-0.2.6/doc/adjstart.jpg0000644000175000017500000002713513534701742014553 0ustar johnjohnJFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?[VH9$! Lk#kO'G^i}ͼqT1_:\ֹӃ,MOe΢پz_&֟OM?焟y"lU\^2@=\`#16 yy ]F8V;WGB t'(M#'cI>AEP0(7.2svpiB)-4%m.!hHwJTÅ!p2'|'MmV [iOvH \=z m5dӵԠS31-6pIS0:/ցUN1Ylb:s-xP|Kֺ{'Kk*!%Pov,x·̼}Ѧ *mA,QWPG+)A$ q@ m5dӵԠS31-6pIS0 <kE/.+k٭uHuw{6#0>r$-ju #cy-W0C,L O/0xxœMU͂(on+Htgd9 owIo 4pw Lo z8N2pwj*$\bN 8\OEQEQEQE_+ ?!^^B?pBM#'cI> (QE6 I{[愀J*p*zs}7jڔ75  Ί 1$w$=sA[')9dCM^=J I%cFKd6X{cmXM%\WQFH[Dʨ=n1ZBꚕEls*qF0 `ND.cjȐGT|GcZC6~z6}mCLe8ڿsb.u'VuK˛j& 61%T KlI .5D67`ޮ$6+(emYzm@٭ F;K\wVڶ/~ޚ(Yb$_pPܖ XZijZ ";‚n;|zW XhwV\$g0V]h o,pi8wzڵsxole%,2<$HbN99k(((( t'+k;WGB=$VLo?$QE ( -^w:6FA*m/SS6C~~߿:⸟-լVl0.rPgp᳴=趾(ԅ^+*#;G =#bqm._hlfϴ+y>ҍBN˽,.t W;׳_ik6BBA$.ߦ no4"NHfFUsMw$5zv6yVmb*+Q0F ɢ-F CXF*fI$I5Wt؟HmZM?GMo;5"Lb1!jKj"8]IHKF퍯ug8ݤ6@ aXiP4u,v,j[g 8j^W*MlV妾!x.rF,n^X ͯzS_Gyyp2$VY5Ք2C1ʑ >@7u{ckv7wn>jy֓yk{}cþB۝n\*3b $\NF[= /th 6:M*.cȬY ~n@$@um//ϳGw7 ``UKV~_ ?G)^r><ӴCw,x%;V9%s((+;WGB t'(ޛ>GrOi\AZ}AEP0(񦩦Z+2kϷ#?p%]@Cކ[xJytw=p$<"_,d@b]HEƝA~JY9B yӜkDa-ZUT/ewev*I9jm|iDŽE Yk79.Ub@G4r"o!nV9xHn\+eaoMOmJH?|* %koЯeMeI0Ac,iT C}-,>_'hpcDqJaêxP-,ӕM;]yf\J'Ğ5k%Ř+m2FYy8GnxXHZT/Iu*ۆ09<`€ Ic-'@m*m@9ڠ=pwmC};^6}ݖ^@&o%A zMh7Z5E$+oW$;y]+;Fij qu9 lU{nVB` hj:|Cnt&ҮHKic kb@G .zsZ|4t2(m.l.Bg,m,&![x 2-WJ`WXnI\YCpO85jhFo;hͻwPN3QEQEW|v\$Ѕ{xo OP7| #'XිMnA+5:Z+~X{H`>~{kҴFuv,UT$sAuiNfTW$ӴReb#K81lH#kf!g `9l/DĺeO#r9}Ƞ+b"ʂ_2HQofۀ8jz˻M>OyQ4r$]Pc=v/xP&Kd)m,0H@n*-Ƃ']_j|rJ/A`F38s,M>e(Aai zzvj3<ťX-wU"2$eNI랃4^x?֯tnt8$ʊkcp?>H ]> ^wln\nHPĩ B;j+",F~@K na#flNkÞnl>DJز(RA | p +45zd7 Zؓa| `Q 3]qj+\ݔ r@H+0@I9*HsEr~5=s厩w"]j2s%vYT2!Bu S}PjsHYuSTl#'vv[)~"]?a|i[}]Fv~Qy??տahIkx-'gX$YlC-/~ܐG!]I /넟zo?cAeYc>';q:i7| d[7CƏ۩ye"vB$z o_7:=Goq{B@q ꣵjQAU*J曻9xIٶ8YV5@22x<8_2 {OӞk^P "۫nm*Ƞ :( ,hZ|]jA4-" Le71 FX\Oc=.QϚ[P0A1bG5Q@ׇi|}PYQq,X^j}^[K Ս,pAAw`pW)ojڑj}k'3[vߙ[i$2צSJnk]Q-؜>$QNIQAۢ9{z}=wW6k$nJ *GBr09QI[{mvWm  R6VM,lVGL´߅ajz-OUK͍Uy dd(18uUaG:ff:iELl 99B%P/"P ox_ڭjL!T"E^I;TO&_J^oиX, @c!o( e$[\b$:\*GojKWp'RGp'-XAB%P/"Po z_^}߿ڣRmH-[y 6g Nу"_D*J֯!]I 8gi w1-gߥxo OP#ޛ>GrOkߵ[xGǓ'-&Y`&TOz\AZ6%ͫmou)#BA,f';_nE3.8H[G+[Gl`) oa5WiW1ŨH ϨE;D Xڻar$$*c_m ݿu]ھѦ͟i V}6;g*xTmm6MfwQvxDL6ƒPBw5VVvqsfPc.7L6p-gEhj'QH9Kdl;NNO|T}^u˘oYoKHtdILȰƨBK 8WNxz=瓩F2HŭKT 1 x`ϯD^\LѼZ HͶ@6啎A\sGEh+o]'N DztQ<ҶHrx@Ϡgo}Oxgo}Oxū矎넟`Y( 9~;WGB?+O7| QE ( {bK}tI /:Fz1:\Kkf +±,\Ȁ\g;H3ym汤|PvvC9uJvrw:.lb^YIY Ehdnymp$ր>//-tW1Yx? [UYOKMJFdԎTd NZxoE7vvZƒIe^+ŵoQ_ӵ%][ە2.pZ8U݇` ՓU<*gK1_+$  ۳zm孟`Xbd Hz*p5=p_m#×SvTHb$v*@\9\FNyuJߍVO"0LyɶlyP9=nO{ۘm@8'Xjv >}my %"8ʓް|u^&ȢRx-v˻pK>aq^v5k > b5:g[{q|h+.8{,]Ak-1\nbyyvrq҉o-`[cmx (U+I,O,$ 'ڤmf&h՛oM=C_>]f!475?L\0uDM[?h{I}i%HDNO@E?ƏHv~@ ?"ڏKE'$Q;Qh?j?-G@G  Zf9$Ԟ>ʿVhQ@Q@xo OWׁ|v\$Ѕ{I>?+OH(IOI#ʠ1߁HnKX"rsGh> '#z 0+ F.9,y9>C4y6d/uZF%/n4#ٵ|nA&~ɶh7x4c_}ƭY)R݊;1M3@_x5C4y6fc_}Ək֗m? C4 (UBUB9x{NvnngK[Kd!LMDžz/}fSR OORn lNTPz4 u:ZΐX]}heǝ 9 ל`OT.R࿼$ҭ-$m9@K=|c <ֿ~̒]y߻08(NN+<%q.keZ͙2:SUJnw/siVŧ4Tf*X Keoq4<3+neCc#8<+^-]fQۛxVt˜'OX?ja?kZ ( /넟}!]I \ ?tͲjl&gMXߏ>ޟ_΍\, şޱzSzy:ͨLm6dk];WYף7?c~?z=W^ şޱz?sx?@1( ?Yף7?c~?Z~y$8U9ݷvqtQi_ J\, şޱz=WG@eįXߏYנ~ i_ J\, şޱz=WG@eįXߏYנ~ҖBA~?| şޱz?sx?@JoO/Fu_.ozXߏ})?x'o OV7.oz??m.oVT1&:@taglog-0.2.6/doc/tutorial_projects.html0000644000175000017500000001177213534701742016677 0ustar johnjohn Taglog tutorial - More about Projects

Taglog tutorial - More about Projects

Taglog uses the term Project to mean a label by which you wish to measure chunks of time.

In conventional usage a project has a beginning, a middle, and an end - but in Taglog there may also be 'projects' which are ongoing. For example your company may want to account for time spent on Safety activities seperately from work which is directly charged to particular customers.

Attributes of a project

Start and End Dates

By default when you add a project the start date is set to the current date and the end date is not specified.

If you are working beyond the end date of the project then it is 'Closed' - which means that it does not show up in the Project selector in the central menu bar for booking time to it. It will still show up when picking entries by project in the File/Open... selector.

Booking Code

It may be that your projects have useful titles, such as 'New Computer Suite', but that you are supposed to book to, for example 'P0152'. You can use the Booking Code field to record the names your time booking system wants you to use for projects, and use a more meaningful name for your own use.

It could also be that your administrative processes generate the official booking code some time after you are expected to start work on the project. As long as you have a booking code by the time you generate the Time Bookings Report taglog will work quite happily on just a title.

Breaks

Projects which are labeled as 'Breaks' are ones which are not working time. If you have, for example, a lunch break which is not part of your working hours you could create a project called Breaks, and 'book' your lunch times to this project.

Breaks projects are counted seperately in the reports.

Overheads

You may have activities which can not be associated directly with an individual chargeable project, but which should be spread in an equitable manner across your other projects - for example filling in your timesheets.

You can create one, or more, projects which are flagged as Overheads.

Active Projects

If you have a large number of projects which are Open (that is, the current date is between their Start and End dates) then you may find that they become difficult to manage. By flagging the ones you are actively working on as Active they are moved to the top of the Project selection list.

Projects which are marked as Active also always appear in the Project Times display invoked through Projects/View.

Immutable Projects

Projects which are flagged as Immutable are (like Breaks projects) not eligible to have Overheads time spread into them. You might wish to use the Immutable flag for projects such as Bank Holidays, Leave, or Sick Leave which should not be 'bulked out' with your administrative overheads.

Working with Projects

Adding a Project

This is done through the Projects/Add menu item.

Editing a Project

This is done through the Projects/Edit menu item. You are presented with a scrollable list of all the projects, and can use this to, for example change the Active flag on a project - if you start actively working on it - or possibly if your involvement with it is largely over. This is also where you set the end date of a project - usually to todays date, to indicate that it is Closed, and hence no longer available for new time bookings.

Note that you might have Actions which are associated with a project - and if you close the project before you have finished all the actions (there is no check for this yet) then you will still accumulate time booked to those actions as booked to that project.

Deleting a Project

Projects can be deleted through the Projects/Edit menu entry. There is a 'Delete' checkbox at the end of each project line. Select the Delete checkbox for each project you wish to delete and click OK.

You may want to keep projects around for a while after they are closed so that they still appear in the dropdown lists for the File/Open... selector.

Importing projects from a central server

It is also possible to set up a central server from which you can import information on the available projects. This is covered in the next section of the tutorial and is what the Projects/Update menu item does.
Next Previous Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/doc/seltime.jpg0000644000175000017500000002703313534701742014376 0ustar johnjohnJFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222Z" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?[VH9$! Lk#kO'G^i}ͼqT1_:\ֹӃ,MOe΢پz_&֟OM?焟y"lZcBpf?7u/;P7pr>vEɠF\wnteUdh@*00~v,v~':n=$O8GV?/sFᾟJ3)D \2=ՋT]&mF8 i D@gEv(_i'# d,w~!KECq̉5)NA)C_fnYRI9$5t'| |Կgl.uX̐؍qɏ B̖#2s^?+\!例&7eϘy#?wڋ\qcOjq\Zg?ufoZPh:q ՞6V$t{um2=@۬PJXEŶ s}J״]OU4&P$#OnԣFI{fZk7W  3DSh6})|Owۼ;>dy݌z銷aa$P^Cs3H(1'*-elPx[͵6h nPG#=j{?^$ *Mۜsy>/۳۷8Ƕ+Bd/d{%O[ҨsA#aѪxro+Ҭ r? NWlpO[8˽fcLI?Ym#o<Ӵt1c_beK iז6M׍/Aߎ9DGGm~x;SNei !9b 08+E^4ZKf-Wr˅iV%,L(w6 R1&oz?3ͼ*U:hvw շ 3px8<RN-xc*9'z^ KϵY$A޺_K/O~?c?yvoxxOv_Egg}K719Y1Ion8 99Fh "T?"L.jLk儞j_ݪXeBw=S^~Wfg)>?ƏEȩ5xl^G+mȓX2mC_ ]!~;l ېªpO c}g|*?Sku+=_NPuЏA  \ǂIϳ-Ӏw8Xn1@X_Y?G"Tރ/.A0ˇs_5V@X">?ƺAg$=,O(dNӰ`,8HCғ^4@+/mATK* >?ƏEȩ5]jg}i)?n+۳~?vs33Iuӵ$Kv7?2|J60A,r~ Cx dЭ^V>R;ctQxE}#-g3cp rW 63P񕝦kz% Ɂlv`(o*x Ɲspd[ɏ"pܱ) (+LwaC<ᾁmk:sBHCy,"h|% |ux=qqi6Ȭr@'Q@y'o,K";;$[?.#=/ꚿ&g_ϰv=<~!6ޡ-WZJGhz9<1quqg--O&0vR/ 7#z"i{5ټaSg=SSE$~~/n>' t8^iojVѹ2@+ݤlwp|%i0YO5 H uRco1C(/v:=ZDk}y8לh>XiE7`b#W66z2ViXWRF!ju,KjKbAPc'cCkqJʒ BFxwJ<]{j!uHmͨiyF ՝Fc'q!qQ%uQ 5"frZUQo%V,vs>E`@4x'H&U( ]t33׵{_n4Ը~al#rۓ`>lg Jcþ4BqfnOw۳*3~5tPJU5wtWf %g,O˃ׯsYoxN6viA yZ\%N1|WQ@{^,&}i}ôS+y#v6ɬ@Os߿޽T? Eśa>[gn̨3qVh t$3kȷ@K'9b!N2;s^EEq}ksF K}q}ksF K}?+O7|  (Q@Q@Q@C,ďmeF|U`#VTϯ< @RK)b a rz+񆫯׺ƣsiB-ݬK s|2<EMvZE~ %G,OKvsduh 1UJ;XϚ\|zẋI/,A:L@[* PIe8;ߊW6\/e.嵸[  Y v͜Qo+ nm)+hn"0 l2N"|7 L&2[kr^Odʟ0U #˶.DVͧOoǪ'J8ʼ) NprqĴԦ{q}uhVhG!~eېrT [@EܭW2nHb#g;9 bKInoYUO,a&9 H6P~ 5|G3G"2;THGK)}hPUv6pFsOt#cIORgd,Xx1Ph^Я[˻SOY?uAO&Y٦sgd~$ r<F3QVdZ_Mmfٗb$Y4Mo`Qf87}[NP2i1.T~rrox_ڭjL!T"E^I;TO&9>"n{sFx4ֳf1I>S~񘲰e  :/߲CkdOvݟlZ_ng29S[x>TQԠk%`I1\.򤌔-=b?m5CiXCb˵x~Υ̋2`nFrUqkmq,.<>[YH6| F_2kmih}"m) bn,06 UR=tD+ (`dı־"жhkuHnp@lF͢kW {ltmn.Bnlxbg<mk*V[1n4ї^pk[;om&][ek-/'̀2HO@zsb_-^=&{7Y+$n2HH*OL7Z$h- 5e`4X2ʤݻr'< 3je͓\ͬjԑXЪ <ذ&akԤ҄SaE{634FǂhxlioK*.Pk)XU%hz ^q{\}I c{kmQ xO}7f#O[{ƐFƨ7q#?)x5oȍ::In "w$!9'C܂Hv2:pH4 ><{x($U'SEPEPEPEPW־;?`Կ_ ؗ־;?`Կ_ #'cI> (QEQ\ֳItj& Av_*~lHBghbiY.]}N-iRI|!ls@Er;Ӭ-~ZP dVl(3Vpy3zv)K;-I-e;U%N@ :gpOqT=Iojŗ.͝ 2ȩMggmf^5ch~c xpJ$G7 ?&?!Vl橨YI6y`ic?fa;co-e1g"-JmRhaѡUiUdo)\2 DF⭝꬯KWgE;KleY3Ǖ י=^ÖڢKŪn-Zw`烑h<Ѿ'V\' u m|eHgBv\ Oy__mؾWڶxݷn{('<OImJX٧ml`(p5xBffOmEJ7% O8 @:Z+Acެw[qZ#5n1 aǽ>Olske"h>*Ƿj[r嶂~u/̀5Η7TR-$ZiɩHF@Qoe 0{`ά?f2d~Lzfx>#VՠܞTʬ%'9TP鸰nq7J?п ?JEYBұn%s$0pm8YG/|U{@i(HMԯ]E E+;:̹lc?1_˪EA5؀%"0&w2Nd?=9HKE;wbUbrI=[$\~;KFBҏ/x*R5{{KRgɱ8bhMamm,.Jƅs3U6%Ep{:/&/A_?@袊(Xz}KXz}K$VLo?$QE (1<]J/yi/~ݮr3q׽eɯkqfak" wۖDR'p 랾kuJڂy3Alk4y-@02XԜ@?6 王¾ðjB{ԻP!1*rn2={^Z7 H֤p̎rHcW'ҵK{i.53Yܛycef6K|^vw-$HA[aV>s=?@xrm'!K~ӾI팑?%Ʉ~u~c;"Y_VriwBh|ê`#a/?}z㢀 uojO-Uh[`M`,~a0r6u]KpT9G@'2&8-Cᵥηw}m%0ݭ74k"魧j.D]M:¾I g桩}f&;obfw ?wugx|>74_ m*O^xcP۞B d]ʝW{=ǿJD2*#rGQKy猟ɠ>zO{ 6narg$`N  mYftLO1 IaT_gx|uO$6 Nc~4 JӴ 9v-6+qǵ'O2rOîЉ.Kl5lUb1NN4Z]^n~m m+g9>oLq߂Oquȸ۷1q?:k}z㢏OtPa?7y[oB]I㷊mm9lO`?>܀-坮j۾74aѰr2Y~--ltؿĊl3 @/T? ȔCP@O^M_,"\CK4,PgbkkxĨH1@EQE5/C5%5/C43I>?+OH(QEQEQEQEQEIo1?I< pZ>b|:.?_o5HW[ktfb.NI8?OJ_{o>z\ѼQ-Jcw$`w“f_.c·wsfm$]wA.\ 1N(ڿ#w~޿l߼s=3S}o'kHuZ^u'F:mF)p$m@<+4s3HV%dlj&F'"?ѪV 67ZżmUL NNHz紟ѯ1n}*v>,XMou%ݳ ePAW;9;նm jpM% !ejT@r_h{I}>75-?I,umJyn<%mHGY ȮɈف+% 'YI/dh QwȤ{v[n)uHຂ[w͇hmM紟ѯg^QK5ak"K,ʑyKȪe ۆAx*ѥgԞGgoH2'?@jVN1/VQEQEQEQEQEQEEq}ksF K}q}ksF K}?+O;/c *l8gLOfG^q ŸsG. 5=\˟j?sS.8Of??=\˟j?sS.8Of??=\˟j?sS./Zw+, Ts><("Ћfjz??ƏM?y-/pZZ^=SO_G?Ƽ?G-/pZ= ȱpzSO_^z~-)Źw0)#6((=׿/_Κ|,u˿'&LʋdyWSosϿ*~o}t_~̈́ &.b>/^;E/_ɪҗ~# ?݁\v03|w$OĒckѤϟ?y9Qeh<<<('~7~aJS-Dӧ <яz/_A;k}=$X\ k4Yu_t_ i+yب/r~wkexVҀk„ hZJ5Gͬx7x-#Tc2ѨC?zoPkжJpM0a"q"P +ϚX|W~Z n9{i={f24ܴW&y;AoF{EQ^J?y޸펟@2T1'l.V6nՀ{}ʙn@yngz#[9]`{z wUlVҀk„ u/_Nӗ6$6{Eqh2a„ĉz[jC/繭F0f=wwwK/ 558(lɓ't׽0nWfr89=&@nb=&@n{:l6X~t<'(Tcg'$)'<ǖބa+#&dۥ u0RpvSbO) V]D6MJ?_ab/s`&D+ cH쩋1?<L[Ajց hTm%9ճnBwRvft'/|Pڥk. #O4}OUI8 hkْ׈ʜ9~so$;Yj r$GoRi^A1fe˝8~_ y%.L0H鉧*$97vi|3o<0I7Zt^y96Y紅Иq?2yVg|:ԃ>&ճug:ms`y5`D3uDm6!(ȯxqbᗲ ȣl|M{fmph˼__]zIr6t+iVϽ _X ̪Wm e #H>(|'7(ߙq]EB /~ߣ'ZV[e>+`Snqߝt=_ipS{XCíRQ]r%Fy(gx=&@n{ʛ`&ag-Rn+n* WlW{m*wwwK/ =y0O.] ` g0b, LES=&3.U3z8IҀW0 9{WzlO!AfbKmJA$(FH4A'HzOVc^o>fYU{^MLИVBOVh$>F]5@ : ݖhsL3N fNБOS D=&@n{n7ksCcX VΏ1 eE~fu0c63=eZmfR^y]|.ƞ񕞑WKsǜf75앲#]{`]) _c~9^ \R+ޓx xcA1=iGw»ܸ)ߙ?WҌgh L^7t'P1LUkQ2{cO6} ]gqnm/L(jNg3IxO11= [ }u>g5-@2XD0mE͙zrLV/}QS& <ǺkW=Z.}-PtN0?RhJ3{z'f=~]]*qpn|ڐu c=ӧя{m\@5cA>fl̤+NCw'ٓ,Qr,Qr,Qr{M 7r{M 7r{M 7r{M 7r{M 7r{Crp;Z=.g9ztnǞn69M9Ki$n|'mEq:>*G"hֱe0XWQ`C=*=q&0F:{T}VzJ%ŞLwJ#ƞ@/=*= U/H'=D\{혮μHƞꪹg.͚ޓnqwk.\H[=?YX+f!{[ 2$s\/bĞv5TO[>e Σ!-Z]Evn c8~J޳ kX[C}2-k?D#r{mlf)x fF ?grO5lkN#,DcefAgkZu&1k3>eϗ@m2fÖj8uuܼ_M,~#9~ւxE,Ya+ͼjÔ"UNPñrV_nYOhngW1ӗsp\^];U?:o:2 ݢ/.{{O,ds])Eհ"^gY}W4`f3M&vJ\ 8ĵҾrN߽p8 xk J<'jStf݇H3ehS-U}"v7w]b;r6T\i",>+(Oy,of]ѰhumEjL\E#9I2K. ^HgbJϴ$a]6]}p}G˹jҘ 2jsGz.,ܥE:}>a 8pqƲRVc3WαRqrv5gqgrwD_DRڎ_JBNl "mR~#ƒkO7#=*t:r[Y=dͦ|v7{ ;"rDvRّ[[ęAq):um(lQzwFPWCzRV]{3_G󣳍ωMJɛ'rѶ;\v1)@t/7; Rѣ~[cOwl왶(&=%^5(Ô{aZI !zٻJ;{6ɏ&k`ȯ3uҵݚW1OGpok3ciн\bOpAƎ5H7<VhzO1|AثʉPjfC X܂{?sO @$ZƹMz@nb=&@nb=&@nb=&@nb=&@nb=&@nb=&@nbpVnGkg,#^9N6sQsww܎xtJ\^}u5(:P9A}5(7&7=>aHG1U&׻ޣHcWQ`SV}<IQ`ؓ7֯ޣx=ޡL CޓcF. =vLγgϞ={6H\Wb~p{y睾 ?ydR\?Ş/_k4&p |w &@n h_.] nx"Ռ=]zIENDB`taglog-0.2.6/doc/taglog_properties.jpg0000644000175000017500000007076113534701742016473 0ustar johnjohnJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222m"] !1"AQ4Sar#26RTUVquEd$3BCDs%e5bctF(Q!1A"a2BR ?L4NARt~jqT% ’Mk|)2BٹytLUi K197y[ m?*t2BN2CuDHHJT)B}tb$)T{i[Xۛվi쀬Is 7TD6~jY棦_LO̢ZR70е*& ~hȳ;, қ^SkwV jQ֑ G3s{“\NhrYE%89NO4/j^le' sXpMa>cȑ42;7ՏC/L9knMcWWvt6tlz-W}Vkez@ΠםR-o՛+Y+yX8TILZn5/0bit!I)83o%0yԻ&B/)xH7UEJ$BdW8 X\F?JiB}/=MqT,S[ZX2DDճlie:!('2cۚ 6j(Za1-Fj%=4P&ERH.];2onlU]:ĩTDjx\Z383}dTK˵:|_]Gsa9n^svoVV@\g-G]~^)̰q)Rl%e}0$qa g]5OqrTՑ*ê@C/k)*$acsL&|`F]JwÿAH]0},KT&yWLJ6`~C jtG pl?/IN8>aHɵEar~x9]洿L NNK:S!B b#wױ`O,i5lܛOˢNL2ȝx-N8YrDgNy)DLRfSpJTGVFz4o(S.4JQ~v^qeh+IUŸ鵄YTLX[RA I*Q8Vit-BFY K1?.4$sŎ=?AvIc5'&miJx7 }WrۮV~Ļ0Kl\ՃlXqB>.8wӚ.c$?"vN%<ܧ/p]ܘ0Jpۘ$Ft|n8ςj'yʅT!>{h_֦1^8Vi!RoZc ōܿ)c=g<;i[f]Xl{&zTyc_o[X!_ǡGoӟԶeg-,6W=]*<>޷gǙ1?EM?Nٗ句6y%voZݜ8?2ev5kX-cYs_XerT0z?Ckvq`BGJ&KXB~/=e_!6CZ[?Mw-ar+V׋ S@$.i)8JlD^Xy-\yҖ+Z%D3ekeߘ }Sj^l/kXCjŃ <-WQypq*Q9*Գl8EdFGvq6gG/Nt^뺴#XV|ߥ>Q\Mtf_k?TybGՃhI}[~Ffs3ңoPˏ:m-JyHN#CBmG2(a 9KJo|̻_6X}S8heHQhu^eMG2Q8pd[wz%ocqٜLf_gGgWXh}ǡL?>퉫Z,6e&zTyau{8pfgz9ogq\Mtfp)XgWxhqPY=X-8ZłR*$ \KCp;HТG80V EХ[?,a86qS?80r ?= ;8>h>ơRSPҢ>3"}&vx1j>ڍcp&sij4vJaץ^wVeEpPM-&Ys!2pÅ%KJW Ԑ $*1, VꍷNDgȕ)eV(**8&+g@}u, hN"d!IJ ō摬U 6JRU`qQr%)&J0p(RN%A+!h*QcANZe^qmiD)N%$r^$,j]E"M֪ qu+ :fp%i1>rHRtyoDԤ-4ؘeRC )-.ڋ%7@ @uW۞JIʜL9-0ۭ(PX27: Ghc)B>w_+zDuJq*ݏse}s?ƏK@fE2e220*pb'(w4Iv}|8K}RA*4nd岢$I֬6V`Req6a`:G:VV1MD4iJi +QlXÆo5HjhLSS/96Do] [.+VRJ (]Kh6UCo-֡\yī 8$쓐*&#^R\Ci2Kmi)ZB%Y @$ EwJyfCOfL!UrAJB !Ȫq2ךRk퍑952I%ØȹA,׹*dt r*l,=(pC/7i7P ոO3hwT$fA+6ea?á2S QXJR Rp-,.0iZ:<32g!Y%A)A2]Dx&tM˖}gʗ5+iRŸ-XZJiY(a/,tYl rp*Hox疚qͰ8ޭ%SENaK]nNim%edm$,PՌjp*%QiM1>9v iĀIPS0.@%JYHv+Jm:BA$4MV/$IYUJ"<ˣu_V_TL^Xbr&g X%j[RS N`$f:yv̫fE!@!@!@!@!@#-[SƧ2eK? #K_5ٯwL>,axk_ώ]~j3 gCj3 gCD\}Ϧb5-KQR(*7yU!DBI I)P#@ze%C,4B 261 0ڦ{{L0ڦ{{Ljãшa(p,Qj3j3 gC*mg61 &ڦ{{Lj3mg61 &ڦ;{f>mSIb(AmS=ߦaL~aML~3f!TowmS=ߦb@ML~3f!TowmS=ߦb@ML~3f!;KnIM9Ҕd u}eK? vퟋGnOf?߫ >8Mvcq?u=z]+K*aɉ@VV}׽1vBbY)[sXQy c$*21ǍKxYi͠?)EK'.ŇlOtFLkeHV؄9f >yoɤ3ON7tAݱVgp9M3@Z7*Ez[tZbAEo )` /u_!rTqY-?y[GFuY'k\R3}bEß$Z6Ub&#BTHdeGr.cէ7M|8j}tB#m}a,vmO^w!8$)Tz4sTyW̰MJB FjF=׌UUtFޑnu:\\҄0HƯPl8^ =!Wf3-Ԭ&R RBg ` A (n:CS}I)=eҕ!֐̡Ce٬Y@qHP)XiᔗkcZQV6Uҷ.AZF:U,YU>ҖkI%!b8H 6**%W"=TMegEM=jp"u,(]*£7J[Ci2aH^.-iǬ%\f\Nm'} |uNWdԗ'9oF¥^Vv7ZP(o܌ĵYGru4IJhJhJٔ/zƶNORs3S()BN!%FyY!!!!!!!!!! 7=}cz-_)c_lXޢ8t~#_5ٯ W]~|px)խQJҔBgI7FLTfi¤CP@t[ N?OiRP)$ûc㔚H5)}1_M U}8F Q6+NS]n^L:]r1.ˎXV۫M7_Mt,԰mfq(68b$s1JȸIJޚRqKBu-.@K谎㗇V9NXJs TV⒒um_r!qx55'S9/rBs-IIKiJtiQH RAe)E2ڛJL%nTJ–(@-{eIU,.8Wt2l*Fۛ&tc[f&V6>~K2BWqare{GT 9f3u3rRϥJM7@ yű캽PcVaÇu[-4"g\D5%O58JnA-t=Ж6Zjk,Ҕ{b!dkZE4ތS_**T7Դ\9z$e*-E!& Twܨ( $M/`Gl !BBBBBBBBBrۖnzg>Ŧ[SkϽDqi/1zFk_ώ]~&55ُË ~oʉ!*<3~T0ӹQ$ ӹP7NDxfQaGsH@Goʆzw?*$xfQaGsH@Goʆzw?*$CtxfQaGsH|xfQaGsA@Goʆzw?*$#7NC =;B<3~T0ӹQ$ #7NC =;B<3~T0ӹQ$ #7NC =;B<3~T0ӹQ$ #7NC =;B<3~T0ӹQ$ #7NC =;B<3~T0~ӹQ$ >6 t# ZZ}'G0F篶~,sQZeK? vퟋGnOk55ُk_ώ]~AotIFBfId1&vWagnKߒ/9bQƮ4|$x8Ǥ* "4i5-4d}䰆y()I% HPI¾7+iV! 9X ojf Jy%EBnXd\Xoq+HXUd8NնX~:7THtT?,Yن&i:*qw•8 /ihCn-Re<쳤-ڈq0<7m|b,[4ri[˅-x$ 6;QYPʤrM;)3("[ imb$Ы*XNZNvv))J*Ya8sdȵ5WnUã9;jfA̸R`P )Vc,*j6qJZĂӬPokr1E9QSTre@(RB(gzܛ:6ei mS`)CZN+]~N5.'S"ʢ\6豱QrrTWO,$LlVr ]rTW`.C($O'K AK-} /iÝkٙ\tqu6u[ ԣQNBnjCΕR*"ql}^yERBP@R@ BVq&G=Y:̇vM%.0Hyl*Ww=s6jSM5-ҜWnIQ Ή$ߔ6ܑqd%S .)$`yD S}eԼn,!ą$- f#xe.CaքaJ@ $=RϽDqi/1篶~,sQZeK? ^f?߫ >8Mvcq;r*iU'&&zL+VS%!xP#7)ZNwy h@g B!TjINuX)Qp#~xjnfuҠGhs+rYiGL9myGM"\XCe4 -a Pϒ  !E8VA9/xqG[@!M!"Kҝqv&H$ @wܻlG,Td>T9klrۖBBBBBBBBBBBBBnzg>Ŧ[SkϽDqi/1zFk_ώ]~&55ُ iyJBZLβMODK4xs 흁0)/6jTdTf&Q!.%1d1ƶ+HTU+Ie1NSU)7%KwZTEġ:XP;~-o{mow$KF6TjtKۙ,c.%(!I8,#wn}R~N&_5ٕ2wied,;quO&$&R*r|zJPiZqsZV+YevVf&[Ŕ>LeDal"X)K%P04rO^Jil{XzWMÌ`JAkFܖL>FysƂ [+4p_Q]v*{*B]u)̒ rFVF?ZKRܕJ%2H.6⏦XiX JFwU<е%iߛeQK:ÉZfV,ucXqp,LSiivfUr%n06(CoJɿ9~t_[Ại ^.a 4Ԥ*$(U0#8AHBBBBBBBBBBBBCF篶~,sQZeK? vퟋGnOk55ُk_ώ]~AQꏩ}ZFmԧDPM9f>xE1 gJKOYN'\ FW'$9m>TkZhͲfd*jie]db$(\a=L6¥h~q쓅v] Tm.`V+ ~775SVC OFY-bi-:*@ # q|C!DR^νNe%.I*0-=M29N~<\vT(k;lttjwݪT-^iLiZqNW_V@AIlq$\>6388Dž?U|N<-ZqA7K,}L䞷j1[^/#Ĥ"ffFMT8APG 'ywo1MMs} L>Q7HqD | (Rf+?GCImNUjhKUz~bPAQ1@ěLOۤ8M^<֞2(dIJKJ zKR֖Ҋ02jblz|Aex4f."NL׾>gD{k/Md"!)$TT]ṹd2*i !.]R)XV5 mKȷVu.j^FØ2SQBbB@,ΎzߚoDvjS3"=4d)*2Dg I:«w*Ѻ`y Znah,8v/)GYh`]7XrkTbH:%q8'Pd*5v* Ȗy3]z&0?L>gD=e٨}Ln/T34^t̬/GŦ[Såk55ُk_ώ]~AaVҊVP )${"R'%2^ )z0w,p͞_Y*s}0p̹0[M:ū6^PVO7?> 9I广oDBBZjM!Kqh\23})V'N%M̝+R(rH>Hj#93OOg_𶻿^г亮g^Ŷ3fTow6}*} p, ۂڶ{TowmS=ߦa͟gt,EmxsńeEԹ&ʼnMJgJ/bN"6&o63fTowO]$4Jm-ҥ/mtN`ҵw=hEI3M%(72Js8R$ l$j3 g9sdt,?ׇ=bքhc".ITg',]g60\ܑ0egS['A6e\l[VΕ^AD\؛ֹTowmS=ߤa:~ɳH,r۾wB3ۂ۷y[mS=ߦaL~͟N8WY}[^^>zy[KkÞŮ3fTowsi8I,?tȷ]?B32-0ڦ{{LÛ>8SY Rڶ{B-^-0ڦ{{LÛ>8XǙ6)Rm-8X\)d"ܑsAW31NmN.״)`% !hڦ{{Lj3>׎:Tқun;4#Ci)R Ea(`. +Ib.,s0ڦ{{Hŝ\ܑ0eg֥y,^} z$8.E|)B -ČZB. @0ڦ{{HM} <> G c*fR$TV+*ue$XB\XmS=ߦaLO |Y:X]m֎vAܠmu'b$TABZ,Gnzg>Ŧ[SkϽDqi/0k55ُk_ώ]~A@ @$~exSx%*RRrI9N@S傦٥;C^4hsž֞m!@\|"=iN=׆)$9m ҝ { S9OuAw ҝ { S9OuNKo,GJv<)6iN=׉! ҝ { S9OuNn? ҝ { S9OuM ҝ { S9OuKB#٥;C^4hsžĐiN=׆)'ЅiN=׆)$yq2V oR;4hsžfxSx2-MO:e. i70fxSxlҝ {Eɔ9m ҝ { S9OuK~HB{4hsžfxSx|[iN=׆)&nX[;B{4hsžfxSxr7{4hsžfxSxЅiN=׆+)I܄,ymY+-4AP%Z.1JuD#.k gmжRx]FX76@sW}JF d0_'w?4<=Kqe*uũl5 ܓ6=3<Ғ"VRq*\ 9q wX-'au󸿞=L6 8 .Aqq/G::R @Q'IE_l瞗SFa JB[ZTUa1d,$<}i_NԬT$&nI9̛8̹+JPBO8\V8 \|\Zy[CH$H#;Qkq/8 ydPTT 7Hy%0k[kHXI&qҒH \s ̼d촰1$6- `wGHl6@Ku§HIaa̰mMZj,*BZӻǺ;3sO2ۭI%ޭK Bl%)Ģ\q3N)ԤZ r׳8_q'iR$ IRpB.hh$ݰI I N ~KCۭ%8JN7M!S))eՒsYJR䏚XJZ^g2Uxy4}KM5*ܫhHm!8G+yos5130Pie-Eo(%8J`͕Ӻ{(-))7G!&J[,%mI ,QrEFh2ƽФ) RPk'}H懃˙SnQ\). i(p\rA_}N-ǘGCE5VbB7@ga"Z](!,`@"kSmÚ$Jm8m(Mu)J=ңso'ۡ}=1Sx䜽JUYԶ]ġV$^1O;S=JڛKE'kn]Q% KIզ̯XάewD9e0JՐXRTmksxyƝh6H%W G2gRV0\:ڐ{2Orro* «JՄ\+ қap懀S!N(@J%EJ“~blon[G!3 .d@0IIۗXsqrG$wZ%m>$RA{f] r|gU*<(r 4q_RpTJIO@r\G<s(iAEwR)I) esq/)Bug 1[A!J* A'u,`K)BqHWxߒ '|7'|7$G#!# $G#!# $G#!# $GIBGCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCf $0ClHeJ* 4^aQퟋGnOzg>Ŧ[S>8Mvcpf?߫C~|1jPTgUN^˴Bu ĠʂQ. !U[(~ME7R5Y) )HqJ R %)Ryo`HC7+U]fMt+t -:Ÿ^T-{ X$#A4IM6j/SXi2^y(@K*ZbUm-N Lw(r.3s 93)NcԴl͎Që oDZeG5tz]^/5,$l.#f̀7#"ZL8u~WsxupW9LJ7*fda+A*Hĕ!- $v#@˽:)Z )yt0)Җ[X n>s*y!î{^$XRrK<+99نe_L⇖RT}- _ R*# zyʓm-%yZ[-$e"j RpWsxupW9vQiY_ԐmVT;C@a7׎ /4eD! %)*MV4Z̹0Z\ sHî{^$jzE'^dz6ve#ZØO&*«%VPiM-\~cFiՉ~aד"v-_qZƋVJ0:U﫜C\ sHGiKd*SAʜԬ6S684 b̌*fiz3RY'K̤%qss J[^$ -Që sHpWsii:J)3L֚ۡid:F X :ЩA%74eK'gm*ZIQSJ̺=,b-Wî{^$}=¯}\;tK*ubqɷCa2}ְT䀵zY3au&NmmH)*.4r݉NWxupW99{ۮ>ӍT]վ7¦-lWUw~zW9IFt֧&Sr3a,TZ[D*1g@FrkB07&nʲiML%I!.6BNDk`Zp$!®sԅJj>I)gf jajJuNjIZo,[le4AmUƔ!sБf@\<Ý\w'sߤ. IEѹJevaz jx֨KccU`#4nM9N2.djօb]\w'sߤ. s4>^%Ԛi,eÈ [Mj[l%'`@hܤS:/"qAĩ8BT,1xkĵ)sߤ8Uw~z)΍ijUPLZy %*Rڲp9*::lO˺B}ï]ujΤ`SD `W9IC\w' n4eNO43͡M6ێmWA)H/:AJTHqh]:[/4ȗο:̳s!KQXJIyk7q`RSq®sԇ OR/  OR*;I=H\/<*;I=Hp$!pRP$!®sԅKC®sԇ OR/  OR*;I=H\/<*;I=Hp$!pRsߤ8UÕIBe[?DQGcIAR`qXQퟋGnOzg>Ŧ[Sáf?߫ >8Mvcq0a4'E<^_GMp)-XIl"U<#Fҩ]EbjE,q-2S*}ଔ$RJ5/?)'8!ieM4ۈ(cNd 9/j7MeHu ͩ3gSiQՂOVMSQɵhK%,L-*qLK NָUno2v](+VTd)A*$]-\6l>m(Uś-HZI*Z dl1wŦ[SkϽDqi/0k55ُk_ώ]~Ap3Ebg[iajXIue-CU*7UԐ ī1AUGj2+-05M#{ m7o&t~JImƔSĸ,О5EQX4~&[|A© ZUŀ ENQPvYmLzՒ1%A(qT!$` ṽ )ԉڄarR%`nIo.:A  2N,[Hum,V0'p \DK% 7ySN<`y¬dMưJ` "*LoFaM&~N'7$kN!j$8R[ R(aS !Tsmb|/XlL;^k1P[ /%!/8 PB) SoEꔓTIr:Zn푄@ $71.}y}h)iMR,J6 ^5uŪ]KY*Q`@g8Eo_Z"7/ SGx^3"7/wֆ)/wևCtC]E h s]E.}4w9.}y}hn;y}hph7AMxph8Eo_Zg8Eo_Z"7/ SGx^3"7/wֆ)/wևCtC]E h s]Ejw/ ,*":\[",EJ'xŦ[Sáf?߫ >8Mvcq0蜖-3<NN$5yW"l 2HGt{aU''u)I S4-bJRuHViAIbme*E.eH(۩Pj\)sct,!BBTQfB(;D[t ?xEvg5<\IoL&q%ܙ;N!V񨄷"^8'L]{x'L]{/kWmب:E.ڍZ8HQ@6g :u9*U*%KKRSqD\ $]y媄t˵:w2tO732iKlɶ$Ƃ qIց%Z4+.i+h}V0KK$7K *.sAo]ӽԀ܊NR#JUYL .aK[*[hYXXMu,n0c7wN̔!mS[Cu`0K5(+XJl-鏰tu!Zc(;H쮘LHʙɩy6QPZŽ▥A)dU^4YfR%StDimo ,@Agktu#iktu#MF𼛓:V kbSk&%wŜ* a#L]{.@F-2t8#L]{B4˵:w2tna n.@C4˵:w* a#L]{.@F-2t8#L]{B4˵:w2tna n.@C4˵zw* `p3B7(:.зbnTQiu>wOWS(褰> sw8RyfIIT^Ԥj"L.IyU`Qm'((O%JiQmQퟋGnOzg>Ŧ[Sk55ُk_ώ]~A6Vʔ*A#x"E49.?ٔP,%BaR0)āhUq E1.)ӥxPTu ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßC^50˧Git$|[͐)MfH ʷ?&d(Ŏ}#LI|=}cz-_)avkkfߟ&1^8wBr+AA8BBBcxBN~B`ɍ4bXg&ahp\hg! 4|"7#k֌!ZDu-s}:ќ[d- QqJHOEܔhp\hQj[_2Էey"\hp\hQj[KYw䆥l+ 7#k֊-K~kW]y!rRDu s}:EGZ䆡H3-\wKkևEl+ K~kW%/xEh8EoGZ2s2t-٧Ҁr•,qosem(%$M'!rRDu s}:EGZ䆥vK_2){ s}:hԷk-[W^K_2){ s}:h7햾ey!lIkW%/xAoGZ 7#Z̯$&e B5@Zw#AȸjԷ햾ey!rR~a4,,-$<"!Sn͸6d'[($_lXޢ8t~s?9-2%/C_5ٯ W]~|pxaAHBBBBBBBHv#'Ĩ&*3MW&tr&[gCmɺTԡ(pJ6܍/ 'g%++Ѫ+nvp9$!TEoƶ;Jii=04[h!h*xӄ)Y(*P06C-!"U>\ )[IIB0'XsMo=?Dv 7mvǪ a6/j/,|ZNgd/I'*eVkYY P $\% M I-3X^M=5$da(RJF-iPZdLÓ )ro\ Xw5$]dx@8 ~]xmVM^3 }Pjzcr8 컉1bΦذ֥[%8%SjĴˁHJ)! wT7+JdDʗ34e!wZq[qAZ$+-rQ=QO[;/DLq+\V_7HSiț*GDQ$3(&CL92(-)8]]+$ dAsSfX w"\UL c6 $$JGN*G$#'ĨKϏThb;19~DEeb|R޷eq^,8ױSQV(R;mFr侹-Բ)[ͶBxQb8m+mt)EK VەR7TbZ^YVXiVqS(Qm 8,-THQF#Ħmhjm'k[aű,RFj;#3qHI-E +JV+ HI&9&E}KD~UQ?)0w7XVZ)#AM۱3'13t-l_f.P3]n-"aJu+T/ ))j(+@ &׸ Z*vM}&ʱ #3)*e=6%ʢiԵ+@^O \[az+TnJK-6V s`(w,VT6'Z]+JmV)B*8\N\a~Ue ӁC2RTuRIĂ8VbbV} <7 W{0PՈR QB%de4vD-DKbqKԙ[qXTPu6bbJdDtn6)Ru'ؚdm\`V橦Ӟ1p5da|VÝSQ턤 l.gȁI*GGX]^*/""_lXޢ8t~s?9-2%/C_5ٯ W]~|pǻxaAHBBBBBBB5P}OfPbIJmaU  >| }^:!W8;H}1x!bW8;H}1x!bW8;H}1x!bW8;Ho끏^/! ,jJIMUL@QRTs>h5P}OfPbIJmaU X!| }^:yX!| }^:yX!| }^:yX!| }^:yX!c׋B4ZSfS*(Dl&(/a 7=}cz-_)c_lXޢ8t~_5ُynX\lO-7g//1^8 L<#?;C+=2:yX L<#?;C+=2:yX L<#?;C+=2:yX L<#mJkF(STܘ<놯81)MJ:wetywgGRw]YԎ;3;3u|HywgGR:)|E}aHyvww>L?#\ST-.6JwOPҺݪKҔ!W A$,JYvcD+L2uІВ)Eb>:?>:o/!~|tV?L~s䂔T=TgJ zVչGjj\$1֥j{KMTXm7AQ%j6ZHN`Gnh̟HBˬ#}R7<^Ꮉ5:Eh%H ы[l *hnY5vh 8$XXܷߜ|amn, Y)\䓘̛I0/!~|tV?|t{V?"zg>Ŧ[S:WMB)%Eq֣>i/1zFhm3dϜE N.c3|6m?Hs$RNfw7C oO-sBt߶ 6m?[ w?ts<G.<(Dž`?}y\?xQ >s<G.<(Dž`?}y\?xQ >s<G.<(Dž`?}y\?xQ >s<G.<(Dž`?}y\?xQ >s<G.<(Dž`?}y\?xQ /O eX c{T_k{⏵ӽGo|VvKo g&a!I?ՖUaUjIJd_;}>Nk{⏵ӽX7Z&yfED,=i?5?m? _6G@OOnI94KH*v2x'n* f5bY2sQ>Nk{⏵ӽX7Z&yfED,=i?5?m? _6G@OOnI94KH*v2x'hQEQYhtϴ$Ld Џzg@OOCW'MQ&( ihjɴ ?5?m?­YM\;ŷZCpΣynԣ88=_ _6G@OOCW'MQ&( ihjɴ ?5o쟇>9T^/y E)d5xPy7 ilc5x[]>K`4ACu' Ɗp8_Sְ޵j@e,y3u-}T5h1c90s]ok~X{Ef7m,es ;% hfU+ Oo*2h=N=*{krjAs /%R@V{kl=11HW)>yqjk{6sn̎x< d-k(:dVt&U/5F\a/__X],-N czkq7+xTYWa0<SO@С[XbxV%nAu1-|5. vOVJ*0'kGɶiB[ǹq g =Os L`R qϭd_X D闐oyr(l6y<ZxV) ت$@hI%zMI$^鮥M%Tas"r@=Fxښck 2ݳI;u_´m|5. vOVJ*0'jk]GHR-da#V!.:@$ ;;WdF (҈lm&HB$iU:;T-q`3ER` IaJm:eXwcP?6_=~G~>8m{=ht?1it!ME3)t ,,_Fy{ _Xc76nW?@0'O0/^wǗocen.nN/= ,R,/қ^-zJ&G71ky7_x.8=.[ ޕML3]d|jk|j?o>CR~{L*x_z7TRX"D7_"X57c=3lLÍ6+c_|5~70 o{ァS?u񞧯~~<z}]Eb7B?mC5 k|ϻ+J|wW?-sF?%N6CL3qsvftҁ , \0_Ta[$캛/hbX.}nC. ~3ﹹ"xb+Xk0Uy^=[ @7E Xlhhhhhhh|On\.RRNٚ&{|ȫ{ yM gP:{'sS=-(.0}vBgͷPXl؅NXBUy`;rbK>xZ̦L(s+Dm 7PXg[bV`zzjtH{x/6"gr?ޣ^Xz3w55,ٝxYW%{=.T9ze5ԪhCr&{?oI{;,JJnbNYUx'Wo](e׹Cuȶ[avF} d5P0 ~CК=qzAzX餗6+777sWX-9g+ٳH@&O6=\KFFOb,k*v(1 }nոq"4- * FFx϶#z@gCE l@?sۄ:whZ#Z#ZcgZ L Ğ8sWX!f 2xٖ~?w+@k@k'Q3Yޯ?͏X=x`Q%/ y n Qmd4t,힚Ƈ@ё !֌RREvOS%»-{k6BPĞjHCxOSh5[C왜 eg Tϭ7N&D hhhmGvφ:A ~ u*_V86@Ž=9/~? x,`u!:}ncBsS|wڼ{Ԓ6 i#Ҭ_(<5*{wUUmŞFy3ovy+53m,Z/Orś33Tyk0@xԍCɩ 2n=S`T6d7orW)^:Dx~?Q7Bu7hߋ+LU*,]Yh'wpL)k$4z-^2G >FG3 0r4]ix(=$?[:#҉LBw #X龚T}:8݌JYbrJWkANEa#txHRH£$lh%fZ&%5~ x, /y*/qGUš%;#i:L3Ğxt=v^׳0/ 7c6VsE>~fA?jٛ$L9QM]벚DI)f_Ko\at:YѤ{7ܨ'R}]i}xqWޔlCU %3Lm^^wq*:cZ+?8Qh>yXHDR6`2m R} @U^>)56xWg>㢓y{ƦGi$\ۄ{>ι}Ýwm&Cyzk = j X繕k,]J4b2ݚe3QL|98bЈ}Sݲ̯EEB([-؂ܼs "ߏt6G7%?ʌsnM@k5 `;z={{{{{{{{{{{{{{{;q=Q9U؎of_jex5bX]j)=L"L^qU1=ݮ0`S.U {x<>{]υ5tR×|F [,L!CPb$T(4{hJkkU$ƞ@(CP.7W-g{}0j{0 aǞe ,;6fyw=W~XNH{/YsHPт=+soaXBrdAl^!`"x<]z1)12uXQbx%88BupLp =x#=ֈ=Jv0 g^& ׭w|Ii Qc]a|CMC%u.MZ^Df'wnf5wh> SBcQJ1N=rYuYL8.dnM"g0*:~oM0uL Z}CKW`xxL$UnUηH2ԇ7^+ӽRFZދ5?JFWɪU.'z{jelM$ weMb4L=Pn>E/e>ѳsՙ'7sMvp>JdCU,x?gd+<\s]hZb5_#z.21sÉ$Ɏ+E{c2.=r~0sthv ?V?tֆ'&_LM։.eA#w`b$RtJC|O][@|x2x0ak|XqL"NѕS7}RwBj)ޔC7U'ihG'n։l]G<&怐^yoKCUr3d;%zLB9G2(~9x_ mwyq3Q}8oIMZI4WQϘ{tY[y+Gg.x'-1R~TLF&IK'r(y7 ;u{ɀMi|#ta3I9aoxG4/8&81{f☔wBۜUPy<&1DgN%ֹ[q*X3OY}guzsٱg%vOj,Tƅ2 !3{fi\(O6gvw6ZABqq<߳]|0z=F 0`& <BW@k@kg۩_E3q٘Dr,s 椢{enw\ԟ+fa8Y{ $*HKJN4Yh\NvL5(Ԛ.؎#Mչ{D`uC `6`3u;@ '-mM܃O'na {{l):~c@{ĞM#}nu^Ǟܬ-˚Ps;͊oYּ4s^}[5oSr8{BTc⭷ʮ`?nYg5Su!nyGDwT<*)v_%mˏń~u5Kyy.WQDg&}#9wx2%Qh|ҫϹJ>"6oy.WQ))U%3!ϼ7S 5#oK`.FOR4u,6Эnh`d8R^*gFdHR%ު{_G7MKgՑz2d܂˒5nfM)sjiϖfrJ}M`]M]iOaA{&ׇٕ*((y/Kyhd{/.,=BG)7{3):N[PJޅo,Tr~u ĞeU-Bhs95; <{7u0E= QO`Όѓvu~u$#<o6+[S~;7z֕ѰͰ-hWflAFO;Q]"ٙ8F ?iSX1]zιʽb p^OpPT&{v>7ൺOn[M 5#8TOoqd$7v%QXPh_G)t"UJڣȩXGKwϥ!䝒 &g1Nr-Hrg(`|(HAm':z*FZ*BՎ*x(TК'8 `"Sh+'%^Ze䭧|zPXWh7%{2~܆p 3ݪ [0a x?dnQ5",}=mn.o؂b&-*CV/R:m*kP">42)۶i.`vN]HnL`cuX#AXR%]:沼xJk.UtRAC*#A6h>7oK;(2OaeRdM|hWad>760>lb*ˎ:+`;sFFFFFFFFFFFFFFFFFFFFFFFFFFJܬ{cz^qU=777znO Ul Bj&]sT*.=lC0v@CP]rFx+CPN{TӇTSONTo櫯*ZNSןS_~o7o} O<傷ۭ11{x`ls+U#񼾾[䂭smzAJ/y(Ǐ¹端Nu9~}Ѫ駴UUM~ tHJXÇ_|Kߧ{r_YEU|l 楿?4򗿔>{O+r{ܗ_~ٛ{O/ύ)7%FkYy×_~R&[E$N~CTi+yJCC9Iƭ/Z6!â*=c X*Eɦ"]˩[XEQ?4wXM<7g뽿o&COMyx@4L? Kה2Tеx=mu=gz7е?pWRKH~(G6x!mA.=V?=(x+xAQ///7,>kXHRXgI@nr=&@nrX)jzhծ y- VDS7:*AR/Xբ+]_P)Q"1b6+d_q=u]/*>O׫2]7RTԞ]Q[ؑ7ꊤw݄x );3#=At n(`kMo$k\1lN|]lқ0ά> >=򔨶p, ಧ;hm쮉Wxx m”g+Yk 7vd~XeYz*sV/ 0J?qۻ́e˩(wP^PV/jݲ_ḰMYEFqOԮ 욘m1L<3SNp,`=68t^M.=$uKoBۧ#Y(vQ q{,<EÇN/R; X݀`+Bם-_sCi[zӛ7o{V~#(\>V߻@9_Evw(@nr=zh{.*qp{|^+B-6y=L9 =yYo߾];ܴ选P9cI`S@nr=;NgK\d6E$j#&%̯L$Pk/1[{f6F&(Y%F")ix3WoǠޓՈYg~%qrliAhdFp4rQ]3<mni牮l"*9{@nr=䦿X`S{䘯G6H9 mnpg=&@n{jظu=Gq\;0Tmnk:`){|>ö@nlRZٶ;3*C6.T Z{N J=Env=sc6`{Ԩ| VPH!L";ޓՔ \VH_)g6Lp:C_{ f#CԀ{W 2FgrY&|isM;Ot f)'LS 7rs,}Y)=r#$l6Ck3rޣs^t>\.S#t6p^MmZї\ `K6FHw%xy!E3lj~[{FTzN` fW!n[$Ȕ[RvZ|zd1Aglq=e/Nbէ_׮o)NWDW'gv1h},\{ ]lWv}iAm/B;L7E!EgI[t`Ń!,>G q4=gJO:{m$1 ~aHk k/҃ƹ z ~Op~/gL'ϓQ;ۻ.]mW)=Tdes ~Aÿgƈ\5"'-{Dk?g0x7h)؂kd2 ZmijrAKmK=3^G\WI@Ђ=E#c > ijV_k?cu^< 8fS|zMp\{KN_0=l=@nre=)/6hC &%q 6,8x([m]OM\[!M|5;g[6h)hJHhU5xh)g @nr=&@nr=&@nr9cjr{~/|^g C@nr=&@nr=&@nrŞ9,!,$\9s(R9NKCnkt{rym{/]bc +|ʑsAu<ٍGbG%0EOQ`v=*=Lԟ{T}װzJ%垲bpJu`aRޓc&.k{^=xR4sϾjv89=].rr) {o?da1W9h-qf6rkI?pkDVkP/lH"и|x筹4JpCd ZdU'jCc] |Y52`ft9^JFjr[ ^?Ψ d#&O/s"j$$=3]z{_gkp-xڗRcCkW)aDM\ijMYXDPHOO<U ^%pGzW:č{/%'=0ױZ 6v'+H<4[m5N*ЖF|Sϼ2ij?_4%qg2h-[ ^2k];/9~&&j27eDk ~TEWh;Q~I7=u 1L1")6mnً`S\A̵3n کfslV|_!|0l]?${iFd}LWמػEf:ڵ_ͯ練߮ZCnVSsO[_3+N-U73YZ6z{5~ tBa]d\)52Ί>Gm}lfLgn#R'fLgn#ҠmM}fڷO>d¹g{y.!,{xc̛uQ{xcGf5=y}g^^.+{VɼROqnfoFP?ȼR#s\'AX2 `NO  wG\4e'R 7ܦT^}6;x=n-{g,R=ύNV`}Jc6YaZ[QJDRH$?'lzFM7Csk7LeX>{%1M=~bD)B[0m)ިǰ=¸GT#3lnI{u f)'RvV=&{K 7E ?$`܎~pPs^Es]Rrd[}uR*OEQw޽yfxx|s v{FwBs0įC`6Tt6p^MmZї\=m1gl*Y;!6 b˒rϸJώ[{)jz0Q[bD-e]|}}ظ'\ 3_e}ocJrzĪlUju9AgN Xfl`RpPS*=ryn>evgXT90N=ٞ繝H{UHTWk{vgrW=9FMw765\D ߵxb]Sҗ.s豋6XC\S+qoE#vIKPgWzzsOoDX*"Hg'1lsh@lRz5q8X\cfb0qH 1L}o؈s z* 1t=xcMFUBx]ugR Sn؈IېG(uݼ.*<]ؾϱZ]~ġ[ A"UfW>R׊F/[ؠ䞠%.evU>fWQvgX<]gN-21=F,Xi?޻SлJAe6+=Ń{WƎ{z`Smsk\7t1Z,^ԔzK*?>"L-GDt:%.tEqne @nr=&@nr=&@nr=&@nr=&@nr=&@nr=&@nr=Yo5[Ggr{| =ϙ8mn=qyMs kPDP9ACu5(7f7FU0ޣ=G 0QQ`^=*=L{ʪZ0=*=L{ҟq=*=L7 o߾M,Ԡ8  {sLxxz|KD'ݻwkЛ7ou<E:n᯿o5@OELY8_k:F;F @nO&J=]P/׌&jIENDB`taglog-0.2.6/doc/tutorial.html0000644000175000017500000000230013534701742014751 0ustar johnjohn Taglog Tutorial

TaglogTutorial

Welcome to taglog This program acts as an electronic diary, with facilities for logging the time spent on different proejcts. It also has facilities for managing actions, and booking time to projects.

This tutorial takes your through the main facilities of the program.

Contents
 

  1. Installation and basic time logging facilities
  2. Action management
  3. Preferences
  4. More about projects
  5. Working with other systems


I hope you find the program useful


Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/doc/tutorial1.html0000644000175000017500000002073213534701742015043 0ustar johnjohn Taglog Tutorial - Getting started and basic logging

Taglog Tutorial - Getting started and basic logging

Contents

  1. Getting Started
  2. Logging by Project
  3. Logging by Activity
  4. Adjusting the Start Time
  5. Exiting the program
  6. Viewing previous logs
  7. Displaying the time spent on projects
  8. Reporting project bookings for a week.

Getting Started

 

 
 
 
 
 
 
 

I assume you have already installed taglog, as described in the installation instructions    Run it in the appropriate way for your platform

The initial screen should look like this:
Initial Screen Image

At the top is a menubar, below that is a window which shows the previous entries for today, which will be empty if this is the first time you have run the program. Below this is a bar with the buttons related to the current entry - like this:

Current Bar Image

Note that the Start time should be the time that you started the program, and that the End time will increase every minute.

Try entering some text in the entry window (the one at the bottom), and then click on 'Next'

The text you entered in the entry window should appear in the days log window, labeled with its start and end times.
What you have learned so far should help you if you simply wish to keep a record of what you did during the day - an electronic day book, with the advantage of having the entries automatically time stamped.

Logging by Project

 

 
 
 
 
 

The next stage is to add some Projects.
Click on Projects on the top menubar, which will bring down a sub menu. Click on 'Add...'
A window will pop up which allows you to type in the name of a project.  Enter names for the projects you spend time on.

On the 'current' menubar is a button labeled Project - click on it to produce a menu, which should include the names of the project or projects you have just added. You can select the name of a project to be associated with the current log entry by selecting the project through that menu entry, or by entering the name of the project in the field next to the 'Project; button. Note that entering the project in the field will not add it to the list of available projects for selection.

Try making some log entries associated with different proejcts, then click on Projects/View in the main menubar. A window will pop up showing the time spent on all the projects you have used. Entries which have no project associated with them are labeled as unknown.

You can find out more about Projects in the Projects chapter of the tutorial.

Logging by Activity

You may also wish to associate log entries by activity. The activiites can be selected from a sub menu of the Project button in the 'current' menubar. The current activity can be cleared by selecting the entry '--'.

You can also select an activity by *Right Clicking* on Next, which pops up a menu of activities. Selecting one starts the next log entry, with the activity field set to whatever you selected.

Under the Reports menu you can select "Time by Activity" which shows a breakdown of how your time is spent on various activities.

The names of the activities are read from a file, usually called activities in the same place as your other taglog files, but the location of this file can be changed in the preferences.

Adjusting the Start Time

Sometimes you will`not be able to click the next button at the time that you start a new acitvity - you might not be at your computer, or you may forget to do it. If you realise that the current log entry should have started earlier than the time shown you can click on the 'Start' button to correct it. This will pop up a window like this:

Start Time Adjustment Image

You can use the slider to alter the time, or enter a new time. If the 'Adjust previous end time' box is checked (the default) then the end time of the previous entry will be adjusted to match.
 

Exiting the program


To exit the program at the end of the day select 'File' in the main menubar, and then 'Exit'. You will be prompted to enter a summary of the days events. You can skip this by pressing 'Cancel' on the summary window.

You can also exit by selecting 'Quit', which exits immediately, without saving the current item.
 
 

Viewing previous logs

Once you have several days worth of logs you will find that you want to find out what you did on a particular day, or follow the history of a particular project. To do this select 'File/Open...' from the main menubar.

You will be offered a popup with the dates for which there are log entries. The dates are in the form monthday - for example 0704 is the Fourth of July.

Log selection window

Select the dates you are interested in, and click OK. You can restrict the display to a particular project by clicking on the Project button and selecting its name from the drop down menu, or by
typing its name in the field next to the Project button.

There is an option to save the displayed entries to a file, which can be used to create a report of work on a particular project, for example to mail to other people interested in progress on that project.
 

Displaying the time spent on projects


The program keeps a running total of the time spent on all the projects you have used today. To display it use the option 'Projects/View' in the main menu bar.

The time spent on the current project, and the total time spent is continously updated. Note that if you have a project called 'breaks' (by default - strictly any project in the breaks_projects list) then it is counted separately from working projects,
 
 

Reporting project bookings for a week.

Once you have been running the program for a week you can produce a report of time spent, by project, for the whole week, with summaries of total time per day, and total time per project. To do this select 'Reports/Weekly time booking by project' from the main menubar.

You will see a pop up window like

Time selection window
 

Enter a week number, or increase or decrease using the '-' and '+' buttoms and press 'OK'
You can display the times as hours and minutes or as decimal hours, or as decimal days.
 


There are other features of the program which are not yet covered in this tutorial, some (such as actions) are not fully complete, but will be added to the tutorial as soon as they are ready. Refer to the TODO list to see which features are still waiting to be implemented, and to the changelog to find out about recent changes. Please feel free to experiment, and to let me know which facilities you find useful, and any ideas which may improve the program


Next Previous Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/doc/tutorial2.html0000644000175000017500000002137513534701742015050 0ustar johnjohn Taglog tutorial - Actions

Taglog tutorial - Actions

  This program uses the term 'Action' where some systems use 'Task'. It describes something which you intend to do. Actions work best if they describe a small lump of work. That way you can cross them off quickly. A future release of the program may have the ability to specify high level tasks, and then split them into finer detail, but the present version is aimed at detailed tasks.

Adding actions


To add an action use Actions/Add... in the main menu.

Most of the fields should prompt you to ask yourself questions about the action
 
 

Priority
How does it fit in with the other things I have to do ?


This program uses priorities where the numerically lowest are most important. The default priority is 50. This may seem like a large number, but the idea is that if you consider a scheme of priorities like

  1. Emergency
  2. Urgent
  3. Important
  4. Fairly important
  5. Default
  6. Non urgent
  7. Wishlist
  8. May get around to doing eventually
  9. Heat death of the universe may occur first
If someone asks you to do a piece of work, or you generate a job for yourself, pick a suitable priority in this range - then multiply it by ten. You can then fine tune the priorities of individual actions to decide which of the Urgent actions should be done first.  Note that the priority may be used in a future release to estimate elapsed time spent on an action on the assumption that you will spend (100-priority) percent of your time on that task - i.e. it will estimate that you will spend 90% our your time on a priority 10 task, 50% on a priority 50 action etc.
 
Expected-completed-date
Is there a deadline ?
Abort-after
Will it go away if I dont do it ? - If this action has not been done by this date then we can forget it.
Risks
What are the risks ?
  • To people
  • To property
  • Financial risks
  • Security risks
What can be done to minimise them.
Assigned-to
Is there someone more appropriate who could do it ? Someone cheaper, someone more experienced/specialised, someone less busy ?
Reason
Why am I doing this ?
Description
What am I supposed to do ?
Deliverables
How will I know when the action is complete ?
Difficulty
How much thought has to go into it ? Often you have some tasks which you must do, which are routine, some which require original thinking. You probably also have times of day when you feel more alert. You may want to match difficult activities to your peaks, and save some easy ones for your troughs.
Status
Do you need to start it now ?

 

 

The possible values for Status are:

  • Pending
  • Active
  • Completed
  • Blocked
  • Aborted
Actions start as Pending and become Active (or they may start as Active as soon as they are entered). They end up Completed or Aborted
Resources
What do I need to do this task ? Do I have all the resources I need ?
Expected-time
How long will it take (in time spent working on it)
Expected-cost
How much will this cost (apart from the cost of your time)

Integrating actions with time logging

If you click on the Action label in the centre menu bar you will be presented with a drop down list of the actions which are currently in the Active state. Selecting one of these actions will set the current project to the project associated with that action, and that action will be associated with the current log entry. You can thus use taglog to track how long an action has taken.

You can clear the current action by selecting the action titled "--" from the list.

Viewing Actions

  The Actions/View menu item allows you to view your actions. You can select the actions to view according to the Project they are associated with, their Status or their Priority.

You can also select the fields from an action to be displayed - this can be useful to allow you to see a summary of the actions, showing, for example, only the titles of the actions.

You can also select actions by the date they are expected to start, or to be completed.

You can select individual actions by Id (which is not very useful most of the time as action Ids are not very memorable) or by title. The Id and Title field names are menu buttons, and when you select them you get a list of all the titles, or Ids, which match all the other criteria you have selected. The menu entries for these buttons are only updated when you click on the Refresh button to their left.

Editing Actions

When you have viewed a set of actions, as described above, you can right click on an action and this will bring up a new window allowing you to edit it.

Changes you make by this means do not trigger any of the processes which can happen when you change the attributes of an action by other means within the program - for example if you change the status of an action there will not be a mail message generated to the Email-status-to recipient.

Changing the Status of an action

In the Actions menu are entries which allow you to Complete an Active action, to Activate a Pending action and to Abort actions which are Active or Pending. These present a menu of the titles of all the actions in the appropriate state (for example all the Active actions are presented for completion). Simply select the action by its title and it will be changed to the new state.

Viewing the History of an action

In section 1 of the tutorial you saw how to view all the log entries which were associated with a particular project, over some space of time. As you start to use actions more you may find that you want to view the history of an individual action.

This is done via the Actions/History menu item, which brings up a selection box similar to that used to view an action. This time you are likely to want to only select a small number (often just one) of actions, and each one will be displayed in its own window with all the log entries associated with that action.

You will see the key information about the action in the top frame of the window, including the total time spent so far on this action, and (if it was specified when the action was added) the Expected-completed-date and the Expected-time.

The next frame contains the history of the action, showing what was done, and when.

At the bottom of the History Window is a 'Revise' button. Pressing this button causes the action information to be updated with a Revised-expected-completed-date and a Revised-expected-time. Note that these are stored as different fields in the action, so you can see the difference between your original estimate and the current estimates of how long the action will take, and when you expect it to be completed.

The bottom of the history window also provides a button to allow you to save the history of the action to a file, and a Cancel button - to remove the window.

Shortcut to editing the current action

If you right click on the word Action in the central menu bar, while there is a current action shown in the box next to it, then a new window will pop up which will let you edit the current action.

Long term action maintenance

After you have used actions for a while you will find that the current actions file will grow. From time to time, depending on how heavily you use actions, you may want to move old actions to an archive file.

To do this select Actions/Extra.../Archive Old Actions from the top menu. This will move all actions which were Completed or Aborted more than one month ago to an archive file, called actions-yyyymm.tag, where yyyy is the year and mm the month of the date of the archive.


Next Previous Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/doc/glossary.html0000644000175000017500000000050513534701742014756 0ustar johnjohnTaglog Glossary

Taglog Glossary

Action
A task which has to be done - actions are often associated with Projects. Actions can be in a number of states (Unassigned, Pending, Active, Blocked, Completed) and may not be able to start until some other action has been Completeed.
taglog-0.2.6/doc/stack4.png0000644000175000017500000001605313534701742014131 0ustar johnjohnPNG  IHDR)OɓIDATx=yR)8RHOvNr/*Ȃ *UE*^ #E* A"0 *v.,FMqm9osfA̝93/Ϟٙ~oW~翚: n~=m4!;u"^|)>.:1>>P ``Fbu}wG?畇~u>ѹO 0,||Ǐ=ꂮd@Ugv;G'xԌό@9FyU`>%sϻI>|C5 Z=tqq<;@9撗(&͛ߺuї_~+֭[ƟzrO%{>t/N+S7}JSYGCJ#'p`o;}7ߨ\u-Uwnvn{>Pu=_u·ǏN'Rgr_Y|wOgˀ[G:W}].^yc޽cu]~ NϞ9H,FxvBҧ)wNj2xBi? ͋/Ԕ4ϟ?wN/)zN%GwuVIH.?|sP`Q>fO#/*P~8ֽM]\w |'?3*'g* 'FN2  ksno4GvQoG޾}W~=ƅ=ll`\/GԹ5 \`အ4{ Ec|dLO g~1~3S}Tcpl3c\yY`⯿ڸ~ٳ;w8'~sܹ~~={?GHHoO{^_>}ϓ'OEOYiO%: T9 0 ]___P[73o|7aE 0 Ϲu29r?ϭ'8o=Sr#|_:09l6{  @~8RnS4o{c @m@m@m@m@m@m@mV+>:j,VP$vÈĒF/B\E% ZN71DV} # Fb#r,Yp]O%K]z4f?\3xy䒨ZX@-}K"cA&Rs^Ո e|S0+H"$8WYtp;4Eo᥮W;c\Fs>̈.vg3J\ yV3=>{r9}e ѵ]U^TfiE8Sh- Yx\um~E-odE0bH\7D'uۛw _x:y$5Or~*Yҋ(pFa$U/*cv]uHC}n]~_Uq 5Ӱwǽzjvn7zoUǵ|c̆@8Iل'm6EN:x`i@9D;]םN|0w(j#j#j#jsGB~v$rz=U(3aj+4r#{+y@ ߟ:YD"D߳,K©{{{_o.L8Kt]d"^D0_T"s>l|Rld0s>aDMcxo=UzuvMpvKyιqc97Չ1{xTs29/H=\2^_ק*]iD >Z5C' fis6uSLN}垈N: IX/ǔ~ޝ}?),$=`¦K_3\m rqS5]vĽ#Ni)X~danT9/rpvg2)>W#K  9弍ASQ+XvJGU6+8#Ͼ+I5yڝuV(FbkmzS;%#]s^OF^Ev/ ,ٝ#eYAScG\v𸊄M7:lb;Rs}Ig-L=;=a(LS"I9ox[$oĊҙ/1mpK6&NĊ+)0e,(ҍ~Nz']!FpvG:O#hmySFk)G)]68CAzi>&5(;ᔅhY 'i\B*FjH#g# d{t<wfQ>M 8'Ts[ׁrIx[]sJgP}j`W0 w9-\ ~S  kÇX܊>X]oĝ #"9bi^膒25}έDn =DV^!j署Cshz!z3*({|>Ҟi s (sn==Z=^*Z'ܓyKi8`vZ=Sv76Qdx;O%4~sJg%2&|'+{~ASOۍe]<~\qZɞ˹D,mJFQޟH:ack/V@SjKRC \7"o)KJ@{Rj? Ԟ=P謹)%30޹D2esOcCG=tpJH#Jgx=!@Q3>8S?0;Sdhj97@m@m@m@m@m@m@m@m@m@m@m@m@m@mw(\^^Vv%rw<3====Bp+o=q^WkZKp8LP#L?xv$O^.hu'cy5PY}@P(!Cb d7Ch85CN{TׇZ}N 4(=tzFCj(~<8%8{fg^\! gGHg^jfR5l6%p! >-d͸sZ>[X?fMj:rĶ!Ip1\ [ml?{EN&Zh%e~DPP[9juppWH^Jy t>˨z,ۤ"\V@PG5a<{v|HzgYN0&ͩf3j!r巰kVJ11傑# ,=>=N~(h{|:mQK&ـ,bŞƈ %F c=^j|201PZI`B\_W7韪a ]B^:M|eJjf }S ;jO}ڏGxu #wh:co5k7"n4J<ڵV3HGa%}/<f٫1KJ1[ 7afT.Byɉy2e=/ZX}01m\`rI __kTa\:miQ{~`mmduRvuW/nqnޥ.-wS[1SH4 ZA7L _!,O b=s3*{2v!Y4RM -;8?ɯ1wuң#&snSI= ΏŸV^ő|H\eI9\:JJ\hBF&/'n`pXITxl, L@m`U}#4a)6IG5x6IG5#LF [1pmJqi~?ImɼІh;LuI1ǘn9s9wsz: =s<1fX25f{~Vսr\ =\\)ן }[h+;==r8FY4 %A9x$Q@.-5V+_D>  Ns^ ``J*G6>]VAiϨ1&̬s6gP H$j#8'?G@;4*Bw@2:G:TzZH=վb;OCթ4;{)\"Hpu KS830vλ ;@fs؍滙-:?õ;UR1~,,SRB G5}@sb%Ã%!9DŽJ>MbTHl%^Xo^zs첇V!D~[^>zol~@@)eڟF \^{@΢䜉M^o?ԇ}_2 Ýl6EaH;WBH4HVʼne +SV>G-XgwRD=y;=J2D+8LS^jEj`HNUPcp+iwRV|v6q.vZǙL|kJDo[9ToY^ GrTcv`Covik솣jI )bFZt:nlmlO=Vz[%#P`dws1u91J]TS_ $]. 6Tf6*$\#wK.{`|>8t'ۃfvn=N0rNJ0,["z sOD^&2~M=6, ~/V-HߐccP{x497JH}oׄzJ !X@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m>,߳nkXwx<ʡ{.//+X9(SsBt$D`,*p ]{r]@ 1:= :=Dù q:=tܣ><=tzG7{ҍxrS gK;zhWWWsf-].ۯ`RGFFvqn: L5EIENDB`taglog-0.2.6/doc/tutorial_with_others.html0000644000175000017500000001230413534701742017375 0ustar johnjohn Taglog tutorial - Working with other systems

Taglog tutorial - working with other systems

Although taglog is primarily focussed on time management for an individual it has some features which help it to work with other systesm. These features require some setup outside of taglog so if you are working purely standalone you can skip this section.

Saving Time Bookings for import to another program

You can save the output of the weekly time bookings as a Comma Separated Value file. This can be used to automate entry into a corporate time recording system, but the exact details will depend on the requirements of your corporate system.

To save the to a file select Reports/Weekly time bookings by project from the main menu and set the week you want to report for.

Select Save As... from the report display. You will be prompted for the file name to use to save the displayed times as a CSV file.

File Format

The file is saved as a line containing the dates for which the report has been generated, comma seperated with an initial leading comma. The dates are expressed as Day/Month.

This is followed by as many lines as there are projects, starting with a project booking code and then the times spent on that project on each day of that week, all separated by commas.

Advanced facilities

There are some advanced facilities which can be set by manually editing your taglog configuration file (~/.taglog on Unix or taglog.cfg on Windows). You can edit this file with an editor and make changes in the section after the line which says
# above this line is automatically saved - put your changes below here
Even if you do know know the TCL language in which taglog is written it is fairly simple to follow the syntax of the lines above the marker, which are set by the File/Preferences menu entry.

Default Timebookings Save File

You can save the default file for the SaveAs operation by putting lines into your taglog configuration file which read
global default_save_timebookings_file
set default_save_timebookings_file "some filename"

You will still be prompted to confirm the filename.

Timebookings File Format

Unix and Windows have different ways to indicate the end of a line of text. If you are running taglog on a Unix or Linux system and saving your Timebookings CSV file to a network drive on a Windows shared drive where it will be read by an application expecting a Windows text file, or you are running taglog on a Windows PC to a network drive where the CSV file will be read by a Unix application you may need to change the file format.

If you are saving to the same kind of system as the one where the file will be read (or you have a flexible program reading the files) then you do not need to set this, but if you do then put the approporiate lines in your taglog configuration:

Saving in Windows format

global timebookings_file_format
set timebookings_file_format crlf
Saving in Unix or Linux format

global timebookings_file_format
set timebookings_file_format lf

Updating Projects information over HTTP

If your organization has a web server which can deliver a list of the currently available project names and booking codes then you can set up a URL in the Projects URL field in preferences.

Once this is enabled you can update your current list of available projects via the Projects/Update menu entry.

Note that this URL could be something like

http://projects.example.com/projects-list.php?jl
to deliver only the projects relevant to a particular person.

Setting up the Projects information server

This section is under construction. The Projects information server should deliver the projects which are valid for the particular user (or possibly just the same set of projects to everybody) in the tagged format described in https://johnlines.github.io/tag-types/ for example it should look like
Tag-accountproj-version: 1.0
End:

Name: breaks
NextActionId: 1
Code:
Flags: Breaks
Flags: Active
StartDate: 2002-12-11
End:
Name: general admin
NextActionId: 1
Code:
Flags: Overheads
Flags: Active
StartDate: 2002-12-11
End:
Name: Major Project1 
NextActionId: 1
Code: MP1
StartDate: 2002-12-11
End:
and so on.

Taglog will detect a project being removed from the active projects list downloaded here and will set the EndDate of such projects to todays date.


Next More about Projects Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/doc/stack1.png0000644000175000017500000004566213534701742014136 0ustar johnjohnPNG  IHDR)OɓgAMA a IDATxyd]VkoR/Z]laóg03`p4b0 Ah M<{n~0̀mK̓?'|Ї>D}YE9uԩSzh£V~];:}?C]ZE;{{uS6TZ[<"Q=s?YG ޳6$Z>|[gϞ]Çwޓ{>tY:㮣-ZfDD~ȨzSHN)#67ҳ}~Vz+cժÇk/{N殣l "j]]?Dw,/Ѳ~W?]wntYBuV"gg6.67uP^7뭮E8|%woܻw NsC\:lOIWoͣ>?|W,>=NTxz_EHSK!V-`n6wէsvJyW@U:glqbƀ]t sK:zkyW;w_=E.uWg*6]jԇP ^+8"\l`p"5xc]ou/h+Y?+ijfY)63xrmFW|Quo>Ͽ-oٞ<Ee~x]G[.ijҌ.z| @EҹscËˏ]i+)>:|ӟ+Oݮ]S]zN6.$k!mVu=/gʈ8p l`cN~ۗ!W}n y8+%ao!@&l`pFQжFu87j{;{C9qD\UKa;,-6'OvtU\[>}k`@{ ha0l= 1333=9sF:s& jWdߟ1oŕwvK yצ='ΏpoX%]B{XtS7ųNSfλ$j rCm3J#Ya7}]|*/Yl4޳[O['ou}s/A{jKoe ܀>wkl`|}ͯ+]J;v ]cG҉ r(| /ڳ:/wn I\=䪷DGE_՚:_iT]`Y0K><7&~5ˏTq}H]l5qϟ?qĩSN:xOOj;+qEybv 8ѿ$&X0usM݆!okwȵ;r࿿!"ټ5 ha0l=M=: "힓'On8{fgg?]C9uTxaUرc=v,=D 5 |nN <v$lpeo= l>7u F {6N9|au,\@{6NmzW%sw5[sL@_%$ڦٸx z*Y|#H|`@=F3+xPF'nڳ = RWj ; 6:R2[}Y. p-6V{vXc0"@{v ۮ`vvvK0l= AgWjSgp;d`@x Ƿ{{ ha3ַJibXDp g)SV̙35=r1XntJԙ3g@w5vݳtR(GfTV: p glD!z \@{6^ <khϦ\ fffN <k{JO5B`rYEA+1 66:R2[}O}`6` ޳#Qv.k,Fhnsn` =f=cn9}::~8uGFMd vFq` k=`X[yn)LLaE`Xg-Q>MZj`A[vπZmb[D?ltRĄvj5=F`@{ ha0l= 6`@{ ha0l= 6`@{ ha0l= 6`@{ ha0l= 6`@{ ha0l= 6`@{ hayCÊvɓ'9vLJ<sر!mvvvVP_Ls Tu|s~릟`#=0}l:k{` kL=6@ڣZ`RS` oCZ!""f"ʷ{z@fb&E`T{7zrɵw,DdijL@"2DȘg+.v kXCMO2JQe"ڎCexhGiʮdX$$ 9Ɛ188TLD Y=kLO6xx'2\xLҔD,kIDn됨Ha13s~:""BcO5q4%\`ҔTZ- CcU " CjAy?yB.9TueAӖc-9qo.q]WTT"N# v1kg͢Ul$!kpee1EG% ZE8rIW FD.!"i?WmwET`\W\|J% }  \l\fC#GƐJ[rMr[{~itecmZKQK걒$h?ͦDZ /rW=TeCvO!N/ =З!"v]<}}.PFRs1LĞGA88Ze 1?3[t`L )dHkI&MsMKNRIQJJ%ͦjI!hPJ>S&'93"ʲ\`TϘMLЗ̹v|0 rZֲz<}+*9r1yyoDj\rPC[qI4lol*g9jsd)J844$hQqFKSC CCCj66aHVcn&bҔԦ)YӔ5zG\DXEqqzhLISHn{ϣ jU*TZrYkwn6~4m#CCɓ۟ze,K$d<E$e1fS5&8$ᢽFwj3NO"y_0yrVT3uYL<͘\SےR&škT*R.S*ڒU*z=s;r\*DA@*Bۛ0|C6fk{@'i<ȊJNM^e$ %I(qaHidhV+7qډNeLGa-űbLZ]j R U4D8*l)kuՂa"b RIJ%*\Z*)Rryse|O$u:NymgݰusU=Y+vw3Ohe)rKg@ϼwU!4,\g3=u((Mfo՞a!""R󈈺 &"sk4HS*^S*[灝ii'] 9Di庬e$ž'{8J=T.K4uR橧8r%R)s4M=Îc![ Q߇QU[?r]QQk&Iu%2QT$uZ3mYnjX@SX˫CDKYcr\W'{:"ctz / &^;ҁhcW S֞bQRLm"E,"6F.]J=9s&[\t) ׾26&K*ccé3jQ=Y+pw3~v'ȥv08Fڢšjz DGUJ[FQ4bjNѩ<$jsVi""f}+:N8q8fIkȱ^*yX:0=ѕx)+A dc?UꥷEGa<qsϥss.A`~ZdlL&&drR&'MG\"!na^" TK,VS,mjmʭ֙/_DŽ!OμnF`D1 ߯ͥW=tٳ=6CDqi9xqLQ$IrUEbZk7}H.WqUqJ 3g]XE~ZZNO,.ԔkJ\I$fnN  oQ˿GDyH0 IVm7_?ߞߜBra~mNXpDX؆aI$MsTeĿ29)SS26Ǜ"ousWt~gΜэbCu뤝=uܓYzn:W>;ߊ>C]_ 1D7(0y穧xqIH 9YFD7c>zY斌]ms=(#ZMSj4YSłe *RRJts嗗xvXK"?wK w/'Hd6˘xc޸mnf3ϡ(B\"O_:Dox+(Ir l5yLwjӲu01, d̹f[Ο)Y\7/||?e!zCaLw ֕#絬uܓ;ɻU#fah^~9;^d~^fZ-ߙxFDYÜDs]9rD<9rvm}b5u8^"{uQDDo"L~_~$==Q׏g~'=ߺ~e6D%:O/B=wO=""2c-!dqD–ߓ,8j˛m}QX̵v}-Xl rJW,͍7Yeϟ7sk68:IbK"%fKT+z|%#{4ݫ(Jq޽f^bf-[;NDxvmo~yG>$"D{[o~aKtm1R;G~3Y2'>=GLfMuZRwRZ-ֺAY-,ix!w{M7(/(4< 5Ɯ=+T՘_w-!Q`b=s7 Vu95)ԡ]ݞ; $!W=N0q"y~j^.].5(&xRG1uDM!ʈZqx 9B*Rw#sg"!wS$S}srYO~pæ # ~Hvvۥd\ ~Q&,&/.V/\/l\0ӷ/LPdCi"Uw]waa!!Jjڕz=QZL:||ێħ>"JR.?fmC=KNl|h8M;?3ܢvWk:\(D~kN`,Mhy ù0ttr>Cl48N"9[ʐ=GĀW7`BA{Z5D:oO^\ {x=0D&lj̾Ͼb$o}k T*NS$"7wt,+^AEvhB% c2X׌NEo]N!"׍H5OijNk`*Qĺ]Cmrႛ$GnY<>ZsO=upr(Yi:̋vc/,z]3?[hbJuܓe3C6-@cz񏞾͞#ٝI;٬3(%3]ߣc' kѣM7'>Gر=i?#yٟuםyZ{NMĄjRJBI- #D(fj-k_KA@Z?ZIE뮳o78?5ue{Ϋ^57==?5e/Y+ccUii/.e K/^0?oΞsxǘ9 Ûp T IDAT sXf}/_AW7Sǡr+c)3cC:߳Zqx'Dx&<rʯ}nD~zsֶDuY$9z[o~KUԶL`x瞮:c=Y[IVȖo$JEI81d=tș.Z๹m<s|$YDQdIBDSA@/<[n0w|Ek_/Ϥ^JG}+_^}iu-|,? u\`wwFIOW=]^ϱr:]K85㥬B{RIj5޽S?%jVh~7l$kl|ϳKɃ2#ĜYs?UBzzU8u mIZ2{Ξ=Qdo+| /.r!9'IP*޼$!"b><9)ss$&M]'ۗ_,,#kI[a\5s{#>606rȺG\d9 :HoU 7"JRLVej8`u"T*yxFC5׊nDC5jӨh[_"s)Rҩ=6 0Y&nU*#Gxly|'&xnyqD +h֢֔KNSe&l,EqcZ  n(¥T*KQ/_V,WTxɁ2>.cc?k .)$g.yɮkC2ONFRev.R19FMRHП$,"Cd5jX\纬fI08똦N89y^j {^Q:g$b_%48ɲ8T.K,muHJ%& 'a(ͦ4jrEhhmC- բ(r53){s{y+4W9B>n~WoD+%4h.m^dd mSYJb!vL,aȭW,}qp̵Zݫ1}wޖ̐OUcĥZ |GU~8 Cg ((,$/"BDqRc,^. ,.n$س<mC>f1STV1)qpj%?*,Qs#-;_LtG&`8GSd`.y^^Ε9/V$hLJle'0(rfr TR ȗێ1k#JGT!be^*lrڣHT RG߂3 #ZMm\-3~TcnV'.G'xVߗp{FV;F E8M)MHVXzjv(\D:Y2NSc"ʃ:KACN8d ktGGCt=4F`dp Q)|5DXߧ ߿jE80".ͬ (p\Dz:yI!MAߣ'633u0lv!ڵd_:D*<,"VT sOSN_A9oKvL;ˀv<CY&ǗGz Fk\3kkP!4}:Uҗg{D}1yw~'YX\,i,.^?t Q  c6H,_y!c\|]W/s]9sSu 62c'>&/}DR8˪ccż5,W( uD5I(3uC~53Z?G 1)QBTTu3N$2\+% ZE:svfXFXy/wqǦ9D:}GvMg2nFYf1]W򜦒,<`0ᡫC;V 5E"Ӕ%r)\fҔG&eYR_&蒦{#qDJbee1hP΋RsF'A6_v_ė/"IL/GjھOGGCMTOglLZOjB&X$I5?|O4ƚjR u2M]WX :}]HtͨD7?s|_:GYkI$LM={dzZHݤ:_ #q,JTq+O?]EFryI"enQJqAz^yZDZ#̢"DN<9M8cC^X9\xZ|BIH&Ӳg+{ؘa{`dhU-߷ڡC|7N9̞H<8yR.Ąj21!ccRJBA A@A@+-cvvCm9Q'z=O.8wΜ;gΝ˅'2?].ݳG$UR.SD\r9}h("kU~(M5#"k\rT{d|'~"uQ*EDYJ$D: Qyhy19l!댹Θq5Dq,+Wg}=o%X'NnZ܂@җ&⸚e%OZǒ$ljt'<AQt0c[K|?oyXDZmG ݋Nqa٬cc JZ^f,~<5>LLLONLN wL,p=tt%^*0dzYQ?c-[봫,#|g̙$W7;ԥKAJv8fqt ԁVi^aXi4*FuqqlaXn60IS":NyQ4kX}lYr}l;w}wX" $#jI׾5Y>/]VX☙GKXK"87s÷|jKUVT"yKU^t.kpk)8 _.:1DdҞ=CuɁyAP l;=+DĎCATab_O"8hau'yOSu܎>i61c癧ZM*'i|RrYK%B/HPxo69iJiaӬ9s<_ȗ.bNMԕQ-믷]'T*y^ u3cTX+[f}*e(4MKe SfML`dMKR.K[v1cc\}qMZ(e"$dL& 5l>áH.x@LJ?|Rq*AA %i+jZi"b~ݭ~_υs=L3g,-/v6x*)uXk՟9?F'^—/+Wx~M\Ș\xgӤܱ[5X~/i݄a-,iCn,SSyTj]DZ.0߷ujq"2"FY6w+UEyYMq3ϐCA^uU\]DYԉ$2 DI1i_9A|hqI7|.×.rp jqQnBx/SS2>ۑCX+W@QDR.xJffdqWΟȋ:ѤZeixC_cf6yG.=njG?Z{#A?P$&E_RIuZfg̝?@_sM/?LhR㼼0W|}OoؘJy^Csu}k>Wy7կKDî+A/m6|;}-,v(/,8f3k6 DDiD[Q[ytisω۷\W{C{ _O'~QK/^B tu`O<&η׾_|w<cx*ly)8fv6w1vgvV|@e TsL2sN+S&$!@78s:\"JScN3s0Ɯ;w>w&ca{1jQaXee!׍$(R<7w\*]B{5굯(?;6`C{r_*R&Dw??<[&Z\ye~jNOLq\0V\}G;]fK\x5{1ϼ9{Vnj1>Gq4͘[<S*uP,岦q_g _DA@;ssWnkC'u ë͹+ߍ6LNQ1+$l^fs"Zٳnj1<3cy5y~1| g% KDYFA ;l^xCr/S.bjo÷\ ;~Oc33D4{TuT8nUqڃѐiZ ϲ~:^\|_핯|pay$4\\VUQh\,Ɛ`6/LԎQcٳ_yo TJEen2ƼAu)0glbb6DzӱWw*/d/3_QDax矧z],nvgfǜ=/9lNjl OJK8 {<#G}wykum<Ƴ܃|;%A2P;=ӧ/8 ;}ղ"OZƽ{07S>x'Do08&k+ZXZ.%4M$%(y/Q4\%R3g"KÇDs||_J%>O}g~?s!QKm~#\.(Q'^*!2̏?x~??X#2]wSO}?G؎g6慯~ȁϟ, SZ]h6SV~O?ȗ??ӿZ$.Gx 8 кwvnBIU:݀FOq.:5>w*IlLD"2;;{ԩ'NjǏ*=!O~$!J=c?8~z W5hpEy26G$gw١mr])f9>U*jPk:hC7>H?*`y'ڛN5FgpIQASau[-M@K$$ynށ,#kU25LOԔqV_7>W$ +P9TMĉ'N8uԩS{`&wݧO.RI9omV3Çמשz i69 % Y#@Y?ZyyE\IT>8s`]IT >i(^8ses[䶵:hiT:rݟ:hp[u ɡ0(ʅ'MYu+M5y̢+^Q&vzZerR&'ebBߒJYn~9ǹ$b{}ЫjM/(gLQ6NΚYFYƺRd ,1NU+JGTƴFkvRC.<%hlLebB&&ETu4`'#j4!{UAq""3wDL1(˾?w1},/N%!^"h)E[,˝cE嶊3YF&BÎkxR󭿵7[e vIN:edf"\&"2"}D7wʲ7-v-YTz]e4ejWQs/qRkSu%ǚN0:Ja܁BZ.Rj3uu;՞v(hpR!#<"CY6gLL\Tt8~W*sy :Z3E>= I8f]8qr桩qUXc9uWYK?MTQUV$Vˍ7v8[=v/IDZm"фpV)> r&Tc4 ZG:+!fb s \?iO h]\[orV\Z-IJftV5Ʊ---E5 MDD\e@)MelT)U۶NCEb,[*9"y9R$XKSI;*%F='E&b(2`wUӳ#P)ryIʢMښDDj~4%kE$O2!0̳T_ЙFEBih8O p<2S84A.Tu`WU3e+_ަN-/H'{T4NE$7DTH-'.]\OMڛƁ4Q"5F۪S- YQ I8tO1Ht6kJOzu3:Y[6E=l8`ev(T,P^hYF"ywa BS ggiOVd(H}tE!8&Z_J βoկXrZkT*ģm,NnO'f7UBOBu?g{Luv +`\SS{>d{ƓVj9 i;{|ga賫+P;_7ctxx-WlSnD}[>{%H ?= A !4ߥ3.a 6 Oy"}'tPqvOWUAayȧsRŞ"F˻g\,;J;?:\ wv<[c/Wm-hZϾήs\  o=kI_;FkT=3m:l>[d'_zJ6-ҿ`llv[n@xtynP]l/ 5C`1D7#j6% `،EW:%|.>}z#]oh|w(4s _.d#±50l=  SN!`q^n&IENDB`taglog-0.2.6/doc/reference.html0000644000175000017500000000217713534701742015060 0ustar johnjohn

Taglog reference manual

 

Files

By default taglog uses a directory called 'diary' which it creates in the users home directory if it does not exist. Underneath this directory if creates a directory called 'logyyyy' where yyyy is the current year.  Each days log entries are stored in a file called 'mmdd.tag' where mm is the current month and dd is the day of month.

Actions are stored in a file called actions.tag in the diary directory.

Users preferences are stored in a file called '.taglog' under Unix, or 'taglog.cfg' under Windows, both in the user's home directory. The preferences file stores the projects the user books to, and can be used to override the default preferences set in the program. The user preferences file must be valid tcl script as it is sourced when the program starts.
 
  taglog-0.2.6/docs/0000755000175000017500000000000013603645436012414 5ustar johnjohntaglog-0.2.6/docs/taglog-background2.gif0000644000175000017500000000270713534701742016561 0ustar johnjohnGIF87a,,,,,ڋ޼H扦ʶ L ĢL*̦ JԪjܮ N (8HXhx 9) i0Yyy XZjJZj7KaK{ڻ7b* EAnv)q1N'ȖLlZ)!j(h*ݞ:kl<r:C=,ɪJ-rDӤٞS߂9. B,,E 9bKoIK{\ol~pT1(Z:x7LӮ-|*Ȼ0 ~N.^\6(3%1b4lb24jiN\GhWN.,Z+r4/vYX6oI Stklxwsuq1,=  `rUn9炦9wkoȢf嵖9[əw=;'l<*|j*T;@.=K.~z䗯?kHoA) h?:3ǟpƉrZ +A[X{h*p 'X%iLX,@*QrPG2lBj1|z("e` 5D OLB+f5h.gQ_]04{jU1)1S9rB#k'Ý\-TD 0B3id6-$@<<65eerk@JV,-,J ~SʈCl%d 1d*sl3);taglog-0.2.6/docs/tutorial3.html0000644000175000017500000001344413534701742015232 0ustar johnjohn Taglog tutorial - Preferences

Taglog tutorial - Preferences

Taglog comes with a set of defaults for the way it is set up which suit many people, but is intended to accommodate a range of user preferences for the way things look, or the places files are stored. There preferences are saved in a configuration file which is read in when the program is started.

You can edit the preferences settings with the 'File/Preferences' menu item.

You will see a window which will look like this:

The first thing to note about this window is that the window title contains the name of the configuration file. This is the full operating system file name with any "~" expanded so you can find out which preferences file you are using.

Within the window are a number of items you can alter

Documentation Directory
Taglog looks for its online help in this directory. Usually you do not need to change this. As with most labels in taglog you can see the online help by clicking on the label, and then on the Help item in the drop down list.
Data directory root
Taglog will store its data files in this directory and directories which it will create under here.
Language
The text within taglog is passed through the TCL message catalog and the help information is intended to be available in multiple languages. At present the only fully supported languages are English and German. If you wish to help with the translation please see the taglog internationalisation guide and send patches to the author. If you change languages then the help text will be available immediately in the new langage, but you will need to click OK in the preferences window and then restart the program to see all the text in your chosen language.
Hours worked per day
Some of taglog reports can be displayed as time in man days. This is where you can adjust the number of working hours in a day to be right for you.
Date Format
You can let taglog know your preferred date format here. Taglog always stores dates in ISO format (YYYY-MM-DD) in files, but the ability to have dates read and presented in your preferred format is being gradually added.
History and Current Window depths
You can decrease the amount of screen real estate that taglog uses by reducing these sizes.
Number of 'Today' actions
At the top of the main taglog window you can record a number of things you intend to do that day. That way you can remind yourself of your top priority tasks every time you look at taglog. The number of actions defaults to three. You can increase it if you feel very productive, or set it to zero to save screen space if you do not find the facility useful.
Id Prefix
If you are working with a group of people on the same projects then you can set your Id Prefix to your initials. This will distinguish your action aa.testproj.1 (if your Id is aa) from your colleages fb.testproj.1 (if their Id is fb)
Start Procs
Taglog runs a number of subroutines when it starts, to create windows, start timers etc. You can specify additional procedures here to customise the way taglog works for you. In particular if you specify "iconify_mainwin doShowProjects" then taglog will start with the Project Times window open and the main window iconified. You can use the Project Times window as a simple project timer, clicking on the projects to switch which one is active.
SMTP Preferences filename
Taglog uses a mail implementation written in TCL. This has its own configuration file, because it might be used in programs other than taglog. This preferences item tells taglog where to find the SMTP (Simple Mail Transport Protocol) preferences file.
SMTP thishost
Part of the SMTP protocol requires your computer to say what it is called. This allows you to set the name in case taglog has not detected it correctly.
SMTP mailhost
The SMTP implementation in taglog is very primitive. You should enter the name of a Smart Host which will accept mail from your computer, and be responsible for delivering it. For Unix systems localhost should be fine.
SMTP email address
You should enter your Internet style email address here
SMTP port
Leave this at 25 unless you understand what you are doing.

Starting with an alternative preferences file

Taglog normally looks for a preferences file in the following locations
  1. ~/.taglog
  2. ~/taglog.cfg
It will use whichever of these files it finds first as the user's preferences file. You can override this behaviour by starting taglog as
taglog -- -c configuration-file-name
From Unix you could set this up as an alias.

From Windows, if you have set up a shortcut to taglog on your desktop you can right click the icon and select Properties and modify the Target of the Shortcut properties as shown.

You can use this to run taglog with a set of preferences on a network drive. This set of preferences can specify the location of the data root as being on that network drive as well.


Next Previous Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/Taglog_shortcut.jpg0000644000175000017500000000250113534701742016260 0ustar johnjohnJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222HD"3 !1"QAaq#2%4U'1!2q"ARa ?DELH^LFFߡ*>C%P-׿?E{IWj }q:;NbQ>gNȱUT=dž8nGv"Q.d{ jmT~@}MG0ЅdalQDdAd,otfD'*kߝ3%aki`}WU'7گڀ5tGɦ=<'nl aWsf~ȳ႞֣Q,՜ 1;Jc.N|;3ll0Z6^WJ5(ڋzHW#jeaK ,14MF#y=GW~˜ <B{_&Yߍy\Ec ;Sc\ydm8П1VoKzeJfpeIG m1٭]?s12gi͉q@olŨbi7b7T>gU!m@UQˢ03!Ae(j-d;tx_+1NŅn&-v*b,qNq!F"" C'taglog-0.2.6/docs/taglog.gif0000644000175000017500000000070313534701742014354 0ustar johnjohnGIF87add,ddڋ޼HBꊶ oںDUL'e)r )j27ƚCcK_ҷ,,g@Wǧu848G#%ghwj#zչ@ZxhDx'7˫H&PO.mH0C>ek Ç -+>ѣE KcRI+GTe]2a&N[C'S9hQ b)RE*,Wf %:0[NrEt }^dSpms YM4kf$Lrɔ/dݑФK>:u;taglog-0.2.6/docs/taglog.es.html0000644000175000017500000000213513534701742015162 0ustar johnjohn Taglog

Taglog - Sistema de gerencia personal de tiempo

Taglog se diseña para cualquier persona que pase la mayoría de su día que se sienta en una computadora, trabajando en varios proyectos. Usted puede hacer notas sobre lo que usted hace, como usted va adelante, asociándolo a los proyectos que usted trabaja encendido. En el final de la semana usted puede producir un informe de cómo su tiempo estuvo pasado, analizado por el proyecto para los propósitos de la reservación. Usted puede visión entradas anteriores, por la fecha, o por proyecto. Usted puede incorporar las acciones que usted se prepone tomar, asociarlas a un proyecto, y marcarlas como activas, o terminar.

Taglog es software libre y se lanza bajo términos de la licencia pública de GNU.


Taglog home page (English)

Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/taglog_prefs.png0000644000175000017500000002104613534701742015575 0ustar johnjohnPNG  IHDR!3 IDATxݿ$u>Y $@#e 3)2dP@bp(؀[CAA 8 9ṔI:軺Uuu1S]];f|?[J>֭H{|ն >L_ɓ'e777৹Z>=Y_ǁq8ϟ?W^'OP ҇{7|{777AyDǿ_q3ek?7 M^DN+Xntr!it#׸K~n?0.~+*݋ZprU3W˗/K?~8\? Rr]rao~1M7w+~L1pHũwX~o}W=%'=ŋ1=~xggpԝnoo\EkomO W/3v|O? |[릥J#ƮSKMJ{1Ս2x=oLoOJ(U?, sVKE NA~j^kSAKO>'4Wr߱~;~\͹ށ&;sL#\&Ä% )2ϖ^s._eU rT?n/n^3.Ž1~RNBa#w]Yu"ow6H Oez-wCdRo00$V3o\uc.s7}12׳ἒ77SAŋ}{![}y $sss3|>T74*u5hҤPmlKf*jZh|^))Y>(<ˏ?x?xgDTN'r_pa(ƗWpC ݄2(U~cM/9S.GOOE;/llҫL܀s\2("~5+*\9Y?KgϞ? Yf%'Ogdgy%h)? J8%涔U:c_j<^E?_ p\׉V pd=~qc6Jl`-!iay睭JN#W` Q -ڨtzh6UӴ/3\rURϿ KTzWW\.eÝNzeiU3p@5ݗe|#X3'I.EyY}sԜ\gQpדӝlr;3(?䱆Ƀދ6t g3Q/*x zQ(#E(uHT +=,ot[ru (9h(P!BUCj~ڵ*y .f>l4c͘dju{ZO> aD%8K?)Pg]gOEɽdcr-$$a|_I9=(aT+fK ƞuU^+zOXQɿ[r~MR?nlѣ<(` AU]Sf" FpeS,nʈJ[ZgunznY@hBs:M+҄g2Lx+o,9}t1˚Lo+gU=.JQZ`1{|GFTZĜ݁1[PB$avU{Fp{چQiI#}"OE_ -D%¼:U1ITBHܣXDwS+'ŜA7}%rKs5`eGI6\f~_*IQl61dTrL #iû-[{\/?RTRs[7~5 % -k$ gk%B_viy%"Vr&wskBR΂z{i +˝|ֹ^gߍ+\q: VOJM^^+۽sGObPˁz$RWLU&d/0}TJvjV/q G]=m5? mt0ϓoqə>9r$L{5 m;6/Pb]#̛'畄璊*?]s)6Dٱ5Rr ;<|u蓵Sw bh'X_kՋ7¦G0ݝӱպuˇ޶yMî5\/+|>Gp ԽmR3ۃÆ: [Z 6 #*',{ nQ } $#8tTB_ -D%¼z2FT:"8B2:p4W:2~ߋ +=&^de;4yjГUMS|Z=*\d+*H]| HKqO[2/<ݚi\^mʂ(WJsa")X̣W/4 (oRp5Zm.{͟&1*Ȕwf,r]Wr*eQ)WWo/hQzQ`1&&]ZZF_iRIhqq6'.W׬KDh :F|8zTߟ7ƳMQ^&OKqNc`#8BT`畎hPk/D#"$2Fps<}%BT` JhT#Q ͐G?e4WBsA7}%.X6H&UmEcrKhkضmuNIg֌&*|eo$ [[8 tJN6W&Ȇw*%&<Ή:w/B_W`~ܝu=Std6|Jk``MgQi5܁E. Q_m@(Az.r:)?Q]{E@/:+MVi%rtsew~ˡl"#4&{In M{c_d0 OTʍ;Y&Wۢ1s@\yk}2`\7J8if^9.SrNa㕭-zy Wj Rk`ǺNИU{ Fphچ Q #8a-OE_ -D%¼ 6'HTB3ONe0$ s{avM_ -D%t6Kl[pufv9!]]sZ[IM 8o!v0fWYݶUFOi*&*Y'4侃w_޹W:V s.Ev;K! ~$oK}ȝ1A ۨ4Dt&՟ |j'm44s]<&t3+ˉ2:-qSFvd7r-0\<˔Op,΁ѷVJC*VW)vn%U8-q6l'|L Z “{%[RT@6䜧'+WpD%t6C+`Q ]`lm ! M0Cd_BT` Q -+a=|i_k*hOWJu{ɠ[Jl11ӤK9tl@H1ٞf\ױ4\[#3F]:y߶X_>a(*ŒoA$x}x<~\gnP{ ƍlX<ن DBy%}B#~qCsK  \()H&29#r)/0W7m{4&7FB[QI]0"Ŕ` .ےdcD"L$JBi=.ݎۓumE%ߜ`t|`0y~` Yٌd 3l|9B*]WJUO%&L>yӟWQ+Sچ3WBXQL LAFpIJDr^0W` Q - )rY|EvgQi_YA JGu67I#p+HƔz#*՘ .u-_tHaM~} Qi3L9-"Fp5f@L䛜vT`N.d=ˀ#iuyh卓Ŕl[Jla^iXCm1d`+[W:.ЯC̺=:窌ӎJDf^sM_ -D%0{#bHauݣ< +dv ;&ErioC6J%X?[8Wg7]&h*R {F' DT BFQPyB=$qž0{)Ɉ)R{~0b($Q(~\043nr\ty7[:V亚6=[Jla^鈎jzA_p!BT:Bcw ʓ~W` Q -D%0M827dcYFpq I}% 3 W` Q -Ҵk2vY܂eZ3L=E&񗩕MYq\NAOQi,v[wW'ʯSxֵʯ682'9⦎ YSo  i^)^9W?Q8A\FS{j2k~/hg4[%2hZ؄;n~35vr:+Ł)(-+iި2d=BD2u _ q'j2"Oa E%67LTXWF$Tԣ?d(vf&;=5s/ ѭLP>@si^n徚6ӼF0# +YPmKkVΚ8STG"ֺQR2BIgZ1AT#fz4 |޺=q̀u~`~ga%1S_ BT${Y70}%t"h:ccl,[Jl!*y% lmD%BBHFp@vJ;tW` Q -%6O>L2x- <5ZK:NcЋEԯy*:& Z:Pq.Ud1׀Sۯ(\~Kryx^@Ϟj& ^ɪ p+M8-z7nP[1er[(+*.[Sh5^p{xu_f͜j>5fV% qJbLf39/q7`.3[<Byɒ/3RZFz}. kOH>\RhϜf&QS9h[5I;^7!BT+$ð<}%BT` Jo4Q st!> vFIwgb,W` Q -&Gb 5'O5Y,8t5+jhh䉤FTĉ!/t9xթ<";,er@%C&6ű5WpH.@(\~K=b^IgX[%g ޽*yFaSt+MSP@$6'JQy}IwaQIb,nۤiwiMN?,`'Qfg[9BdJ'!\;%-q7`$V-;t&&^Rff\cr4,Gb[Jla^ m<ZXD 0! m1,$@sBT` Q -+P'?M@&L`H_㠯Țۋ^O_ -D%t< > >eWnL֖|j*H>f,lRѡ[%2hx}kT3/*r𪫳/%5W/FIUK16% Wv⎘Pf -U21N|N6yaj+W':y%]( QRp,;y^Jad7OmfSGbۧmj䂑P~cESKuWSP (uȻ$O*qC卭V;Y>f-mftFn ^̨JS\b<.v bdWd#"M[zרKWU<.N\:E Nz3WzWXt:n(u'i~m) O<̬Yqz׾{[V>h`ğ|&w %czh7A0q ]^OokVr#0Wz0 wwwzi\3g{2Ɵ|>{+I7sjzA_ t!B_ }@;D%T.,[Jl!*y%ll/mJ|աfAp\$+|Jl!*\gr%Wx Qn!:;Q'M/P-W] VK%vaB!thzkV>`^'qa?k8=Tr!9Gt$bWd"I9Id2?V?.#NU#Q'dm]s!3B),1xf\ @yl1?E=MO?V|s'DX^dVVUD4'}c[aC'+X#Fp0e!=B|1R @_ -D%0'GhTG_ZIDATi?6N֚E_!_[6o|}TZԡ[Jl!*[f6koRmؤ% &3Gij[1$}o˹, v+)0h;Im@hX&JY%ޓdI/MÂ+c!$ {juaY Q Y{ 50dN].[=laaWZ_p'k+OjM>tr9.*0=\ Ldot4 ŷCa !eR.K.aģ W` Q -7Y@_ -D%BT` mfIԀ4.O 1Jsݽ;[Mo'Q|>oJWWWϞ=+ӧ{رaUTnN Ϝl7[Jl!*0 [7a&?m xb_IENDB`taglog-0.2.6/docs/initial.jpg0000644000175000017500000003327213534701742014552 0ustar johnjohnJFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?E/4r# # IX@(1@=iCԵ-Ħ(]FܢkO&4 o19?3jiѝ9);OgNVDdhޛQNW8 ǭxxZhu1*.BNj ?xaI<}I#5mZv"ҷ aPIŽNg)@ѹfA|Oq|;\}˦#ܡ;8<}1^k?#GPN|_G'R>/s?x?*B/s?x?*B/s?x?*B/s?x?*B+{bO*4<[-+¬38 9m<7w ,Yq@LOR1o]u+]_-]v/-ێ  :˥L-s/q <`UhdM {c?ZP-k$3<6{8zwn85e,V$zHW'ןTń^XiH lxĂzWy56;4q)@g`;qx_QMjsk}s=ܖ#YfFGe*e KּA[yeiC0pI ?YkNLF؆Fv(Ǡp `%^ƿi^331Uf!29eӵQhF,洟ϊkyb,cu`Fn ț%eG U6pa *p |B.m$>6]DYD_W 2H56 Qk/;5s)آEb8ʨ % 2vՠYH|ydns7.l$1EM{J4+uCDՀV;ڹsaN_\|$tѧ1k/6)ZvJ90(Xml 44㗳ѴkgRvo,rJ&:N{qgr- {)9T(W`k^ x[ՂynbX")$ GӁG~K+6Oi+*%DA&-5)NDyHLs0Ϳ-e aAZB]vtH mXJ Z7~> nCĄoc9, , k{C-K#Bc3h Pdhzycݷ~-8>&Xi/$zݺBݽer că8UYu5LV1Hp#ӿA' .,u'Y"Y)VO)_3 m%2VVg㨆 [g9!87wЭ4.E ̷m>L_U*cXd_bxT\d7 *xq@Mb-sN[+ è8$dt  25ڽŬHq䑎Yf>?ƀ-U?44jikhSSO_G?ƀ-U?44jikhSSO_G?ƀ-U?44jikhSSO_G?ƀ-U?44jikhSSO_G?ƀ}}LݍI3ӟxsڹk/6W[%y$VSb pAvy(m`$:=wjk)灵2g9m¶|A`I?A@aWT_?#[^Zx& <MQ]S?aWTmyi=({7P/EuOQQ]S?յoO@_?#GEuOVז?ɿ-?baWT_?#[^Zx& <MQ]S?aWTmyi=({7P/EuOQQ]S?յoO@_?#GEuOVז?ɿ-?baWT_?#[^Zx& <MQ]S?aWTmyi=({7P/EuOQQ]S?յoO@-*8T_G,Đ $zZb ) #QEP\?2M]p>05gz֟)i\E-AEPP^^A^?ooK+$rxzP{[hnm09_tK[j 盁m' +0]R6ZaFðjWDeh-$ڣ$S8[Y 56ͦٛ60/Jc'BTxkAH4ؒOFV^@;εa "ui yq d* wm]](ne(H]&%w.##]Fal ((XP:qA)595 .kXUn @΃_/Gtߺ'?ƍI?4C:TU~礟6=$?uRTgA ah@?KQ*_*zI|l?OP΃_/Gtߺ'?ƍI?4C:TU~礟6=$?uRTgA ah@?KQ*_*zI|l?OP΃_/Gtߺ'?ƍI?4C:TU~礟6=$?uRTgA ah@ tX"rr~OZm>VW|p@2 ( |a!#Bj贈S ;8KH֟*ιY4l1v1F{z +:wN.!C#'Tu'm#~kU-cU{Rd| c y$ 6?  |=ZCsn9py|D]Wg@m@)"1d.+m#v2Ǯ&V@X]Ny v.R:s1O-zm3:mNfPېJ>uia:oep-l\!ϫ W m'K%Q,%]'XM.QQf 1$RO{KL7Yߔr+c@=E%iM- -j*P^>?|-A >?~MQ >?~MPzZߕ ?+$I7G$I7@ek~W(T?'E?'EOυ_/O _POğOğ?^>?|-A >?~MQ >?~MPzZߕ ?+$I7G$I7@ek~W(T?'E?'EOυ_/O _POğOğ?^>?|-A >?~MQ >?~MPzZߕ ?+$I7G$I7@ek~W(T?'E?'EjȋDE `S+2OhXIoEdMCm#~kW qWsms Fpq\7?2M@ޟGWP;U·v1?.Z?OsAN;;KkX"2B.P[ŸOJߖQ-$Et 2! C4y6V6M3Gm? j*ϓm? C4ZC4y6V6M3@>M3Gm? j*ϓm? C4ZC4y6V6M3@>M3Gm? S/+|a!#Bj)ʙ~Fܠ1+|a!#BjBgEr 0Rܖ [6?/<@P 'M$LÀX@95uyXjWOya}O"a]94֓cD-^eE\d $Plr3ѼI6g&`i{lHV%Ozu / WN^Jnͪsh6ޛC'mZ>e{n p˳{I Fq7Cp׭PWz\nx|_=a2Crj28g Z^N8< 3Wӧ I-']F#@#߈F&f>.Qce_rIW[I4 *LA+ʄ[$T6Þ}9$gxy7;<'.nbHSN !4ZF or.L7= 29$`fbI$.s#ڳ܂JFGN  T"BA@(614ghZA럳I ˁa}ϭWՕ8%Z8+u<=<}VN9kkHUWiU qqͨ#Ȗ1t-䈹i.Im# :oh$Ay\B]YYJg~v*YXڥS]2&pfv9坋ϵGmp s! _ic|iZ1< D|ϗ xʃϵrZg"?DgI3*D@wH L3EIYHiK4y<8~xl7W"dJ1E~܊rATW%][i,\[[\pIF]ъ`pAdi/泊eu4R`U$1.F1/)“5HI1qHsI#Ԋ--24qkpi<\yi0 bvϚ핅_f@-!Oz f {.g[>Tzٜv9:EՌ6r\j [vW2! f9^9O:f/ :wF7!|͇nnU&Z {2wS" jjZj|OIMG b*.cYd,fqq" `pKaX\Ie.ª *͔ I$mY\3b(?uRTgA ah@?KQ*_*zI|l?OSLyV{ ҥzn7wI'& 'uyhzRkZ3 r# `k-yP6* ΃_/Gtߺ'?ƍI?4C:TU~礟6=$8tw5g *__ z fG!A55`ѣ@ݟMR%qȻ8ظꭣ8T᷒I/^lFGo_1l(Jevr+[~q}Ftȏ4ۅ5x>q=ĚsJKĊߧnslP3'#}?#kZgHOG#:GG֢2?"?Α>Ƶ Ftȏ43ϧDj('#}?#kZgHOG#:GG֢2?"?Α>Ƶ Ftȏ43ϧDj('#}?#kZgHOG#:GG֢2?"?Α>Ƶ Ftȏ43ϧDj('#}?#kZgHOG#:GG֢2?"?Α>Ƶ Ftȏ43ϧDj(Ac[&ȕA qܚa!#Bj)A05!3?OsA [?**??T6o?訩OS3[OS3[ ((((((((((((((((Ey?2M^?"O?&&wiq"y_GEES׭}02u +v +vQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@O=S ЧX?_WC)\GԄ??T6o?訪c8PN!=On!=On0((((((((((((((((IA05ze?Кޟ׭}L֟*^TT?'`?'`QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEI?"O?&B`q^{ qR;8P\ECk:??XZ??@Š(((((((((((((((( 'X?_WC)\GS/+|a!#BjBgz֟*^TU1ZmzQS'P`gтk P`gтhQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE$e?К Ey?2MHLO\ECk?OsA [?**`d 0Vaj 0V ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ($`q^{ qWO=S ZmzQTiq"y_GEEL CBzF ݬ-CBzF ݠaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP/+|a!#Bj)A05!3?OsA [?**??T6o?訩OS3[OS3[ ((((((((((((((((Ey?2M^?"O?&&wiq"y_GEES׭}02u +v +vQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@O=S ЧX?_WC)\GԄ??T6o?訪c8TT{!u\L CBzF ݬK.S췋32ہOj۠aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP/+|a!#Bj)A05!3?OsAJ`Nʱ*Xt"5nxX71h/fl՟/>o].~Go㹭|&o P5c4b>} }hI.|{qwm%JdԿoM0Q\,[G,[@\ꨮW--.uTW+ } }:+{>h{>h UŽ|4Ž|4ΪbϿ>??bϿ>?UEroMoMs_X&X&Q\,[G,[@\ꨮW--.uTW+ } }:+{>h{>h UŽ|4Ž|4ΪbϿ>??bϿ>?UEroMoMs_X&X&O=S :W.yc _Sջ[Btaglog-0.2.6/docs/stack6.png0000644000175000017500000001544713534701742014324 0ustar johnjohnPNG  IHDR)OɓIDATxݿyv Rp):rpAdBWX^* \"_ #* !!0x*v),E7ňggfݽ~@s3u~𻩫h_O]w7/ikht:M]7`ϟ?'~wFMy{/?|?L0Ă&b:cn6<|?} |ứշ㏙` &1_?~Quuueىқ~~eO>{39xŋKFJƞ7I>|C3 Z=7nإsŽj)y^|94͛7}o޼~&tNW]Ч'{+3Lq1\&` 盬hh>n޼it=띛{o~uͯ>Pu=_uʇǏ___痺eN.bN? &`b)Ό7txym]<功9_m͹sǏ͵wwpGϢDtdza@rӌ7=}[o4~Ͻ7}Iie?hzI{\&D?sNtՕ B|cK2Gx`-L#*s^]fNt~{|3e3\&` ':&s{> u;֭[LR{'~R-lh{6]kZp&L0 k }䥷 LvT'ywO n{Rfn83gϞegϞݾ};ӧ]ݾ}ӧ6Ӧ9sͯ7D? g`c푸݉pT S*ɓ''Ozz"sF?5A63mC7_M;pgsfhd &`B8Ẻ,?p^"춋};41L'1NƎynsP0Ƹt\\\L]Db׿Oש+8gk z @wܽ4?S-e9=m6b@Fh#El6|t<T*(7[7H5GX:ūPV֤nu@%oo̭6aPAd |wBa'`fQ{\XveR{!*ÎZ:{3JդwG]|$]!Ϡ&wlɩ_[p',3yx魉whUgˊ~*YWIcik. @dKޒ(GIԔ]4bJy<7*TIUT(;4oci[O7 MNEgZ a5F m+P82៭ԞI}OPvLnnV6|HeFzǽgԀͼyDM`j*xuVދ5d9|T=825$ɗTcB&k2RìeM]:$[:]}_G5qzZhwǽxr{};~ܜsK'}ZA]'ůT\Pb<6~/Z] ˭9JnWz6b@H~nxs:TU~o96{0+SW8[<g-8SWasBb{օkIVʮAFiϾ\LHqY0+i '+`=@wԄ(٩^01,cn-yiHLMl?"8{Tռ޼fYbO{K ӌ7q$pGU4 gtUޥةpNsk& 2,6b@=Gfس*NCFh|*pi50Χ n  2@!O1=np&ʮAƘ[{WRlX=x^,Ӣ^ c {X.=-ygb#B2R,U5",{S;BPĞfHlƋCUh%jֆ3:{@*{A>q1N=ܚ Db|L><`{ڈ=mY8`X0Ğ Vt:M]=m-=Hp8env5s17cRs3pڢ+=#p.ʰ1A *_";J!NF>AҴFX<Ƕ)σ:N׎ /gŢVBSk4YM\4lM=×fE빶 8®i+s&auNOmr™7_̦]0Hլhg5)-}۶5y=mԵut26ӧĞh {S juƞgWZB\nA2h#Q8%s0(,X4CP4yJf<FD H=/sz!_Pty;={ 0< z.!=ma4X3=X1f3+ƨƴ6I36,FQHcTCz&q@ҳD3lQL)#lqRjh{(UԜ躧>=K4:3pfSG 3L`?jJh|u殻WayA`f~htwȦLF=2yG~Q;HhϣJΐ˔` 6wl/]Jܸ,KY.L{=-qwSzxE*Hޤ57谠̈} `%2CdM|hyh;a>›CAcDsh#{ڈ=m6b@Fh#{ڈ=m6b@FhBv&GcN‡áie\n ` ~'r#{NvU `%ƺzTx dG~vHܵ]2ks%CsCP,{P{{'=cM >CPI{za а~@P>Z8F#1QΞn5v<^=~Y֩E?sP `Z{v^w7O c! "R4~h~,7!ym_6\p{&kp"mRonmff\- ;65~Nrm676\pY7ݏ{j6Mu1gY& LVMVV0:3\P$|,IMtm),n;9dfMt6{r&$ o/*ZXO_ j4MZw;s8mM5ɬBV,Co谪E ymR Ty@zHv";Km'a7ӓ&|OXl懻V716[%^M2n]Tpb^NS3Iۃ*4:l{~ hqך_R̲RM9ÚTjh!a}jDGG7OY&tLJE*=7|ϑ)c{ڱu^ݺOZ5qOE敏*[\flDJzf<(IVC"c,M3^a_g\ƞp/J}Ty[p쭪at}tD^Jg2b$իZ%C }9E+xx#fؘm1WJH=BSI=‚6)qljի,[|oi~.Ѐ~9#,e?\J`1gm6hs:Gc]6̰ x3ZKN%f*0J5-[ܫP7&iѳ =e:"<LT aȧMԂ6 7_;~c~ 5]|JƞNg>Л$ЂkVvh'K5KqCegPMµRt6zVc:=j~&6~0 _ia܀{x4`<17PR {5'{j= Eh#{ڈ=m6b@Fh#{ڈ=m6b@Fh#{ڈ=m6b@Fh#{ڈ=m6b@Fh#{|v8Xdgi~tnUD<\\\(1$\9Pk l2W"04*y: +NX.CP'47CP?5CPO{LׇZ|N4ȟ@ް~@P0S.dD=U8v[sj<̽{}M^uwѣGC{nRE?{kXQ8{ڈ=m7:O(GqjVxAMcyoz ʜΠOjj%L}:4~8m+`dEKBC B: J_7ϙwc1:b+āՄB s~##|{vcvG {sN"שF% 0yҭHdgYN׉cS2N1T%u;-e2P9 xeUά90fpq`㸦Xjx,C3YKucPx^gd7jX. g|񝻺?Sh_Y?G"T?">?ƏEȩ4/ϟEO}g|*?Sh_Y?G"T?">?ƏEȩ4/ϟEO}g|*?Sh_Y?G"T}7IAYOy,BA 99z̋g𦄱\<. 1a'z6$#ot+[(|K[WzOn+3>GrOiQEQEr,hikkfw# d1c{>!wU# a:jڼ6!ڊ9  Ϡ%Eautatbenw@ق߈wX%׉-aOhI*%%O׶+袊(((+ڍbVP{˻y< ňxz!7K2izmX7qW*:K2`SUKӮ%3?B *hlQF{^T>g '߻ݏݝ8z:((k濌>zk6\AZ}QEQX#$?^G~ gsןR?oK ݄ߗ^y>mV=R15/ jߛIUeFE;cbO)nD>ZfnG@Xo7ް;[ ʉϱ((((+.SF!2Y&6x C̜=A?vZ[-ҮXv,ʰ, u) ՞-;P )G IU79>kMǿvdfEQEQEVO^b;{}tY\Cm. VATӜOGFV*aRCAZb}+B=HojQѴ\_]isBi#6'#cw۾<'X3,+r_VgEב}n۷8;ZAre{䀫ws֣{cyOl.'bʢbQA=?G{,q5+O4rVU!2!P. =gEQEQEQU5O^MPНc#w`%pښH9_~qϾ1ڳ?Ǡii֪tj-QOΑ0 <)oڒ[$вBvߕWq'd׮mxsAƃmI44;{VQEQEQEdE*Γ!O۷jV{^^O+^jũ_~qϾ1ڲz=E`m3w{7ךk/6M6ey!GbK;77lpjQEQEQEUMSA\j{gTaVg>߱ZLTQǐؠg_9|f?_NYV/h(((+'/]?1Vt xݿWj!\OթˣjޤsZqP,V#nvāzk/ \@ QEQEQEQEdE*Γ!O۷jV{^^O+gM[WJZY=}&zS?U5׿ ׼yo=ibE1ÿ́ nVVmScu⩼;7y\nT>ô sЀT}6o M$Kfd/o)9B񍖻}^Z\Kb)r8(8yuEEQEQEQU5O^M`A!J7^ZrB%CEQEQEQEQY>&zS?U5׿ xG]5kc\Qc`vʭ}x"בOyonb:γ(uH`mfH #f~OoðLK4,\\zQEQEQET?{\A5l*ӿOk>zk/ \@ QEQEQEQEdE*Γ!O۷jV{^^O* K/atDca< V<GxG&mug!,C00cڣV>,[iOU{Qw$t)8}wL}*.vy@$|r2x5EQEQEQU5O^M`A!J7^ZrB%CEQEQEQEQY>&zS?U5׿ ڤo&[};  0sw_i,~g3wMqG;m>L .HmVAxheU8+(((/& uZzw|GX}9e!X((((ȽuY)vM]k Rgռ&XINe۾~yg۞34Eyk=\%ž:$pFG#=j?Y37R}ufs'](((/& uZzw|GX}9e!X((((ȽuY)vM]k yWb-_m]a>R|G˞Euvvf-0yi HnyfV8jFl!].I-!B4b' syKoM+uWOh, 罢(((/& uZzw|GX}9e!X((((ȽuY)vM]k ]?Σ(((* ?#c`iV 3_7|f?_NYV/h(((+'/]?1Vt xݿWj!^A$_7y̖`OS$]]vff|>ҷ3ɂny v=(.R+)bGL@ʹ%@ G7?6D}[YXɸ,DE@> F~^EQEQEQU5O^M`A!J7^ZrB%CEQEQEQEQY>&zK{/d%֛ raq+E$b]QUppBQѴ\_]isBi#6'#cw۾<'XvH܀99:WIm-汓TDkG :Yv_o-%Ogw@ tQsQY-QFx/DΤ, c^x(((* *l;F`;]eւIܢNxQү$f2hӌF;'3,+r_Vw?ƏM?ښ?44jikh/_SO_G?ƏM?ښ?44jikh/_SO_G?ƳsWpHn$vA,!|jPjZIg7;yG=x?ϵmI k,lpgZ)kWw7٧D DO60dLtcf_}GݻnsfKo {݇i5D8uUJ*IHAi~%fddNDj]?44jikh/_SO_G?ƏM?ښ?44jikh/_SO_Uu-JM.ٙpJmRMجQTg 2z֖}mec3y@T޴젖>͉!1H&k#׬־u 1VB /O _G^>?|-zZߕ ?+ek~W(Qυ_/O _G^>?|-zZߕ ?+ek~W(Qυ_/O _G^>®F-n;iN>[QV\?03皌cv#7>T*ؿ*m_G? /ʟ[_QOB(VySЫkb [?!#I\υ_/O _G^>?|-zZߕ ?+ek~W(Qυ_/O _VH~N8ORo'i+9t,k揌>zk6\AZ}QEQEQEy=SO1 ɧߛ|Ic:0_xLM6?mfCW;+|mwd5ψ.㳖YK]^'󭼿2tC+.zA-u^xk{]3ϳ[m2X8gk9(W8U=w~(-uT67p#e+G»u֣xsHґ$ar(((dXnmy07^xz}3G `{fk{h0ŸPzDt/O?l濕[omyyOEygc)8<×Xqҭi:%řT%Oʠ 6ɢ+ic4Q*؀!#[_`?}y\?xQ >s<G.<(DžK Ь"`uF(((7^ZM$VEQEQEQE\+He1g<~G<~UtmFk͉*ElXW>OU/x(Bҏ/x(Bҏ/x(Bҏ/x*P%g Kx3QEQEQES_[} |GX}&?+O(((쟇x_@ӭM 5v6RDk,тN9=8F=ߋ5M]{="MV"x"$0qو*_[]Zm 2n+4q.P,pWgT/1ekΧ][F AO-nYe]Ѫap99Gҏ:?~y{Ώߥt(GJ<QGҏ:?~y{Ώߥt)*`=+>zkO^1˶pIUX/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_?;s/Q (Kn% ?c?_A۟X/G,v_]WX5w\@cAֿtaglog-0.2.6/docs/adjstart.jpg0000644000175000017500000002713513534701742014736 0ustar johnjohnJFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?[VH9$! Lk#kO'G^i}ͼqT1_:\ֹӃ,MOe΢پz_&֟OM?焟y"lU\^2@=\`#16 yy ]F8V;WGB t'(M#'cI>AEP0(7.2svpiB)-4%m.!hHwJTÅ!p2'|'MmV [iOvH \=z m5dӵԠS31-6pIS0:/ցUN1Ylb:s-xP|Kֺ{'Kk*!%Pov,x·̼}Ѧ *mA,QWPG+)A$ q@ m5dӵԠS31-6pIS0 <kE/.+k٭uHuw{6#0>r$-ju #cy-W0C,L O/0xxœMU͂(on+Htgd9 owIo 4pw Lo z8N2pwj*$\bN 8\OEQEQEQE_+ ?!^^B?pBM#'cI> (QE6 I{[愀J*p*zs}7jڔ75  Ί 1$w$=sA[')9dCM^=J I%cFKd6X{cmXM%\WQFH[Dʨ=n1ZBꚕEls*qF0 `ND.cjȐGT|GcZC6~z6}mCLe8ڿsb.u'VuK˛j& 61%T KlI .5D67`ޮ$6+(emYzm@٭ F;K\wVڶ/~ޚ(Yb$_pPܖ XZijZ ";‚n;|zW XhwV\$g0V]h o,pi8wzڵsxole%,2<$HbN99k(((( t'+k;WGB=$VLo?$QE ( -^w:6FA*m/SS6C~~߿:⸟-լVl0.rPgp᳴=趾(ԅ^+*#;G =#bqm._hlfϴ+y>ҍBN˽,.t W;׳_ik6BBA$.ߦ no4"NHfFUsMw$5zv6yVmb*+Q0F ɢ-F CXF*fI$I5Wt؟HmZM?GMo;5"Lb1!jKj"8]IHKF퍯ug8ݤ6@ aXiP4u,v,j[g 8j^W*MlV妾!x.rF,n^X ͯzS_Gyyp2$VY5Ք2C1ʑ >@7u{ckv7wn>jy֓yk{}cþB۝n\*3b $\NF[= /th 6:M*.cȬY ~n@$@um//ϳGw7 ``UKV~_ ?G)^r><ӴCw,x%;V9%s((+;WGB t'(ޛ>GrOi\AZ}AEP0(񦩦Z+2kϷ#?p%]@Cކ[xJytw=p$<"_,d@b]HEƝA~JY9B yӜkDa-ZUT/ewev*I9jm|iDŽE Yk79.Ub@G4r"o!nV9xHn\+eaoMOmJH?|* %koЯeMeI0Ac,iT C}-,>_'hpcDqJaêxP-,ӕM;]yf\J'Ğ5k%Ř+m2FYy8GnxXHZT/Iu*ۆ09<`€ Ic-'@m*m@9ڠ=pwmC};^6}ݖ^@&o%A zMh7Z5E$+oW$;y]+;Fij qu9 lU{nVB` hj:|Cnt&ҮHKic kb@G .zsZ|4t2(m.l.Bg,m,&![x 2-WJ`WXnI\YCpO85jhFo;hͻwPN3QEQEW|v\$Ѕ{xo OP7| #'XිMnA+5:Z+~X{H`>~{kҴFuv,UT$sAuiNfTW$ӴReb#K81lH#kf!g `9l/DĺeO#r9}Ƞ+b"ʂ_2HQofۀ8jz˻M>OyQ4r$]Pc=v/xP&Kd)m,0H@n*-Ƃ']_j|rJ/A`F38s,M>e(Aai zzvj3<ťX-wU"2$eNI랃4^x?֯tnt8$ʊkcp?>H ]> ^wln\nHPĩ B;j+",F~@K na#flNkÞnl>DJز(RA | p +45zd7 Zؓa| `Q 3]qj+\ݔ r@H+0@I9*HsEr~5=s厩w"]j2s%vYT2!Bu S}PjsHYuSTl#'vv[)~"]?a|i[}]Fv~Qy??տahIkx-'gX$YlC-/~ܐG!]I /넟zo?cAeYc>';q:i7| d[7CƏ۩ye"vB$z o_7:=Goq{B@q ꣵjQAU*J曻9xIٶ8YV5@22x<8_2 {OӞk^P "۫nm*Ƞ :( ,hZ|]jA4-" Le71 FX\Oc=.QϚ[P0A1bG5Q@ׇi|}PYQq,X^j}^[K Ս,pAAw`pW)ojڑj}k'3[vߙ[i$2צSJnk]Q-؜>$QNIQAۢ9{z}=wW6k$nJ *GBr09QI[{mvWm  R6VM,lVGL´߅ajz-OUK͍Uy dd(18uUaG:ff:iELl 99B%P/"P ox_ڭjL!T"E^I;TO&_J^oиX, @c!o( e$[\b$:\*GojKWp'RGp'-XAB%P/"Po z_^}߿ڣRmH-[y 6g Nу"_D*J֯!]I 8gi w1-gߥxo OP#ޛ>GrOkߵ[xGǓ'-&Y`&TOz\AZ6%ͫmou)#BA,f';_nE3.8H[G+[Gl`) oa5WiW1ŨH ϨE;D Xڻar$$*c_m ݿu]ھѦ͟i V}6;g*xTmm6MfwQvxDL6ƒPBw5VVvqsfPc.7L6p-gEhj'QH9Kdl;NNO|T}^u˘oYoKHtdILȰƨBK 8WNxz=瓩F2HŭKT 1 x`ϯD^\LѼZ HͶ@6啎A\sGEh+o]'N DztQ<ҶHrx@Ϡgo}Oxgo}Oxū矎넟`Y( 9~;WGB?+O7| QE ( {bK}tI /:Fz1:\Kkf +±,\Ȁ\g;H3ym汤|PvvC9uJvrw:.lb^YIY Ehdnymp$ր>//-tW1Yx? [UYOKMJFdԎTd NZxoE7vvZƒIe^+ŵoQ_ӵ%][ە2.pZ8U݇` ՓU<*gK1_+$  ۳zm孟`Xbd Hz*p5=p_m#×SvTHb$v*@\9\FNyuJߍVO"0LyɶlyP9=nO{ۘm@8'Xjv >}my %"8ʓް|u^&ȢRx-v˻pK>aq^v5k > b5:g[{q|h+.8{,]Ak-1\nbyyvrq҉o-`[cmx (U+I,O,$ 'ڤmf&h՛oM=C_>]f!475?L\0uDM[?h{I}i%HDNO@E?ƏHv~@ ?"ڏKE'$Q;Qh?j?-G@G  Zf9$Ԟ>ʿVhQ@Q@xo OWׁ|v\$Ѕ{I>?+OH(IOI#ʠ1߁HnKX"rsGh> '#z 0+ F.9,y9>C4y6d/uZF%/n4#ٵ|nA&~ɶh7x4c_}ƭY)R݊;1M3@_x5C4y6fc_}Ək֗m? C4 (UBUB9x{NvnngK[Kd!LMDžz/}fSR OORn lNTPz4 u:ZΐX]}heǝ 9 ל`OT.R࿼$ҭ-$m9@K=|c <ֿ~̒]y߻08(NN+<%q.keZ͙2:SUJnw/siVŧ4Tf*X Keoq4<3+neCc#8<+^-]fQۛxVt˜'OX?ja?kZ ( /넟}!]I \ ?tͲjl&gMXߏ>ޟ_΍\, şޱzSzy:ͨLm6dk];WYף7?c~?z=W^ şޱz?sx?@1( ?Yף7?c~?Z~y$8U9ݷvqtQi_ J\, şޱz=WG@eįXߏYנ~ i_ J\, şޱz=WG@eįXߏYנ~ҖBA~?| şޱz?sx?@JoO/Fu_.ozXߏ})?x'o OV7.oz??m.oVT1&:@taglog-0.2.6/docs/tutorial_projects.html0000644000175000017500000001177213534701742017062 0ustar johnjohn Taglog tutorial - More about Projects

Taglog tutorial - More about Projects

Taglog uses the term Project to mean a label by which you wish to measure chunks of time.

In conventional usage a project has a beginning, a middle, and an end - but in Taglog there may also be 'projects' which are ongoing. For example your company may want to account for time spent on Safety activities seperately from work which is directly charged to particular customers.

Attributes of a project

Start and End Dates

By default when you add a project the start date is set to the current date and the end date is not specified.

If you are working beyond the end date of the project then it is 'Closed' - which means that it does not show up in the Project selector in the central menu bar for booking time to it. It will still show up when picking entries by project in the File/Open... selector.

Booking Code

It may be that your projects have useful titles, such as 'New Computer Suite', but that you are supposed to book to, for example 'P0152'. You can use the Booking Code field to record the names your time booking system wants you to use for projects, and use a more meaningful name for your own use.

It could also be that your administrative processes generate the official booking code some time after you are expected to start work on the project. As long as you have a booking code by the time you generate the Time Bookings Report taglog will work quite happily on just a title.

Breaks

Projects which are labeled as 'Breaks' are ones which are not working time. If you have, for example, a lunch break which is not part of your working hours you could create a project called Breaks, and 'book' your lunch times to this project.

Breaks projects are counted seperately in the reports.

Overheads

You may have activities which can not be associated directly with an individual chargeable project, but which should be spread in an equitable manner across your other projects - for example filling in your timesheets.

You can create one, or more, projects which are flagged as Overheads.

Active Projects

If you have a large number of projects which are Open (that is, the current date is between their Start and End dates) then you may find that they become difficult to manage. By flagging the ones you are actively working on as Active they are moved to the top of the Project selection list.

Projects which are marked as Active also always appear in the Project Times display invoked through Projects/View.

Immutable Projects

Projects which are flagged as Immutable are (like Breaks projects) not eligible to have Overheads time spread into them. You might wish to use the Immutable flag for projects such as Bank Holidays, Leave, or Sick Leave which should not be 'bulked out' with your administrative overheads.

Working with Projects

Adding a Project

This is done through the Projects/Add menu item.

Editing a Project

This is done through the Projects/Edit menu item. You are presented with a scrollable list of all the projects, and can use this to, for example change the Active flag on a project - if you start actively working on it - or possibly if your involvement with it is largely over. This is also where you set the end date of a project - usually to todays date, to indicate that it is Closed, and hence no longer available for new time bookings.

Note that you might have Actions which are associated with a project - and if you close the project before you have finished all the actions (there is no check for this yet) then you will still accumulate time booked to those actions as booked to that project.

Deleting a Project

Projects can be deleted through the Projects/Edit menu entry. There is a 'Delete' checkbox at the end of each project line. Select the Delete checkbox for each project you wish to delete and click OK.

You may want to keep projects around for a while after they are closed so that they still appear in the dropdown lists for the File/Open... selector.

Importing projects from a central server

It is also possible to set up a central server from which you can import information on the available projects. This is covered in the next section of the tutorial and is what the Projects/Update menu item does.
Next Previous Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/taglog.ico0000644000175000017500000000030613534701742014360 0ustar johnjohn( ?{{'taglog-0.2.6/docs/seltime.jpg0000644000175000017500000002703313534701742014561 0ustar johnjohnJFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222Z" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?[VH9$! Lk#kO'G^i}ͼqT1_:\ֹӃ,MOe΢پz_&֟OM?焟y"lZcBpf?7u/;P7pr>vEɠF\wnteUdh@*00~v,v~':n=$O8GV?/sFᾟJ3)D \2=ՋT]&mF8 i D@gEv(_i'# d,w~!KECq̉5)NA)C_fnYRI9$5t'| |Կgl.uX̐؍qɏ B̖#2s^?+\!例&7eϘy#?wڋ\qcOjq\Zg?ufoZPh:q ՞6V$t{um2=@۬PJXEŶ s}J״]OU4&P$#OnԣFI{fZk7W  3DSh6})|Owۼ;>dy݌z銷aa$P^Cs3H(1'*-elPx[͵6h nPG#=j{?^$ *Mۜsy>/۳۷8Ƕ+Bd/d{%O[ҨsA#aѪxro+Ҭ r? NWlpO[8˽fcLI?Ym#o<Ӵt1c_beK iז6M׍/Aߎ9DGGm~x;SNei !9b 08+E^4ZKf-Wr˅iV%,L(w6 R1&oz?3ͼ*U:hvw շ 3px8<RN-xc*9'z^ KϵY$A޺_K/O~?c?yvoxxOv_Egg}K719Y1Ion8 99Fh "T?"L.jLk儞j_ݪXeBw=S^~Wfg)>?ƏEȩ5xl^G+mȓX2mC_ ]!~;l ېªpO c}g|*?Sku+=_NPuЏA  \ǂIϳ-Ӏw8Xn1@X_Y?G"Tރ/.A0ˇs_5V@X">?ƺAg$=,O(dNӰ`,8HCғ^4@+/mATK* >?ƏEȩ5]jg}i)?n+۳~?vs33Iuӵ$Kv7?2|J60A,r~ Cx dЭ^V>R;ctQxE}#-g3cp rW 63P񕝦kz% Ɂlv`(o*x Ɲspd[ɏ"pܱ) (+LwaC<ᾁmk:sBHCy,"h|% |ux=qqi6Ȭr@'Q@y'o,K";;$[?.#=/ꚿ&g_ϰv=<~!6ޡ-WZJGhz9<1quqg--O&0vR/ 7#z"i{5ټaSg=SSE$~~/n>' t8^iojVѹ2@+ݤlwp|%i0YO5 H uRco1C(/v:=ZDk}y8לh>XiE7`b#W66z2ViXWRF!ju,KjKbAPc'cCkqJʒ BFxwJ<]{j!uHmͨiyF ՝Fc'q!qQ%uQ 5"frZUQo%V,vs>E`@4x'H&U( ]t33׵{_n4Ը~al#rۓ`>lg Jcþ4BqfnOw۳*3~5tPJU5wtWf %g,O˃ׯsYoxN6viA yZ\%N1|WQ@{^,&}i}ôS+y#v6ɬ@Os߿޽T? Eśa>[gn̨3qVh t$3kȷ@K'9b!N2;s^EEq}ksF K}q}ksF K}?+O7|  (Q@Q@Q@C,ďmeF|U`#VTϯ< @RK)b a rz+񆫯׺ƣsiB-ݬK s|2<EMvZE~ %G,OKvsduh 1UJ;XϚ\|zẋI/,A:L@[* PIe8;ߊW6\/e.嵸[  Y v͜Qo+ nm)+hn"0 l2N"|7 L&2[kr^Odʟ0U #˶.DVͧOoǪ'J8ʼ) NprqĴԦ{q}uhVhG!~eېrT [@EܭW2nHb#g;9 bKInoYUO,a&9 H6P~ 5|G3G"2;THGK)}hPUv6pFsOt#cIORgd,Xx1Ph^Я[˻SOY?uAO&Y٦sgd~$ r<F3QVdZ_Mmfٗb$Y4Mo`Qf87}[NP2i1.T~rrox_ڭjL!T"E^I;TO&9>"n{sFx4ֳf1I>S~񘲰e  :/߲CkdOvݟlZ_ng29S[x>TQԠk%`I1\.򤌔-=b?m5CiXCb˵x~Υ̋2`nFrUqkmq,.<>[YH6| F_2kmih}"m) bn,06 UR=tD+ (`dı־"жhkuHnp@lF͢kW {ltmn.Bnlxbg<mk*V[1n4ї^pk[;om&][ek-/'̀2HO@zsb_-^=&{7Y+$n2HH*OL7Z$h- 5e`4X2ʤݻr'< 3je͓\ͬjԑXЪ <ذ&akԤ҄SaE{634FǂhxlioK*.Pk)XU%hz ^q{\}I c{kmQ xO}7f#O[{ƐFƨ7q#?)x5oȍ::In "w$!9'C܂Hv2:pH4 ><{x($U'SEPEPEPEPW־;?`Կ_ ؗ־;?`Կ_ #'cI> (QEQ\ֳItj& Av_*~lHBghbiY.]}N-iRI|!ls@Er;Ӭ-~ZP dVl(3Vpy3zv)K;-I-e;U%N@ :gpOqT=Iojŗ.͝ 2ȩMggmf^5ch~c xpJ$G7 ?&?!Vl橨YI6y`ic?fa;co-e1g"-JmRhaѡUiUdo)\2 DF⭝꬯KWgE;KleY3Ǖ י=^ÖڢKŪn-Zw`烑h<Ѿ'V\' u m|eHgBv\ Oy__mؾWڶxݷn{('<OImJX٧ml`(p5xBffOmEJ7% O8 @:Z+Acެw[qZ#5n1 aǽ>Olske"h>*Ƿj[r嶂~u/̀5Η7TR-$ZiɩHF@Qoe 0{`ά?f2d~Lzfx>#VՠܞTʬ%'9TP鸰nq7J?п ?JEYBұn%s$0pm8YG/|U{@i(HMԯ]E E+;:̹lc?1_˪EA5؀%"0&w2Nd?=9HKE;wbUbrI=[$\~;KFBҏ/x*R5{{KRgɱ8bhMamm,.Jƅs3U6%Ep{:/&/A_?@袊(Xz}KXz}K$VLo?$QE (1<]J/yi/~ݮr3q׽eɯkqfak" wۖDR'p 랾kuJڂy3Alk4y-@02XԜ@?6 王¾ðjB{ԻP!1*rn2={^Z7 H֤p̎rHcW'ҵK{i.53Yܛycef6K|^vw-$HA[aV>s=?@xrm'!K~ӾI팑?%Ʉ~u~c;"Y_VriwBh|ê`#a/?}z㢀 uojO-Uh[`M`,~a0r6u]KpT9G@'2&8-Cᵥηw}m%0ݭ74k"魧j.D]M:¾I g桩}f&;obfw ?wugx|>74_ m*O^xcP۞B d]ʝW{=ǿJD2*#rGQKy猟ɠ>zO{ 6narg$`N  mYftLO1 IaT_gx|uO$6 Nc~4 JӴ 9v-6+qǵ'O2rOîЉ.Kl5lUb1NN4Z]^n~m m+g9>oLq߂Oquȸ۷1q?:k}z㢏OtPa?7y[oB]I㷊mm9lO`?>܀-坮j۾74aѰr2Y~--ltؿĊl3 @/T? ȔCP@O^M_,"\CK4,PgbkkxĨH1@EQE5/C5%5/C43I>?+OH(QEQEQEQEQEIo1?I< pZ>b|:.?_o5HW[ktfb.NI8?OJ_{o>z\ѼQ-Jcw$`w“f_.c·wsfm$]wA.\ 1N(ڿ#w~޿l߼s=3S}o'kHuZ^u'F:mF)p$m@<+4s3HV%dlj&F'"?ѪV 67ZżmUL NNHz紟ѯ1n}*v>,XMou%ݳ ePAW;9;նm jpM% !ejT@r_h{I}>75-?I,umJyn<%mHGY ȮɈف+% 'YI/dh QwȤ{v[n)uHຂ[w͇hmM紟ѯg^QK5ak"K,ʑyKȪe ۆAx*ѥgԞGgoH2'?@jVN1/VQEQEQEQEQEQEEq}ksF K}q}ksF K}?+O;/c *l8gLOfG^q ŸsG. 5=\˟j?sS.8Of??=\˟j?sS.8Of??=\˟j?sS./Zw+, Ts><("Ћfjz??ƏM?y-/pZZ^=SO_G?Ƽ?G-/pZ= ȱpzSO_^z~-)Źw0)#6( Tag Logging Program

Tag Logging Program

Where does the time go ?

What are my priority jobs for today ?

How can I spend less time on routine adminstrative tasks ?

Taglog is written to answer these questions.

What is taglog?

The current version is 0.2.6

Taglog provides an electronic workbook, combining logging of time to projects with keeping a detailed diary of what you actually do. Individual work elements can be tagged by project, allowing you to produce, for example, a record of work on one particular project, even if your time is spread across a number of projects.

Work items can also be tagged by activity type - for example meeting, phone, programming etc - allowing you to analyse where your time is going by activity. Note that this activity type is orthogonal to the project axis, so that - for example - user support would be a project - in the larger sense WHAT you are doing - and phone calls to users - HOW you are doing it - would be the activity type.

Screenshot

This shot shows the main window, plus an action being added and a new project (bookable entity) being added. Screenshot

Downloading and Installing

The current version of the software is available at the Github release page for taglog

Look here for the latest changes

Taglog is what is known as Free Software, or Open Source.

Taglog is written in the TCL scripting language, which is available for Unix, Windows and Macintosh systems. See http://www.tcl.tk - the TCL developer Exchange for more information - including downloading TCL for free.

Taglog is in regular use on Unix (Linux and Solaris) and Windows systems.

The installation instructions are included with the distribution, but are available here for convenience.

Windows users will need a program, such as Powerarchiver or pkzip to unpack the distribution. Alternatively you could install Cygwin which gives you many powerful Unix tools for free on your Windows PC.

The Tutorial

You may wish to read a taglog tutorial (which is included in the documentation in the distribution) before you download.

Applications

You can find descriptions of how various kinds of people might use taglog by following these links. Note that these are just examples to draw out particular facilities of the program

Developer information

Patches and suggestions are welcomed. Please bear in mind that taglog is targetted at a range of platforms and TCL versions. The internal structure is not fully stable, so there is not much developer documentation yet, though there is a Unix manual page for the main tag.tcl package.

If you are not a TCL programmer, but can write in a language for which taglog internationalisation is not yet available you can still help, as described in the Internationalisation Guide or translating this page, or the tutorial

Further information

The log file format for taglog, and the file format for its actions files are described in the tag-types home page

Other links can be found in the Time Management Resources page.

Github

Taglog is now a project on Github - to allow use of its code management and bug tracking facilities, and you can obtain the releases from there as well.
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/stack2.png0000644000175000017500000001511513534701742014310 0ustar johnjohnPNG  IHDR)OɓIDATxݽ}`q $ʻJ^Ha9UrqW\-€JiIN!HʆmH J] [dMA א<8r!odQ@^wt1~åKɓ~Z?Ѳ`Bi"tym0>(=׿/_Κ|,u˿'&LʋdyWSosϿ*~o}t_~̈́ &.b>/^;E/_ɪҗ~# ?݁\v03|w$OĒckѤϟ?y9Qeh<<<('~7~aJS-Dӧ <яz/_A;k}=$X\ k4Yu_t_ i+yب/r~wkexVҀk„ hZJ5Gͬx7x-#Tc2ѨC?zoPkжJpM0a"q"P +ϚX|W~Z n9{i={f24ܴW&y;AoF{EQ^J?y޸펟@2T1'l.V6nՀ{}ʙn@yngz#[9]`{z wUlVҀk„ u/_Nӗ6$6{Eqh2a„ĉz[jC/繭F0f=wwwK/ 558(lɓ't׽0nWfr89=&@nb=&@n{:l6X~t<'(Tcg'$)'<ǖބa+#&dۥ u0RpvSbO) V]D6MJ?_ab/s`&D+ cH쩋1?<L[Ajց hTm%9ճnBwRvft'/|Pڥk. #O4}OUI8 hkْ׈ʜ9~so$;Yj r$GoRi^A1fe˝8~_ y%.L0H鉧*$97vi|3o<0I7Zt^y96Y紅Иq?2yVg|:ԃ>&ճug:ms`y5`D3uDm6!(ȯxqbᗲ ȣl|M{fmph˼__]zIr6t+iVϽ _X ̪Wm e #H>(|'7(ߙq]EB /~ߣ'ZV[e>+`Snqߝt=_ipS{XCíRQ]r%Fy(gx=&@n{ʛ`&ag-Rn+n* WlW{m*wwwK/ =y0O.] ` g0b, LES=&3.U3z8IҀW0 9{WzlO!AfbKmJA$(FH4A'HzOVc^o>fYU{^MLИVBOVh$>F]5@ : ݖhsL3N fNБOS D=&@n{n7ksCcX VΏ1 eE~fu0c63=eZmfR^y]|.ƞ񕞑WKsǜf75앲#]{`]) _c~9^ \R+ޓx xcA1=iGw»ܸ)ߙ?WҌgh L^7t'P1LUkQ2{cO6} ]gqnm/L(jNg3IxO11= [ }u>g5-@2XD0mE͙zrLV/}QS& <ǺkW=Z.}-PtN0?RhJ3{z'f=~]]*qpn|ڐu c=ӧя{m\@5cA>fl̤+NCw'ٓ,Qr,Qr,Qr{M 7r{M 7r{M 7r{M 7r{M 7r{Crp;Z=.g9ztnǞn69M9Ki$n|'mEq:>*G"hֱe0XWQ`C=*=q&0F:{T}VzJ%ŞLwJ#ƞ@/=*= U/H'=D\{혮μHƞꪹg.͚ޓnqwk.\H[=?YX+f!{[ 2$s\/bĞv5TO[>e Σ!-Z]Evn c8~J޳ kX[C}2-k?D#r{mlf)x fF ?grO5lkN#,DcefAgkZu&1k3>eϗ@m2fÖj8uuܼ_M,~#9~ւxE,Ya+ͼjÔ"UNPñrV_nYOhngW1ӗsp\^];U?:o:2 ݢ/.{{O,ds])Eհ"^gY}W4`f3M&vJ\ 8ĵҾrN߽p8 xk J<'jStf݇H3ehS-U}"v7w]b;r6T\i",>+(Oy,of]ѰhumEjL\E#9I2K. ^HgbJϴ$a]6]}p}G˹jҘ 2jsGz.,ܥE:}>a 8pqƲRVc3WαRqrv5gqgrwD_DRڎ_JBNl "mR~#ƒkO7#=*t:r[Y=dͦ|v7{ ;"rDvRّ[[ęAq):um(lQzwFPWCzRV]{3_G󣳍ωMJɛ'rѶ;\v1)@t/7; Rѣ~[cOwl왶(&=%^5(Ô{aZI !zٻJ;{6ɏ&k`ȯ3uҵݚW1OGpok3ciн\bOpAƎ5H7<VhzO1|AثʉPjfC X܂{?sO @$ZƹMz@nb=&@nb=&@nb=&@nb=&@nb=&@nb=&@nbpVnGkg,#^9N6sQsww܎xtJ\^}u5(:P9A}5(7&7=>aHG1U&׻ޣHcWQ`SV}<IQ`ؓ7֯ޣx=ޡL CޓcF. =vLγgϞ={6H\Wb~p{y睾 ?ydR\?Ş/_k4&p |w &@n h_.] nx"Ռ=]zIENDB`taglog-0.2.6/docs/taglog.pt.html0000644000175000017500000000211113534701742015170 0ustar johnjohn Taglog - Sistema de gerncia pessoal do tempo

Taglog - Sistema de gerncia pessoal do tempo

Taglog projetado para qualquer um que gasta a maioria de seu dia que se senta em um computador, trabalhando em vrios projetos. Voc pode fazer anotaes sobre o que voc faz, porque voc vai longitudinalmente, associando o com os projetos que voc trabalha sobre. No fim da semana voc pode produzir um relatrio de como seu tempo foi gastado, quebrado para baixo pelo projeto para finalidades do booking. Voc pode ver entradas precedentes, pela data, ou pelo projeto. Voc pode incorporar as aes que voc pretende fazer exame, para as associar com um projeto, e marc-las como ativas, ou termin-las.

Taglog software livre e liberado sob os termos da licena pblica de GNU.


Taglog home page (English)

Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/taglog.nl.html0000644000175000017500000000201213534701742015156 0ustar johnjohn Taglog - Het persoonlijke systeem van het tijdbeheer

Taglog - Het persoonlijke systeem van het tijdbeheer

Taglog wordt ontworpen voor iedereen wie het grootste deel van hun dagzitting bij een computer besteedt, die aan diverse projecten werkt. U kunt nota's maken over wat u, aangezien u gaan, associrend hen met de projecten u aan werkt. Begin de week kunt u een rapport van indienen hoe uw tijd werd doorgebracht, opgesplitst door project voor het boeken doeleinden. U kunt vorige ingangen, door datum, of door project bekijken. U kunt de acties ingaan u van plan bent te nemen, hen te associren met een project, en hen te merken actief, of te voltooien.

Taglog is Vrije Software.


Taglog home page (English)

Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/taglog.cy.html0000644000175000017500000000103013534701742015157 0ustar johnjohn Taglog - Rheoli Amser

Taglog - Rheoli Amser

Olrheinydd Amser Personol

Mae hwn yn feddalwedd rhydd ac mae modd ei ail ddosbarthu o dan amodau GNU GPL

(Dydw i ddim yn siarad Gymraeg)


Taglog home page (English)

Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/taglog_properties.jpg0000644000175000017500000007076113534701742016656 0ustar johnjohnJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222m"] !1"AQ4Sar#26RTUVquEd$3BCDs%e5bctF(Q!1A"a2BR ?L4NARt~jqT% ’Mk|)2BٹytLUi K197y[ m?*t2BN2CuDHHJT)B}tb$)T{i[Xۛվi쀬Is 7TD6~jY棦_LO̢ZR70е*& ~hȳ;, қ^SkwV jQ֑ G3s{“\NhrYE%89NO4/j^le' sXpMa>cȑ42;7ՏC/L9knMcWWvt6tlz-W}Vkez@ΠםR-o՛+Y+yX8TILZn5/0bit!I)83o%0yԻ&B/)xH7UEJ$BdW8 X\F?JiB}/=MqT,S[ZX2DDճlie:!('2cۚ 6j(Za1-Fj%=4P&ERH.];2onlU]:ĩTDjx\Z383}dTK˵:|_]Gsa9n^svoVV@\g-G]~^)̰q)Rl%e}0$qa g]5OqrTՑ*ê@C/k)*$acsL&|`F]JwÿAH]0},KT&yWLJ6`~C jtG pl?/IN8>aHɵEar~x9]洿L NNK:S!B b#wױ`O,i5lܛOˢNL2ȝx-N8YrDgNy)DLRfSpJTGVFz4o(S.4JQ~v^qeh+IUŸ鵄YTLX[RA I*Q8Vit-BFY K1?.4$sŎ=?AvIc5'&miJx7 }WrۮV~Ļ0Kl\ՃlXqB>.8wӚ.c$?"vN%<ܧ/p]ܘ0Jpۘ$Ft|n8ςj'yʅT!>{h_֦1^8Vi!RoZc ōܿ)c=g<;i[f]Xl{&zTyc_o[X!_ǡGoӟԶeg-,6W=]*<>޷gǙ1?EM?Nٗ句6y%voZݜ8?2ev5kX-cYs_XerT0z?Ckvq`BGJ&KXB~/=e_!6CZ[?Mw-ar+V׋ S@$.i)8JlD^Xy-\yҖ+Z%D3ekeߘ }Sj^l/kXCjŃ <-WQypq*Q9*Գl8EdFGvq6gG/Nt^뺴#XV|ߥ>Q\Mtf_k?TybGՃhI}[~Ffs3ңoPˏ:m-JyHN#CBmG2(a 9KJo|̻_6X}S8heHQhu^eMG2Q8pd[wz%ocqٜLf_gGgWXh}ǡL?>퉫Z,6e&zTyau{8pfgz9ogq\Mtfp)XgWxhqPY=X-8ZłR*$ \KCp;HТG80V EХ[?,a86qS?80r ?= ;8>h>ơRSPҢ>3"}&vx1j>ڍcp&sij4vJaץ^wVeEpPM-&Ys!2pÅ%KJW Ԑ $*1, VꍷNDgȕ)eV(**8&+g@}u, hN"d!IJ ō摬U 6JRU`qQr%)&J0p(RN%A+!h*QcANZe^qmiD)N%$r^$,j]E"M֪ qu+ :fp%i1>rHRtyoDԤ-4ؘeRC )-.ڋ%7@ @uW۞JIʜL9-0ۭ(PX27: Ghc)B>w_+zDuJq*ݏse}s?ƏK@fE2e220*pb'(w4Iv}|8K}RA*4nd岢$I֬6V`Req6a`:G:VV1MD4iJi +QlXÆo5HjhLSS/96Do] [.+VRJ (]Kh6UCo-֡\yī 8$쓐*&#^R\Ci2Kmi)ZB%Y @$ EwJyfCOfL!UrAJB !Ȫq2ךRk퍑952I%ØȹA,׹*dt r*l,=(pC/7i7P ոO3hwT$fA+6ea?á2S QXJR Rp-,.0iZ:<32g!Y%A)A2]Dx&tM˖}gʗ5+iRŸ-XZJiY(a/,tYl rp*Hox疚qͰ8ޭ%SENaK]nNim%edm$,PՌjp*%QiM1>9v iĀIPS0.@%JYHv+Jm:BA$4MV/$IYUJ"<ˣu_V_TL^Xbr&g X%j[RS N`$f:yv̫fE!@!@!@!@!@#-[SƧ2eK? #K_5ٯwL>,axk_ώ]~j3 gCj3 gCD\}Ϧb5-KQR(*7yU!DBI I)P#@ze%C,4B 261 0ڦ{{L0ڦ{{Ljãшa(p,Qj3j3 gC*mg61 &ڦ{{Lj3mg61 &ڦ;{f>mSIb(AmS=ߦaL~aML~3f!TowmS=ߦb@ML~3f!TowmS=ߦb@ML~3f!;KnIM9Ҕd u}eK? vퟋGnOf?߫ >8Mvcq?u=z]+K*aɉ@VV}׽1vBbY)[sXQy c$*21ǍKxYi͠?)EK'.ŇlOtFLkeHV؄9f >yoɤ3ON7tAݱVgp9M3@Z7*Ez[tZbAEo )` /u_!rTqY-?y[GFuY'k\R3}bEß$Z6Ub&#BTHdeGr.cէ7M|8j}tB#m}a,vmO^w!8$)Tz4sTyW̰MJB FjF=׌UUtFޑnu:\\҄0HƯPl8^ =!Wf3-Ԭ&R RBg ` A (n:CS}I)=eҕ!֐̡Ce٬Y@qHP)XiᔗkcZQV6Uҷ.AZF:U,YU>ҖkI%!b8H 6**%W"=TMegEM=jp"u,(]*£7J[Ci2aH^.-iǬ%\f\Nm'} |uNWdԗ'9oF¥^Vv7ZP(o܌ĵYGru4IJhJhJٔ/zƶNORs3S()BN!%FyY!!!!!!!!!! 7=}cz-_)c_lXޢ8t~#_5ٯ W]~|px)խQJҔBgI7FLTfi¤CP@t[ N?OiRP)$ûc㔚H5)}1_M U}8F Q6+NS]n^L:]r1.ˎXV۫M7_Mt,԰mfq(68b$s1JȸIJޚRqKBu-.@K谎㗇V9NXJs TV⒒um_r!qx55'S9/rBs-IIKiJtiQH RAe)E2ڛJL%nTJ–(@-{eIU,.8Wt2l*Fۛ&tc[f&V6>~K2BWqare{GT 9f3u3rRϥJM7@ yű캽PcVaÇu[-4"g\D5%O58JnA-t=Ж6Zjk,Ҕ{b!dkZE4ތS_**T7Դ\9z$e*-E!& Twܨ( $M/`Gl !BBBBBBBBBrۖnzg>Ŧ[SkϽDqi/1zFk_ώ]~&55ُË ~oʉ!*<3~T0ӹQ$ ӹP7NDxfQaGsH@Goʆzw?*$xfQaGsH@Goʆzw?*$CtxfQaGsH|xfQaGsA@Goʆzw?*$#7NC =;B<3~T0ӹQ$ #7NC =;B<3~T0ӹQ$ #7NC =;B<3~T0ӹQ$ #7NC =;B<3~T0ӹQ$ #7NC =;B<3~T0~ӹQ$ >6 t# ZZ}'G0F篶~,sQZeK? vퟋGnOk55ُk_ώ]~AotIFBfId1&vWagnKߒ/9bQƮ4|$x8Ǥ* "4i5-4d}䰆y()I% HPI¾7+iV! 9X ojf Jy%EBnXd\Xoq+HXUd8NնX~:7THtT?,Yن&i:*qw•8 /ihCn-Re<쳤-ڈq0<7m|b,[4ri[˅-x$ 6;QYPʤrM;)3("[ imb$Ы*XNZNvv))J*Ya8sdȵ5WnUã9;jfA̸R`P )Vc,*j6qJZĂӬPokr1E9QSTre@(RB(gzܛ:6ei mS`)CZN+]~N5.'S"ʢ\6豱QrrTWO,$LlVr ]rTW`.C($O'K AK-} /iÝkٙ\tqu6u[ ԣQNBnjCΕR*"ql}^yERBP@R@ BVq&G=Y:̇vM%.0Hyl*Ww=s6jSM5-ҜWnIQ Ή$ߔ6ܑqd%S .)$`yD S}eԼn,!ą$- f#xe.CaքaJ@ $=RϽDqi/1篶~,sQZeK? ^f?߫ >8Mvcq;r*iU'&&zL+VS%!xP#7)ZNwy h@g B!TjINuX)Qp#~xjnfuҠGhs+rYiGL9myGM"\XCe4 -a Pϒ  !E8VA9/xqG[@!M!"Kҝqv&H$ @wܻlG,Td>T9klrۖBBBBBBBBBBBBBnzg>Ŧ[SkϽDqi/1zFk_ώ]~&55ُ iyJBZLβMODK4xs 흁0)/6jTdTf&Q!.%1d1ƶ+HTU+Ie1NSU)7%KwZTEġ:XP;~-o{mow$KF6TjtKۙ,c.%(!I8,#wn}R~N&_5ٕ2wied,;quO&$&R*r|zJPiZqsZV+YevVf&[Ŕ>LeDal"X)K%P04rO^Jil{XzWMÌ`JAkFܖL>FysƂ [+4p_Q]v*{*B]u)̒ rFVF?ZKRܕJ%2H.6⏦XiX JFwU<е%iߛeQK:ÉZfV,ucXqp,LSiivfUr%n06(CoJɿ9~t_[Ại ^.a 4Ԥ*$(U0#8AHBBBBBBBBBBBBCF篶~,sQZeK? vퟋGnOk55ُk_ώ]~AQꏩ}ZFmԧDPM9f>xE1 gJKOYN'\ FW'$9m>TkZhͲfd*jie]db$(\a=L6¥h~q쓅v] Tm.`V+ ~775SVC OFY-bi-:*@ # q|C!DR^νNe%.I*0-=M29N~<\vT(k;lttjwݪT-^iLiZqNW_V@AIlq$\>6388Dž?U|N<-ZqA7K,}L䞷j1[^/#Ĥ"ffFMT8APG 'ywo1MMs} L>Q7HqD | (Rf+?GCImNUjhKUz~bPAQ1@ěLOۤ8M^<֞2(dIJKJ zKR֖Ҋ02jblz|Aex4f."NL׾>gD{k/Md"!)$TT]ṹd2*i !.]R)XV5 mKȷVu.j^FØ2SQBbB@,ΎzߚoDvjS3"=4d)*2Dg I:«w*Ѻ`y Znah,8v/)GYh`]7XrkTbH:%q8'Pd*5v* Ȗy3]z&0?L>gD=e٨}Ln/T34^t̬/GŦ[Såk55ُk_ώ]~AaVҊVP )${"R'%2^ )z0w,p͞_Y*s}0p̹0[M:ū6^PVO7?> 9I广oDBBZjM!Kqh\23})V'N%M̝+R(rH>Hj#93OOg_𶻿^г亮g^Ŷ3fTow6}*} p, ۂڶ{TowmS=ߦa͟gt,EmxsńeEԹ&ʼnMJgJ/bN"6&o63fTowO]$4Jm-ҥ/mtN`ҵw=hEI3M%(72Js8R$ l$j3 g9sdt,?ׇ=bքhc".ITg',]g60\ܑ0egS['A6e\l[VΕ^AD\؛ֹTowmS=ߤa:~ɳH,r۾wB3ۂ۷y[mS=ߦaL~͟N8WY}[^^>zy[KkÞŮ3fTowsi8I,?tȷ]?B32-0ڦ{{LÛ>8SY Rڶ{B-^-0ڦ{{LÛ>8XǙ6)Rm-8X\)d"ܑsAW31NmN.״)`% !hڦ{{Lj3>׎:Tқun;4#Ci)R Ea(`. +Ib.,s0ڦ{{Hŝ\ܑ0eg֥y,^} z$8.E|)B -ČZB. @0ڦ{{HM} <> G c*fR$TV+*ue$XB\XmS=ߦaLO |Y:X]m֎vAܠmu'b$TABZ,Gnzg>Ŧ[SkϽDqi/0k55ُk_ώ]~A@ @$~exSx%*RRrI9N@S傦٥;C^4hsž֞m!@\|"=iN=׆)$9m ҝ { S9OuAw ҝ { S9OuNKo,GJv<)6iN=׉! ҝ { S9OuNn? ҝ { S9OuM ҝ { S9OuKB#٥;C^4hsžĐiN=׆)'ЅiN=׆)$yq2V oR;4hsžfxSx2-MO:e. i70fxSxlҝ {Eɔ9m ҝ { S9OuK~HB{4hsžfxSx|[iN=׆)&nX[;B{4hsžfxSxr7{4hsžfxSxЅiN=׆+)I܄,ymY+-4AP%Z.1JuD#.k gmжRx]FX76@sW}JF d0_'w?4<=Kqe*uũl5 ܓ6=3<Ғ"VRq*\ 9q wX-'au󸿞=L6 8 .Aqq/G::R @Q'IE_l瞗SFa JB[ZTUa1d,$<}i_NԬT$&nI9̛8̹+JPBO8\V8 \|\Zy[CH$H#;Qkq/8 ydPTT 7Hy%0k[kHXI&qҒH \s ̼d촰1$6- `wGHl6@Ku§HIaa̰mMZj,*BZӻǺ;3sO2ۭI%ޭK Bl%)Ģ\q3N)ԤZ r׳8_q'iR$ IRpB.hh$ݰI I N ~KCۭ%8JN7M!S))eՒsYJR䏚XJZ^g2Uxy4}KM5*ܫhHm!8G+yos5130Pie-Eo(%8J`͕Ӻ{(-))7G!&J[,%mI ,QrEFh2ƽФ) RPk'}H懃˙SnQ\). i(p\rA_}N-ǘGCE5VbB7@ga"Z](!,`@"kSmÚ$Jm8m(Mu)J=ңso'ۡ}=1Sx䜽JUYԶ]ġV$^1O;S=JڛKE'kn]Q% KIզ̯XάewD9e0JՐXRTmksxyƝh6H%W G2gRV0\:ڐ{2Orro* «JՄ\+ қap懀S!N(@J%EJ“~blon[G!3 .d@0IIۗXsqrG$wZ%m>$RA{f] r|gU*<(r 4q_RpTJIO@r\G<s(iAEwR)I) esq/)Bug 1[A!J* A'u,`K)BqHWxߒ '|7'|7$G#!# $G#!# $G#!# $GIBGCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCe>G@Ie>GCf $0ClHeJ* 4^aQퟋGnOzg>Ŧ[S>8Mvcpf?߫C~|1jPTgUN^˴Bu ĠʂQ. !U[(~ME7R5Y) )HqJ R %)Ryo`HC7+U]fMt+t -:Ÿ^T-{ X$#A4IM6j/SXi2^y(@K*ZbUm-N Lw(r.3s 93)NcԴl͎Që oDZeG5tz]^/5,$l.#f̀7#"ZL8u~WsxupW9LJ7*fda+A*Hĕ!- $v#@˽:)Z )yt0)Җ[X n>s*y!î{^$XRrK<+99نe_L⇖RT}- _ R*# zyʓm-%yZ[-$e"j RpWsxupW9vQiY_ԐmVT;C@a7׎ /4eD! %)*MV4Z̹0Z\ sHî{^$jzE'^dz6ve#ZØO&*«%VPiM-\~cFiՉ~aד"v-_qZƋVJ0:U﫜C\ sHGiKd*SAʜԬ6S684 b̌*fiz3RY'K̤%qss J[^$ -Që sHpWsii:J)3L֚ۡid:F X :ЩA%74eK'gm*ZIQSJ̺=,b-Wî{^$}=¯}\;tK*ubqɷCa2}ְT䀵zY3au&NmmH)*.4r݉NWxupW99{ۮ>ӍT]վ7¦-lWUw~zW9IFt֧&Sr3a,TZ[D*1g@FrkB07&nʲiML%I!.6BNDk`Zp$!®sԅJj>I)gf jajJuNjIZo,[le4AmUƔ!sБf@\<Ý\w'sߤ. IEѹJevaz jx֨KccU`#4nM9N2.djօb]\w'sߤ. s4>^%Ԛi,eÈ [Mj[l%'`@hܤS:/"qAĩ8BT,1xkĵ)sߤ8Uw~z)΍ijUPLZy %*Rڲp9*::lO˺B}ï]ujΤ`SD `W9IC\w' n4eNO43͡M6ێmWA)H/:AJTHqh]:[/4ȗο:̳s!KQXJIyk7q`RSq®sԇ OR/  OR*;I=H\/<*;I=Hp$!pRP$!®sԅKC®sԇ OR/  OR*;I=H\/<*;I=Hp$!pRsߤ8UÕIBe[?DQGcIAR`qXQퟋGnOzg>Ŧ[Sáf?߫ >8Mvcq0a4'E<^_GMp)-XIl"U<#Fҩ]EbjE,q-2S*}ଔ$RJ5/?)'8!ieM4ۈ(cNd 9/j7MeHu ͩ3gSiQՂOVMSQɵhK%,L-*qLK NָUno2v](+VTd)A*$]-\6l>m(Uś-HZI*Z dl1wŦ[SkϽDqi/0k55ُk_ώ]~Ap3Ebg[iajXIue-CU*7UԐ ī1AUGj2+-05M#{ m7o&t~JImƔSĸ,О5EQX4~&[|A© ZUŀ ENQPvYmLzՒ1%A(qT!$` ṽ )ԉڄarR%`nIo.:A  2N,[Hum,V0'p \DK% 7ySN<`y¬dMưJ` "*LoFaM&~N'7$kN!j$8R[ R(aS !Tsmb|/XlL;^k1P[ /%!/8 PB) SoEꔓTIr:Zn푄@ $71.}y}h)iMR,J6 ^5uŪ]KY*Q`@g8Eo_Z"7/ SGx^3"7/wֆ)/wևCtC]E h s]E.}4w9.}y}hn;y}hph7AMxph8Eo_Zg8Eo_Z"7/ SGx^3"7/wֆ)/wևCtC]E h s]Ejw/ ,*":\[",EJ'xŦ[Sáf?߫ >8Mvcq0蜖-3<NN$5yW"l 2HGt{aU''u)I S4-bJRuHViAIbme*E.eH(۩Pj\)sct,!BBTQfB(;D[t ?xEvg5<\IoL&q%ܙ;N!V񨄷"^8'L]{x'L]{/kWmب:E.ڍZ8HQ@6g :u9*U*%KKRSqD\ $]y媄t˵:w2tO732iKlɶ$Ƃ qIց%Z4+.i+h}V0KK$7K *.sAo]ӽԀ܊NR#JUYL .aK[*[hYXXMu,n0c7wN̔!mS[Cu`0K5(+XJl-鏰tu!Zc(;H쮘LHʙɩy6QPZŽ▥A)dU^4YfR%StDimo ,@Agktu#iktu#MF𼛓:V kbSk&%wŜ* a#L]{.@F-2t8#L]{B4˵:w2tna n.@C4˵:w* a#L]{.@F-2t8#L]{B4˵:w2tna n.@C4˵zw* `p3B7(:.зbnTQiu>wOWS(褰> sw8RyfIIT^Ԥj"L.IyU`Qm'((O%JiQmQퟋGnOzg>Ŧ[Sk55ُk_ώ]~A6Vʔ*A#x"E49.?ٔP,%BaR0)āhUq E1.)ӥxPTu ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßF}?׍D 239=4g/sxB/y>ßC^50˧Git$|[͐)MfH ʷ?&d(Ŏ}#LI|=}cz-_)avkkfߟ&1^8wBr+AA8BBBcxBN~B`ɍ4bXg&ahp\hg! 4|"7#k֌!ZDu-s}:ќ[d- QqJHOEܔhp\hQj[_2Էey"\hp\hQj[KYw䆥l+ 7#k֊-K~kW]y!rRDu s}:EGZ䆡H3-\wKkևEl+ K~kW%/xEh8EoGZ2s2t-٧Ҁr•,qosem(%$M'!rRDu s}:EGZ䆥vK_2){ s}:hԷk-[W^K_2){ s}:h7햾ey!lIkW%/xAoGZ 7#Z̯$&e B5@Zw#AȸjԷ햾ey!rR~a4,,-$<"!Sn͸6d'[($_lXޢ8t~s?9-2%/C_5ٯ W]~|pxaAHBBBBBBBHv#'Ĩ&*3MW&tr&[gCmɺTԡ(pJ6܍/ 'g%++Ѫ+nvp9$!TEoƶ;Jii=04[h!h*xӄ)Y(*P06C-!"U>\ )[IIB0'XsMo=?Dv 7mvǪ a6/j/,|ZNgd/I'*eVkYY P $\% M I-3X^M=5$da(RJF-iPZdLÓ )ro\ Xw5$]dx@8 ~]xmVM^3 }Pjzcr8 컉1bΦذ֥[%8%SjĴˁHJ)! wT7+JdDʗ34e!wZq[qAZ$+-rQ=QO[;/DLq+\V_7HSiț*GDQ$3(&CL92(-)8]]+$ dAsSfX w"\UL c6 $$JGN*G$#'ĨKϏThb;19~DEeb|R޷eq^,8ױSQV(R;mFr侹-Բ)[ͶBxQb8m+mt)EK VەR7TbZ^YVXiVqS(Qm 8,-THQF#Ħmhjm'k[aű,RFj;#3qHI-E +JV+ HI&9&E}KD~UQ?)0w7XVZ)#AM۱3'13t-l_f.P3]n-"aJu+T/ ))j(+@ &׸ Z*vM}&ʱ #3)*e=6%ʢiԵ+@^O \[az+TnJK-6V s`(w,VT6'Z]+JmV)B*8\N\a~Ue ӁC2RTuRIĂ8VbbV} <7 W{0PՈR QB%de4vD-DKbqKԙ[qXTPu6bbJdDtn6)Ru'ؚdm\`V橦Ӟ1p5da|VÝSQ턤 l.gȁI*GGX]^*/""_lXޢ8t~s?9-2%/C_5ٯ W]~|pǻxaAHBBBBBBB5P}OfPbIJmaU  >| }^:!W8;H}1x!bW8;H}1x!bW8;H}1x!bW8;Ho끏^/! ,jJIMUL@QRTs>h5P}OfPbIJmaU X!| }^:yX!| }^:yX!| }^:yX!| }^:yX!c׋B4ZSfS*(Dl&(/a 7=}cz-_)c_lXޢ8t~_5ُynX\lO-7g//1^8 L<#?;C+=2:yX L<#?;C+=2:yX L<#?;C+=2:yX L<#mJkF(STܘ<놯81)MJ:wetywgGRw]YԎ;3;3u|HywgGR:)|E}aHyvww>L?#\ST-.6JwOPҺݪKҔ!W A$,JYvcD+L2uІВ)Eb>:?>:o/!~|tV?L~s䂔T=TgJ zVչGjj\$1֥j{KMTXm7AQ%j6ZHN`Gnh̟HBˬ#}R7<^Ꮉ5:Eh%H ы[l *hnY5vh 8$XXܷߜ|amn, Y)\䓘̛I0/!~|tV?|t{V?"zg>Ŧ[S:WMB)%Eq֣>i/1zFhm3dϜE N.c3|6m?Hs$RNfw7C oO-sBt߶ 6m?[ w?ts<G.<(Dž`?}y\?xQ >s<G.<(Dž`?}y\?xQ >s<G.<(Dž`?}y\?xQ >s<G.<(Dž`?}y\?xQ >s<G.<(Dž`?}y\?xQ /O eX c{T_k{⏵ӽGo|VvKo g&a!I?ՖUaUjIJd_;}>Nk{⏵ӽX7Z&yfED,=i?5?m? _6G@OOnI94KH*v2x'n* f5bY2sQ>Nk{⏵ӽX7Z&yfED,=i?5?m? _6G@OOnI94KH*v2x'hQEQYhtϴ$Ld Џzg@OOCW'MQ&( ihjɴ ?5?m?­YM\;ŷZCpΣynԣ88=_ _6G@OOCW'MQ&( ihjɴ ?5o쟇>9T^/y E)d5xPy7 ilc5x[]>K`4ACu' Ɗp8_Sְ޵j@e,y3u-}T5h1c90s]ok~X{Ef7m,es ;% hfU+ Oo*2h=N=*{krjAs /%R@V{kl=11HW)>yqjk{6sn̎x< d-k(:dVt&U/5F\a/__X],-N czkq7+xTYWa0<SO@С[XbxV%nAu1-|5. vOVJ*0'kGɶiB[ǹq g =Os L`R qϭd_X D闐oyr(l6y<ZxV) ت$@hI%zMI$^鮥M%Tas"r@=Fxښck 2ݳI;u_´m|5. vOVJ*0'jk]GHR-da#V!.:@$ ;;WdF (҈lm&HB$iU:;T-q`3ER` IaJm:eXwcP?6_=~G~>8m{=ht?1it!ME3)t ,,_Fy{ _Xc76nW?@0'O0/^wǗocen.nN/= ,R,/қ^-zJ&G71ky7_x.8=.[ ޕML3]d|jk|j?o>CR~{L*x_z7TRX"D7_"X57c=3lLÍ6+c_|5~70 o{ァS?u񞧯~~<z}]Eb7B?mC5 k|ϻ+J|wW?-sF?%N6CL3qsvftҁ , \0_Ta[$캛/hbX.}nC. ~3ﹹ"xb+Xk0Uy^=[ @7E Xlhhhhhhh|On\.RRNٚ&{|ȫ{ yM gP:{'sS=-(.0}vBgͷPXl؅NXBUy`;rbK>xZ̦L(s+Dm 7PXg[bV`zzjtH{x/6"gr?ޣ^Xz3w55,ٝxYW%{=.T9ze5ԪhCr&{?oI{;,JJnbNYUx'Wo](e׹Cuȶ[avF} d5P0 ~CК=qzAzX餗6+777sWX-9g+ٳH@&O6=\KFFOb,k*v(1 }nոq"4- * FFx϶#z@gCE l@?sۄ:whZ#Z#ZcgZ L Ğ8sWX!f 2xٖ~?w+@k@k'Q3Yޯ?͏X=x`Q%/ y n Qmd4t,힚Ƈ@ё !֌RREvOS%»-{k6BPĞjHCxOSh5[C왜 eg Tϭ7N&D hhhmGvφ:A ~ u*_V86@Ž=9/~? x,`u!:}ncBsS|wڼ{Ԓ6 i#Ҭ_(<5*{wUUmŞFy3ovy+53m,Z/Orś33Tyk0@xԍCɩ 2n=S`T6d7orW)^:Dx~?Q7Bu7hߋ+LU*,]Yh'wpL)k$4z-^2G >FG3 0r4]ix(=$?[:#҉LBw #X龚T}:8݌JYbrJWkANEa#txHRH£$lh%fZ&%5~ x, /y*/qGUš%;#i:L3Ğxt=v^׳0/ 7c6VsE>~fA?jٛ$L9QM]벚DI)f_Ko\at:YѤ{7ܨ'R}]i}xqWޔlCU %3Lm^^wq*:cZ+?8Qh>yXHDR6`2m R} @U^>)56xWg>㢓y{ƦGi$\ۄ{>ι}Ýwm&Cyzk = j X繕k,]J4b2ݚe3QL|98bЈ}Sݲ̯EEB([-؂ܼs "ߏt6G7%?ʌsnM@k5 `;z={{{{{{{{{{{{{{{;q=Q9U؎of_jex5bX]j)=L"L^qU1=ݮ0`S.U {x<>{]υ5tR×|F [,L!CPb$T(4{hJkkU$ƞ@(CP.7W-g{}0j{0 aǞe ,;6fyw=W~XNH{/YsHPт=+soaXBrdAl^!`"x<]z1)12uXQbx%88BupLp =x#=ֈ=Jv0 g^& ׭w|Ii Qc]a|CMC%u.MZ^Df'wnf5wh> SBcQJ1N=rYuYL8.dnM"g0*:~oM0uL Z}CKW`xxL$UnUηH2ԇ7^+ӽRFZދ5?JFWɪU.'z{jelM$ weMb4L=Pn>E/e>ѳsՙ'7sMvp>JdCU,x?gd+<\s]hZb5_#z.21sÉ$Ɏ+E{c2.=r~0sthv ?V?tֆ'&_LM։.eA#w`b$RtJC|O][@|x2x0ak|XqL"NѕS7}RwBj)ޔC7U'ihG'n։l]G<&怐^yoKCUr3d;%zLB9G2(~9x_ mwyq3Q}8oIMZI4WQϘ{tY[y+Gg.x'-1R~TLF&IK'r(y7 ;u{ɀMi|#ta3I9aoxG4/8&81{f☔wBۜUPy<&1DgN%ֹ[q*X3OY}guzsٱg%vOj,Tƅ2 !3{fi\(O6gvw6ZABqq<߳]|0z=F 0`& <BW@k@kg۩_E3q٘Dr,s 椢{enw\ԟ+fa8Y{ $*HKJN4Yh\NvL5(Ԛ.؎#Mչ{D`uC `6`3u;@ '-mM܃O'na {{l):~c@{ĞM#}nu^Ǟܬ-˚Ps;͊oYּ4s^}[5oSr8{BTc⭷ʮ`?nYg5Su!nyGDwT<*)v_%mˏń~u5Kyy.WQDg&}#9wx2%Qh|ҫϹJ>"6oy.WQ))U%3!ϼ7S 5#oK`.FOR4u,6Эnh`d8R^*gFdHR%ު{_G7MKgՑz2d܂˒5nfM)sjiϖfrJ}M`]M]iOaA{&ׇٕ*((y/Kyhd{/.,=BG)7{3):N[PJޅo,Tr~u ĞeU-Bhs95; <{7u0E= QO`Όѓvu~u$#<o6+[S~;7z֕ѰͰ-hWflAFO;Q]"ٙ8F ?iSX1]zιʽb p^OpPT&{v>7ൺOn[M 5#8TOoqd$7v%QXPh_G)t"UJڣȩXGKwϥ!䝒 &g1Nr-Hrg(`|(HAm':z*FZ*BՎ*x(TК'8 `"Sh+'%^Ze䭧|zPXWh7%{2~܆p 3ݪ [0a x?dnQ5",}=mn.o؂b&-*CV/R:m*kP">42)۶i.`vN]HnL`cuX#AXR%]:沼xJk.UtRAC*#A6h>7oK;(2OaeRdM|hWad>760>lb*ˎ:+`;sFFFFFFFFFFFFFFFFFFFFFFFFFFJܬ{cz^qU=777znO Ul Bj&]sT*.=lC0v@CP]rFx+CPN{TӇTSONTo櫯*ZNSןS_~o7o} O<傷ۭ11{x`ls+U#񼾾[䂭smzAJ/y(Ǐ¹端Nu9~}Ѫ駴UUM~ tHJXÇ_|Kߧ{r_YEU|l 楿?4򗿔>{O+r{ܗ_~ٛ{O/ύ)7%FkYy×_~R&[E$N~CTi+yJCC9Iƭ/Z6!â*=c X*Eɦ"]˩[XEQ?4wXM<7g뽿o&COMyx@4L? Kה2Tеx=mu=gz7е?pWRKH~(G6x!mA.=V?=(x+xAQ///7,>kXHRXgI@nr=&@nrX)jzhծ y- VDS7:*AR/Xբ+]_P)Q"1b6+d_q=u]/*>O׫2]7RTԞ]Q[ؑ7ꊤw݄x );3#=At n(`kMo$k\1lN|]lқ0ά> >=򔨶p, ಧ;hm쮉Wxx m”g+Yk 7vd~XeYz*sV/ 0J?qۻ́e˩(wP^PV/jݲ_ḰMYEFqOԮ 욘m1L<3SNp,`=68t^M.=$uKoBۧ#Y(vQ q{,<EÇN/R; X݀`+Bם-_sCi[zӛ7o{V~#(\>V߻@9_Evw(@nr=zh{.*qp{|^+B-6y=L9 =yYo߾];ܴ选P9cI`S@nr=;NgK\d6E$j#&%̯L$Pk/1[{f6F&(Y%F")ix3WoǠޓՈYg~%qrliAhdFp4rQ]3<mni牮l"*9{@nr=䦿X`S{䘯G6H9 mnpg=&@n{jظu=Gq\;0Tmnk:`){|>ö@nlRZٶ;3*C6.T Z{N J=Env=sc6`{Ԩ| VPH!L";ޓՔ \VH_)g6Lp:C_{ f#CԀ{W 2FgrY&|isM;Ot f)'LS 7rs,}Y)=r#$l6Ck3rޣs^t>\.S#t6p^MmZї\ `K6FHw%xy!E3lj~[{FTzN` fW!n[$Ȕ[RvZ|zd1Aglq=e/Nbէ_׮o)NWDW'gv1h},\{ ]lWv}iAm/B;L7E!EgI[t`Ń!,>G q4=gJO:{m$1 ~aHk k/҃ƹ z ~Op~/gL'ϓQ;ۻ.]mW)=Tdes ~Aÿgƈ\5"'-{Dk?g0x7h)؂kd2 ZmijrAKmK=3^G\WI@Ђ=E#c > ijV_k?cu^< 8fS|zMp\{KN_0=l=@nre=)/6hC &%q 6,8x([m]OM\[!M|5;g[6h)hJHhU5xh)g @nr=&@nr=&@nr9cjr{~/|^g C@nr=&@nr=&@nrŞ9,!,$\9s(R9NKCnkt{rym{/]bc +|ʑsAu<ٍGbG%0EOQ`v=*=Lԟ{T}װzJ%垲bpJu`aRޓc&.k{^=xR4sϾjv89=].rr) {o?da1W9h-qf6rkI?pkDVkP/lH"и|x筹4JpCd ZdU'jCc] |Y52`ft9^JFjr[ ^?Ψ d#&O/s"j$$=3]z{_gkp-xڗRcCkW)aDM\ijMYXDPHOO<U ^%pGzW:č{/%'=0ױZ 6v'+H<4[m5N*ЖF|Sϼ2ij?_4%qg2h-[ ^2k];/9~&&j27eDk ~TEWh;Q~I7=u 1L1")6mnً`S\A̵3n کfslV|_!|0l]?${iFd}LWמػEf:ڵ_ͯ練߮ZCnVSsO[_3+N-U73YZ6z{5~ tBa]d\)52Ί>Gm}lfLgn#R'fLgn#ҠmM}fڷO>d¹g{y.!,{xc̛uQ{xcGf5=y}g^^.+{VɼROqnfoFP?ȼR#s\'AX2 `NO  wG\4e'R 7ܦT^}6;x=n-{g,R=ύNV`}Jc6YaZ[QJDRH$?'lzFM7Csk7LeX>{%1M=~bD)B[0m)ިǰ=¸GT#3lnI{u f)'RvV=&{K 7E ?$`܎~pPs^Es]Rrd[}uR*OEQw޽yfxx|s v{FwBs0įC`6Tt6p^MmZї\=m1gl*Y;!6 b˒rϸJώ[{)jz0Q[bD-e]|}}ظ'\ 3_e}ocJrzĪlUju9AgN Xfl`RpPS*=ryn>evgXT90N=ٞ繝H{UHTWk{vgrW=9FMw765\D ߵxb]Sҗ.s豋6XC\S+qoE#vIKPgWzzsOoDX*"Hg'1lsh@lRz5q8X\cfb0qH 1L}o؈s z* 1t=xcMFUBx]ugR Sn؈IېG(uݼ.*<]ؾϱZ]~ġ[ A"UfW>R׊F/[ؠ䞠%.evU>fWQvgX<]gN-21=F,Xi?޻SлJAe6+=Ń{WƎ{z`Smsk\7t1Z,^ԔzK*?>"L-GDt:%.tEqne @nr=&@nr=&@nr=&@nr=&@nr=&@nr=&@nr=Yo5[Ggr{| =ϙ8mn=qyMs kPDP9ACu5(7f7FU0ޣ=G 0QQ`^=*=L{ʪZ0=*=L{ҟq=*=L7 o߾M,Ԡ8  {sLxxz|KD'ݻwkЛ7ou<E:n᯿o5@OELY8_k:F;F @nO&J=]P/׌&jIENDB`taglog-0.2.6/docs/tutorial.html0000644000175000017500000000230013534701742015134 0ustar johnjohn Taglog Tutorial

TaglogTutorial

Welcome to taglog This program acts as an electronic diary, with facilities for logging the time spent on different proejcts. It also has facilities for managing actions, and booking time to projects.

This tutorial takes your through the main facilities of the program.

Contents
 

  1. Installation and basic time logging facilities
  2. Action management
  3. Preferences
  4. More about projects
  5. Working with other systems


I hope you find the program useful


Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/tutorial1.html0000644000175000017500000002073213534701742015226 0ustar johnjohn Taglog Tutorial - Getting started and basic logging

Taglog Tutorial - Getting started and basic logging

Contents

  1. Getting Started
  2. Logging by Project
  3. Logging by Activity
  4. Adjusting the Start Time
  5. Exiting the program
  6. Viewing previous logs
  7. Displaying the time spent on projects
  8. Reporting project bookings for a week.

Getting Started

 

 
 
 
 
 
 
 

I assume you have already installed taglog, as described in the installation instructions    Run it in the appropriate way for your platform

The initial screen should look like this:
Initial Screen Image

At the top is a menubar, below that is a window which shows the previous entries for today, which will be empty if this is the first time you have run the program. Below this is a bar with the buttons related to the current entry - like this:

Current Bar Image

Note that the Start time should be the time that you started the program, and that the End time will increase every minute.

Try entering some text in the entry window (the one at the bottom), and then click on 'Next'

The text you entered in the entry window should appear in the days log window, labeled with its start and end times.
What you have learned so far should help you if you simply wish to keep a record of what you did during the day - an electronic day book, with the advantage of having the entries automatically time stamped.

Logging by Project

 

 
 
 
 
 

The next stage is to add some Projects.
Click on Projects on the top menubar, which will bring down a sub menu. Click on 'Add...'
A window will pop up which allows you to type in the name of a project.  Enter names for the projects you spend time on.

On the 'current' menubar is a button labeled Project - click on it to produce a menu, which should include the names of the project or projects you have just added. You can select the name of a project to be associated with the current log entry by selecting the project through that menu entry, or by entering the name of the project in the field next to the 'Project; button. Note that entering the project in the field will not add it to the list of available projects for selection.

Try making some log entries associated with different proejcts, then click on Projects/View in the main menubar. A window will pop up showing the time spent on all the projects you have used. Entries which have no project associated with them are labeled as unknown.

You can find out more about Projects in the Projects chapter of the tutorial.

Logging by Activity

You may also wish to associate log entries by activity. The activiites can be selected from a sub menu of the Project button in the 'current' menubar. The current activity can be cleared by selecting the entry '--'.

You can also select an activity by *Right Clicking* on Next, which pops up a menu of activities. Selecting one starts the next log entry, with the activity field set to whatever you selected.

Under the Reports menu you can select "Time by Activity" which shows a breakdown of how your time is spent on various activities.

The names of the activities are read from a file, usually called activities in the same place as your other taglog files, but the location of this file can be changed in the preferences.

Adjusting the Start Time

Sometimes you will`not be able to click the next button at the time that you start a new acitvity - you might not be at your computer, or you may forget to do it. If you realise that the current log entry should have started earlier than the time shown you can click on the 'Start' button to correct it. This will pop up a window like this:

Start Time Adjustment Image

You can use the slider to alter the time, or enter a new time. If the 'Adjust previous end time' box is checked (the default) then the end time of the previous entry will be adjusted to match.
 

Exiting the program


To exit the program at the end of the day select 'File' in the main menubar, and then 'Exit'. You will be prompted to enter a summary of the days events. You can skip this by pressing 'Cancel' on the summary window.

You can also exit by selecting 'Quit', which exits immediately, without saving the current item.
 
 

Viewing previous logs

Once you have several days worth of logs you will find that you want to find out what you did on a particular day, or follow the history of a particular project. To do this select 'File/Open...' from the main menubar.

You will be offered a popup with the dates for which there are log entries. The dates are in the form monthday - for example 0704 is the Fourth of July.

Log selection window

Select the dates you are interested in, and click OK. You can restrict the display to a particular project by clicking on the Project button and selecting its name from the drop down menu, or by
typing its name in the field next to the Project button.

There is an option to save the displayed entries to a file, which can be used to create a report of work on a particular project, for example to mail to other people interested in progress on that project.
 

Displaying the time spent on projects


The program keeps a running total of the time spent on all the projects you have used today. To display it use the option 'Projects/View' in the main menu bar.

The time spent on the current project, and the total time spent is continously updated. Note that if you have a project called 'breaks' (by default - strictly any project in the breaks_projects list) then it is counted separately from working projects,
 
 

Reporting project bookings for a week.

Once you have been running the program for a week you can produce a report of time spent, by project, for the whole week, with summaries of total time per day, and total time per project. To do this select 'Reports/Weekly time booking by project' from the main menubar.

You will see a pop up window like

Time selection window
 

Enter a week number, or increase or decrease using the '-' and '+' buttoms and press 'OK'
You can display the times as hours and minutes or as decimal hours, or as decimal days.
 


There are other features of the program which are not yet covered in this tutorial, some (such as actions) are not fully complete, but will be added to the tutorial as soon as they are ready. Refer to the TODO list to see which features are still waiting to be implemented, and to the changelog to find out about recent changes. Please feel free to experiment, and to let me know which facilities you find useful, and any ideas which may improve the program


Next Previous Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/taglog.it.html0000644000175000017500000000201613534701742015165 0ustar johnjohn Taglog - Sistema personale per la gestione del tempo

Taglog - Sistema personale per la gestione del tempo

Taglog studiato per coloro che passano molto del loro tempo seduti davanti ad un computer, lavorando su vari progetti. Si possono creare delle note su cosa si sta facendo, mano a mano che si lavora, associandole con i progetti su cui si sta lavorando. Alla fine della settimana, si possono produrre dei rapporti su come si occupato il tempo, in base ai diversi progetti, a scopo di contabilizzazione. Si possono vedere le voci precedenti, ordinate per data o per progetto; si possono inserire le cose che si pensa di fare, associarle ad un progetto e marcarle come attive o completate.
Taglog home page (English)

Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/taglog-background.gif0000644000175000017500000000237413534701742016477 0ustar johnjohnGIF87a,,,,,c ڋ޼H L^d v+h$*]¦ --%:E.48^G0ˋNamm#O Aw(gW0ؔ(vXU8hy9FY ))Iw*+;9 0Jj;| vK))-[: LТU>w*Zgc9vԆږ`;`=`aE<SL8{!l @|jzOKlY}c5UJ:5f!<.x`llWHИ6XD:@%䐻wA$1L֨IQR$INjf啩LI]z JZ4&qy&`iR )0u&K3s6YZFbͱ'j#\FZNak6) )jUʜЕHpzݪZ\6-.ݫ% hp QB6[@5t$m~G-_ӆƲ>-hc.8*:N*ӽBU/R9NwLI;\/@\1Yh<6r Dq̻PⵌBr24"65Sf|BC }AP]?`-[sbMvfvjvn wrMwvߍwzw~ xNxx/x?yONy_yoyz袏Nz馟zꪯz뮿{N{ߎ{{|O||/|?}OO}_}o}~O~柏~~Oߏ p,*p lJp/ jp?p$, Op,l _p4 o;taglog-0.2.6/docs/teachers.html0000644000175000017500000000236613534701742015103 0ustar johnjohn Taglog for Teachers

Taglog for Teachers


Teachers, in the UK at least, face a avalanche of paperwork in addition to their activities directly related to the curriculum. While taglog can not do much to assist teachers in the classroom it may be useful in planning and recording non contact time. Future developments may be useful to help with the lesson planning and assessment. It can also be used to record the split of non contact time accross subject areas, for example by teachers who have a responsibility for a subject, or for Special Needs provision.

You could use Taglog's contacts facility to keep a class list, and use that to keep track of actions related to specific pupils. A future facility will let you import and export contacts from Outlook or other email systems which use the vCard format, and you could use that to make a class mailing list.

Coming to this page will be instructions on how to extract portions of your class list to other programs and print them - for example as a list of people going on a trip.
taglog-0.2.6/docs/programmers.html0000644000175000017500000000041313534701742015632 0ustar johnjohn Taglog for Programmers

Taglog for Programmers



taglog-0.2.6/docs/lawyers.html0000644000175000017500000000433013534701742014764 0ustar johnjohn Taglog for lawyers

Taglog for lawyers


First a disclaimer.

Please note that Taglog is Free Software, make available for your use at your own risk under the terms of the GNU Public License. If you are concernedabout having someone carry the liability for the program you are free to hire a software consultant to customise the program to your requirements. You should ask them to review the proper functioning of the program in the areas in which you use it. If they find any bugs they should report them back to me.

Having got that out of the way - what are the areas where you might want to use Taglog ?

Client time recording

Set up each client as a Project, and when you are doing work for them switch to their 'clock'. If they phone you then use the facility to right click on Next when the phone rings to mark the Activity as an incomming phone call. If you ring them then you can similarly mark the activity as an outoing phone call. If you make notes of the conversations then you can use the log searching facilites to check, for example what you said to them on any particular date. You may wish to make paper notes, and then edit the entry afterwards.

Client action management

You can use the actions facility to keep track of all the things which will need to be done for a particular client, those which you are actively working on and those which you have completed.

Client communications

If you add the client as a Contact, and they have email, then you can arrange for the client to be automatically kept up to date with your progress on their work by setting up actions with client address set up in the Email-status-to field of the action.



taglog-0.2.6/docs/tutorial2.html0000644000175000017500000002137513534701742015233 0ustar johnjohn Taglog tutorial - Actions

Taglog tutorial - Actions

  This program uses the term 'Action' where some systems use 'Task'. It describes something which you intend to do. Actions work best if they describe a small lump of work. That way you can cross them off quickly. A future release of the program may have the ability to specify high level tasks, and then split them into finer detail, but the present version is aimed at detailed tasks.

Adding actions


To add an action use Actions/Add... in the main menu.

Most of the fields should prompt you to ask yourself questions about the action
 
 

Priority
How does it fit in with the other things I have to do ?


This program uses priorities where the numerically lowest are most important. The default priority is 50. This may seem like a large number, but the idea is that if you consider a scheme of priorities like

  1. Emergency
  2. Urgent
  3. Important
  4. Fairly important
  5. Default
  6. Non urgent
  7. Wishlist
  8. May get around to doing eventually
  9. Heat death of the universe may occur first
If someone asks you to do a piece of work, or you generate a job for yourself, pick a suitable priority in this range - then multiply it by ten. You can then fine tune the priorities of individual actions to decide which of the Urgent actions should be done first.  Note that the priority may be used in a future release to estimate elapsed time spent on an action on the assumption that you will spend (100-priority) percent of your time on that task - i.e. it will estimate that you will spend 90% our your time on a priority 10 task, 50% on a priority 50 action etc.
 
Expected-completed-date
Is there a deadline ?
Abort-after
Will it go away if I dont do it ? - If this action has not been done by this date then we can forget it.
Risks
What are the risks ?
  • To people
  • To property
  • Financial risks
  • Security risks
What can be done to minimise them.
Assigned-to
Is there someone more appropriate who could do it ? Someone cheaper, someone more experienced/specialised, someone less busy ?
Reason
Why am I doing this ?
Description
What am I supposed to do ?
Deliverables
How will I know when the action is complete ?
Difficulty
How much thought has to go into it ? Often you have some tasks which you must do, which are routine, some which require original thinking. You probably also have times of day when you feel more alert. You may want to match difficult activities to your peaks, and save some easy ones for your troughs.
Status
Do you need to start it now ?

 

 

The possible values for Status are:

  • Pending
  • Active
  • Completed
  • Blocked
  • Aborted
Actions start as Pending and become Active (or they may start as Active as soon as they are entered). They end up Completed or Aborted
Resources
What do I need to do this task ? Do I have all the resources I need ?
Expected-time
How long will it take (in time spent working on it)
Expected-cost
How much will this cost (apart from the cost of your time)

Integrating actions with time logging

If you click on the Action label in the centre menu bar you will be presented with a drop down list of the actions which are currently in the Active state. Selecting one of these actions will set the current project to the project associated with that action, and that action will be associated with the current log entry. You can thus use taglog to track how long an action has taken.

You can clear the current action by selecting the action titled "--" from the list.

Viewing Actions

  The Actions/View menu item allows you to view your actions. You can select the actions to view according to the Project they are associated with, their Status or their Priority.

You can also select the fields from an action to be displayed - this can be useful to allow you to see a summary of the actions, showing, for example, only the titles of the actions.

You can also select actions by the date they are expected to start, or to be completed.

You can select individual actions by Id (which is not very useful most of the time as action Ids are not very memorable) or by title. The Id and Title field names are menu buttons, and when you select them you get a list of all the titles, or Ids, which match all the other criteria you have selected. The menu entries for these buttons are only updated when you click on the Refresh button to their left.

Editing Actions

When you have viewed a set of actions, as described above, you can right click on an action and this will bring up a new window allowing you to edit it.

Changes you make by this means do not trigger any of the processes which can happen when you change the attributes of an action by other means within the program - for example if you change the status of an action there will not be a mail message generated to the Email-status-to recipient.

Changing the Status of an action

In the Actions menu are entries which allow you to Complete an Active action, to Activate a Pending action and to Abort actions which are Active or Pending. These present a menu of the titles of all the actions in the appropriate state (for example all the Active actions are presented for completion). Simply select the action by its title and it will be changed to the new state.

Viewing the History of an action

In section 1 of the tutorial you saw how to view all the log entries which were associated with a particular project, over some space of time. As you start to use actions more you may find that you want to view the history of an individual action.

This is done via the Actions/History menu item, which brings up a selection box similar to that used to view an action. This time you are likely to want to only select a small number (often just one) of actions, and each one will be displayed in its own window with all the log entries associated with that action.

You will see the key information about the action in the top frame of the window, including the total time spent so far on this action, and (if it was specified when the action was added) the Expected-completed-date and the Expected-time.

The next frame contains the history of the action, showing what was done, and when.

At the bottom of the History Window is a 'Revise' button. Pressing this button causes the action information to be updated with a Revised-expected-completed-date and a Revised-expected-time. Note that these are stored as different fields in the action, so you can see the difference between your original estimate and the current estimates of how long the action will take, and when you expect it to be completed.

The bottom of the history window also provides a button to allow you to save the history of the action to a file, and a Cancel button - to remove the window.

Shortcut to editing the current action

If you right click on the word Action in the central menu bar, while there is a current action shown in the box next to it, then a new window will pop up which will let you edit the current action.

Long term action maintenance

After you have used actions for a while you will find that the current actions file will grow. From time to time, depending on how heavily you use actions, you may want to move old actions to an archive file.

To do this select Actions/Extra.../Archive Old Actions from the top menu. This will move all actions which were Completed or Aborted more than one month ago to an archive file, called actions-yyyymm.tag, where yyyy is the year and mm the month of the date of the archive.


Next Previous Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/_config.yml0000644000175000017500000000003513534701742014535 0ustar johnjohntheme: jekyll-theme-modernisttaglog-0.2.6/docs/internationalisation.html0000644000175000017500000000711313534701742017536 0ustar johnjohn Taglog Internationalisation

Taglog Internationalisation

Taglog has an entry under File/Preferences which allows a user to specify their preferred language. This document explains what lies behind this, so that you can add support for another language, and have it added to the main distribution.

Status

LanguageHelp fileMessage Catalogue
EnglishCompleteComplete
DeutschComplete (by native speaker)Complete (by native speaker
Francaisnot yetPartial (by non-native speaker and machine translation)

Help files

Taglog has online help from most screens and menu buttons. This is implemented by calling the routine "taghelp help-id". This looks up help-id in taglog_help_language.tag where language is a two character language code which should match the value of the language variable set in Preferences.

To create a new taglog_help_language.tag file first copy taglog_help_en.tag to the new file, and then edit the sections between

Description:: END_D
and
END_D

Note that the UNKNOWN entry is output when the help system can not find an entry for a particular help-id.

The current version of the program is substituted for $1 in the About entry. Further entries with variable text may appear in the future.

Message catalogs

Much of the text in taglog (menu buttons etc) is passed through the TCL msgcat system before it is output. Translations for these messages are held in files called language.msg, for example de.msg for Deutsch.

The file for the language set in File/Preferences is read in when the program starts. To change the language used for the messages catalog you have to restart the program.

The message cataglog for a particular language can have comment lines starting with a # character, followed by a line which reads

namespace import -force msgcat::mcset
This is followed by lots of lines of the form
msgcat language EnglishText TranslatedText
for example
msgcat de Help Hilfe

Note that while the bulk of the program text is output through the message catalog there are still some bits which are not.

Web pages and other documentation

I would welcome assistance in translating the taglog web pages into other languages. At present I have only brief descriptions (taken from the Debian package description translations) of the program in:
Deutsch Italiano
and based on Google translations in:
Français Español Português
Put together from bits and pieces Gymraeg Nederlands
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/scientists.html0000644000175000017500000000113113534701742015462 0ustar johnjohn Taglog for scientists

Taglog for scientists


A scientific researcher can use taglog on a computer in their laboratory as a research log. They could use the Action Sequences facility to set up the steps they expect to take in an experiment, and then follow the actions as they are displayed. Their notes about what happened will be associated with the log entry for the action.

taglog-0.2.6/docs/links.html0000644000175000017500000000606713603645436014433 0ustar johnjohn Time Management Resources

Time Management Resources

Programs

There are a large number of programs available which cover some aspect of Time Management - I cover some of the Free Software ones here.

Note that I am the author of one of the these programs ( TagLog) , but with Free Software there is no advantage to me in whether you decide to use it, or some other package.

Free Software projects are often differentiated by different design goals, so programs which may seem to perform a similar function are not nescessarily in competition - for example Apache and thttpd both serve web pages, but one is targeted at flexibility and the other at small size. Thus while I describe things below as strengths or weaknesses for simplicity it would be more accurate to describe them as design goals and non-goals.

TagLog

My own program - keeps an electronic log of what you did, and allows you to analyse it in various ways.

Strengths

  • Combines pure time recording with keeping a diary
  • Portable across platforms (Unix/Linux and Windows)
  • Logs can be processed by other tools
  • Available in English and German - other languages can be added.

Weaknesses

  • The user interface take a bit of getting used to.
  • It uses more screen space than a pure task timer.
  • Not integrated with KDE,Gnome etc.
  • Need to install TCL/TK

GTimer

Gtimer is a task timer and report generator, with a Gnome interface.

Strengths

  • Smaller desk footprint than taglog
  • Integrated into the Gnome environment
  • Can time more than one task at a time.

Weaknesses

  • Only for Unix/Linux

TimeSleuth

TimeSleuth is a time tracking application for Linux PDAs, such as the Sharp Zaurus.

Web pages

There are a number of pages about Time Management scattered around the web, these are just a few of the ones I have encountered.

Project Management & Bug Tracking for Linux

Links to many Bug Tracking projects for Linux, and some Time Management projects.

Linuxlinks ProductivityTools Timers section

Links to a comprehensive list of timer programs available under Linux

Other links

The Myers & Briggs Foundation

The Myers-Briggs personality type indicator test lets you work out which of 16 personality types you are. All have their own strengths and weaknesses, and if you know what type of person you are it can help you to know where to look for time management problems.
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/changelog0000644000175000017500000006020013534701742014260 0ustar johnjohnChanges to taglog. Version 0.2.4 Bug fix in taglog_action - rewrite actin_setup_fields to not need to upvar an array element Version 0.2.3 File/Open now resizes to handle multiple decades better. Project/Add has the ability to record the amount of time you expect to spend working on the project before it is complete. Project/Edit can now edit additional details of a project by clicking on the project name "Reports/Total Time for a Project" now reports the total expected time. The displayed time format is now set via Preferences (patch from Kirill) Version 0.2.2 There is now a History button on the action edit display, which allows a shortcut to display of the history of that action. Delegated actions can be have Active-after set on them and they will automatically become active after that time. Fix a bug in setupAutoId when entering an action and no project had been set. Version 0.2.1 Fix install.tcl to handle the Debian install New report - Active Actions Review. The subroutine dateRangeToLogfileList has moved from taglog to taglog_util, and the end date - if automatically generated - is the time the function is run, not that start of that day. If the Expected-Time or Expected start or end dates are revised then the original Expected-Time is preserved as Original-Expected-Time etc, so that Expected-Time etc can be used as the current value for these. New routine doReviseAction with most of the logic from doRevise, but decoupled from the History window. In system mode install.tcl sets the library files to world readable. Version 0.2.0 The installer now creates the directory into which the activities file will be copied if it does not already exist. Skeleton Internationalization files for French and Dutch are installed, though they are not yet usable. A new routine handleMidnight is called at midnight if the program is still running to switch to a new log file. This is still experimental. Initial support for Subtasks - they can be added from Add or Edit an action via the Add Subtask option. Fix a bug where if Add/Edit log was used to create a file for new day the headers were incorrect. Fix a bug where Add/Edit removed headers from existing files. New tag.tcl function 'tag findval [] returns the index into taglist of the entry where field == value. New tag.tcl function 'tag find [] which is like tagfindval, but for arbitrary tests as per tag extract. New utility facility Actions/Extra.../Update All Subtasks, manually updates the Subtask field in all actions. The preferences item showtime_spreadoverheads is now a selection, rather than boolean. It can be (at present) off, byweek, byday If debug is enabled in the preferences file the command File/Debug is available. This creates a window into which TCL commands can be entered for debugging purposes. e.g. 'global debug; puts "debug is $debug"' or 'source ./mainwin.tcl' The activeactions internal list now contains an index into allact. The setactionsmenu procedure has moved from the main taglog file into taglog_action.tcl The active action selector now moves subtasks into submenus (one level only) The code to automatically generate Action Ids is now in setupActionId Find taglog_help_en.tag when in local system install case (bug report and patch from Greg Simpson. There is the start of support for spreading overheads by day rather than by week - this is not yet complete. Version 0.1.57 The today action reminders are now read in on a restart. Projects which have been closed can be archived. Version 0.1.56 The preferences file ~/.taglog is sourced early to permit it to be used to store the location of the library files. The libsdir variable is preserved in the preferences. Make openNewLogFile only write the logentries if dealing with today. Version 0.1.55 Fix bug whereby the initial header was not written to the daily log file under some circumstances. The log view results window can be resized. Incorporate patched version of install.tcl from Michael Schlenker, with user interface improvements Version 0.1.54 Add monthly and annual summaries. The annual summaries can also be edited from the Open... menu. Version 0.1.53 install.tcl puts the activities file into a system location for the system type installs. The Day Summary is only saved once if you exit multiple times in a day. Log file viewing can show only the summary of the selected days. Todays summary can be edited without exiting the program. reorganise fillpreventries so it does not read from file, which is now done by readlogentries. In tag.tcl setorreplace now takes an optional extra argument as an end label for updating muliline entries. Version 0.1.52 Implement an immutable flag for projects. Update FirstDayOfWeek to match ISO 8601 definition of a week. A new tutorial section covers projects in more depth. Version 0.1.51 New toplevel menu entry Reports/Active and pending actions - generates a todo list (short cut to doing Actions/View and selecting Active, Pending and Sort by Priority) The Actions View Save As uses tk_getSaveFile The 'Today actions' are automatically updated when an action is added or changes state Version 0.1.50 New procedure in tag.tcl tag_entryVal, returns the value of an entry. taglog_getList in taglog_util.tcl uses allproj (new internal format of the projects information), rather than projects (old format) taglog_action.tcl uses taglog_getList to get the active projects. Take unneeded referenced to projects out of logEdit.tcl, mainwin.tcl taglog_init.tcl taglog_report.tcl now uses allproj rather than projects global array. taglog_projects using allproj rather than projects in initProjTimes, setupProjMenu,isbreak,isoverhead etc. Version 0.1.49 Fix a couple of bugs when trying to save information which does not exist. Check action titles before saving, also check activitiesfile for existence. Improve the tutorial section on actions, and on working with other systems. Version 0.1.48 The default_save_timebookings_file can be specified as a global variable in the taglog config file. The timebookings_file_format can be overridden, to force crlf line termination (for example) There is a new tutorial secion dealing with working with other systems. The totals handling has been tidied up within the showTimeBookings procedure to fix a bug in reporting on multiple weeks (thanks Patrice) Add /usr/share/taglog to the locations searched for help files Version 0.1.47 Add /usr/share/taglog to the locations searched for the library files. Tidy up format of the TimeBookings SaveAs report, removing unwanted spaces. Make the default file type .csv for TimeBookings SaveAs Version 0.1.46 Patch from Giuseppe Barisan to store activity types in a seperate file (called activities). There is a Save As option on the Time Bookings report. It saves the bookings information as Comma Seperated Value format. Note that this feature is new and the format of the file it saves to may change a little depending on feedback from users. Version 0.1.45 Check for tcl versions <8.2 and use slower file parsing method and no binary search for help. Version 0.1.44 taglog has a 'package require Tk' so it can be wrapped with sdx install.tcl has a new -vfs argument which builds a taglog.vfs Actions can have a Summary, which can be updated to reflect its current status. The update can be done by editing the action from within the Action/View and right click edit system, or by editing from within the Action/History display and then clicking Revise. Today actions in mainwin created in display_today_actions, ready to make this more flexible Right click in Action in the central Actions bar to edit the current action. Version 0.1.43 The Project Progress Report defaults to all projects if no project is specified. Total Time for a project report shows breakdown by activity - patch from Giuseppe Barisan The Project Progress Report can save its report as HTML Version 0.1.42 The help facility now uses sorted help files and a binary search. The projects in the 'Projects View' display are sorted before display to make it easier to find a particular project. Version 0.1.41 Rewrite 'tag readfile' in tag.tcl. Hopefully faster and uses less memory. Version 0.1.40 Updated German translations from Alexander Spanke The default for the week that time bookings starts is a preferences item. (You can default to last week or this week) Version 0.1.39 In the weekly time bookings report an absense of entries for Saturday or Sunday is not reported as an error. In taglog_report the firstDayOfWeek calculation separated into its own routine, and fixes off by two weeks bug. dateformat_tcl is now saved in preferences in addition to dateformat_view The summary of the day is now read in when the file is read in, so if you exit and restart the summary is preserved. The current project is first selection in the actions/add Projects selections Incorportate updated German translations and mc patches from Alexander Spanke Version 0.1.38 In the logedit window the description area expands if the window is resized. In action input Active after is now labeled as a date, so can be picked from a calendar widget. In the logedit window the Rate can be edited. In the logedit window the stack info is preserved. Fix a bug in adding actions where the language was not set to English Version 0.1.37 In taglog_init can choose the Data directory root with tk_chooseDirectory if tclversion >= 8.3 Cancel the wm protcol WM_DELETE_WINDOW at the start of doquit New action status - Delegated and field - Delegated-to Increase the size of the Projects URL field in Preferences The defaults for whether overheads are spread or not is a preferences item, and now defaults to true. Improvements to the rounding of times in the Time Bookings report. The time bookings report is more robust against weeks with no bookable time Version 0.1.36 Catch errors with start procedures. Sanity checks on the number of today actions and window sizes in prefs tag.tcl has a new subcommand 'tag readbuf' - like 'tag readfile' but it reads from a buffer. Can get projects list from a web server over http (Projects/Update) Some minor updates to the help (in English) New users automatically get the preferences page. Windows users now store files under USERPROFILE directory by default Projects in the Project selection menu are sorted so that those flagged as Active appear first in the list. Version 0.1.35 The 'builders are here' release Fix a bug in the setup of start_procs where it was possible to set it to a blank, but non empty string, which stopped taglog starting. New package taglog_stack, which provides an actions and projects stack - you can push your current action onto it and return to it when you are done. Added some general time management hints under the main help section. Bugfix for finding the help files under ~/lib/taglog Version 0.1.34 Fix installation on Windows to drives other than C: (patch from Ron Fox) From Actions/Extras you can archive actions which were completed or aborted more than a month ago. Note that if you have actions from a version of taglog which did not add a Completed-date then you will have to add this yourself by hand. The archived actions are stored in the data directory root with a name based on the year and month) New tutorial section on Preferences. Version 0.1.33 The location of the preferences file can be read from the commmand line. (taglog -c prefsfile) The data files can be read and written in locations under the data directory root - for example on a network drive. The procedures which are run at startup can be modified via the preferences, allowing the program to start with the main window iconified and the Projects View window opened. Create the document directory on installation if it does not exist. Version 0.1.32 Fix week 8 problem (and document the convoluted code so I dont tidy it up again) Version 0.1.31 Fix project times total initialisation bug. Saveprefs if we found projects in them, makes sure they are in the projects.tag file Tidy up Edit projects window a little - anchor the breaks label to the left and the active label to the right Display the native name of the prefs file in the title of the Edit Preferences window. Use trace to highlight the current project in Projects/View. Help overviews for the main window items. Version 0.1.30 The previous entries window is now marked as disabled for user text input. New maintenance program sort_taghelp - sorts taghelp entries. Projects can now be flagged as Active, in which case they always appear in the Time Bookings (Projects/View) window. The current project is highlighted in the Projects/View window. You can switch active projects from the Projects/View window by clicking on the project labels. Version 0.1.29 Time Bookings reports can be mailed. Fix bug in Weekly Time Bookings report intialisation (stopped working in 2002) Add a large number of translation fixes from Alexander Spenke Version 0.1.28 Bugfix for unix system installed version to locate help files Bugfix for failing to create an action when contacts is empty. Bugfix for Projects/edit with no projects Projects are now read from projects.tag, rather than from preferences Bugfix for Edit of old logs - labels for times wrong when langauge was english. New field Default-as can be entered in contacts, but it does not do anything yet, it is a placeholder for a future release. Version 0.1.27 New files logEdit.tcl and taglog_widgets.tcl replace tkCal.tcl and calUtil.tcl logEdit.tcl from Alexander Spanke replaces 'File/Add old' entry with greatly improved editing system for old log entries. New Unix system installation option - see INSTALL All modules are now invoked as packages. The display setup has been moved from taglog to mainwin.tcl Incorporate the following changes from Alexander Spanke - translation continued (de.msg) - autocompletion of text in entry widgets which are associated with taglog lists (list of projects, activities ...) - two new variables GL_autoComCase and GL_autoComMsec in taglog_init.tcl control the behaviour of the autocompletion - function "menu_create" modified, autocompletion can automatically started within that function (uses function taglog_getList) - the entry widget for project in the main window resize automatically to the length of the largest project name - new function taglog_getList in taglog_util.tcl provides one of the taglog lists (list of projects, activities ...) - new function taglog_getMaxMembLen in taglog_util.tcl provides the length of the largest name in a taglog list Update install.tcl to aid debian packaging. Add a very brief manual page for taglog. Version 0.1.26 Line up the labels in the Actions input/edit window Change actionInputWindow to allow it to be called several times simultaneously. The selector for the time bookings report now indicates the range of dates which have been selected - patch by Alexander Spanke Active actions are displayed in priority order for tcl version 8 Patch from Alexander Spanke to fix the totals display formatting in the time bookings report under Windows Initial support for message catalogs for tcl >=8.2 - Translations welcomed ! Fix bug in selector for File/Open Complete and Abort from the End button enabled. Log entry Id now contains the seconds value as well as hhmm Action sequences - with Next-action and Abort-action fields. Version 0.1.25 This release is decicated to those who died in the terrorist actions of 11th September 2001. No cause is furthered by the taking of innocent lives. Projects are saved as a tagged accountproject type (but also saved to the preferences file). They are still read from preferences now. New calendar widgets, contributed by Alexander Spanke-Meppen allow dates to be selected more easily - click on the calendar icons. Minor fixes to the English help file, and an updated German help. Fix install.tcl bug which did not install German help. Take out all references to array unset for tcl8.2 compatibility. Fix bug in editing actions which caused multiple actions to be offered up for edit. Version 0.1.24 taghelp can take an additional argument and this will be substituted for $1 in the help description. Help/About is now done through the help system. German help translation provided by Alexander Spanke-Meppen Minor help file fixes. Fix Time Bookings report for hh:mm format (was doing hh:mm:ss) The 'Select Log Files...' display has each decade on a new line An Id prefix can be set in preferences and will be prepended to Auto action Ids The projects in the actions view selector can be all projects or only active projects The titles of the actions at the top of the display can be selected from the actions which are active at startup. New tag.tcl command sort - returns a tagged list in sorted order Selected actions in Actions/View can be sorted by Priority before display The Action drop down list in the middle menu bar is sorted by priority Version 0.1.23 Additional fields in Contacts for notes, organisation Separators in Contacts listing Edit contacts by right click after a listing. Preferences settings for the sizes of the history and current frame Preferences setting for number of reminder actions to display (Above changes to allow taglog to occupy less screen space) Fixed SMTP init for Win32 systems (was trying to find a username from the environment) smtp tag attachments are now named noname.tag by default or given a name with the -attachname switch to the smtp send command. taglog_report no longer uses 'array unset' for tcl3.2 compatibility taglog_util and taglog_project split from main taglog file Log file listings (from File Open..) can be saved as html Version 0.1.22 The action input menu is now scrollable, for use in systems with small displays. Edit an action by right click from the Action/View display A little bit of the help translated with the aid of babel.altavista.com Fix a bug in logfilename2date which swapped US and European date formats The weekly timebookings by project report will do several weeks Version 0.1.21 Incorporate many patches from Greg A. Woods The root directory (defaulting to ~/diary) is now a preferences item. The date input and display format is a preferences item. (Not used everywhere yet) View Contacts started You can mail an action to someone instead of adding it to your own actions file Projects/Edit is now scrollable. Delete projects within Projects/Edit implemented Actions/View selections for expected dates improved. Version 0.1.20 The 'End' button in the cnetre panel now allows a Contact name and/or a Rate (such as Overtime) to be associated with a log entry. Log file entries can be searched on Contacts and Activities. Version 0.1.19 Fix 'millenium bug' in Weekly Time bookings by project. It had hard- wired date calculation which only worked for Year 2000. Remove many warnings reported by Frink, the static TCL checker found at ftp://catless.ncl.ac.uk/pub/frink.tar.gz Version 0.1.18 Help information extended to more areas. Edit Preferences command in the File menu. The start of a facility to manage contacts, initially as a helper for the Email-status-to action field. Version 0.1.17 There is the start of a context sensitive help system, potentially in multiple langauges - translators welcomed. Fixed a bug which prevented the start time of the first entry of the day from being adjusted via the Start button Minor improvements to install.tcl - it may work for Windows now You can right click (button 3) on a log entry in the previous entries window to edit it. Version 0.1.16 Can add old log entries, currently aimed at 'blocking in' whole days of leave, or working off site. The new entry is always appended to the log file - it does not sort them into chronological order. Implement the active_after facility which allows actions to be activated automatically after a given date and time. Changed the handling of actions so they are not read in on every change (but now reside in memory) Version 0.1.15 Time bookings displayed by Project Code instead of, or as well as project name now implemented Implemented a first pass at the time by activity report. The install.tcl script works for the case of Unix user install Version 0.1.14 Action related routines now in taglog_action.tcl The action ID is now taken from the project title plus a serial number, giving more meaningful action IDs, e.g. This_Project.1 not taglog.20000926 Added the ability to clear the current action. Dont save the description of a log entry if it is empty. Rudimentary mail support (in smtp.tcl) New Action field - Email-status-to - when the status of an action changes this address is notified. Totals in the Time Bookings report are now displayed in bold Version 0.1.13 History of an action can be saved to a file The expected time and expected completion date of an action can be revised from the action history menu. New tag.tcl routine update - update an entry in a tagged file New tag.tcl routine setorreplace - replace an item in an entry if it exists, or add it as an new item. Version 0.1.12 New tag.tcl routine - readselected (combines readfile and extract) Install.tcl does a basic install for limited cases, with no selection. Initialisation routines now in taglog_init.tcl Dont output a tab on the end of report lines in the time bookings report Total time for a project report now picks up project start and end dates The basics of 'History of an action' now work. Version 0.1.11 Internal routines now operate in seconds rather than minutes The view old logs display has the date of the entries as seperators Bug fixes to the logfilename2date routine, thanks to Bruce Gingery Add a menu for easier selection of typical priority values when adding an action Add a menu for easier selection of typical Expected-time values when adding an action. Menu item to allow a Closed Action to be Reactivated. The abiltity to add notes to an action when it changes state Report procedures are now in taglog_report.tcl Started a project progress report routine. Can select actions to view by their expected start or completed dates Version 0.1.10 Allow Actions for viewing to be selected from more than one file Version 0.1.9 More information in the total time for a project report Actions state change selections now scroll Spread overheads across other bookable projects Version 0.1.8 Report on time bookings for a project. (still with a couple of rough edges) Minor tutorial updates Version 0.1.7 Ability to display time bookings in decimal days Formatting impovements to Time Bookings display. Projects have a start and end date, set in Projects/Add and Edit Fix bug in Projects/Edit where flags could only be set, now can be unset as well. Projects which are past their end date do not appear in the list for booking time to. Version 0.1.6 Projects edit works for all fuctions except delete Difficulty setting in actions/add is now a button to select possilbe values New Actions menu items to abort pending or active actions Bugfix - 0.1.4 changes had the test for a breaks project the wrong way round Version 0.1.5 New menu items Actions/Complete and Actions/Activate move actions from active to completed and pending to acitve respectively Version 0.1.4 Each element of the projects list is now a list, first eleement is name, then action index, bookas, overheads flag, breaks flag Menu entry (probably temporary) Actions/Refresh Active - refresh the active actions list. (still have to edit actions file outside the program Version 0.1.3 Ability to select actions by priority Book time to actions as well as projects Select which actions fields are diplayed Start of ability to edit projects (not yet working) Tutorial extended. Ability to select log entries which contain some string Right click on the 'Next' button gives a next action menu Can enter a Difficulty field in Actions/add Version 0.1.2 tutorial.html started. Version 0.1.1 Weekly report of time bookings works (for year 2000 at least) taglog-0.2.6/docs/stack4.png0000644000175000017500000001605313534701742014314 0ustar johnjohnPNG  IHDR)OɓIDATx=yR)8RHOvNr/*Ȃ *UE*^ #E* A"0 *v.,FMqm9osfA̝93/Ϟٙ~oW~翚: n~=m4!;u"^|)>.:1>>P ``Fbu}wG?畇~u>ѹO 0,||Ǐ=ꂮd@Ugv;G'xԌό@9FyU`>%sϻI>|C5 Z=tqq<;@9撗(&͛ߺuї_~+֭[ƟzrO%{>t/N+S7}JSYGCJ#'p`o;}7ߨ\u-Uwnvn{>Pu=_u·ǏN'Rgr_Y|wOgˀ[G:W}].^yc޽cu]~ NϞ9H,FxvBҧ)wNj2xBi? ͋/Ԕ4ϟ?wN/)zN%GwuVIH.?|sP`Q>fO#/*P~8ֽM]\w |'?3*'g* 'FN2  ksno4GvQoG޾}W~=ƅ=ll`\/GԹ5 \`အ4{ Ec|dLO g~1~3S}Tcpl3c\yY`⯿ڸ~ٳ;w8'~sܹ~~={?GHHoO{^_>}ϓ'OEOYiO%: T9 0 ]___P[73o|7aE 0 Ϲu29r?ϭ'8o=Sr#|_:09l6{  @~8RnS4o{c @m@m@m@m@m@m@mV+>:j,VP$vÈĒF/B\E% ZN71DV} # Fb#r,Yp]O%K]z4f?\3xy䒨ZX@-}K"cA&Rs^Ո e|S0+H"$8WYtp;4Eo᥮W;c\Fs>̈.vg3J\ yV3=>{r9}e ѵ]U^TfiE8Sh- Yx\um~E-odE0bH\7D'uۛw _x:y$5Or~*Yҋ(pFa$U/*cv]uHC}n]~_Uq 5Ӱwǽzjvn7zoUǵ|c̆@8Iل'm6EN:x`i@9D;]םN|0w(j#j#j#jsGB~v$rz=U(3aj+4r#{+y@ ߟ:YD"D߳,K©{{{_o.L8Kt]d"^D0_T"s>l|Rld0s>aDMcxo=UzuvMpvKyιqc97Չ1{xTs29/H=\2^_ק*]iD >Z5C' fis6uSLN}垈N: IX/ǔ~ޝ}?),$=`¦K_3\m rqS5]vĽ#Ni)X~danT9/rpvg2)>W#K  9弍ASQ+XvJGU6+8#Ͼ+I5yڝuV(FbkmzS;%#]s^OF^Ev/ ,ٝ#eYAScG\v𸊄M7:lb;Rs}Ig-L=;=a(LS"I9ox[$oĊҙ/1mpK6&NĊ+)0e,(ҍ~Nz']!FpvG:O#hmySFk)G)]68CAzi>&5(;ᔅhY 'i\B*FjH#g# d{t<wfQ>M 8'Ts[ׁrIx[]sJgP}j`W0 w9-\ ~S  kÇX܊>X]oĝ #"9bi^膒25}έDn =DV^!j署Cshz!z3*({|>Ҟi s (sn==Z=^*Z'ܓyKi8`vZ=Sv76Qdx;O%4~sJg%2&|'+{~ASOۍe]<~\qZɞ˹D,mJFQޟH:ack/V@SjKRC \7"o)KJ@{Rj? Ԟ=P謹)%30޹D2esOcCG=tpJH#Jgx=!@Q3>8S?0;Sdhj97@m@m@m@m@m@m@m@m@m@m@m@m@m@mw(\^^Vv%rw<3====Bp+o=q^WkZKp8LP#L?xv$O^.hu'cy5PY}@P(!Cb d7Ch85CN{TׇZ}N 4(=tzFCj(~<8%8{fg^\! gGHg^jfR5l6%p! >-d͸sZ>[X?fMj:rĶ!Ip1\ [ml?{EN&Zh%e~DPP[9juppWH^Jy t>˨z,ۤ"\V@PG5a<{v|HzgYN0&ͩf3j!r巰kVJ11傑# ,=>=N~(h{|:mQK&ـ,bŞƈ %F c=^j|201PZI`B\_W7韪a ]B^:M|eJjf }S ;jO}ڏGxu #wh:co5k7"n4J<ڵV3HGa%}/<f٫1KJ1[ 7afT.Byɉy2e=/ZX}01m\`rI __kTa\:miQ{~`mmduRvuW/nqnޥ.-wS[1SH4 ZA7L _!,O b=s3*{2v!Y4RM -;8?ɯ1wuң#&snSI= ΏŸV^ő|H\eI9\:JJ\hBF&/'n`pXITxl, L@m`U}#4a)6IG5x6IG5#LF [1pmJqi~?ImɼІh;LuI1ǘn9s9wsz: =s<1fX25f{~Vսr\ =\\)ן }[h+;==r8FY4 %A9x$Q@.-5V+_D>  Ns^ ``J*G6>]VAiϨ1&̬s6gP H$j#8'?G@;4*Bw@2:G:TzZH=վb;OCթ4;{)\"Hpu KS830vλ ;@fs؍滙-:?õ;UR1~,,SRB G5}@sb%Ã%!9DŽJ>MbTHl%^Xo^zs첇V!D~[^>zol~@@)eڟF \^{@΢䜉M^o?ԇ}_2 Ýl6EaH;WBH4HVʼne +SV>G-XgwRD=y;=J2D+8LS^jEj`HNUPcp+iwRV|v6q.vZǙL|kJDo[9ToY^ GrTcv`Covik솣jI )bFZt:nlmlO=Vz[%#P`dws1u91J]TS_ $]. 6Tf6*$\#wK.{`|>8t'ۃfvn=N0rNJ0,["z sOD^&2~M=6, ~/V-HߐccP{x497JH}oׄzJ !X@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m@m>,߳nkXwx<ʡ{.//+X9(SsBt$D`,*p ]{r]@ 1:= :=Dù q:=tܣ><=tzG7{ҍxrS gK;zhWWWsf-].ۯ`RGFFvqn: L5EIENDB`taglog-0.2.6/docs/screenshot-small.jpg0000644000175000017500000007225213534701742016405 0ustar johnjohnJFIFZ CREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222>" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?e+Kl2TcֵA0[qYG@x?t{MV9cIU 'j쿲4ߕ n98D}ۜ,\Y-LGB=H 'XMr3,%$"°Py1yc>Q>TXJ@nקfs#ݞsǸigZǗ#~Nѐ0rz?4ߕ ?4ߕ ,8xB!FF*\+2Tױ²Χ?ƽ'#M}_#M}_cͿ54jjs[k?4q_ozΑc%G")ti i)8ܮ< ??ƏMCnuٺE5֞ 3ķ&fYIft Ia gy5KI^C$sq?hX54jjs[k>сHD4h? ??ƏMCnwh?h? ??ƏMCnwh?h? ??ƏMCnzST.&lјIdi+X,y??ƏMCnzOF@_GF@_EǛjjs[kkOR/o~>))' N1=k~W(F?j _!w:t31G/onz}F3p%i&mAcdR00X'glt4ߕ ľӟb@Ư.k&ы)bIǵWWOa#2a|f- /((T ׭l5k˲RKx(_-`s9|QFx]V}6Z%ʮE2 l /@5{k"-Fc_?sp UԟE?JҼwecϭYIoe^o5wY2pr[oö!Lj/ƃtDcx-?) y /Ao[+NB.5\&VŻ[ƻB2cEwՕX|E=+W@o].AXB)$$Ra'G a}IV']eм;dms# D3TKwXdH*B;eV QE-XR ?ԟEeɡOZm,s#%&2੒ZW{yXd[®# D];'k`-XR ?ԟEutWY*j-g)00019#f#qE-XR ?ԟEv>`Q` ?ԟE']>X,q'G a}IWoF G a}IQ-XRQE-XR ?ԟEv>`Q`Gxɭ}-vU]۹٘X{jzuM=:[]R5 ˩͜PͷBPd{{eX#/cN}_$಼!X2{;^ܤ@.M>Қm6%O9WfWmf#PA>/ _i*Ir3ב^m?:)sh.fd opʆ \p l.-{&P-+Dn xz=j:C3:Ԧ39E(3힝kWFQ3\qyn7} hT q7@W73Gq0E>d .40KbkM-vdrqҗZV19:20%dV\|80y:o[qLH$4UP>qU՝neqrC u8W+8}--eC$s5ir`͟@MT[ t;K +ctYx Rs3qXxj}EKF,X4i"dr_B$O*%Q[Ĝk>[]=+{g1; mS;w:է\t^_ٷDSvs?{wlgn;g~lK]XMيάA>(CH'3Kgi$4āFJwc99He@ȗLUԌAG4fיcO41f3q|ֈ$?gϭ[ԟzGOH?Tϭ[ԟzGOH?TM6nԿ[ }/GA8/3R[O o"3R[O o"?'UzG"8_.RTcIQjibz䓀TQEiw5 AF9?oֿ݃Aj):{?VUχz]TUK TR41WlPq.̳ Eg(f9!NX df7BYdG$q-*T8<]UWɖ\yq|'~юNwxsMK{#e ]A4A"ȡ9egk-̖̊Op,C')VvJrg#9к_[JHR$ROgi:fn-+bxϙGG!א qOq(X&_*@2rdwV??#Gjw}Ew}E?3A]S?a ֫k_]k_]S??#Gjw}Ew}E?3A]S?a ֫k_]k_]S??#Gjw}Ew}E?3A]S?a ֫k_]k_]S??#Gjw}Ew}E?3A]S?<*Ə+3c Xs˃*_@ۿ/.ig@g=.*_*KU(`#K C+(aNTg8I珎_;=?d-LkT)kSA-u(9;iƓL$mŷV h3ϖf;ٝ亿j‘ܢgSku1&Yw=+?kSpJ@iH%vͶ"dY?ӴTorPyAcb\Ьu= kAs UMUfNGr$d5M"K۩5$y%eHw"A;*+ ɒ6(Y _yvʐo-+$kXa&gw&S+damI14 6;[_(&ќtlJצ9Q&`,1˜(K+r˼'ShIc lH`HN NʺE0ij #Adrq*])e4W6lc^ه?OZcs0Fbn/Zz6[)fUQ (Bk]A!)cJcVż\gYlR5d"tX]VFp18Nխ_"SE W_G?ɿ¨fi+fi+_G?ɿ¨fi+fi+_G?ɿ¨fi+fi+_G?ɿ¨fi+fi+_G?ɿ¨fi+fi+_G?ɿ¨fi+fi+_G?ɿ¨fi+fi+_JR݀X=+?3N}_0Z[[`̠.p-Q@|G{O>9i`ђPL=3SAOuO򖻺ҷ<P+3dr4fXeI3!d`0$pAЂ)g-E̒G!UT I8}< y%w\ 5Y>v;L |cp_.@- %,הj[P̈ct<?΋{u 0P@>i^Kr%i#"Q!i 2d#ZLExA3BRDzO.0pPU-Nm9_2?5Hj:PPdN9>m/Ak/@)LcLA=?ZZ*=2I<ZZ6?<ZZ6?<ZZ6?<ZZ6?<ZZf"70MFzt'K9O(LZvؿ&0[]aҩi7_kQKz$V#ʀ|2/u Sft~gi vH&r0F;~xx('ni)-yf,hŽVݷ VvbWPp%;e985NW{V&2  RقF9hXmJYte䙬 ᶒI >u>6saos+i%?ܺ\(>7 ˃4}2+nfk FpXG GU] >om[!v${dtlo |FK Ls$GyfU$u%$s8uY-*H {f3i#UUabŋ~^Hv8g4(űCɓ*o/ۍ JafRXY3n<q@4WKjwѳ2neb>=AႰʬ ǩ]6zSJe(@CGs>Xe@0K啌Z|"HK]0IRĶXC'5gI`y\! |@ k]j]6.xAuP&frdg^#jB+4kT 7 aө+sK'xTKUlmd?.\o6m>"mBv҅i^-!p‘ }*+˻֕E DI1#}qI[}+b*T`MтT `ۛx#%`̨ ?.˽C*mKx,$ZJ4mLrFGHd`on즌Dw-Z2#266c˽C(/}ǒ3\_ZmiKylUq!pʐZFˡ5ɪ +yGl!*ąd ʽTYjywE5qoXzYr6fIO0` D",R6n+[Tb(b* 0;eǙE|G{O=珎_;=?d=LkT)kSA-u(Z΢4PԌ~o-ݷ~-8pkokmQ/!bgTS*,x#A(A!6gqkSuGkO8&$1.@`rvE;(j:[Oe[K"?T^S޼yST6W&úխtmBkX`t@ Q,[c0R "xD}ʁJ[Hкwp'_>Ѣ?4G٧O|b(b(G'Mfy?k;SNSN O<4}ɬOA;/"OA;/"4~?i&?>?&PIv 1} 1rAV3+˅s<wLZvf/p9kLZvf/p9i:{?VUO 7hcIb%nH/d\h Q$܁PZxCpi^SDO#T`3hoUu&gfySy>~mSNc=څ&7 ri*B@y% ރ^k|LFXj.^ 9i`ђW|G{Og -wu|5SH?֕6qhyHK*($sN XnbVxe ѱ#ޥԬ"t:wtFLn TyC8uF{=ydF?,۴$&PH<=]4Z*E ]F '8_[O8W@&wXgm5`ԮmIw.Al,`܀ՇBvp+4F8R^@$oo.&F *lD&b 1\\qZΆypfB19s@y}?ry#{G7Q@O9Gi*?HMO@y}?ry#{G7Q@O9Gi*?HMO@y}?ry#{G7Q@O9Gi*?HMO@y㔢 yo?ɿ$h& H#!@ 1Tp #Lpxր93Fk?m3Fk?YQaj-L]B'QTر{P#MI9o|?c>cEAjM)P?rS r<{#B7^"[De2uHtw~IP (GEf`7W ibL|sjӿ@t{}mqwm߻zPKQ.f|pG6aVdVPC2MU d]qrɕv7X|;#O!I,6m&,D1)'M&; <7&W W=cwcc5EZliCbl˅>H$ 6n#E[xIx73 4`7'$Si]rA3,9dgi f Bf5?z]ɶ £hDܨc pNh{ٚy$$F2g]7pr9vs%׊Ep)eQK]0PېkVQWX4J]a2!' sWx#;q|JnfH췼~lbgtTX#f;.uZ-t.Yks#ʁbV[a"bnO nj70ir܅i_!DJP7Ic;[zLjIՠm6y[v$Ib]%1`7fU< EQo=ėSDRB*+d兼GS9wKO}؏b+oǙ~\VΧ4oCi<$Vbi!0} ' Q$g ēE_"ObvAqr:WWך\Pu#62Dv4lRBboiwH; :ѧ)6yavw۷p |JJ03O7'c7chcw͚mݚۏk$ h2ŏ8Bn’JXE:u0_I,P4{ e&"'T(瞔w&|-6k~W(53 f}R&*+.˽C(6k~W(ɰ _O/}< ?"a>+.˽C(6k~W*;{xc46«ywE1?6vOX@:g-[1sY*ƺ䁟Z3eW?$J+K?MZT\0i(\0i(\0i(((((jO%}{Wwz(&{N] Riwg yGeq -wuoyo?ITu M*Yi`P$PZC{qtIc GWCʧ:z;yִ. 7Uf%+gkgmFZ/_kPfުv JqEtK c7 n_?~mq`a>gX 2]ʻ "bIEU qxE2| kri8?tA==ё6# O>GI𮋡ܴ^ZW*A)8Q 9՞iCHG|{@ihA?-9K8#춸=G[hz Ga[ &HPr;F8@3S̟E'hz @ XY t"R F?]cLe{26^'PgX:rd?O/[(Ѳ?€?>}@/ Ѳ?/[(~}@/ ?O/[(Ѳ?€?>}@/ Ѳ?/[(~}@/ aD+ #0ߏTloOV+g ɖCO'OͿƏ1?~m51kzN?j؋??Z?oֿ݃Ajً??ZlΞՕ_?MZ5o%ZѤhQEQEQEQEQEQEQEQEQEQEQE|G{O=珎_;=?d=LkT)kSA-u+ωf-Aqʮk0GW!_tgnK8u2JƥQIaձ#c+⍧nCqveYI<Kwͽ >lo+a7cMr9>q?$`( 0QAǃPϤ7KhO)fϚTLX0z7 -LJ2t>X"2C/mb8KCM벮Gש -sbs9d~}AѴ6Rkˇr_(mq&}BL7>b`L hY8Y[\hquN(Ghυ_/O}_ Cz?Gޏ/??€/ Cz?T?ߕ ?ߕ 74y Pk~W(k~W(ޏ/75C/O}_/O}_ Cz?Gޏ/??€/ Cz?T?ߕ ?ߕ 74#'*Ãzk~W*X- x#67yh8PQEsg-ZӺ0߽r@Ny)KxYQ"RKkhXe]$@!ft~g&gd3n2U}=+N㵌L`$ǒŐ $ka,Q|Χ㯠4詶ш?|Z $9= 5 &)P2,-IECF?2U䕎'QSb?ƌA4RKw̳]ʅ'x 99'T_ښGa 4}V5+43 :_gz~QxUU:Ղ{lI,F /qSH?T5A?#UME2;2P;"mjM: 0T-A?#UL{Wwz+ߟU5 r;G#__%c>?ZkT)k+|lau _dZycݷ~-󎞕fIIeDi[da N=KMkqu=4vbp.O=k3iܶ HR3خKÜ }xX!tI>ʻC#emY7)fUi۸VjvZwUJ $[8+ϡF|Acqp@љ՘z'Md2Ԇ֛u[qREYAr?j*J#U'M?1='εvS 1cpO8:][Gҧ[(dn.LaH>c˽C(1}[ƂhcKk/6Fvb0rp Y{9DI&h) wL{{AQb! y4вgp 1G+Ԓ$S"t`xSza!H h.˽C*Gp4_vnxLqk*J gIraxl0yo˽C(1}Ȗqq/1b5bۜO G )eݢqHH-tRΤU$.˽C)\Y* #;eu=#ޟXTM]/G{AQXTMhuIb!ywEhuIXTM]/VJȐ$f*Ii[?kϨY٨Q}@hA@P?$E3VuR;'x[y |IQr*9X}I sH1jU=i8# gMSm9y̺]I"  2>X.u8&5QᕑpOYTC9Ю{&zz_7|-ZoZߕ m./7,4H7o'Vс ֏Th/nJFJ+ dQrX--wߍZ:gZ vʹ0rA4:b8AUN同ds%MfPВ?&k.\:!fB`hcsW{+KW]x zs@M֍ (nl87r$`:쵡gcI^>;NuHI"'-RH?vz;|-zwZߕ ŗMկ䁣%gK{+Cڎ %K1Z> MS}܁?v f(c(ʗ7a6Aq.s(R~4gNuR;kyX`DLl618mAkח34DmmU @߻J1/Əƀ0--CO?ZkT)k+|lau2()2_In͋ՐgnQ9Ih+ܲ6 [ݐ*0 IW$}_R9 wlRyR waPP4{$ӡ"bCq̻pۃ GAxLuo=?n8 7gʃ(95Cy D|U9DwNFU!U=;m="{B5\?ϿSkz; P'i|@js^b(];;) t47Rd֤2CqoX) F0 rQ jXGYa≒{ɭarL3syG{ڈ텹዇߿!#9.h7>';B O{k:V`J Y$1*ϰcm˜|ƗO^TEٜ7uzӷZm>pĠP?߭եw%FI1#4epϩ5߭ը/ЈY('cO[>=2YXۅb4;bTA Wq4[^;hT :cֱ#*O]ghhM3\D"x _n7زnI;ݜgzr |,[jO1!k\;\*['ssذ`9R[ҼSN&fjxQ$x_N3OqijM:<9qf1Вr`_ؿJXPZX[\jw)&HB~5;yp)cc-,o,% I$iU:PaGgk+}QêCqs 9#WR2!VDY|G7;aYEhwÞ09Sxb ;6[UF:0;:FJY`. m>%ޱIPY^['w5'}b5|7bbnʍJN71ďvC_ؿ>PSQ@W/*%.vr{ެQ@~7n憎>7n憎EE.c*w}6בP} K]v ?"v}Oj?_uO򖻺>?ZJ8X]JZΡ}Ig)lg3ôޛy}wke,qZؖz2Dۇ%XMu4Vgqŷk-h%"8>dm e8*c`FyZZt{;km0$݆ *8 ;x"HB"UP0(OXkPV\XwUw r'B/OA7Oѫ7bPp~Oc>_,"M+"E[((((((( '?Σ'?ΣLZvf/p9kLZvf/p9i:{?VTO 7iVsIkFQEQEQEQEQEQEQEQEQEQEQEէǴ!Yi/u?R? -wu|5SH?ֵ6qeQYEP]L컠]tL#$䊩As{nFeV,B i>bZ"3ד"0vkin1q$4:=2TGXP2 dqVt XJ"ˁ?UJZQZUJ0=(AkGAkV0=( :g?:g?XҀ+hhcҌJZQZUJ0=(AkGAkV0=( :g?:g?X>byt,H锧%sg-[1sXg-[1sMIkF?MZ4(((((((((((=#= =OHiB1kT)kSA-uԥy^om߱Kc<8o6s̷\d-71&}'%JM W0Iʅ7VR0A:l4J6["Q'o?g_juO).DR_,%tN{6 SJD}:H{KvcbpT1ٴ 0<>6q9|%:,JVAppTz~u$>9 iG!uuC89Njar<\'u۸ąYvǻs io@z-6i4}.y4>2Y˿ 7[ʁT##Ɯ[O0h%_5y>k3AS#6Hvs:[Q{V[9fXN 6&@D`aT{iGWg& 3zλ*֫Ǘ'4S kfe%SH^<%i0h$&Iˤe*!v8Gĭ99D),mf.(댑m6k8ѳHa X~G4ŰV$]TILUXxWVzftKimSW^\j5մgXlm봱#8<)'w|Q)'w|P*اGا@W:AjݬM615.OSnkn3`{VSfFIH;[o66Yu"@ՁS+]\~ilgzHaES(7P[Y&H1:'kp59 w.XnIyjݴg/2&h6&.NV7574Ӯ */[v\v97vr?e,Sj#:"o'h75=ǵIy猟ɣ?Qڌ{Pgx|WGKtNv=( m??PGO2O8bhxQ@kny֭ҿi~ V6gOg>9i`ђW|G{OS?Zԭ&L&6=v.>e7ķ[xk֋%kvܫ( ?19&67`~mv3_8>gʦ!s5{rO&{u5-?g%a(? ?Etde>ڶXGv@'Rbܱ]G_Y?Sa(? ?E~?F6l&;k;i?+G-?g%a(ɭ ;^y,MdkZ~3JQ OX?k2=>W$|x$2\t1ҠӸssPٿ3V"̿h$>lX!t!X6$㧥S)9?,?i?+G-?g%a(ɭ J 2o+ڗRLj3V"̿h-;n&igD@T)c?ޫ_dkZ~3JQ OX?k2=>׷w_ 'GY?3V"̿ho<O&q? ?EgA"/#{u4k;i?+]g|]zk,pۦݲFqh '𨩖T9IYz){Y??jBKSg㖆{Y%Ia@2A{q郑k!{NIm ;v';YP'+A?UtVpt*H5f/p9k>{o=ۈ#Xđ$A(Dhx,c-CV*~'IVk9?$JHaEPEPEP7M7'Woos@Rtմ-CM&H<›RFqzUsUty.!V IHUU`ʢžWĺggXAIg]AE8;z,jvk⫭RȂ 28dTNN9tiՃIc` Gڳ5I#.Qu3Bഡ ݶ,A|#B4 _(?+G _Eߢi>,A|#B4 _(?+G _Eߢi>,A|#B4 _(?+G _Eߢi>,A|#B4 _(?+G _Eߢi>,A|#B4 _(?+H| _AE'9  ~?_G WDh3} H$O*ϙ[t~vdu _y\rֶ+|naA . E\M]i ieD`*zyrzg}GO=G5?l@hߔ$6Eh8"X|huZ+f7?ߔ_V( (@[ :VH]O]?۟quvҭZo'x#aI;C٢ l|G{O=珎_;=?d>) ((((((((((((vk<32? :m_Hu;khen FOǽn':wE^c7J,:Cyc^T(/,[D2*[^5 Ԯ>'Eyq]_Vsڭ39?G'>?'+ȸJ>[Wgs"N|7?2~OWqG}Z=j]'Eo~d"Ҏ=({o_ φO?9?^EǥzQhʿ=w ̟s"J8U~?z'>?'('EyqGգ?*N|7?2~OQ φO.=(ҏGmVUo~d ̟\zQǥVpڭ39?G'>?'+ȸJ>[Wgs"N|7?2~OWqG}Z=j]'Eo~d"Ҏ=({o_9#m.=Q񿊱IO^(nmcg.{az0qGգsY~?taglog-0.2.6/docs/tutorial_with_others.html0000644000175000017500000001230413534701742017560 0ustar johnjohn Taglog tutorial - Working with other systems

Taglog tutorial - working with other systems

Although taglog is primarily focussed on time management for an individual it has some features which help it to work with other systesm. These features require some setup outside of taglog so if you are working purely standalone you can skip this section.

Saving Time Bookings for import to another program

You can save the output of the weekly time bookings as a Comma Separated Value file. This can be used to automate entry into a corporate time recording system, but the exact details will depend on the requirements of your corporate system.

To save the to a file select Reports/Weekly time bookings by project from the main menu and set the week you want to report for.

Select Save As... from the report display. You will be prompted for the file name to use to save the displayed times as a CSV file.

File Format

The file is saved as a line containing the dates for which the report has been generated, comma seperated with an initial leading comma. The dates are expressed as Day/Month.

This is followed by as many lines as there are projects, starting with a project booking code and then the times spent on that project on each day of that week, all separated by commas.

Advanced facilities

There are some advanced facilities which can be set by manually editing your taglog configuration file (~/.taglog on Unix or taglog.cfg on Windows). You can edit this file with an editor and make changes in the section after the line which says
# above this line is automatically saved - put your changes below here
Even if you do know know the TCL language in which taglog is written it is fairly simple to follow the syntax of the lines above the marker, which are set by the File/Preferences menu entry.

Default Timebookings Save File

You can save the default file for the SaveAs operation by putting lines into your taglog configuration file which read
global default_save_timebookings_file
set default_save_timebookings_file "some filename"

You will still be prompted to confirm the filename.

Timebookings File Format

Unix and Windows have different ways to indicate the end of a line of text. If you are running taglog on a Unix or Linux system and saving your Timebookings CSV file to a network drive on a Windows shared drive where it will be read by an application expecting a Windows text file, or you are running taglog on a Windows PC to a network drive where the CSV file will be read by a Unix application you may need to change the file format.

If you are saving to the same kind of system as the one where the file will be read (or you have a flexible program reading the files) then you do not need to set this, but if you do then put the approporiate lines in your taglog configuration:

Saving in Windows format

global timebookings_file_format
set timebookings_file_format crlf
Saving in Unix or Linux format

global timebookings_file_format
set timebookings_file_format lf

Updating Projects information over HTTP

If your organization has a web server which can deliver a list of the currently available project names and booking codes then you can set up a URL in the Projects URL field in preferences.

Once this is enabled you can update your current list of available projects via the Projects/Update menu entry.

Note that this URL could be something like

http://projects.example.com/projects-list.php?jl
to deliver only the projects relevant to a particular person.

Setting up the Projects information server

This section is under construction. The Projects information server should deliver the projects which are valid for the particular user (or possibly just the same set of projects to everybody) in the tagged format described in https://johnlines.github.io/tag-types/ for example it should look like
Tag-accountproj-version: 1.0
End:

Name: breaks
NextActionId: 1
Code:
Flags: Breaks
Flags: Active
StartDate: 2002-12-11
End:
Name: general admin
NextActionId: 1
Code:
Flags: Overheads
Flags: Active
StartDate: 2002-12-11
End:
Name: Major Project1 
NextActionId: 1
Code: MP1
StartDate: 2002-12-11
End:
and so on.

Taglog will detect a project being removed from the active projects list downloaded here and will set the EndDate of such projects to todays date.


Next More about Projects Contents
Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/taglog.fr.html0000644000175000017500000000212713534701742015163 0ustar johnjohn Taglog

Taglog - Systme personnel de gestion du temps

Taglog est conu pour n'importe qui qui dpense la majeure partie de leur jour se reposant un ordinateur, travaillant sur de divers projets. Vous pouvez faire des notes au sujet de ce que vous faites, car vous allez le long, les associant aux projets que vous travaillez dessus. la fin de la semaine vous pouvez produire un rapport de la faon dont votre temps a t pass, dcompos par le projet pour la rservation. Vous pouvez regarder les entres prcdentes, la date, ou par le projet. Vous pouvez crire les actions que vous avez l'intention de prendre, les associer un projet, et les marquer comme actives, ou accomplir.

Taglog est logiciel libre et libr en vertu du permis public de GNU.


Taglog home page (English)

Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/docs/stack1.png0000644000175000017500000004566213534701742014321 0ustar johnjohnPNG  IHDR)OɓgAMA a IDATxyd]VkoR/Z]laóg03`p4b0 Ah M<{n~0̀mK̓?'|Ї>D}YE9uԩSzh£V~];:}?C]ZE;{{uS6TZ[<"Q=s?YG ޳6$Z>|[gϞ]Çwޓ{>tY:㮣-ZfDD~ȨzSHN)#67ҳ}~Vz+cժÇk/{N殣l "j]]?Dw,/Ѳ~W?]wntYBuV"gg6.67uP^7뭮E8|%woܻw NsC\:lOIWoͣ>?|W,>=NTxz_EHSK!V-`n6wէsvJyW@U:glqbƀ]t sK:zkyW;w_=E.uWg*6]jԇP ^+8"\l`p"5xc]ou/h+Y?+ijfY)63xrmFW|Quo>Ͽ-oٞ<Ee~x]G[.ijҌ.z| @EҹscËˏ]i+)>:|ӟ+Oݮ]S]zN6.$k!mVu=/gʈ8p l`cN~ۗ!W}n y8+%ao!@&l`pFQжFu87j{;{C9qD\UKa;,-6'OvtU\[>}k`@{ ha0l= 1333=9sF:s& jWdߟ1oŕwvK yצ='ΏpoX%]B{XtS7ųNSfλ$j rCm3J#Ya7}]|*/Yl4޳[O['ou}s/A{jKoe ܀>wkl`|}ͯ+]J;v ]cG҉ r(| /ڳ:/wn I\=䪷DGE_՚:_iT]`Y0K><7&~5ˏTq}H]l5qϟ?qĩSN:xOOj;+qEybv 8ѿ$&X0usM݆!okwȵ;r࿿!"ټ5 ha0l=M=: "힓'On8{fgg?]C9uTxaUرc=v,=D 5 |nN <v$lpeo= l>7u F {6N9|au,\@{6NmzW%sw5[sL@_%$ڦٸx z*Y|#H|`@=F3+xPF'nڳ = RWj ; 6:R2[}Y. p-6V{vXc0"@{v ۮ`vvvK0l= AgWjSgp;d`@x Ƿ{{ ha3ַJibXDp g)SV̙35=r1XntJԙ3g@w5vݳtR(GfTV: p glD!z \@{6^ <khϦ\ fffN <k{JO5B`rYEA+1 66:R2[}O}`6` ޳#Qv.k,Fhnsn` =f=cn9}::~8uGFMd vFq` k=`X[yn)LLaE`Xg-Q>MZj`A[vπZmb[D?ltRĄvj5=F`@{ ha0l= 6`@{ ha0l= 6`@{ ha0l= 6`@{ ha0l= 6`@{ ha0l= 6`@{ hayCÊvɓ'9vLJ<sر!mvvvVP_Ls Tu|s~릟`#=0}l:k{` kL=6@ڣZ`RS` oCZ!""f"ʷ{z@fb&E`T{7zrɵw,DdijL@"2DȘg+.v kXCMO2JQe"ڎCexhGiʮdX$$ 9Ɛ188TLD Y=kLO6xx'2\xLҔD,kIDn됨Ha13s~:""BcO5q4%\`ҔTZ- CcU " CjAy?yB.9TueAӖc-9qo.q]WTT"N# v1kg͢Ul$!kpee1EG% ZE8rIW FD.!"i?WmwET`\W\|J% }  \l\fC#GƐJ[rMr[{~itecmZKQK걒$h?ͦDZ /rW=TeCvO!N/ =З!"v]<}}.PFRs1LĞGA88Ze 1?3[t`L )dHkI&MsMKNRIQJJ%ͦjI!hPJ>S&'93"ʲ\`TϘMLЗ̹v|0 rZֲz<}+*9r1yyoDj\rPC[qI4lol*g9jsd)J844$hQqFKSC CCCj66aHVcn&bҔԦ)YӔ5zG\DXEqqzhLISHn{ϣ jU*TZrYkwn6~4m#CCɓ۟ze,K$d<E$e1fS5&8$ᢽFwj3NO"y_0yrVT3uYL<͘\SےR&škT*R.S*ڒU*z=s;r\*DA@*Bۛ0|C6fk{@'i<ȊJNM^e$ %I(qaHidhV+7qډNeLGa-űbLZ]j R U4D8*l)kuՂa"b RIJ%*\Z*)Rryse|O$u:NymgݰusU=Y+vw3Ohe)rKg@ϼwU!4,\g3=u((Mfo՞a!""R󈈺 &"sk4HS*^S*[灝ii'] 9Di庬e$ž'{8J=T.K4uR橧8r%R)s4M=Îc![ Q߇QU[?r]QQk&Iu%2QT$uZ3mYnjX@SX˫CDKYcr\W'{:"ctz / &^;ҁhcW S֞bQRLm"E,"6F.]J=9s&[\t) ׾26&K*ccé3jQ=Y+pw3~v'ȥv08Fڢšjz DGUJ[FQ4bjNѩ<$jsVi""f}+:N8q8fIkȱ^*yX:0=ѕx)+A dc?UꥷEGa<qsϥss.A`~ZdlL&&drR&'MG\"!na^" TK,VS,mjmʭ֙/_DŽ!OμnF`D1 ߯ͥW=tٳ=6CDqi9xqLQ$IrUEbZk7}H.WqUqJ 3g]XE~ZZNO,.ԔkJ\I$fnN  oQ˿GDyH0 IVm7_?ߞߜBra~mNXpDX؆aI$MsTeĿ29)SS26Ǜ"ousWt~gΜэbCu뤝=uܓYzn:W>;ߊ>C]_ 1D7(0y穧xqIH 9YFD7c>zY斌]ms=(#ZMSj4YSłe *RRJts嗗xvXK"?wK w/'Hd6˘xc޸mnf3ϡ(B\"O_:Dox+(Ir l5yLwjӲu01, d̹f[Ο)Y\7/||?e!zCaLw ֕#絬uܓ;ɻU#fah^~9;^d~^fZ-ߙxFDYÜDs]9rD<9rvm}b5u8^"{uQDDo"L~_~$==Q׏g~'=ߺ~e6D%:O/B=wO=""2c-!dqD–ߓ,8j˛m}QX̵v}-Xl rJW,͍7Yeϟ7sk68:IbK"%fKT+z|%#{4ݫ(Jq޽f^bf-[;NDxvmo~yG>$"D{[o~aKtm1R;G~3Y2'>=GLfMuZRwRZ-ֺAY-,ix!w{M7(/(4< 5Ɯ=+T՘_w-!Q`b=s7 Vu95)ԡ]ݞ; $!W=N0q"y~j^.].5(&xRG1uDM!ʈZqx 9B*Rw#sg"!wS$S}srYO~pæ # ~Hvvۥd\ ~Q&,&/.V/\/l\0ӷ/LPdCi"Uw]waa!!Jjڕz=QZL:||ێħ>"JR.?fmC=KNl|h8M;?3ܢvWk:\(D~kN`,Mhy ù0ttr>Cl48N"9[ʐ=GĀW7`BA{Z5D:oO^\ {x=0D&lj̾Ͼb$o}k T*NS$"7wt,+^AEvhB% c2X׌NEo]N!"׍H5OijNk`*Qĺ]Cmrႛ$GnY<>ZsO=upr(Yi:̋vc/,z]3?[hbJuܓe3C6-@cz񏞾͞#ٝI;٬3(%3]ߣc' kѣM7'>Gر=i?#yٟuםyZ{NMĄjRJBI- #D(fj-k_KA@Z?ZIE뮳o78?5ue{Ϋ^57==?5e/Y+ccUii/.e K/^0?oΞsxǘ9 Ûp T IDAT sXf}/_AW7Sǡr+c)3cC:߳Zqx'Dx&<rʯ}nD~zsֶDuY$9z[o~KUԶL`x瞮:c=Y[IVȖo$JEI81d=tș.Z๹m<s|$YDQdIBDSA@/<[n0w|Ek_/Ϥ^JG}+_^}iu-|,? u\`wwFIOW=]^ϱr:]K85㥬B{RIj5޽S?%jVh~7l$kl|ϳKɃ2#ĜYs?UBzzU8u mIZ2{Ξ=Qdo+| /.r!9'IP*޼$!"b><9)ss$&M]'ۗ_,,#kI[a\5s{#>606rȺG\d9 :HoU 7"JRLVej8`u"T*yxFC5׊nDC5jӨh[_"s)Rҩ=6 0Y&nU*#Gxly|'&xnyqD +h֢֔KNSe&l,EqcZ  n(¥T*KQ/_V,WTxɁ2>.cc?k .)$g.yɮkC2ONFRev.R19FMRHП$,"Cd5jX\纬fI08똦N89y^j {^Q:g$b_%48ɲ8T.K,muHJ%& 'a(ͦ4jrEhhmC- բ(r53){s{y+4W9B>n~WoD+%4h.m^dd mSYJb!vL,aȭW,}qp̵Zݫ1}wޖ̐OUcĥZ |GU~8 Cg ((,$/"BDqRc,^. ,.n$س<mC>f1STV1)qpj%?*,Qs#-;_LtG&`8GSd`.y^^Ε9/V$hLJle'0(rfr TR ȗێ1k#JGT!be^*lrڣHT RG߂3 #ZMm\-3~TcnV'.G'xVߗp{FV;F E8M)MHVXzjv(\D:Y2NSc"ʃ:KACN8d ktGGCt=4F`dp Q)|5DXߧ ߿jE80".ͬ (p\Dz:yI!MAߣ'633u0lv!ڵd_:D*<,"VT sOSN_A9oKvL;ˀv<CY&ǗGz Fk\3kkP!4}:Uҗg{D}1yw~'YX\,i,.^?t Q  c6H,_y!c\|]W/s]9sSu 62c'>&/}DR8˪ccż5,W( uD5I(3uC~53Z?G 1)QBTTu3N$2\+% ZE:svfXFXy/wqǦ9D:}GvMg2nFYf1]W򜦒,<`0ᡫC;V 5E"Ӕ%r)\fҔG&eYR_&蒦{#qDJbee1hP΋RsF'A6_v_ė/"IL/GjھOGGCMTOglLZOjB&X$I5?|O4ƚjR u2M]WX :}]HtͨD7?s|_:GYkI$LM={dzZHݤ:_ #q,JTq+O?]EFryI"enQJqAz^yZDZ#̢"DN<9M8cC^X9\xZ|BIH&Ӳg+{ؘa{`dhU-߷ڡC|7N9̞H<8yR.Ąj21!ccRJBA A@A@+-cvvCm9Q'z=O.8wΜ;gΝ˅'2?].ݳG$UR.SD\r9}h("kU~(M5#"k\rT{d|'~"uQ*EDYJ$D: Qyhy19l!댹Θq5Dq,+Wg}=o%X'NnZ܂@җ&⸚e%OZǒ$ljt'<AQt0c[K|?oyXDZmG ݋Nqa٬cc JZ^f,~<5>LLLONLN wL,p=tt%^*0dzYQ?c-[봫,#|g̙$W7;ԥKAJv8fqt ԁVi^aXi4*FuqqlaXn60IS":NyQ4kX}lYr}l;w}wX" $#jI׾5Y>/]VX☙GKXK"87s÷|jKUVT"yKU^t.kpk)8 _.:1DdҞ=CuɁyAP l;=+DĎCATab_O"8hau'yOSu܎>i61c癧ZM*'i|RrYK%B/HPxo69iJiaӬ9s<_ȗ.bNMԕQ-믷]'T*y^ u3cTX+[f}*e(4MKe SfML`dMKR.K[v1cc\}qMZ(e"$dL& 5l>áH.x@LJ?|Rq*AA %i+jZi"b~ݭ~_υs=L3g,-/v6x*)uXk՟9?F'^—/+Wx~M\Ș\xgӤܱ[5X~/i݄a-,iCn,SSyTj]DZ.0߷ujq"2"FY6w+UEyYMq3ϐCA^uU\]DYԉ$2 DI1i_9A|hqI7|.×.rp jqQnBx/SS2>ۑCX+W@QDR.xJffdqWΟȋ:ѤZeixC_cf6yG.=njG?Z{#A?P$&E_RIuZfg̝?@_sM/?LhR㼼0W|}OoؘJy^Csu}k>Wy7կKDî+A/m6|;}-,v(/,8f3k6 DDiD[Q[ytisω۷\W{C{ _O'~QK/^B tu`O<&η׾_|w<cx*ly)8fv6w1vgvV|@e TsL2sN+S&$!@78s:\"JScN3s0Ɯ;w>w&ca{1jQaXee!׍$(R<7w\*]B{5굯(?;6`C{r_*R&Dw??<[&Z\ye~jNOLq\0V\}G;]fK\x5{1ϼ9{Vnj1>Gq4͘[<S*uP,岦q_g _DA@;ssWnkC'u ë͹+ߍ6LNQ1+$l^fs"Zٳnj1<3cy5y~1| g% KDYFA ;l^xCr/S.bjo÷\ ;~Oc33D4{TuT8nUqڃѐiZ ϲ~:^\|_핯|pay$4\\VUQh\,Ɛ`6/LԎQcٳ_yo TJEen2ƼAu)0glbb6DzӱWw*/d/3_QDax矧z],nvgfǜ=/9lNjl OJK8 {<#G}wykum<Ƴ܃|;%A2P;=ӧ/8 ;}ղ"OZƽ{07S>x'Do08&k+ZXZ.%4M$%(y/Q4\%R3g"KÇDs||_J%>O}g~?s!QKm~#\.(Q'^*!2̏?x~??X#2]wSO}?G؎g6慯~ȁϟ, SZ]h6SV~O?ȗ??ӿZ$.Gx 8 кwvnBIU:݀FOq.:5>w*IlLD"2;;{ԩ'NjǏ*=!O~$!J=c?8~z W5hpEy26G$gw١mr])f9>U*jPk:hC7>H?*`y'ڛN5FgpIQASau[-M@K$$ynށ,#kU25LOԔqV_7>W$ +P9TMĉ'N8uԩS{`&wݧO.RI9omV3Çמשz i69 % Y#@Y?ZyyE\IT>8s`]IT >i(^8ses[䶵:hiT:rݟ:hp[u ɡ0(ʅ'MYu+M5y̢+^Q&vzZerR&'ebBߒJYn~9ǹ$b{}ЫjM/(gLQ6NΚYFYƺRd ,1NU+JGTƴFkvRC.<%hlLebB&&ETu4`'#j4!{UAq""3wDL1(˾?w1},/N%!^"h)E[,˝cE嶊3YF&BÎkxR󭿵7[e vIN:edf"\&"2"}D7wʲ7-v-YTz]e4ejWQs/qRkSu%ǚN0:Ja܁BZ.Rj3uu;՞v(hpR!#<"CY6gLL\Tt8~W*sy :Z3E>= I8f]8qr桩qUXc9uWYK?MTQUV$Vˍ7v8[=v/IDZm"фpV)> r&Tc4 ZG:+!fb s \?iO h]\[orV\Z-IJftV5Ʊ---E5 MDD\e@)MelT)U۶NCEb,[*9"y9R$XKSI;*%F='E&b(2`wUӳ#P)ryIʢMښDDj~4%kE$O2!0̳T_ЙFEBih8O p<2S84A.Tu`WU3e+_ަN-/H'{T4NE$7DTH-'.]\OMڛƁ4Q"5F۪S- YQ I8tO1Ht6kJOzu3:Y[6E=l8`ev(T,P^hYF"ywa BS ggiOVd(H}tE!8&Z_J βoկXrZkT*ģm,NnO'f7UBOBu?g{Luv +`\SS{>d{ƓVj9 i;{|ga賫+P;_7ctxx-WlSnD}[>{%H ?= A !4ߥ3.a 6 Oy"}'tPqvOWUAayȧsRŞ"F˻g\,;J;?:\ wv<[c/Wm-hZϾήs\  o=kI_;FkT=3m:l>[d'_zJ6-ҿ`llv[n@xtynP]l/ 5C`1D7#j6% `،EW:%|.>}z#]oh|w(4s _.d#±50l=  SN!`q^n&IENDB`taglog-0.2.6/docs/screenshot.jpg0000644000175000017500000030723113534701742015275 0ustar johnjohnJFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?ѿ;Bŵ^DźIs^{wO!]/Zn%N9ukUqzuf4{]YIOƤeٟgW }%k=gKY.\|+'nի{}{R'c-HFp2z՝29lirҰAO~x;j_/6g}3Smms9AoÓVfl#(I8{tEes>r#}f21q@jRX qS}e[;`3 jM:[d9v+؃ۭl]k6r4obkA3ڀ0Q]陎$u)YYJ+gG ,w6*۴%[i'Er# q=R]nI[x{+1{ ɬ#1(dcz {I,#;:~nP`HF$Np{d{rϬ~yLs>Pis[kvZ]ʧPFHj es8 mBXQfSw??Ə=CU-is[h?Z(??Ə=CU-is[h?Z(??Ə=CU-is[h?Z(??Ə=CU-is[h?Z(??Ə=CU-is[h?Z(??Ə=CU-is[h?Z(??Ə=CU-is[h?Z(??Ə=CU-is[h?Z(??Ə=CU-is[k{Ѿow-TEsrErxZhuTL 3}h_65 EbuokwǤZAq +(s47z0j>l׆]y98G}m䉞NȠ;w@ Tv64K(UP2I$pkA+xmo5f,n#1YX({W\f?XC]V…d g杦M|VeCz0"<RM_Uq2y( x851Gi\éLIs3 #v)U<0O41x橧YY#Ycդ1叽Ԟ|Ms=d=^Ăqg)xy/$pzth犿xsn?a5/Lq?::#N滓PG!9̟G#GL5}t{?xg{[v] $[4b6=Ϯ?g- o"$ԫ.N9=&_G<9@iWGWM()"@Ac9Ss l$.rmqp;tmVu-$HxA mBpi+^V8MG?2r賕h)r =sjPYi&+%]mxmD˷[?fOch?qEu9o<^?2xs3'`W9̟G#GL4X,yu?xs3'?2 ]Ez#GL49̟EǗQ^?2xs3'`W9̟G#GL4X,yu?xs3'?2 ]Ez#GL49̟EǗQ^?2xs3'`W9̟G#GL4X,yu?xs3'?2 ]Ez#GL49̟EǗQ^?2xs3'`W9̟G#GL4X,yu?xs3'?2 ]Ez#GL49̟EǗQ^?2xs3'`W9̟G#GL4X,yu?xs3'?2 ]Ez#GL49̟EǗQ^?2xs3'`xNDPyQ,~:?fOn|#KwZS;3`Wm}}o?cק;zun:F%&Ì~l_3G N4zg k(\աRʀf~VvoNB8`@$uЧc/. O-cvGr*_P:HpSp*g%IrXiMm[FdBIJV(Q;Чcd ER< e]r#NxA|膢YxY" ƏEoȯ5Ec-ϟEm|+lQ@h_h[F?[P?"7W?ѿ">ƏEoȯ5X-[o+4z}"1VF m|+h_kuo>Ԡt-؞As$98?E*y;nit{t;[gϵM+CSZu擤 ۤ $k46 aOlvG#evw1KiHӅc8+ gWʇ^e_*zsC8Ou{K\>Y~9e_*z?뮢9e_*z?뮢9e_*z?뮢9e_*z?뮢9e_*z?뮢9e_*z?뮢1šj9bkp<9[F?] ~!Um|+h_kb[F?G"7Wآ1ѿ">ƶ( Eoȯ4-ϟE(m|+WGvH}m댟a]¹ ?|B]=¹ ?=<HV)q"8?\?<)m2k^0UnIEyxszOוxJg?תЍSQO~G]xjKK8٩Eg,׊Z8cpĹy8kKj:V4zz_A%, `?8bH%sߌƺeΩ{;ˏQ_ل'>^~CJݻ݌{OM8Aq r :f9H n2&'W>yidb_j۟/vݹk"6#R͢RmE69.CLk37vl]bx\} K-{sNXFHB=2) {vK ,1̌)An9䃉_>w2i:N"BJ́PD\ ߧ| ;w'xOI/$|&)p9z׍/)ckܥ4*h.p*yl acUt߉S-my}p3C[#!r1T Z@]M' vJ\*i->˧i[Zk&:UƕkWtXyQ g9`U曪^]hؒ+H3e yDb4ܜ`@TAm?\tzhkG,j8r\W>S].&7^ )IQ2r#2:;+[Kf"oeJ!0y\n$pqOWϩ]# fo ˌ$(W=..ryoQO?x~>^uhWKzZQ¤%HQY[8R0;,-`wӯ6Z˩Vj8bg>*x!&_CN(\ 1 7o_Bt7pZvuM:hFxػA9u^m楨S_siimɵ(iF8;IcnӒ@6 s[ 1ۥܧ.qYw "Bo涼-{$@ے"d\ NN%,ck \HjI<*O[ W4)/[YB6g9\-,ا%t\\m<髋-牴^]yOK eXm2і8f(((((((((((((((4x{յ-V;K4bZ(G]7S"n~&>-͍ʙ/g'|RXa_z3Oe4_Mغ_gǝmg'Jc lb})OAbIma<▚47QYm3 _hE`'h.[vz/넟 -{y{B *ݧ.!w X 'z 'hhkɴ ֢5m?€5 85 +{)S$nF##=*@?OCXMP} ^@`IFD C|W8$WMY?m? c6@<1at|;f|0AbAsV[16u5l:?4k3Ir2]3+;CXMQ&(߃l|,sjVMBnvLoY2e}KHwHUf dTm? c6@pR[A[$Pơ#6j?&(?i >sssgvyV15$x!7$(l 9MOk=Z%>T[qO=h?5m?›K4Dpٳ2FgdtR̭!3W]&Q]a'\YCpHS?ihkɴ ycmxEup~;}j#:?G?5m?Ftȏ43ϧDCXMQ&(gGOG#:?G?5m?Ftȏ43ϧDCXMQ&(gGOG#:?G?5m?Ftȏ43ϧDCXMQ&(gGOG#:?G?5m?Ftȏ43ϧDCXMQ&(gGOG#:?G?5m?Ftȏ43ϧDCXMQ&(gGOG#:?G?5m?Ftȏ43ϧDCXMQ&(gGOG#:?G?5m?Ftȏ43ϧDCXMQ&(gGOG#:?G?5m?Ftȏ43ϧDCXMQ&(gGOG#:?G?5m?Ftȏ4|/WO YEm]Ě«2$W9u :},5渝@]Wyϫ]hq3oa wک?4'68K㨹Y8$16n?㹠=kjb爵y #Hc! 2q _{ҩ[:`sOZ<7joٶ\u$/_c#TH^Vƛt~n.N2I$I$@%֌?izlemf1JF#;^Cq.]_GjFdS7/p~MdUtC]oP֠Wi-䑢;]H }*൚)V;^|Ρ4cG,==9G}.ku t3O.pbw@bwUS-Vu6X&)f`eܭMH -vSuG<5!%܌RǕ$dfeK (D2(Uv80:]XX oyUHw*$>c Kˏ*}ant*XT,p\ːc"S}eWgw4!tu!;d 8|t$VJDDY lo*DY 6,H+0xw\5. $m)>e^IB{gGjBio{}u[3<2B&Ďu&7˓x2{ef8dbj&;WngU7 bGluc(lC;]V'Ks;[rX@v+9|]{ؒ8no FX`.'1)&N}Ӵ絇Hlc[S]Nr19RqV܌^{ebQDw$ec@!oP0ŅȷyaCKq Krj*ϝm>[ϧD4Z[ϧD4y V uC@>uCGm>j*ϝm>[ϧD4Z[ϧD4y V uC@>uCGm>j*ϝm>[ϧD4Z[ϧD4y V uC@>uCGm>j*ϝm>[ϧD4Z[ϧD4y V uC@>uCGm>j>b|:ζOiV2@̿QӤ2W|cq'(((O?E5|Q_ܿ)7OοwF_1BkĴo+_?nf:O(=((I}K^8Mrh [g"$S2 `@=Zjv:=Z\nukFԢG`͝H5U)ݭZku3[7Y *xfe9xOJXū^HZM!0 xB':n:lIq c9`]n;MwՓ6ysii۹xdpG֢lS+D#Ae$''8RY.KYQ]1re   c6G@?OKäjPafP{]$H*QFoV;{kdkN\ZMn~g<;Ԏ~mT0*&(?iC-VIRXYi64PGw7nwۖ5Ku}:d󭵖KuhMu,yLkhkɴ ?5dxWx1Ypɴ~a$uWN~|Iy1 Ü?@45m?³.V+`$vbݘ39aoq6e6刵,n'Wk9fw@45m?¹;i7:/5ҥԕE UV_+)`uKmlcY*Am"eZO0񒤝2\/ m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@?m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@?m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@]k7CEU,qf͇~#U(((̼U%3ß_?nf_S<9\O5jŽzş ( ( ( (1?)ɼ>gvyV1ƏFtȏ5Ed3ϧD}?#kQ@?hgGOZPO#:?G?"?ֵΏ>ƏFtȏ5Ed3ϧD}?#kQ@?hgGOZPO#:?G?"?ֵΏ>ƏFtȏ5Ed3ϧD}?#kQ@?hgGOZPO#:?G?"?ֵΏ>ƏFtȏ5Ed3ϧD}?#kQ@?i_FyV,kN΀,ihUT`:)%|uQEQEQEy}>(_Wf~g_ g;wO!^s]5Z7tB?3Qy'QEsQEQEU]TyM|-v`{(]ڞqw0GN@#| ׺SiZ:M<!/Ür(]kN%LBeHGS1((:Tw4-/=2Yf{@33mN~Q7^ %Σ}j[J3Ѱ2mm? c6@2f)/eY"R UXXpAPG<D%K6lKdvY0@bK| F c6G@?O V XoIbhLSLe"=cDv*pEHUame=ȳ4lI}+͘:bRV0{&(?i >ssssss#:?G?"?m>[ϧD5Ώ>ƏFtȏ4[ϧD4y `3ϧD}?#o uCXhgGO@uCGm>#:?G?"?m>[ϧD5Ώ>ƏFtȏ4[ϧD4y `3ϧD}?#o uCXhgGO@uCGm>#:?G?"?m>[ϧD5Ώ>ƏFtȏ4[ϧD4y `3ϧD}?#o uCXhgGO@uCGm>#:?G?"?m>[ϧD5Ώ>ƏFtȏ4[ϧD4y `3ϧD}?#o uCXhgGO@uCJ"?ƭgXJn$N4W4TDb0(((O?E5|Q_ܿ)7OοwF_1BkĴo+_?nf:O(=(((5MKO|O~G云h|O)'nH`@Ǘ^&ZMe4 ~\GA1$3H^o̭9,Sw<q1Eǂ &է\XL>j '>u9~ y.ȋ1kF_, u5,wvZ4A=ݔsq,{G.e P+ܟJƽui-Mk6ad*A\c#=x>g1Mw Bi9VBJ0<@97M?}s'}|gs8s4UjڟꮤF.HA;-_m|;oۻnvvw%u[h x_2#m 'sNHb'Eދ>i\I%4 9 s=,zA-%?4ʯ23]$:TG1HM`ڙ>3Z5絔 ߍQ<~Waϭswvy5 ḂXO0`|B;>)ы[Q6 3.X T&Gq$,-BdUT\!@5 goMyL;1bؤy1oIkxbk;.b]m0By Q] ^ DjmHαجre͓Lum=:ędjDkW`_{䵲MK p 2F>0c ?u+urY6VP! fަ0v1>t3#m\uP7Gybg&r)bAvjI|'ەE] ap W|{fotC!\A쫐`jsI&MRfd0DaM nnov1냞hSWN_G?ƀ-U?t4jkh "{&_g'̇i|g[~u=OѴ}GгjΩ$b<2xnwvںw?t4v;i䰆4ӭ[Y.ʔf#6ùyu\68HxfözR5;.ٔ*X`Wjkhӿ/oz?(_QG~_r覢0>c:x^9C| ۟ѿ;mN?/P+((+WztTi|ڑ[[hT;^#/*w[ 9=?X/^e atG20.0 reQ|M֎k`am5)kfVe !pp>W'f mC[O%YݔȂEFRJS!#kL/]N/4˫ﮦ@;;>ݡ ͌)PFHVes,l~4&q? Ϋ{n#G͜FdNT Id YDw/!al9a@<(GCXMQ&+y'ӭ/t[[֟Oծ/=ϔvtAe|"ΕuC2]fc8:m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@?m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@?m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@?m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@K}]$]lC)*>b|:.?_袊((/Lq?::۟2WM𣞟g/넟 I͵d`֖ 'j-ҭ$6G=}y: K)-`Eyr~s8#[@&ҭ1DeFkV-歧6 խa(]n@t$ݥ_(еkMrEiQ=hayY %T 㜌ϣ&SK0E, .V 'z$c?+;D[f8;2ҝͽv2r1^]MY%Q O>h!_,29@&w>k%YZĉ&2)Y.j%\ҼzƗ.£&?/vr  aV\v7m},:iXHN1(ڧʋ<06 2E=FQ:L`-Hch1iY~A' '9O,U גTm^i} [n3K_TKOygN'$ϣjahQ x9Sٻؘʹ6&}Pmq,M&p \o6iYi\C1UM J2T9,ר6s_ADI ?waHP~fD/gdt@8|-U{}kkMB!I1ϼtt92-&[{YYF*\ȹ,fCۑJ[^ol cIyLe oepɻV652j7aXAƸy;BƙNyaJմA6sƣlK#D/d?vd;ǧi6O#5]|~oݱ(988 m^IM7RR^+C2t `s7(#Iam-~e”3),8f{+N _\~}sxwIe, I2>_4$R[ o5-xw\dfMcMY4WJbv,`񌌒@&|'$[} oȇk;(WU<R@f Uht ya-̡ ,3!bx2Vt:RGJҧh4H.B0$0<;j]>}}mq4$ZǨA̒g6;#B ;MgZynRA(\uq$M`cu%*F2 E; ͝տZ[[]I3G­@?+eik~W*S+N _GV>­@?+eik~W*S+N _GV>­@?+eik~W*S+N _GV>­@?+eik~W*S+N _GV>­@?+eik~W*S+N _GV>­@?+eik~W*S+N _GV>­@ gciomu$DUܑ8L*?uuZ<ME?/j+ ?S3ѿ;m-C| ۟r (p((*ik W.^|8jEbC /M#g܋H>\gvO,G=*'M)XIطd/Q@I&9VX1r|5.fFЬl-QmXc,Xi*YPXcPVpi6Vv,Q&Iڊ0O':#CD{vӼU!Fx=yJ]^yJ"hUPؼkfQ>2IY~SĎi.đsVǿvdfmJMmmP*&F sڀ0-Akog"[[HIXHeY$ +1 OUX`M̶o2Ʋ"‡R8Ԧrx;??۾1ךeׇ[-,.!]G5:ĸ ŒF[mg;O dD`(rv1j۳Y a$qk߅.1_EgY"e]Kde8<{;1ZR֮q,-IF#bF6[j u5k?%b 7G2~gQs# }^LҼUy{Ɨ+k mbn9݂9<(ߓLQQ]ܴJeE3q}j T>XY˰ol\juM[0m?d1`2w]CܹPcKTmf1$pK yn#:~H3ݷݎ3m{kbתK ?0#<^u8oQ.CwU֯iۺ f%k*fTR6'-ѴM[X6  *eW94[hUֺmnn"VI2rw09 _>-1| ]eG \^%ںM 7$#*yʆRxq)eX[rV9bXOYZk{m ͻ|SF# yߟwZe^]@cEP6t zA9;v ]OHQg $RtvFʜXENNHK[|l'n9+>үC VG$Pơ#*j|U-SFy4+OۋpYS/eiha$#i$I5j Zm6P(Vn݄ٷoL{k|MD*HʜR/ Zkoqω-# .ӕ1Jծ#G>Z+=.\ݢ0PUn7H_" xX`Jm;~>cNNy4j"c\w1wU&F "DF!j֙kfvT*-b`޸PNNݧnFҵ K6! +6ऑFiENNHK[|l'n9+>Ҁ9˝KZb̶s˨Oor) E+m;i]^] [M+lw 7NP\2lKXO :ki,B gLAWF1\g@~ա1,1y諑ŒcɮPjŃiZEҴv E>ͼ}̌I}hkgyO`e wmL嶐 H+z&'`w|$joEH зCd1Iohh:Fj~W;i.g9mp>C H攪m2n޲>=7~oGq [R֥.m㼶Y8$pfT~U+7|WnuWl/i<նE'ө1"cil1[ e=㵍k t%` T:Zˡ["{HE嶌`dqր05kZ%ܶ^}Ťh Go,0%$F0V0P$tB͎HRI=~j7R\ c4pGyǒl h:-JMDھ!~@q˞F@.JGk8ࣃTx<AAyekZ76MtlP2ukOQH$Ko(348Ke-q[-j,(cIsr.73?6@?Q<}z{TvV}Z[Cmn1EI?ewmt>{8~m%٥+ ; a5][=4߷@[|æɃ6֯ᘵX^ߥՍ;!)frbR6.>SQJMUİ+IF##1ހ1[}P䅣c,7&(z;#w:KxfѣY  m\ڵd,%bd{dw-Qy62{Ztu;۸e XDz9v (r0i3Iյ )Ѵu;d/lU[`Įq(|As[xGI&`okX'E*c S6?/tveX[rV9bXOLҠh4k8YXԶϵG=څbB-0퍲(]%_pF85ziT cmg 6K€39TQEQEQEf:Va+?/j(ASQ]o1/O՜!?cЅ{kt?׉h?W~CF'tu×QE{EPEP\GVgk[{yK-And\ .++Gúf}S%qV[y dl#89MyޓjZÏk;OFjr%Q&aA9)|qZw;b˦Κ)g1@dU^m98TXGK[2)#``C 啁;d>~`j;od5{p2%kE[#>*ֆ˔]e̳U%F'9䏻2H"_ ֖v7JgIIĮȏF Q~_/ni (mۣcV H`|fسF̮ bN$rqր7>cosbY3dg#?+n_C+\Cw,$& eQo+c~V{b8 "5 hU ;Vf֞Kfc4I\6a<3&h\J/&.KK3JK&0jȧ .<滨Kmi5rK-崪TC,h`@`wnp,709 #*C)# GBE21Ym${^)"HI'fdRX䓓N@8mcڮK1aԤ 9%E֏-q |zn5J=^-ɵdeD7u}Ѵ7Ozڹwc fXEVF_ *[%I,Ng\t@ݾ5vkxm2~:U@9y`cֶs<@?`_?Z >s<@?`_?Z >s<@?`_?Z >s<@?`_?Z >s<@?`_?Z >s<@?`_?Z >s<@-UBbaU(((/Lq?::۟2WM𣞟g/넟 6/j&#K(7_ UF/UM"Cg_K,P( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (,W_U?uuZ<ME?/j+ ?S3ѿ;m-C| ۟r (p((3]^Geok?"+ LۤqF>b3z&z&Zowv>;~za$:0ݝ5[  Wn1w;AgV}).!T7\aIPK%H2SEy+忳݂ t w-.FZfX뚶cJOFii  OҀ="_ź֥٘Y-,maDx9:Iv#b&ME~& ˹,s18"D2,"B9ONH7_ UF/@ugS?KQͨ첗Jƽ o'>c`f$o|Ÿj++hɯmhPAFA'wQS?wQOX~XYs&^X(-㻎h%ڦM4Vۺr m;>EWė)g I&c., 8ة?ۺ zRO4ZZt _Jk!+jV^Ԯm;%ѰppE ¸"tZC sO&I+[yJcvp3z)#6myl^UKUUA0m*Qof$K`eڋ5]7\#VPn2$p=EI^~+ү m,ō&AbF{rn!ԅ>n<)o7uO [iM0ܡTXne`wl [*n?)Ч??[u_ CO@ssw+\Z[ y%JUx;G=c/O=xwRo\phgsw5eѬ￴5]"D-*|͍ 3/?/"|3qm7G^IlmwH[%m%U;|#\@jWԭrp2M$Ơvv0]hאYͷʸc##kHj 2-6dH.h%ahLH0[Hӯ}Hͦ#{.bvU,pehʡl@ۺ z#I<1J#Vl' Q-3m;d)!vaJ($On;gVW4e-$E2nLɿs^iʻ:a;ƝLȪr#`JwQOX~խΛŵ0β\r%n֏D5S}x%ՌKx@ j4vy %Ք+pFpG<^# VE Y' 28 ;kmSVg}F[62Ѐ%n]WbM߇W֗Xè]F*@ـ\ {deJЧ??GBlm@ۺ zn?)Ч??GBlm@ۺ zn?)Ч??GBlm@Q@Q@Q@Q@Q@Q@Q@Q@Q@a+f:@iG~_r覢?E5نY?W~Cx!?cЅ{kt?bwG^I9zQ\ǸQEbO-"}RSy ϴIm<fڹp=}hCBk{շEq yah60vwZO)gw,SjےnHX ḭg:ohy&+ !v%@R0@=@EEb/4!cYcŨms3$.dv-m<OxnYMϙ'%F,2͸K'5Q@+ó#P}1>.]du 8p `a VP;i8-1U#YHbYODĢpHqL{cOl.gbʢbQA# tTP"CB:>|Z>3s<\pWBH"&(?}y°?5m?€7slA{ycq{u'ooK+$rx /|x,v9_am{,$gcSlaʼVuasf4{iu9U7<{yW,H#%B- =ίa .$(I {8j;NZ-> Jyy$9$0W;rh7t>!M}"E hU'lCphwpEjIkV6ӢFT&[eHqcp6rzcSQN/]4%u琹+s}*y 'TԼ;TP2I'\Z}}流76cQ c`vv~a;@=lEm*E j^I($w :Tl+7~׶u?gsskuCDzΕ/(_Wf~g_ g;wO!^s]5Z7tB?3Qy'QEsQEbk߈,_-~Eatt9n[?x3\_^ 5m:OKr8u|6GŭMLsY\cpxr* LOWYB1bH@?kݷo^hvK:mG9ݑMzѦLf nc[k~R-eWgFb}]q(8@,|!i_d|~ϕ6rz@ oU:|)y.-"YwJ4KdԔ's;d~u-gw=< ,3(%@9XcV H`|fسF̮ bN$rqֺ8a$$qTP0@>~xYJc!MĆ\%@.&S:5ͮu2d24Nhn_)vmKYkVF r\< 7+#):lG᥎mZE$E.n^pHuJ4KjnEv]rO+IZ +t+!K7#Iq/Xg4҉Ov$v.NYpF$ahmLdwlw%NEYDž`_ U\/xQ EYDž`_ U\/xQ EYDž`_ U\/xQ EYDž`_ U\/xQ EYDž`_ U\/xQ EYDž`_ U\/xQ EYDž`_ U\/xQ EYDž`_ f[?,BbaP( (<_S<9\O5k̼U%3ß_?nf(Y" 'jͷ4Aگ/넟 6/2M"C/ci|Oƒ,2PLcאGM"C/bYOȳ)(2A@ ;IӵWP!en4mcب0DyRzv;W)qjȋꒆC$HX*1w1W<-4ڼ>#KXƢF`@QvúdVSJ'I=̲$v.NYpF$ηM֟ncӑu͚[3Ɓf\hĈ6)тN06汩Zǧ en"j,yQ# ͲoGtϰʛoyi1wݷ~ˏ WPYܢٳ<& ɢ`g, 1f$r5m (DWRi"|7+`&XH;AėQ_\$|?cyVʦ pm~{nn 8ap7agqY$>!յ-N+5\ZW:acD!c j$s@$5rͽŵArdiDy@6Kd,@Q]{m;7ڝd5°[xTm&eд$.fܮ&qk`f\3FF bMw2+pW\$r ڪp1Ҁ3|SiGqC%g"r'w ~c*;'M?UMc LR$W-dg+".GA &kyRK#_e% ( RKji6* }ċ e|s ^3&PD۾2YK x'@=py-ۉ#3qМe=mggsoasw$fiaҿ'rSP͔)go+Zηc0:R[ ZBӧEr(N덮уap WiW1Ŗw XX VT@ kWdWYn|bv wgy9=Bfx§SM+θڵޗ̦P:oPU>S"8bml-#0\Ub m-'5Tx7FOfyO w1cr@ ]m/|?ڿnyG3ݷc;>ju)u[).%H O$VRh;GPiconeckq*+LM%,8<úS,vr>exm2H3~7HUּG.='O[y2L)؉%瓈jPK]e5к&eM%%qέjsP6ݎgE2NH/-#n>cT~dȄe;B lW3xMWV:}ŒDA5M$2y"0>bSx#'#5eYwLKhG" nedHDBQ:|q.-WRij2FX9o  YrWO]If nD&bH;Z%8 tn W|OJA`G*A@ *#g~Mۻnvvw>:a<:JD2\%R<%O%L9ZKm5>-Rf䤢DfP!O6cI<#pynR$#qxј,A,NNr| Z#!\30Fv+,gt>i]\c @ђ3- s^X"FN 3rg'55=zU[Њlb# J0dc${7P'ksxuېI 構BӠMps:HαX;'9~dhzKH l N#9rUmGO;6/eȍVdSH0+wĶ7Z5=:Bn. QTBqq3/ ]1lJyW`?嘙9@Kq;Vm-cӬƣyrm#B^C+nv( > a+x6x %NrQ!xؓCNOq6kL%atqTu_ˡiviw5ÇH2%ROV$AM#VUG\O3f G~:|J]^}^NI-'K{MC#PBȄR@ =jsP6ݎgE2NH/-#n>c] NQBmg;6Fa0$m\`;Hu˯k6fIy -!Fz*ΗBӧEr(N덮уap WѠ(((((((( 0Ǖjy]?V4ASQG}|z~to+_?nfKF_1Bj1;$B(c +~ͪsp@H=OW^9 3Oȧ$$u4WxŚPҴHU|;>E6 (1܂I~O1}M )., r +oUxs\=^ç-8HP7,Sv5]RUlah鱚nU,r䂬'|}oYwg.v@@?OCXMV~%󕻼Epb!B-rNMIIgMo/-S{T%JV@˽x'W J&(?iO_{䵲MK p 2F>0c uHu`_*M>v-~!Ls9 E&(?i}=~.Vk=fYD!'Γ`Xd`+Kw]Y^^<0"-4R@8l;r6m&(?iEdhkɴ ?5kQ@?m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@?m? c6ZPO@?OCXMV&(?iEdhkɴ ?5kQ@?m? c6ZPO@?OCXMV&(?iE",.bX-?-Y?*yxszkt?יxJg?צ~CSQO~EMWAO՛oiU_^ ?Vmה_ IeE*ο#vmX&zݥ_(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@a+f:@iG~_r覢?E5نY?W~Cx!?cЅ{kt?bwG^I9zQ\ǸsllZIJhh8!&wNzY^.{gn{M"mç4lKxI}뷢0;ODp]$utxpwF (R@( "K'KT̐f $%=7 FO:\"OّII, !Q+öbYR8e%$LJ nA Ebi>д;Ӭ|i݌@ca@'(8Vt~n"~0ArsV E,u 9,|}fy̎ž\ PKO r."\(@P8,Ng]sIlnm3oy+ry,\rzNaحpN*8U(W𮉮V 7T? Ȕg5[[[3_q$$I$I$IDkV+}(SXP/"QB%Z|; K=4KF _SZ`_(/K8'Efܮ.Dm `Hڸ?(v-Gid1{XErXCPGT? Ȕ >ssss8u;.PKmWMXbcq)/c v>$5޵h7Zپթ_0inDPƮ&+`tD}J6q@&K8L,tZtEkd1#s\`>ڤżgĐD_/$q6 f^;\M,j3 ѶHKDыtV0R[vx9hzAk46mJ00tm*k]6 ɷy@$9; zO 7-on1ƒyO,q+.{|aWJ.[w:uݲưpGPsqpFEtz6ȒYivΑQPeq'2sV+$xXdRF]H#p> ] ך͝Cڬ6r#+L^kOɪ:FC$mʔ)pT3Xtl"v㒸?*=)hU>Ϧ=fU7.ހ<x{CR.m"4Khؤq) Y~cG5mKVW7^x~QfH|qxhG~ү){+;OiѼ*3@#=<+XPVw[%J N;Pm]g]qxV>Rq4$kZ<;k[X3IyK"`dwQIadp{6g?~Bwo~zqD6uirg|s~Gͷzv7oƧiw,ry]aH?ZX ~e}seB>yL|{g84m*;[kTlQ5K@I V'#MOgekڥ6靑CD\zIM:xbk";^S.}9am*CiZ[InxL| ǔ/9ɯa,5GhhʫGwj IM]:-:K !bm4(bF琸?3s}hOL<)u}{ygK[y നǕrQ aJ< ![QhZ}%GOMѫuU>dQަ{yӮ&mI2MrADZ}Ln=ϭPRQ6_f_3!|q瑐9vi-o6Vfy0LY v-ﺌi,8L72$qf>_|Y0% &7XʣVOs_sAI4n-LR1981aMJӬ49v-HخATǵh-WFRWѠ[=:XEs3]蔨;Fx QZEiX[5ߕ#X[ xf97y;NW o iVv3XpYͻͷ5Xܠ`{Tz=jB3(p98`rIhUſG? UſG? UſG? UſG? UſG? UſG? UſG? UſG? UſG? UſG? UſG? UſG? f[o}ԑD,ٍ|Jg?צ~Cyxszkt???T{\$MYF^Q5[UEpA5fA_yEԝ_^b7iEo:_b.EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEf:Va+?/j(ASQ]o1/O՜!?cЅ{kt?׉h?W~CF'tu×QE{EPEP=>yLz63ʰ+.Yo9ckr9%EԌ;מ_>8KJN-K0pH8|c<^.NԒR=*̑BejH߾-Iݸ(Exkk;44nݡE"SvwRL{NJn -|-mKAZ X"fQsO+~Uѭ|AjPEʳ$ $m9+?*zDm5K}HԞYlo#Zˀ$HZ@X ]I=.ъ08 <ׅj>ԥzN ?w X nQ* 9.<ׯ~~-lD椓,M)L4O`g>Hk yTI㌑J ޕ /*daWT_?#ZPOEuOQQ]S?խEdaWT_?#ZPOEuOQQ]S?խEdaWT_?#ZPOEuOQQ]S?խEdaWT_?#ZPOEuOQQ]S?խEdaWT_?#ZPOEuOQQ]S?խEdaWT_?#ZPOEuOQQ]S?խEdaWT_?#ZPOEuOQQ]S?խEdaWT_?#ZPOEuOQQ]S?խEdaWThYiIej>bF3gaPj( ( (<_S<9\O5k̼U%3ß_?nf(Y" 'jͷ4Aگ/넟 6/2M"Cg_K,UoȽuYnv(((((((((((((((((((((((((( 0Ǖjy]?V4ASQG}|z~to+_?nfKF_1Bj1;$B(c ( ([X)K}g~ˎX4/g^+BVR#<ۉHBbi,u'I.KVIZVd[u,1$FI7EwTV;Di-Fqh #~lQxG',.c !gAe 6(g[@'$s-Jķ72X2G-)Qe7(?|v8/ak D 1\x4MFmu n K3З09.h@Ow&C ܷk4l;YYu,@ܠFzOm RI1D;T|ҙŏ^AWu [y$@vU#s6M.ٙBXĤsҀ4t_G?jV>;|-YںOZwZߕ ?+gWA4j??ƫeik~W(ӿP]'υ_+N _@t_G?jV>;|-YںOZwZߕ ?+gWA4j??ƫeik~W(ӿP]'υ_+N _@t_G?jV>;|-YںOZwZߕ ?+gWA4j??ƫeik~W(ӿP]'υ_+N _@t_G?jV>;|-YںOZwZߕ ?+gWA4j??ƫeik~W(ӿP]'υ_+N _@t_DΑaWy[+N _GV>€$As J=xZ[Zm∴q:eQEQEyxszkt?יxJg?צ~CSQO~EMWAO՛oiU_^ ?Vmה_ IeE*ο#vmX&zݥ_(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@a+f:@iG~_r覢?E5نY?W~Cx!?cЅ{kt?bwG^I9zQ\ǸQED3-w/پn]IcꂛIJ۶?0{m'snEO%ӓn%Ӵݱl.- n O/i3VIy8Ux*.A' 1Q@ˑNA,  2 y W|9qr+RN`dt,˂*('\j{IfFfYoU$%qsW 5k ؕb:ms}% h mI1ڲG(UE @I"GWXne7hC61ia[1h8"jN *%?O ?v O@?G%?O]SP+ O@?@h_ ?SP+*%?O ?v O@?G%?O]SP+ O@?@h_ ?SP+*%?O ?v O@?G%?O]SP+ O@?@h_ ?SP+*%?O ?v O@?G%?O]SP+ O@?@h_ ?SP+*%?O ?0m*I.-PIkm-k8㊎ ( (<_S<9\O5k̼U%3ß_?nf(Y" 'jCOӒF$Lv㎞"IMuvW%uW#<5'AsQ?370AjnWVOK|eCzݥ_(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@a+f:@iG~_r覢?E5نY?W~Cx!?cЅ{kt?bwG^I9zQ\ǸQE]~c6.Mm#j"{ O-e`ozY{_K=kkr:qVRQ9o x[#O{mfV-c*DQ`ci98_kEu+}?u#j`f@\:3vnSyaXu|<"{y^w=]eehC( FTiAEH`5Xiid$#l 0@ [j?3FQZA+nn!6ۏvx[Nih}}q.̪6Rvrynz%(geY#O!û(|McXY:zO`nD˸$,-`k?SE5hfI)m2. k|So?ֵhm_]/ bpAm| huǸ(u9'&42K` ]3 KMm$,K2Aܟ"ʫvz@ڗDѣao( Xs"<$cemx=si:4a:Ѻ8p?w=}fN776{H67(u#Q.?ծPhK:)Q/''OLq@:?kVUFU~?4'2&?4'2&?4'2&?4'2&?4'2&?"sss-a"I˹ēME?/j+ ?S3ѿ;m-C| ۟r (p(((Vm_hjZVH6KArOSMφ+1#)+L[{wm'WZa{I\wI#,!*b妙aܚTKzgWar,yi7%?\z*i`&Ÿ;i*XN +W?ff+DzcHjpCr1^}Zu l_}B(-a+EI+c54ijWQ宏.g=GV5QgE_kZ35Gƽ@?5kJ׿'dխ*(7c^Llk V {2j&O ZҢ35Gƽ@?5kJ׿'dխ*(7c^Llk V {2j&O ZҢ35Gƽ@?5kJ׿'dխ*(7c^Llk V {2j&O ZҢ35Gƽ@?5kJ׿'dխ*(7c^Llk V {2j&O ZҢ35Vs=[ƒ-! Uy]?WfgbI'4Q@Q@Q@e)'GG^oʼU%3ßmPuSQO~Ez czޛ?nPi.m٤BI*̬6rɯOvzU"'QGr~ZFs@"8-C![[o^KitVcApC<3s]&_`aMWv7۷lu=Vd P-څ.;FɑRjj}GKG{|sfzq:ֳCa?d浇| \1r9u_^ ?T ڎyi-ӽ%`;*'  'hΕ"MҿUv?Si[-uٽvʊL/H@.Hl拏DL746sZERbG rh~+cocݐKKd)VG*FE%]q b YdƎq}g_is\k K(djtk-}iB" #Gvgw^jݟn-$w./&eHØb'n&[t4y.܅ɸ( neuP]`ˉKPy5 {+.%B~ T3Is?Soh:;e[\[$i{D|r )磰W$'E-kȪ HFyn(5otU"I~Ϲ߸y퍬ʹUuլdyH3N2H Y/z.ͻF2cq*>l[$jŽv-`rifw4m!i xZ=]&Z |U [$1`H x'bS&P]h- E`QճL7]ׂZ7^ZJ]#;!u* 5O&\%$+ިrlYO9Mo*?&|u:$˩[B'.%%B: .Y _.2;N9l?mhYB$#s@Ki.:gRs<͉p+ o6i ]MaMBZB# +eSĜtyv/RmBX#Y#c-nܸi"QckKB9n]n"Tg&vێ26z&K?4'2&(_Wf~g_ g;wO!^s]5Z7tB?3Qy'QEsQEQExGEf{chԱoJ0F$+O<=O:å-ϖH{()<96*ax+?Q!~of 0%7SFf\RĝHtP;x.Jq:F;TFT0)+!=ͱ\_E #q$wm@K=^KK-4Cm"RX`UWr|cpMEGGög`3 d$}G5 EYDž`_ G\Xح8{ ?_D \/xQ (?}y°?_D*JDž`_(7s€$ݵ??ƔkƥjΠ/0` +eik~W('͟_C]k[+N _GV>€2|kQl5ߨƵ+eik~W('͟_Ԛ{Y\\s\9VV>;|-IkAX ۶ZwZߕ ?+'a4nVQeik~W(ӿP۶ҍv0'SAN񨿲+eik~W(.X&\v,qzdM6C%-keik~W(ӿPOٴ.9h6C%-keik~W(ӿPOٴ.9h6C%-keik~W(ӿPmzMڎ.%Q 1#5kAX Gυ_+N _@nVGa5V>;|-IkAX ۶ZwZߕ ?+'a4nVQeik~W(ӿP۶kAX Gυ_+N _@ ay6n 88}*hgGz*N ?j;|-\ X"|*HœgG~TO=h{I}i?G'F$DO紟Ѩ >?4}'j:(>(_QG~_r覢0>c:x^9C| ۟ѿ;mN?/P+Kaޠ-^w:6FA(՞Ka{k_L+!7Y't()!1sW=jpx/hI?md UFTA΁ihzl8&]k;[dWl@M}]^Kx+RU"[(ݔ,A]LNzsƏ{ٗUYͧZq&gh%Q@q08+e΁?hzl|iF|~ffZiXiecml*#1*TPB:P9MW\o&i]KqK:;!`dr6㡮#W᩿H|Y 죷 He2 T!eo,u W)x< JͳO!|c{y;ΗMel2gqfB `mW' m]9kIcb-,YFrK&0ˀ9sOsXM5ʄI-U=)UѦ͟i V}6ڀ<xS[Z/#X\ZƨUm#$C3axZNn";-Nӽ$#؛-A>a,2Nnd푕#Bb?^"HBG(UE8+r>#kWȒ,!s`Gq 4)wP?QPA*KX-txU<@+s3zn5Rt;9u)hy,Kx%H.}PW qLشԚE`Ԛ$Y"rpǔwks*].{8vVƭxT @j4ؖwIh&uTiT8`{Zm;]R;su糜 x21.HK6/Z\F15nH\41bD`㵳atFs 1D[`P.]hwq5oI]l$eN@z ?/~ħ;6/{qe9|McqM6WFQD%3;fc`wg|'>Wlo~coe|:q) Z (<_S<9\O5k̼U%3ß_?nf(Y ,/,j"cMfMC: j+'m~O>amO3Fіa8{h 6? IoEdMCm~gw"2TɲKD LBɂ c^XҼrޕ5u̗772ogvYT<~m~h(QxcX{7SL¬r,'Ώid,0>RW1e#mQc86l Ze*qGF_1BkĴo+_?nf'ti^EW1Q@Q@Q@Q@Q@rE=6z.EX WWY>5p1y#}[#hgKa<ŌږF3rq냑[6$ĕÁ5Lz@Or:9x # ` ) "~fKl%9;_?#\j3j:h͝ ,R~pBr7|v|7{k52WlI }2 t?_?#GEuOW=hW'AcDf[<7gT5+GZ/֫dWi6pݔ711GwR@l3g<$渽K&w*uw^;[~uNATcϥAOn֣(. Dxq;i+![KHT7-#:F$mU_ѱgsSu 5iʺDVRq&Fc(: P F EuOQQ]S?.5H-J'r`K,HFߍsPOEuOTt}ֳGooK+E'dJ4 6|6uZ k{u` r!JLȾbrlIu/ ke!ђd1Y.@5Z($5 ^fE,"K =IQ]S?:^7Sl eqmlYgh|P>P1~Oji׷"%;̛$*yg ,^qr`jڦ5K}BW&A-be۟{H-O@Y b kRp[hXijIz}nx1hK d!\A0:/֣ ԲgKNHFKIe3*055Ήxھ& &KK $o5nO䌅EuOT2G֥.rG0){T o{"뼼%7<(57wo mu` Q<@_zH~3@4]&QSx#8>o |+i-cX&s-HAKd;+3~ያmQٚG$rnDv"&Y~@6T&o^H%_W su#8>U/֪~ӎڠM.n` yIR#bnaל POEuOVq,Y%Y<΀+QEQE^*tu?3^e)'GG^s]5OG=?5_^ ?U;n[ڼ1B ՝WAO]b 7GKkxRI^(ʌ.x^&*Xoͱ[Vٟ'U>v?[x&+0 *0J23#+P67 Cbzzs[>%>J%@ !1FFG^Aƀ9-ٷ7C iWwmٰ'fèT6vg6,b2tڍZ[L΀HnGF2eS8YC±Rݴr.ϓfb.&"# \(  027zF6o\ -˲9 PLKn!s>?}KY/0$..eȌ>r1qSaK㿼IbknGdW $` m;H*@2@PR$/<gˣkSfI?| @7*S7Zd^[Q0I4H oal`*2s m̊rS׀}ڹ/iFEE0S#wdh/lKhWh7^>VwXխt=.mFN@f $2 I&]}yvۋV#b;ry9E5 $Ft` U8 A4.m,.kfژo?nY }_pb+n!}Aɧw7k{w-/6%ܟ4FA*B6+m$|:\b>s1ᇗ]ja[S wK}o2e䐹pR|y`+A5 < q,o,*!$dr[ӕΌ]eȴO-xA#C+`߻n0T-2,jQJIW}f)̒cٍ fMWRh'^QDݴ}vO)ZxGhK6HU;`s"ḱN ;_ϩYfV}?6ޯPYfeXjo3IM8v$w?繭z7SP?SUo=rGo@?N+nZutQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEfo:Vf+_ QEQEyxszkt?יxJg?צ~CSQO~EMWAOt G:/넟 6/+UЮ|@e8==i_bxE*ο#vmX QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEY<ΫUG̟7i3'zE!-wO!^s]5Z7tB?3]Xd×QE{EP뚖]mn$drJm?|'"'K/O$-wh#mi]# 8<|Qؒ?LRt[NЋL1׭c$kL-S?_" SFc<n?}y\/xV~AO?XJ'.<(Dž`gD?oy\/xV~AO?XJ'.<(Dž`gD?oy\/xV~AO?XJ'.<(Dž`gD?oy\/xV~AO?XJ'.<(Dž`gD?oy\/xV~AO?XJ'.<(Dž`gD?oy\/xV~AO?XJ'.<(Dž`gD?oy\/xV~AO?XJ'.<(Dž`gD?oy\/xV~AO?XJ'.<(Dž`gD?oy\/xV~AO?XJ'.<)QV 7d~5gDԊkKxeuP'^QEQEyxszkt?יxJg?צ~CSQO~EMWAO՛oiU_^ ?Vmה_ IeE*ο#vmX&zݥ_(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@a+f:@3'zE_^qQHGh?W~Cx!?cЅ{kt?V'tx'QEsQEQEQEQEQEVGJV-\zѴ}9V{dOAh=b;JOt2=8] #Pxj첛_ >X`skYxzDgdim$PQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@YjYhQ@Q@e)'GG^s]5^*tu?3Ts,_SUEpA5fA_yEmWAO՛oiRt~&zݥ_*^b7iEEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPY<ΫPz_^qQF#2׬TR7tB?3^%wO!^s]5Չ&I9zQ\ǸQEWn|]nk<cr ?pO#W3:uگ6ds.+'J<^Yw;6y7l7mqmrI {,o;۞=Qpr{O~4FG=$~޻‚b0HOs|G+䶖+xgtsnޤqf1( ~ 'J<^fڕ pX8scvLʹLAP0`s\.z(ߥy{i7"'ccaPH<KiOq{ 2ƒ2\:9sG+J;)A~c% 'J<^EE 'J<^EE 'J<^]Aֵco2[$eKGdh A'J<\^e.|1RI!>[̊eIonSW|\k49c9Yq@'J<^MFOO+vPT\V11 o*q^>&_hq&a8Frv@;/9?UmCUҴfB>mwm7~^V{呭dFI60N܁HҶG^JbS*| b]X6l w_-XA{EPIKRGj 93ٍ^X>cfs3ʥ%QYXLeL,o8/ BBb)Fyo/ѢV7ki~W* km,tL R#yr# VzRVErkv)7p۰8e 㞣=;mV 6x]OZO7 6w<;zv"mYCmZ=bRw~UJ8tf ^@mlףd+d+X,qM)h$R;pH)U s}DX70*۱njw:o?:o? qGwqC K{@sּ7#k pϦ0}s穿Ӭ Ӯ]!vS)ڲ"ѷXAu5+0b3*$"Yfկ'a7qn`\ gA=zٳ\"7n!Q\nx-?]?.Crd0vfO8j垝B'G0 pzϵtyONϱCٿn?\sҧfotTX,py~al[v=i37Z*?-?]  37Z*OOIXJ#Vl8V8ҋ-?]G/6cT YU$rE <6ՅıWHU0$xsQ~;x[Xe߿'819Qiym,ޘqvy3b52`[G'j%񝅆Kgh7^\,j/.!2 uv?.FfOELgj}ܯ%kp&\*cUI?!=;SDLLŖl"6 *(Cvzt?.FfOEHG Эm4eI!&RJH͐ԩ9 Q ҽ? M$lΊ!a=v#TEpv]ǦH @> JƭWV?F5oن (,W_U?uuZ#fOC4f⢐ѿ;m-C| ۟N2O(=(((((]q^=B<5ivA+m,AT$~Tom>˛ڍN`;{#ϓeoĒx=IUŕ֭y}5 P/F؃~*׉hHTEێs~?G2&#<Oy猟ɠ>?4}'h:*O?4}'h:*O?4}'h:*O?4}'h:*OK +GlB{ ^ywk$2m)Mh O;_k &  ԭKJKTB].\r@$ǷQ@%jok9Ҷ:loU˷9드ܚ~ ` V3DHER8; }:(x]Tg$*͍6}]Tm2Iu^6څ╱Z`43e0BWifBR-E?muNaM,Ƥ pd0M3Gm? Iem7nm#i :̒[2'ʩ+]+{}wVE H]69Y#uù*FIʶѷofGǫ\j"R(XFwel~ UK7nΡx"R(&+%1g%YJĚ}Y+Y~,݇I2(RpWmzm? K&[&њH&{)Mǹ!Yr 2u=v]&$F[xoe^Rdn$!8`O\,YF,DM>~s&RCJm!b|:'șgvʏ 5M` NAr?:j߬ȥcm?cVUOOxz/(y]?V0ǕjK?o*(fOCB<[F_1BkĴo+_?nf;?/P+((((u xb2K:q>JҬo :P̺v۸\"i> H䰆>m0ap8Vd._Q 'v"ݚ9= 8#Uo-l ow.{ #yFm1Un 4uc֠ ߴx{iԴ}O*(7(-hGkJG?綟}KGHDFoK|t9>?[XcdU sq׊ j W ECuWM˸[x:H:PͶ[qY7)ʿ) "tjeiYhϧo3N-zWt:_hfeId؇‚sgc5!j}?sry^F6=|!=t뻛F JnblwayP蚎i_geLc8Fq.u*J ɶVΫ$8T@zi뚮@iwMd6H04N#⹓/x{mgڮ!B."f;6ya Jąo_b8LHx9OH nocWE rwWϧ=* jNtsmo2<ȱmAqɮ֯cs"ն=żVF*qX}̀zоQ%~nV>Ra =JZU卽!α]CʞUY#agzaj4u* *H޼LVnIГ\ԭ uA4SĉF ~SxLִw%5"l` "UX PaEPEPEP\j+"^@|"э[jߪ EQRta+f:@3'zE_^qQHGh?W~Cx!?cЅ{kt?V'tx'QEsQEQEQEQEVVGШ`ڄCVu_%45ƕMq$١f? pǽ7Kn4]8hhi0A㸭+8ݡ : kVN#lZQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEUFUF+QEQEQE^*tu?3^e)'GG^s]5OG=?5_^ ?Vmה_ V{\$MYF^Q5'Ao:_bxE*ο#vmX QEQEQEQEQEQEQEQEw#?}mV-6? q~MOAN((oOJ_ SPp4 @~?} t Ꚍ 5Ʈ Rʅ8 #ָ'%ė:C^W֗z|׷8}0G1$!Nqߊ+?tXl ǩFFJv*0O;dtqkeŨ3#?E<8@kkp-b̝UBQG8oiQŨjZtSEs,2  hxĨ[C$xfI*@xٔ0#U{hI}$Sp`؝^(kV}O[hF#a7e%zQ Oy_?mؾWڶxݷn{h0mv<.~]j[]Oqd̑$4jQf 7p}x_tۇR{/*%I!!w guW$> XMYiIy$"3;*7ʥOL⏉qDwZIn(`Lyl(8!H\ͯ/ˍ2[]{bWHU+܃9 ( ( #ȇףWY\jj߬ȥcm?cVUOOxz/(y]?V0ǕjK?o*(fOCB<[F_1BkĴo+_?nf;?/P+(WZÍZkkvK s29?*k\fg62=/S]S7V 3XiIj̄Ca8q\LB/|I]Bk%K+ ~5EQt} P<+[wlޥs=3\w-ZU^5ZK;3$(8⻪(ΦY>kmKYi6mk9{nU dwOyWPP(gԭ/nc[M @l7r 2']N" lmXar?ihkɴ žDlc?b1<2n!l$&(?iEdhkɴ ?5kQY?m? c6@G[Fo c6XVu.bX-?_WV?F5oR1~|'=QEIY<ΫUG̟7?/j+jTyyx9oE36dS#_CO_J۟O&{ ^&۟G7vtp&޽Š(:Š((((u_%5X!%cc"3@xH[TeQ< `{-NQvI/Qki 1E4vv\ꆟh-! iʃ9ìֵd0@5@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@YjYhQ@Q@Q@w]_|L ȴy*,d?3\Mߝ 3O^TܯB3v?3E`5_^ ?Vmה_ V{\$MYF^Q4~&zݥ_*^b7iEEPEPEPEPEPEPEPEPX8*GVbc`i@ntj c$Ѱ|2ݡDA.yzx^AYZ8'ⵞtS- 䘬*rؔPyH'Hp24bܯ% ʼn$%ZƝu&bAw$[`9>e`<|3"C5cJ4[Wi,$rij1$G,.lϒ0f,HO3hVzH.إ2;3׿V>O3h/A?h6O?>O3h/A?h6&x {?QO}EVz㢏_tPj*:(}EVz㢏_tPj*:(}EVz㢏_tPj*:(}EV6o?Z(((9YIE2Դ"(rvɑBK29?~Cq\ڟ;ɿ\/>rf3?nf/넟 6/j&#K(c2M"Cg_K,UoȽuYnv((((((((nqUŻW>Ҁ6/S)QEQE4YCI|%C.w ## Zs L TUltaycƟigWt+}̲J|#;.X.ĬvwP~ĖO&xH &ǞbnX0` ={bK}|I /:Fz׈ڞxJKQC{bH̊T+y :]o,a'x[f 1lSI+ e0ݴv t GWx#b#8b2>գ^ojZFvihl_ )@?(C\Mi~Ѵ{m_k-R{DFK8RB00 8?iW0y^qo]=3S׊ JAg(.fԯ|ZX7&k"FV*NZ06&>^бٴh^_zp[vo ݳ@aqqxTTvg $` Q}?../+m^* OQҧ/o"H(ƲUFf Ur[:TCI!O1ʾJHm%dV5'/6[6(lNAABvlqe'9G6X葘??<5=e dI1mN\#`;<3so{5+g-::'&Ʌ/ϘWQEQEG[F?!w_)XOտX Jƭ9_QE'Af:Va+?/j(ASQ]o1/O՞wS6Us]5wS6Us]5}0QEQEQEQEQEQEQEQEQEQEf?d?f?d?{Ğ útssss:Z! gn<(|g-6zjzvpre`*w2Ќ[|AZY>;C(&&$ռ/ҭaOi&i%f*XSPn1F3O2PY]60283ވ-]fQۛxVt͗8T9'PN#lZՓìֵQEQEQEQEQEQEQEQEQEQEsVS t?3\կ~GC]+t?SUEpA5fA_yEmWAO՛oiLf_^b7iEo:_b.EQEQEQEQEQEQEQEV-6? X8*GP} u5>: ( ( +>"ROmsr׷qCM#28sޟmjuEȕ7®lv@ 8xJ4}-.m% ^4Mc^xG"ys}?nفy{7{=VtYjViya-]FFNŒ%I '~jjwvy9~71PH6Kh~.gioڮ#cr*_Ƚu\6j,i9F0X}??&~Ftȏ43ϧD &~ɶk}?#hɶhm!gGOG#:?Gm!ƀ7ofLZ̉>}kgGO[2dfb0@ ((O?zz5uG[F JƭWV?F5oTτw(: 0Ǖjy]?V4ASQG}|z~ ۜ?xzMi^^SsN3j~!V~NyO'nq{P**YU2@j'TTQEW'D=o#ȇףPȥcm?cV`x+E+i|l~AETY<ΫP|Q_ܿ)MEva|u?Vy'??[EۻcިV"-76f]7^%kw76,ZPNR`(溛oim8Zquۈ/nu8ZEMBDŽgݑdzpI=>^V"Z^3JWs]K@.[+>C܃-/g%a(? ?EqQjȾ?ix?+G-/g%a+PE ga KX?ix?+\}}Z/3;Z^3JQ KX?}9V"Z^3JWEVA3V"(_rfvgA3Gը"s3? ?EgA>>C܃-/g%a(? ?EqQjȾ?ix?+G-/g%a+PE ga KX?ix?+\}}Z/3;Z^3JQ KX?}9V"Z^3JWEVA3V"(_rfvgA3Gը"s3? ?EgA>>C܃-/g%a(? ?EqQjȾ?ix?+G-/g%a+PE ga KX?ix?+\}}Z/3;Z^3JQ KX?}9V"Z^3JWEVAdCK/Zl%tf/~` #;wxx)ҼaCelˉp qqEx8ڞμV+U֦kG85ZVM9!$,s jpp< 1ɥ""),c:R\έgmi<ir73!dǁ\Xeʌ oXm<'deݧ{ҠI2sw8硏L湞/%o2Zo8]?%yGžԼKC[[7rH߆۰xsR`Z]$]vx: (,5Z5Z3MwNў;ٜMt̰C /4j ,@3ThN5GK{IQY>v*r9 Ɠ.rϦͥ6i$t@[iy댃\}{ڳ_WR"@@w>[(܌@cXjWWse/pUbɌp +⟪"IlwZ->!{xH<>z$NI%A{UEpA4gJVN_*) ~{7n^oyo1y۴j2/"ȷ$E!Cu]X:5YW0}An!QsNVEb[r$c@Ԡoo_ɠ.\MIRxDgm`q"i?&^Z~+֞O I>ȭ!;.z_Ň/}lݻc95-7[5~0-7E60VFv@zR#FK(-$/Р-NKzmɴsT6sֶ5 s'>Rꡧץ=-b"@ fB1`>_mh:xixMi$k].ʘX6@kOͻ˓c.pO j_9izMPŧ_] *ڈzHsyeq\ppJ] p%v-w@6[''9'4#mZՓãoVQEG[F?!w_)XOտX Jƭ9_QE'Af:Va+?/j(ASQ]o1/O՚t˿o},yr V].Qr^@o/8!ǹdO^E7VO1Ožu\e*:oNFF厵տ~CnǔͿa?~CKEMWAO՛oiU_^ ?Vmה_ !~&zݥ_*^b7iEEPEPEPEPEPEPEPEPX8*GVs-u ;GREb8SPBq~\Gɷm)cpS֤GY?۞%6۞%6kMCm~dnxnxc?coydU~ݽ>9}$?7 / m(/ m(jvztMy~ve8=t5nxnxQ\Mo9GMo9@erCѨ/ m++IJ]桦'oc]m:Rx+E+i#Wwmmn~2G#V\1'O{/(r?uuZW_U>(_QG~_r覢0>c:x^=(#邊((((((((((((((((((((((((((((nʰ?nfnʰ?nf*j&#K("Igi:c{z.d@IQ_Zco:_bj/R1[&G8}w88Jݥ_(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@a+f:@iG~_r覢?E5نYQEqLQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQECwS6Us]5wS6U Kی}WAO>-G<(F?S%|7c8jHLd#@SSSd6* y}O־#vmX.KZqTQM6zž*98`'='lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4'lGl@R}|4}|4,?uuZmB%ܦdCU4??/j)>(͠[SQ]o1/O՞EWEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPW6m..T1dlR>+ȴBK/ɴ _W2,(93јc8潊Jm`;s<h^4Ծxm ayHEyؗ~/6o*x5uӇw_b_ٿ>Ŀ}Uf=;;[K?7Gؗ~/6o*G`{+}fU(p[eo/_lUb_ٿEu% K?7Vhð}n󿽕Ŀ}T}f{8vwؗ~/6o*/_lUYgVQ% 4Q>_b_ٿ>Ŀ}Uf=;;[K?7Gؗ~/6o*G`{+}fU(p[eo/_lUb_ٿEu% K?7Vhð}n󿽕Ŀ}T}f{8vwؗ~/6o*/_lUYgVQ% 4Q>_b_ٿ>Ŀ}Uf=;;[K?7Gؗ~/6o*G`{+}fU(p[eo/_lUb_ٿEu% K?7Vhð}n󿽕Ŀ}T}f{8vwؗ~/6o*/_lUYgV[(d;͹8#8f#?fi%Noz(,((((((((((((((((((((((((((((=ҿ[GE|[3Yf+ 3w( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?taglog-0.2.6/docs/taglog.de.html0000644000175000017500000000216013534701742015141 0ustar johnjohn Taglog

Taglog - Persönliches Zeitmanagementsystem

Taglog wurde für alle geschrieben, die ihren Tag hauptsächlich am Computer sitzend und and verschiedenen Projekten arbeitend verbringen. Sie können Notizen über Ihre Tätigkeiten anfertigen und im Weiteren mit den bearbeiteten Projekten assoziieren. Sie können zum Wochenende einen Bericht zur Buchhaltung anfertigen, in dem Ihre Tätigkeiten nach Zeit für die diversen Projekte aufgeschlüsselt ist. Sie können Ihre Einträge nach Datum oder Projekt sortiert durchsehen. Sie können Ihre geplanten Aufgaben eingeben, mit einem Projekt assoziieren und als aktiv oder erledigt kennzeichnen.

Taglog ist freie Software und steht unter der GNU Public License.


Taglog home page (English)

Author: John Lines john+taglog@paladyn.org
taglog-0.2.6/version0000644000175000017500000000000613603645470013066 0ustar johnjohn0.2.6 taglog-0.2.6/worklog.dsc0000644000175000017500000000125413534701742013641 0ustar johnjohnTag-dsc-version: 1.0 Describes: worklog Introduction:: END_I Describes the worklog record format END_I End: Tagname: Id Type: Primary Description:: END_D provides an identifier for that action. Often based on the current time when the record was created - but can be anything which will make that record unique END_D End: Id Tagname: StartTime Description: The time the activity starts End: Tagname: EndTime Description: The time the activity ends End: Tagname: Project Description: The project field indicates the project being worked on End: Tagname: Description Description:: END_D What actually happened during the period between the StartTime and the EndTime END_D End: taglog-0.2.6/README.md0000644000175000017500000000021513534701742012735 0ustar johnjohn# taglog Taglog provides an electronic workbook, combining logging of time to projects with keeping a detailed diary of what you actually do taglog-0.2.6/changelog0000644000175000017500000006052713603645436013350 0ustar johnjohnChanges to taglog. Version 0.2.6 Periodic Action feature - actions which re-activate Daily, Weekly, Monthly or Yearly Version 0.2.5 Fixes to URLs in Documentation for change from old paladin.demon.co.uk domain to github hosting Version 0.2.4 Bug fix in taglog_action - rewrite actin_setup_fields to not need to upvar an array element Version 0.2.3 File/Open now resizes to handle multiple decades better. Project/Add has the ability to record the amount of time you expect to spend working on the project before it is complete. Project/Edit can now edit additional details of a project by clicking on the project name "Reports/Total Time for a Project" now reports the total expected time. The displayed time format is now set via Preferences (patch from Kirill) Version 0.2.2 There is now a History button on the action edit display, which allows a shortcut to display of the history of that action. Delegated actions can be have Active-after set on them and they will automatically become active after that time. Fix a bug in setupAutoId when entering an action and no project had been set. Version 0.2.1 Fix install.tcl to handle the Debian install New report - Active Actions Review. The subroutine dateRangeToLogfileList has moved from taglog to taglog_util, and the end date - if automatically generated - is the time the function is run, not that start of that day. If the Expected-Time or Expected start or end dates are revised then the original Expected-Time is preserved as Original-Expected-Time etc, so that Expected-Time etc can be used as the current value for these. New routine doReviseAction with most of the logic from doRevise, but decoupled from the History window. In system mode install.tcl sets the library files to world readable. Version 0.2.0 The installer now creates the directory into which the activities file will be copied if it does not already exist. Skeleton Internationalization files for French and Dutch are installed, though they are not yet usable. A new routine handleMidnight is called at midnight if the program is still running to switch to a new log file. This is still experimental. Initial support for Subtasks - they can be added from Add or Edit an action via the Add Subtask option. Fix a bug where if Add/Edit log was used to create a file for new day the headers were incorrect. Fix a bug where Add/Edit removed headers from existing files. New tag.tcl function 'tag findval [] returns the index into taglist of the entry where field == value. New tag.tcl function 'tag find [] which is like tagfindval, but for arbitrary tests as per tag extract. New utility facility Actions/Extra.../Update All Subtasks, manually updates the Subtask field in all actions. The preferences item showtime_spreadoverheads is now a selection, rather than boolean. It can be (at present) off, byweek, byday If debug is enabled in the preferences file the command File/Debug is available. This creates a window into which TCL commands can be entered for debugging purposes. e.g. 'global debug; puts "debug is $debug"' or 'source ./mainwin.tcl' The activeactions internal list now contains an index into allact. The setactionsmenu procedure has moved from the main taglog file into taglog_action.tcl The active action selector now moves subtasks into submenus (one level only) The code to automatically generate Action Ids is now in setupActionId Find taglog_help_en.tag when in local system install case (bug report and patch from Greg Simpson. There is the start of support for spreading overheads by day rather than by week - this is not yet complete. Version 0.1.57 The today action reminders are now read in on a restart. Projects which have been closed can be archived. Version 0.1.56 The preferences file ~/.taglog is sourced early to permit it to be used to store the location of the library files. The libsdir variable is preserved in the preferences. Make openNewLogFile only write the logentries if dealing with today. Version 0.1.55 Fix bug whereby the initial header was not written to the daily log file under some circumstances. The log view results window can be resized. Incorporate patched version of install.tcl from Michael Schlenker, with user interface improvements Version 0.1.54 Add monthly and annual summaries. The annual summaries can also be edited from the Open... menu. Version 0.1.53 install.tcl puts the activities file into a system location for the system type installs. The Day Summary is only saved once if you exit multiple times in a day. Log file viewing can show only the summary of the selected days. Todays summary can be edited without exiting the program. reorganise fillpreventries so it does not read from file, which is now done by readlogentries. In tag.tcl setorreplace now takes an optional extra argument as an end label for updating muliline entries. Version 0.1.52 Implement an immutable flag for projects. Update FirstDayOfWeek to match ISO 8601 definition of a week. A new tutorial section covers projects in more depth. Version 0.1.51 New toplevel menu entry Reports/Active and pending actions - generates a todo list (short cut to doing Actions/View and selecting Active, Pending and Sort by Priority) The Actions View Save As uses tk_getSaveFile The 'Today actions' are automatically updated when an action is added or changes state Version 0.1.50 New procedure in tag.tcl tag_entryVal, returns the value of an entry. taglog_getList in taglog_util.tcl uses allproj (new internal format of the projects information), rather than projects (old format) taglog_action.tcl uses taglog_getList to get the active projects. Take unneeded referenced to projects out of logEdit.tcl, mainwin.tcl taglog_init.tcl taglog_report.tcl now uses allproj rather than projects global array. taglog_projects using allproj rather than projects in initProjTimes, setupProjMenu,isbreak,isoverhead etc. Version 0.1.49 Fix a couple of bugs when trying to save information which does not exist. Check action titles before saving, also check activitiesfile for existence. Improve the tutorial section on actions, and on working with other systems. Version 0.1.48 The default_save_timebookings_file can be specified as a global variable in the taglog config file. The timebookings_file_format can be overridden, to force crlf line termination (for example) There is a new tutorial secion dealing with working with other systems. The totals handling has been tidied up within the showTimeBookings procedure to fix a bug in reporting on multiple weeks (thanks Patrice) Add /usr/share/taglog to the locations searched for help files Version 0.1.47 Add /usr/share/taglog to the locations searched for the library files. Tidy up format of the TimeBookings SaveAs report, removing unwanted spaces. Make the default file type .csv for TimeBookings SaveAs Version 0.1.46 Patch from Giuseppe Barisan to store activity types in a seperate file (called activities). There is a Save As option on the Time Bookings report. It saves the bookings information as Comma Seperated Value format. Note that this feature is new and the format of the file it saves to may change a little depending on feedback from users. Version 0.1.45 Check for tcl versions <8.2 and use slower file parsing method and no binary search for help. Version 0.1.44 taglog has a 'package require Tk' so it can be wrapped with sdx install.tcl has a new -vfs argument which builds a taglog.vfs Actions can have a Summary, which can be updated to reflect its current status. The update can be done by editing the action from within the Action/View and right click edit system, or by editing from within the Action/History display and then clicking Revise. Today actions in mainwin created in display_today_actions, ready to make this more flexible Right click in Action in the central Actions bar to edit the current action. Version 0.1.43 The Project Progress Report defaults to all projects if no project is specified. Total Time for a project report shows breakdown by activity - patch from Giuseppe Barisan The Project Progress Report can save its report as HTML Version 0.1.42 The help facility now uses sorted help files and a binary search. The projects in the 'Projects View' display are sorted before display to make it easier to find a particular project. Version 0.1.41 Rewrite 'tag readfile' in tag.tcl. Hopefully faster and uses less memory. Version 0.1.40 Updated German translations from Alexander Spanke The default for the week that time bookings starts is a preferences item. (You can default to last week or this week) Version 0.1.39 In the weekly time bookings report an absense of entries for Saturday or Sunday is not reported as an error. In taglog_report the firstDayOfWeek calculation separated into its own routine, and fixes off by two weeks bug. dateformat_tcl is now saved in preferences in addition to dateformat_view The summary of the day is now read in when the file is read in, so if you exit and restart the summary is preserved. The current project is first selection in the actions/add Projects selections Incorportate updated German translations and mc patches from Alexander Spanke Version 0.1.38 In the logedit window the description area expands if the window is resized. In action input Active after is now labeled as a date, so can be picked from a calendar widget. In the logedit window the Rate can be edited. In the logedit window the stack info is preserved. Fix a bug in adding actions where the language was not set to English Version 0.1.37 In taglog_init can choose the Data directory root with tk_chooseDirectory if tclversion >= 8.3 Cancel the wm protcol WM_DELETE_WINDOW at the start of doquit New action status - Delegated and field - Delegated-to Increase the size of the Projects URL field in Preferences The defaults for whether overheads are spread or not is a preferences item, and now defaults to true. Improvements to the rounding of times in the Time Bookings report. The time bookings report is more robust against weeks with no bookable time Version 0.1.36 Catch errors with start procedures. Sanity checks on the number of today actions and window sizes in prefs tag.tcl has a new subcommand 'tag readbuf' - like 'tag readfile' but it reads from a buffer. Can get projects list from a web server over http (Projects/Update) Some minor updates to the help (in English) New users automatically get the preferences page. Windows users now store files under USERPROFILE directory by default Projects in the Project selection menu are sorted so that those flagged as Active appear first in the list. Version 0.1.35 The 'builders are here' release Fix a bug in the setup of start_procs where it was possible to set it to a blank, but non empty string, which stopped taglog starting. New package taglog_stack, which provides an actions and projects stack - you can push your current action onto it and return to it when you are done. Added some general time management hints under the main help section. Bugfix for finding the help files under ~/lib/taglog Version 0.1.34 Fix installation on Windows to drives other than C: (patch from Ron Fox) From Actions/Extras you can archive actions which were completed or aborted more than a month ago. Note that if you have actions from a version of taglog which did not add a Completed-date then you will have to add this yourself by hand. The archived actions are stored in the data directory root with a name based on the year and month) New tutorial section on Preferences. Version 0.1.33 The location of the preferences file can be read from the commmand line. (taglog -c prefsfile) The data files can be read and written in locations under the data directory root - for example on a network drive. The procedures which are run at startup can be modified via the preferences, allowing the program to start with the main window iconified and the Projects View window opened. Create the document directory on installation if it does not exist. Version 0.1.32 Fix week 8 problem (and document the convoluted code so I dont tidy it up again) Version 0.1.31 Fix project times total initialisation bug. Saveprefs if we found projects in them, makes sure they are in the projects.tag file Tidy up Edit projects window a little - anchor the breaks label to the left and the active label to the right Display the native name of the prefs file in the title of the Edit Preferences window. Use trace to highlight the current project in Projects/View. Help overviews for the main window items. Version 0.1.30 The previous entries window is now marked as disabled for user text input. New maintenance program sort_taghelp - sorts taghelp entries. Projects can now be flagged as Active, in which case they always appear in the Time Bookings (Projects/View) window. The current project is highlighted in the Projects/View window. You can switch active projects from the Projects/View window by clicking on the project labels. Version 0.1.29 Time Bookings reports can be mailed. Fix bug in Weekly Time Bookings report intialisation (stopped working in 2002) Add a large number of translation fixes from Alexander Spenke Version 0.1.28 Bugfix for unix system installed version to locate help files Bugfix for failing to create an action when contacts is empty. Bugfix for Projects/edit with no projects Projects are now read from projects.tag, rather than from preferences Bugfix for Edit of old logs - labels for times wrong when langauge was english. New field Default-as can be entered in contacts, but it does not do anything yet, it is a placeholder for a future release. Version 0.1.27 New files logEdit.tcl and taglog_widgets.tcl replace tkCal.tcl and calUtil.tcl logEdit.tcl from Alexander Spanke replaces 'File/Add old' entry with greatly improved editing system for old log entries. New Unix system installation option - see INSTALL All modules are now invoked as packages. The display setup has been moved from taglog to mainwin.tcl Incorporate the following changes from Alexander Spanke - translation continued (de.msg) - autocompletion of text in entry widgets which are associated with taglog lists (list of projects, activities ...) - two new variables GL_autoComCase and GL_autoComMsec in taglog_init.tcl control the behaviour of the autocompletion - function "menu_create" modified, autocompletion can automatically started within that function (uses function taglog_getList) - the entry widget for project in the main window resize automatically to the length of the largest project name - new function taglog_getList in taglog_util.tcl provides one of the taglog lists (list of projects, activities ...) - new function taglog_getMaxMembLen in taglog_util.tcl provides the length of the largest name in a taglog list Update install.tcl to aid debian packaging. Add a very brief manual page for taglog. Version 0.1.26 Line up the labels in the Actions input/edit window Change actionInputWindow to allow it to be called several times simultaneously. The selector for the time bookings report now indicates the range of dates which have been selected - patch by Alexander Spanke Active actions are displayed in priority order for tcl version 8 Patch from Alexander Spanke to fix the totals display formatting in the time bookings report under Windows Initial support for message catalogs for tcl >=8.2 - Translations welcomed ! Fix bug in selector for File/Open Complete and Abort from the End button enabled. Log entry Id now contains the seconds value as well as hhmm Action sequences - with Next-action and Abort-action fields. Version 0.1.25 This release is decicated to those who died in the terrorist actions of 11th September 2001. No cause is furthered by the taking of innocent lives. Projects are saved as a tagged accountproject type (but also saved to the preferences file). They are still read from preferences now. New calendar widgets, contributed by Alexander Spanke-Meppen allow dates to be selected more easily - click on the calendar icons. Minor fixes to the English help file, and an updated German help. Fix install.tcl bug which did not install German help. Take out all references to array unset for tcl8.2 compatibility. Fix bug in editing actions which caused multiple actions to be offered up for edit. Version 0.1.24 taghelp can take an additional argument and this will be substituted for $1 in the help description. Help/About is now done through the help system. German help translation provided by Alexander Spanke-Meppen Minor help file fixes. Fix Time Bookings report for hh:mm format (was doing hh:mm:ss) The 'Select Log Files...' display has each decade on a new line An Id prefix can be set in preferences and will be prepended to Auto action Ids The projects in the actions view selector can be all projects or only active projects The titles of the actions at the top of the display can be selected from the actions which are active at startup. New tag.tcl command sort - returns a tagged list in sorted order Selected actions in Actions/View can be sorted by Priority before display The Action drop down list in the middle menu bar is sorted by priority Version 0.1.23 Additional fields in Contacts for notes, organisation Separators in Contacts listing Edit contacts by right click after a listing. Preferences settings for the sizes of the history and current frame Preferences setting for number of reminder actions to display (Above changes to allow taglog to occupy less screen space) Fixed SMTP init for Win32 systems (was trying to find a username from the environment) smtp tag attachments are now named noname.tag by default or given a name with the -attachname switch to the smtp send command. taglog_report no longer uses 'array unset' for tcl3.2 compatibility taglog_util and taglog_project split from main taglog file Log file listings (from File Open..) can be saved as html Version 0.1.22 The action input menu is now scrollable, for use in systems with small displays. Edit an action by right click from the Action/View display A little bit of the help translated with the aid of babel.altavista.com Fix a bug in logfilename2date which swapped US and European date formats The weekly timebookings by project report will do several weeks Version 0.1.21 Incorporate many patches from Greg A. Woods The root directory (defaulting to ~/diary) is now a preferences item. The date input and display format is a preferences item. (Not used everywhere yet) View Contacts started You can mail an action to someone instead of adding it to your own actions file Projects/Edit is now scrollable. Delete projects within Projects/Edit implemented Actions/View selections for expected dates improved. Version 0.1.20 The 'End' button in the cnetre panel now allows a Contact name and/or a Rate (such as Overtime) to be associated with a log entry. Log file entries can be searched on Contacts and Activities. Version 0.1.19 Fix 'millenium bug' in Weekly Time bookings by project. It had hard- wired date calculation which only worked for Year 2000. Remove many warnings reported by Frink, the static TCL checker found at ftp://catless.ncl.ac.uk/pub/frink.tar.gz Version 0.1.18 Help information extended to more areas. Edit Preferences command in the File menu. The start of a facility to manage contacts, initially as a helper for the Email-status-to action field. Version 0.1.17 There is the start of a context sensitive help system, potentially in multiple langauges - translators welcomed. Fixed a bug which prevented the start time of the first entry of the day from being adjusted via the Start button Minor improvements to install.tcl - it may work for Windows now You can right click (button 3) on a log entry in the previous entries window to edit it. Version 0.1.16 Can add old log entries, currently aimed at 'blocking in' whole days of leave, or working off site. The new entry is always appended to the log file - it does not sort them into chronological order. Implement the active_after facility which allows actions to be activated automatically after a given date and time. Changed the handling of actions so they are not read in on every change (but now reside in memory) Version 0.1.15 Time bookings displayed by Project Code instead of, or as well as project name now implemented Implemented a first pass at the time by activity report. The install.tcl script works for the case of Unix user install Version 0.1.14 Action related routines now in taglog_action.tcl The action ID is now taken from the project title plus a serial number, giving more meaningful action IDs, e.g. This_Project.1 not taglog.20000926 Added the ability to clear the current action. Dont save the description of a log entry if it is empty. Rudimentary mail support (in smtp.tcl) New Action field - Email-status-to - when the status of an action changes this address is notified. Totals in the Time Bookings report are now displayed in bold Version 0.1.13 History of an action can be saved to a file The expected time and expected completion date of an action can be revised from the action history menu. New tag.tcl routine update - update an entry in a tagged file New tag.tcl routine setorreplace - replace an item in an entry if it exists, or add it as an new item. Version 0.1.12 New tag.tcl routine - readselected (combines readfile and extract) Install.tcl does a basic install for limited cases, with no selection. Initialisation routines now in taglog_init.tcl Dont output a tab on the end of report lines in the time bookings report Total time for a project report now picks up project start and end dates The basics of 'History of an action' now work. Version 0.1.11 Internal routines now operate in seconds rather than minutes The view old logs display has the date of the entries as seperators Bug fixes to the logfilename2date routine, thanks to Bruce Gingery Add a menu for easier selection of typical priority values when adding an action Add a menu for easier selection of typical Expected-time values when adding an action. Menu item to allow a Closed Action to be Reactivated. The abiltity to add notes to an action when it changes state Report procedures are now in taglog_report.tcl Started a project progress report routine. Can select actions to view by their expected start or completed dates Version 0.1.10 Allow Actions for viewing to be selected from more than one file Version 0.1.9 More information in the total time for a project report Actions state change selections now scroll Spread overheads across other bookable projects Version 0.1.8 Report on time bookings for a project. (still with a couple of rough edges) Minor tutorial updates Version 0.1.7 Ability to display time bookings in decimal days Formatting impovements to Time Bookings display. Projects have a start and end date, set in Projects/Add and Edit Fix bug in Projects/Edit where flags could only be set, now can be unset as well. Projects which are past their end date do not appear in the list for booking time to. Version 0.1.6 Projects edit works for all fuctions except delete Difficulty setting in actions/add is now a button to select possilbe values New Actions menu items to abort pending or active actions Bugfix - 0.1.4 changes had the test for a breaks project the wrong way round Version 0.1.5 New menu items Actions/Complete and Actions/Activate move actions from active to completed and pending to acitve respectively Version 0.1.4 Each element of the projects list is now a list, first eleement is name, then action index, bookas, overheads flag, breaks flag Menu entry (probably temporary) Actions/Refresh Active - refresh the active actions list. (still have to edit actions file outside the program Version 0.1.3 Ability to select actions by priority Book time to actions as well as projects Select which actions fields are diplayed Start of ability to edit projects (not yet working) Tutorial extended. Ability to select log entries which contain some string Right click on the 'Next' button gives a next action menu Can enter a Difficulty field in Actions/add Version 0.1.2 tutorial.html started. Version 0.1.1 Weekly report of time bookings works (for year 2000 at least) taglog-0.2.6/README0000644000175000017500000000250613534701742012343 0ustar johnjohn Taglog - an actions logging program Taglog provides an electronic workbook, combining logging of time to projects with keeping a detailed diary of what you actually do. Individual work elements can be tagged by project, allowing you to produce, for example, a record of work on one particular project, even if your time is spread across a number of projects. Work items can also be tagged by activity type - for example meeting, phone, programming etc - allowing you to analyse where your time is going by activity. Note that this activity type is orthogonal to the project axis, so that - for example - user support would be a project - in the larger sense WHAT you are doing - and phone calls to users - HOW you are doing it - would be the activity type. Initialisation -------------- Taglog reads a configuration file to find default values for some things. It looks in /etc/taglog.conf and ~/.taglog and sources each of these in turn, so these must contain valid TCL. If it does not find either it uses defaults built into the program. The main thing it finds in the configuration file is the list of projects you are working on. It is best to create this using Project/Add from within the program. Then you can override the other preferences settings yourelf. Most of the preferences can be edited from the File/Preferences menu item. taglog-0.2.6/src/0000755000175000017500000000000013603645436012253 5ustar johnjohntaglog-0.2.6/src/taglog_help_it.tag0000644000175000017500000000107713534701742015732 0ustar johnjohnTag-help-version: 1.0 Translated-by: John Lines End: Id: UNKNOWN Description:: END_D Non ci aiuto per questo articolo in Italiano. Sarei molto riconoscente se poteste fornire una traduzione a john+taglog@paladyn.org END_D End: Id: prefs_language Description:: END_D Questo campo indica il vostro linguaggio preferito, come codice di linguaggio di iso 639. Attualmente soltanto le informazioni di aiuto sono disponibili sono disponibili in pi di un linguaggio. L' aiuto con le traduzioni migliori e pi linguaggi sempre apprezzato END_D End: taglog-0.2.6/src/de.msg0000644000175000017500000003003613534701742013351 0ustar johnjohn# namespace import -force msgcat::mcset mcset de Help Hilfe mcset de Cancel Abbruch mcset de Quit Abbruch mcset de Exit Ende mcset de Next Weiter mcset de Action Aktion mcset de Actions Aktionen mcset de actions Aktionen mcset de Reports Berichte mcset de Preferences Einstellungen mcset de Open... ffnen mcset de Pause Anhalten mcset de Resume Fortfahren mcset de {Add/Edit Log} {Log Hinzufgen/ndern} mcset de Add... Hinzufgen... mcset de View Ansicht mcset de Complete Abschlieen mcset de Activate Aktivieren mcset de {Abort Active} {Abbruch Aktiv} mcset de {Abort Pending} {Abbruch Wartend} mcset de Abort Abbrechen mcset de Reactivate Reaktivieren mcset de Projects Projekte mcset de Add Hinzufgen mcset de Edit Bearbeiten mcset de About ber mcset de {Please select the date of log} {Bitte das Datum fr Logeintrge auswhlen,} mcset de {entries to be input or edited} {die bearbeitet oder neu eingegeben werden sollen} mcset de {Input and editing of log entries} {Eingabe und Bearbeitung von Logeintrgen} mcset de "Log edit" Log-Bearbeitung mcset de "Date selection" "Datumauswahl" mcset de "No date selected" "Kein Datum ausgewhlt" mcset de "Invalid date format" "Ungltiges Datumsformat" mcset de "Editing of log file" "Bearbeitung einer Log-Datei" mcset de Day Tag mcset de day Tag mcset de days Tage mcset de week Woche mcset de "Import of log entries" "Import von Logeintrgen" mcset de File Datei mcset de {No entries found in file} {Keine Eintrge gefunden in Datei} mcset de "Import all" "Alles" mcset de Import Importieren mcset de Project Projekt mcset de "End " Ende mcset de End Ende mcset de Delete Lschen mcset de "Edit log entry" "Bearbeitung eines Log-Eintrages" mcset de "Add a new entry" "Neuer Log-Eintrag" mcset de {Start Time} Startzeit mcset de {End Time} Ende mcset de {ActionTitle} {Titel der Aktion} mcset de Activity Aktivitt mcset de Contact Kontakt mcset de Contacts Kontakte mcset de Save Speichern mcset de "Save As..." "Speichern unter..." mcset de Description Beschreibung mcset de "Adjust to previous EndTime" "Zeit an vorheriges Ende anpassen" mcset de "Adjust to following Startime" "An nchste Startzeit anpassen" mcset de "Invalid date range" "Zeitbereich ungltig" mcset de "The StartTime is greater\nthan the EndTime" "Startzeit grer als Endzeit" mcset de "Invalid date" "Ungltiges Datum" mcset de {Please enter a value for} {Bitte einen Wert eingeben fr:} mcset de {is not a valid\ntime value for} {ist keine gltige\nZeit fr Tag} mcset de "There are overlapping (marked with '>')\nand inconsistent (marked with '!') time ranges." "Es existieren berlappende ('>')\nund inkonsistente '(!)' Zeitbereiche." mcset de "There are overlapping time ranges (marked with '>')." "Es existieren berlappende Zeitbereiche." mcset de "There are inconsistent time ranges (marked with '!')." "Es existieren inkonsistente Zeitbereiche." mcset de {Do you want to save?} {Wollen Sie trotzdem abspeichern?} mcset de "Weekly time bookings by project" "Projekte: Wchentliche Zeitbuchungen" mcset de "Time by activity" "Gesamtzeit je Aktivitt" mcset de "Total time for a project" "Gesamtzeit fr ein Projekt" mcset de "Project Progress Report" "Projektfortschritt" mcset de Directory Verzeichnis mcset de "Current Directory" "Aktuelles Verzeichnis" mcset de "File name :" "Dateiname:" mcset de "Save Text" "Speichern als Text" mcset de "Save HTML" "Speichern als HTML" mcset de "Save HTML..." "Speichern als HTML ..." mcset de "Description contains" "Beschreibung enthlt" mcset de "Documentation Directory" "Dokumentationsverzeichnis" mcset de "Data directory root" "Wurzelverzeichnis fr Daten" mcset de Language Sprache mcset de "Hours Worked per Day (decimal)" "Arbeitsstunden pro Tag (dezimal)" mcset de "Date Format" Datumsformat mcset de "European (DD/MM/YYYY)" "Europisch (DD/MM/YYYY)" mcset de "American (MM/DD/YYYY)" "Amerikanisch (MM/DD/YYYY)" mcset de "History Window Depth" {Zeilen fr Historien-Fenster} mcset de "Current Window Depth" "Zeilen fr Log-Fenster" mcset de "Number of 'Today' actions" "Anzahl der 'Heute'-Aktionen" mcset de Prefix Prfix mcset de "SMTP Preferences filename" "Dateiname fr SMTP-Einstellungen" mcset de "email address" "EMail-Adresse" mcset de traditional traditionell mcset de "local mail submission port" "lokaler Mail-Port" mcset de "Input an action" "Eingabe einer Aktion" mcset de {Edit action} "Bearbeite Aktion" mcset de Title Titel mcset de Date Datum mcset de Priority Prioritt mcset de Expected-cost "Erwartete Kosten" mcset de Expected-time "Erwartete Zeit" mcset de Expected-Time "Erwartete Zeit" mcset de Revised-expected-time "Gend. Erwartete Zeit" mcset de Expected-start-date "Erwartete Startzeit" mcset de Completed-date "Fertigstellungsdatum" mcset de Active-date "Aktivierungsdatum" mcset de Aborted-date "Abbruchdatum" mcset de Expected-completed-date "Erw-Fertigstellungsdatum" mcset de Expected-Completed-Date "Erw-Fertigstellungsdatum" mcset de Revised-expected-completed-date "Gend. Erw-Fertigstellungsdatum" mcset de Revised-date Gend-Datum mcset de Precursor Vorgnger mcset de Active-after "Aktiv nach" mcset de Subtask-of "Unteraufgabe von" mcset de Next-action "Nchste Aktion" mcset de Abort-action Abbruch-Aktion mcset de Difficulty Schwierigkeit mcset de nobrainer simpel mcset de trivial trivial mcset de easy leicht mcset de tricky anspruchsvoll mcset de hard schwer mcset de "very hard" "sehr schwer" mcset de Email-status-to "Sende-Status an" mcset de Deliverable Auslieferbar mcset de Reason Grund mcset de Message Nachricht mcset de "Mail to" "Sende an" mcset de "Mail an action" "Sende eine Aktion" mcset de "Add a new project" "Neues Projekt" mcset de "Project name" Projektname mcset de "Book as breaks" "Als Pause buchen" mcset de "Book as overheads" "Als Overhead buchen" mcset de "Booking Code" "Buchungs-Code" mcset de "Start Date" "Startdatum" mcset de "End Date" "Beendigungsdatum" mcset de "Edit Projects" "Projekte bearbeiten" mcset de Breaks Pausen mcset de "Project Times" Projektzeiten mcset de Total Gesamt mcset de "Total (non breaks)" "Gesamt (ohne Pausen)" mcset de Today Heute mcset de "Select date range" "Zeitbereich" mcset de "Enter Project details" Projektdetails mcset de "Enter information for Project Progress Report" "Projektfortschritt" mcset de "Select Time Period" "Auswahl der Zeitbereichs" mcset de "Time Format" Zeitformat mcset de "Decimal hours" "Stunden dezimal" mcset de "Decimal days" "Tage dezimal" mcset de "Spread overhead projects" "Overhead Projekte aufteilen" mcset de "Book by Project" "Sortieren nach Projekt" mcset de Year Jahr mcset de weeks Wochen mcset de "starting at number" "Start bei" mcset de "Time by Activity" "Gesamtzeit je Aktivitt" mcset de "Project Progress Report for" "Projektfortschrittsbericht fr" mcset de "Total Times for" "Gesamtzeit fr" mcset de "Time Bookings" "Zeitbuchungen" mcset de Sun "So " mcset de Mon "Mo " mcset de Tue "Di " mcset de Wed "Mi " mcset de Thu "Do " mcset de Fri "Fr " mcset de Sat "Sa " mcset de "Breaks total" "Pausen gesamt" mcset de "Time Bookings for week" "Zeitbuchungen fr Kalenderwoche" mcset de of von mcset de "Warning - cant open" "Warnung - folgende Datei kann nicht geffnet werden:" mcset de "Total time" Gesamtzeit mcset de "Total time for" "Die Gesamtzeit fr" mcset de is ist mcset de "decimal days" "dezimale Tage" mcset de Examined "Untersucht wurden" mcset de "files and found entries for" "Dateien. Gefunden wurden Eintrge fr" mcset de "of them" "von ihnen" mcset de "First date was" "Erstes Datum:" mcset de "last date was" "Letztes Datum:" mcset de "Adjust start time" "Startzeit anpassen" mcset de "Adjust start time back towards previous start time of" "Startzeit anpassen in Richtung auf vorherige Startzeit von" mcset de "Adjust start time back towards the start of the day" "Startzeit an Tagesbeginn anpassen" mcset de "Adjust previous end time" "Vorherige End-Zeit anpassen" mcset de "New Start Time" "Neue Startzeit" mcset de "Minutes to Subtract from StartTime" "Zu subtrahierende Minuten" mcset de Set "Startzeit setzen" mcset de calendar Kalender mcset de Calendar Kalender mcset de Su So mcset de Tu Di mcset de We Mi mcset de Th Do mcset de January Januar mcset de February Februar mcset de March Mrz mcset de April April mcset de May Mai mcset de June Juni mcset de July Juli mcset de August August mcset de September September mcset de October Oktober mcset de November November mcset de December Dezember mcset de "Select Contacts to view" "Auswahl zum Anzeigen von Kontakten" mcset de Forename Vorname mcset de Phone Telefon mcset de Type Typ mcset de Surname Nachname mcset de "Contacts Display" "Anzeige der Kontakte" mcset de Close Schlieen mcset de Address Adresse mcset de Short-id Kurz-Id mcset de "Input a contact" "Kontakt eingeben" mcset de "Edit contact" "Bearbeite Kontakt" mcset de Mr Herr mcset de Ms Frulein mcset de Mrs Frau mcset de "Default-as" "Vorbesetzen mit" mcset de "Mobile Phone" Mobiltelefon mcset de Postcode Postleitzahl mcset de Country Land mcset de Note Bemerkung mcset de "Select Actions ..." "Aktionen auswhlen ..." mcset de Filename Dateiname mcset de All Alle mcset de Any Beliebig mcset de Unclaimed Unveranlagt mcset de Pending Wartend mcset de Active Aktiv mcset de Blocked Blockiert mcset de Completed Abgeschlossen mcset de Aborted Abgebrochen mcset de "Date Expected" "Erwartetes Datum" mcset de Tomorrow Morgen mcset de Later Spter mcset de Earlier Frher mcset de "Show Fields" "Felder anzeigen" mcset de "Due Date" "Flligkeitsdatum" mcset de Refresh Aktualisieren mcset de "Sort by" "Sortieren nach" mcset de "Actions view of" "Aktionen, Sicht von:" mcset de "Save Action History As ..." "Speichere Aktions-Historie unter..." mcset de "Action history" "Historie fr Aktion" mcset de Revise ndern mcset de History Historie mcset de Duration Dauer mcset de "Total duration" Gesamtdauer mcset de "Save Actions Display As ..." "Speichere Aktionsanzeige unter ..." mcset de "Save Log View Display As ..." "Speichere Log-Anzeige unter ..." mcset de "Select Log Files ..." "Auswahl von Log-Dateien" mcset de "Log view" "Log-Anzeige" mcset de "Edit Preferences" "Bearbeite Einstellungen" mcset de Displayed Angezeigt: mcset de "Total expected time" "Gesamte erwartete Zeit:" mcset de unknown unbekannt mcset de "Pick an action to move from" "Wechsel des Status einer Aktion von" mcset de to nach mcset de "Refresh Active" "Liste der aktiven Akt. neu aufbauen" mcset de "Active Time Blocked" "Aktiviere fllige Aktionen" mcset de "Archive Old Actions" "Archiviere alte Aktionen" mcset de colleague Kollege mcset de customer Kunde mcset de supplier Lieferant mcset de contact Kontakt mcset de friend Privat mcset de "Interruptions Report" "Unterbrechungen" mcset de "There were a total of" "Es gibt insgesamt" mcset de "interruptions in" "Unterbrechungen in" mcset de "days." "Tagen." mcset de "The average number of interruptions in a day was" "Die durchschnittliche Anzahl von Unterbrechungen pro Tag war" mcset de "The peak number of interruptions per day was" "Die Spitzen-Anzahl von Unterbrechungen pro Tag war" mcset de "vCard Files" "vCard Dateien" mcset de " vCard files to Import" " Zu importierende vCard Dateien" mcset de "Introduction" "Einfhrung" mcset de "Hints" "Hinweise" mcset de "Actions overrun" "berschreitung der geplanten Zeiten" mcset de "Actions not completed" "Aktivitten nicht beendet" mcset de "Interruptions" "Unterbrechungen" mcset de "Progress from" "Fortschritt von" mcset de " to " " bis " mcset de "Achievements" "Erreichtes" mcset de "Tasks completed since last report" "Seit letztem Bericht erledigte Aufgaben" mcset de "Expected" "Erwartet" mcset de "Actual" "Tatschlich" mcset de "Tasks started since last report" "Seit letztem Bericht gestartete Aufgaben" mcset de "Tasks slipped since last report" "Aufgaben, die die Zeit berschreiten werden" mcset de "Active tasks" "Aktive Aufgaben" mcset de "Scheduled" "Geplant" mcset de "Forecast" "Prognose" mcset de "Completion" "Erledigung" mcset de "Delegated-to" "Delegiert an" mcset de "Delegated" "Delegiert" mcset de "delegated" "delegiert" mcset de "Pick" "Auswahl" mcset de "Update" "Aktualisierung" mcset de "meeting-preparation" "Besprechungsvorbereitung" mcset de "meeting" "Besprechung" mcset de "email" "EMail" taglog-0.2.6/src/taglog.xbm0000644000175000017500000000052013534701742014231 0ustar johnjohn#define taglog_width 16 #define taglog_height 16 #define taglog_x_hot 7 #define taglog_y_hot 8 static unsigned char taglog_bits[] = { 0xc0, 0x01, 0x80, 0x00, 0xec, 0x1b, 0x1c, 0x1c, 0x08, 0x08, 0x0c, 0x14, 0x1a, 0x22, 0x72, 0x21, 0xc2, 0x20, 0x02, 0x21, 0x02, 0x22, 0x04, 0x14, 0x08, 0x08, 0x10, 0x04, 0xe0, 0x03, 0x00, 0x00}; taglog-0.2.6/src/taglog_report.tcl0000644000175000017500000014712513534701742015635 0ustar johnjohn# # taglog_report.tcl - report procedures for taglog # Copyright John Lines (john+taglog@paladyn.org) July 2000, October 2005 # # This program is released under the terms of the GNU Public Licence # package provide taglog_report 0.1 proc doTotalTimeForProjectOK {} { #changed by gbarisan@ieee.org to show activities breakdown global totalprojtimessel_project totalprojtimessel_startdate totalprojtimessel_enddate showtime_format GL_tableFont toplevel .totalprojtimesres wm title .totalprojtimesres "[mc {Total Times for}] $totalprojtimessel_project" frame .totalprojtimesres.main #text .totalprojtimesres.main.body -height 5 #pack .totalprojtimesres.main.body set projtotal "00:00" set firstdate "" set lastdate "" set numprojdays 0 set fileslist [dateRangeToLogfileList $totalprojtimessel_startdate $totalprojtimessel_enddate] set numfileschecked [llength $fileslist] foreach filename $fileslist { set logs [ tag readfile $filename ] set logs [ lrange $logs 1 end ] set thisproject unknown set foundinthisfile 0 foreach entry $logs { set starttime 0 set endtime 0 foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } { # Because this is the end tag we should have all the values we are going # to get if { $thisproject == $totalprojtimessel_project } { set duration [timediff $starttime $endtime] inctime projtotal $duration if {$firstdate==""} { set firstdate $filename } set lastdate $filename if {! $foundinthisfile } { set foundinthisfile 1 incr numprojdays } } set duration "00:00" set thisproject "" } elseif { $tagname == "StartTime" } { set starttime $tagvalue } elseif { $tagname == "EndTime" } { set endtime $tagvalue } elseif { $tagname == "Project" } { set thisproject $tagvalue } else { } } } } ########### Calculating the activities breakdown #added by gbarisan@ieee.org on 2003-11-07 # set activities {} set acttotal "00:00" set actProj "" foreach filename $fileslist { set logs [tag readfile $filename] foreach entry $logs { set starttime 0 set endtime 0 set activity unknown foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } then { if { $actProj == $totalprojtimessel_project} { set duration [timediff $starttime $endtime] # more to do here inctime acttotal $duration if { [lsearch -exact $activities $activity] == -1 } { lappend activities $activity set acttime($activity) "00:00" } inctime acttime($activity) $duration} } elseif { $tagname == "StartTime" } { set starttime $tagvalue } elseif { $tagname == "EndTime" } { set endtime $tagvalue } elseif { $tagname == "Activity" } { set activity $tagvalue } elseif { $tagname == "Project"} { set actProj $tagvalue } else { } } } } set resultheight [expr {[array size acttime] + 12} ] if { $resultheight > 20 } { text .totalprojtimesres.main.body -rel sunk -yscrollcommand ".totalprojtimesres.main.sb set" -height $resultheight \ -font $GL_tableFont -tabs { 5c left 2c 2c left } pack .totalprojtimesres.main.body -in .totalprojtimesres.main -side left -fill y scrollbar .totalprojtimesres.main.sb -rel sunk -command ".totalprojtimesres.main.body yview" pack .totalprojtimesres.main.sb -in .totalprojtimesres.main -side left -fill y } else { text .totalprojtimesres.main.body -rel sunk -height $resultheight \ -font $GL_tableFont -tabs { 5c left 2c 2c left } pack .totalprojtimesres.main.body -in .totalprojtimesres.main -side left -fill y } pack .totalprojtimesres.main .totalprojtimesres.main.body insert end "[mc {Total time for Project}] '$totalprojtimessel_project' [mc is] " set saved_format $showtime_format set showtime_format 2 DisplayTime .totalprojtimesres.main.body projtotal .totalprojtimesres.main.body insert end " [mc {decimal days}] = " set showtime_format 0 DisplayTime .totalprojtimesres.main.body projtotal .totalprojtimesres.main.body insert end " hh:mm\n" .totalprojtimesres.main.body insert end "[mc Examined] $numfileschecked [mc {files and found entries for}] '$totalprojtimessel_project' in $numprojdays [mc {of them}]\n" set firstdate [logfilename2date $firstdate] set lastdate [logfilename2date $lastdate] .totalprojtimesres.main.body insert end "[mc {First date was}] $firstdate - [mc {last date was}] $lastdate\n\n" .totalprojtimesres.main.body insert end "[mc Activity]\t[mc {Total time}]\n\n" foreach act [array names acttime] { .totalprojtimesres.main.body insert end "$act\t$acttime($act)\n" } .totalprojtimesres.main.body insert end "\t--------\n" .totalprojtimesres.main.body insert end "\n[mc Total]\t$projtotal\n" ############ end of gbarisan changes set proj_ExpectedTime [proj_getExpectedTime $totalprojtimessel_project ] .totalprojtimesres.main.body insert end "[mc {Total Expected}]\t$proj_ExpectedTime\n" pack .totalprojtimesres.main frame .totalprojtimesres.bot button .totalprojtimesres.bot.ok -text OK -command {doCancel .totalprojtimesres } pack .totalprojtimesres.bot.ok -in .totalprojtimesres.bot pack .totalprojtimesres.bot tkwait window .totalprojtimesres } proc TotalTimeForProjectProjSel { project } { global totalprojtimessel_project totalprojtimessel_startdate totalprojtimessel_enddate set totalprojtimessel_project $project set totalprojtimessel_startdate [getprojstart $project] set totalprojtimessel_enddate [getprojend $project] } proc doTotalTimeForProject { } { global allproj totalprojtimessel_project toplevel .totalprojtimes wm title .totalprojtimes [mc "Enter Project details"] frame .totalprojtimes.selproj frame .totalprojtimes.selproj.p menubutton .totalprojtimes.selproj.p.project -text [mc Project] -menu .totalprojtimes.selproj.p.project.m menu .totalprojtimes.selproj.p.project.m .totalprojtimes.selproj.p.project.m add command -label "--" -command "set totalprojtimessel_project \"\"" foreach proj $allproj { set pname [tag_entryVal $proj Name] .totalprojtimes.selproj.p.project.m add command -label $pname \ -command "TotalTimeForProjectProjSel \"$pname\"" } entry .totalprojtimes.selproj.p.projectentry -textvariable totalprojtimessel_project -width 20 pack .totalprojtimes.selproj.p.project .totalprojtimes.selproj.p.projectentry -in .totalprojtimes.selproj.p -side left pack .totalprojtimes.selproj.p frame .totalprojtimes.selproj.s menubutton .totalprojtimes.selproj.s.start -text [mc "Start Date"] -menu .totalprojtimes.selproj.s.start.m menu .totalprojtimes.selproj.s.start.m # .totalprojtimes.selproj.s.start.m add command -label "--" -command "set totalprojtimessel_startdate xxx" # .totalprojtimes.selproj.s.start.m add command -label "--" -command "set totalprojtimessel_startdate \"[getprojstart $totalprojtimessel_project\"" #entry .totalprojtimes.selproj.s.startentry -textvariable totalprojtimessel_startdate -width 10 calUtil_win .totalprojtimes.selproj.s.startentry "" totalprojtimessel_startdate pack .totalprojtimes.selproj.s.start .totalprojtimes.selproj.s.startentry -in .totalprojtimes.selproj.s -side left pack .totalprojtimes.selproj.s frame .totalprojtimes.selproj.e menubutton .totalprojtimes.selproj.e.end -text [mc "End Date"] -menu .totalprojtimes.selproj.e.end.m menu .totalprojtimes.selproj.e.end.m calUtil_win .totalprojtimes.selproj.e.endentry "" totalprojtimessel_enddate pack .totalprojtimes.selproj.e.end .totalprojtimes.selproj.e.endentry -in .totalprojtimes.selproj.e -side left pack .totalprojtimes.selproj.e pack .totalprojtimes.selproj frame .totalprojtimes.bot button .totalprojtimes.bot.ok -text OK -command doTotalTimeForProjectOK button .totalprojtimes.bot.cancel -text [mc Cancel] -command { doCancel .totalprojtimes } pack .totalprojtimes.bot.ok .totalprojtimes.bot.cancel -in .totalprojtimes.bot -side left pack .totalprojtimes.bot tkwait window .totalprojtimes } proc DisplayTime { window timevar args } { global showtime_format showtime_hours_per_day global tcl_platform set mm 0 set hh 0 set ss 0 upvar $timevar time if { ! [ info exist time ] } { $window insert end " " return } scan $time "%d:%d:%d" hh mm ss if { $showtime_format==0 } { if { $ss > 30 } { incr mm } set showtime [format "%02d:%02d" $hh $mm] } elseif { $showtime_format == 1 } { # set mins [expr { $mm*100/60 } ] set mins [expr {round( $mm*100.0/60.0) } ] if { $ss > 30 } { incr mm } set showtime [format "%02d.%02d" $hh $mins] } elseif { $showtime_format == 2 } { # show time in decimal days set mins [expr { $hh*60 + $mm } ] set days [ expr { $mins / ( $showtime_hours_per_day * 60) } ] set showtime [ format "%5.2f" $days ] } if {$args == "bold"} { if {$tcl_platform(platform) == "windows"} { $window tag configure boldtag -foreground blue } else { $window tag configure boldtag -font {-weight bold} } $window insert end "$showtime" boldtag } elseif { $args == "bodydata" } { $window insert end "$showtime" bodydata } else { $window insert end "$showtime" } } proc displayProject {} { global showtime_bookbycode } proc mailTimeBookingsOK { } { global mailtb_to set mailtb_message [string trim [.mailtb.message.body get 1.0 end]] set timebook_body [string trim [.timebook.main.body get 1.0 end]] set mailtb_message "$mailtb_message\n\n$timebook_body" if { $mailtb_to != "" } { if { ! [ smtp init ] } { # put up a dialog box saying that mail is not initialised } else { smtp send -subject "Time Bookings report" $mailtb_message $mailtb_to } } destroy .mailtb } proc mailTimeBookings {} { global allcontacts set w .mailtb toplevel $w wm title .mailtb [mc "Mail Time Bookings"] getallcontacts frame .mailtb.main menubutton .mailtb.main.l -text [mc "Mail to"] -menu .mailtb.main.l.m menu .mailtb.main.l.m .mailtb.main.l.m add command -label "--" -command "set mailtb_to \"\"" foreach contact $allcontacts { set thisid "" set thisemail "" foreach item $contact { if { [lindex $item 0] == "Id" } { set thisid [lindex $item 1] } elseif { [lindex $item 0] == "Email" } { set thisemail [lindex $item 1] } } .mailtb.main.l.m add command -label "$thisid" -command "set mailtb_to \"$thisemail\"" } .mailtb.main.l.m add separator .mailtb.main.l.m add command -label [mc "Help"] -command "taghelp mailtb_to" entry .mailtb.main.v -textvariable mailtb_to -width 20 pack .mailtb.main.l .mailtb.main.v -side left -in .mailtb.main pack .mailtb.main frame .mailtb.message menubutton .mailtb.message.l -text [mc Message] -menu .mailtb.message.l.m menu .mailtb.message.l.m $w.message.l.m add command -label [mc Help] -command "taghelp mailtb_message" text $w.message.body -rel sunk -wrap word -yscrollcommand "$w.message.sb set" scrollbar .mailtb.message.sb -rel sunk -command ".mailtb.message.body yview" pack $w.message.l -side left -in $w.message pack $w.message.body -side right -in $w.message pack $w.message.sb -fill y -side right -in $w.message pack $w.message frame $w.bot button $w.bot.ok -text Mail -command "mailTimeBookingsOK " button $w.bot.cancel -text [mc Cancel] -command " doCancel $w " button $w.bot.help -text [mc Help] -command "taghelp mailtb" pack $w.bot.ok $w.bot.cancel $w.bot.help -side left -in $w.bot pack $w.bot tkwait window $w } proc saveTimeBookings {} { global html_public_dir default_save_timebookings_file timebookings_file_format set saveas_dir $html_public_dir set saveas_file "" if {[info exists default_save_timebookings_file ]} { set saveas_dir [file dirname $default_save_timebookings_file] set saveas_file [file tail $default_save_timebookings_file] } set tbfile [tk_getSaveFile -title [mc "Save Time Bookings File"] -defaultextension ".csv" -initialdir $saveas_dir -initialfile $saveas_file -filetypes {{{CSV files} {.csv}} { {All files} {*}}}] if { $tbfile == "" } { return } set f [ open $tbfile "w"] if { [info exists timebookings_file_format ] } { fconfigure $f -translation $timebookings_file_format } # Get the contents of the .timebook.main frame # set timebook_body [string trim [.timebook.main.body get bodydata.first bodydata.last]] set i 1.0 set done 0 set timebook_body "" while { ! $done } { set r [ .timebook.main.body tag nextrange bodydata $i] if { $r == "" } { set done 1 } else { set timebook_this [ .timebook.main.body get [lindex $r 0] [lindex $r 1]] set timebook_body "$timebook_body$timebook_this" set i [lindex $r 1] } } # Change tabs to commas regsub -all \t $timebook_body , timebook_body2 # Change ,, to , 0.0 , regsub -all ",," $timebook_body2 ,0.0, timebook_body # Repeat to catch the ones we miss with only one pass regsub -all ",," $timebook_body ,0.0, timebook_body2 # Now deal with a trailing comma regsub -all ,\n $timebook_body2 ,0.0\n timebook_body # Trim white space set timebook_body [string trim $timebook_body] set timebook_body [string trimright $timebook_body \n] puts $f $timebook_body close $f } proc firstDayOfWeek { weekno year } { # returns the day number of the first day of week weekno for a particular year set firstday [clock format [clock scan "1 jan $year"] -format "%w"] if { $firstday <= 4 } { incr firstday 7 } set offset [expr { 1- $firstday } ] return [expr { $weekno*7 + $offset }] } proc showTimeBookings {} { global timebook_year timebook_weekno rootdir showtime_format showtime_spreadoverheads showtime_bookbycode timebook_numweeks global GL_tableFont proc getProjectTimes { filename timearray booked_proj } { # return an array with the project times used during that day. # Note that timearray is the name of the array. # The array indices are the real projects used, upvar $timearray daytimes upvar $booked_proj booked_projects set logs [ tag readfile $filename ] set logs [ lrange $logs 1 end ] set thisproject unknown foreach entry $logs { set starttime 0 set endtime 0 foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } { # Because this is the end tag we should have all the values we are going # to get set duration [timediff $starttime $endtime] # add the project to booked_projects if we have not seen it before if { [lsearch -exact $booked_projects $thisproject ] == -1 } { lappend booked_projects $thisproject ## set projtotals($displayname) "00:00" } inctime daytimes($thisproject) $duration set thisproject unknown } elseif { $tagname == "StartTime" } { set starttime $tagvalue } elseif { $tagname == "EndTime" } { set endtime $tagvalue } elseif { $tagname == "Project" } { set thisproject $tagvalue } else { } } } } toplevel .timebook wm title .timebook [mc "Time Bookings"] ####### set newway 0 if { $showtime_spreadoverheads == "byday" } { set newway 1 } # We wont display errors unless we have to set display_errors 0 frame .timebook.errors text .timebook.errors.body -rel sunk -wrap word -yscrollcommand ".timebook.errors.sb set" -height 8 scrollbar .timebook.errors.sb -rel sunk -command ".timebook.errors.body yview" pack .timebook.errors.body -in .timebook.errors -side right pack .timebook.errors.sb -in .timebook.errors -side right -fill y frame .timebook.main text .timebook.main.body -rel sunk -wrap word -yscrollcommand ".timebook.main.sb set" \ -font $GL_tableFont \ -tabs {4.7c left 2c 2c 2c 2c 2c 2c left } \ -height 20 scrollbar .timebook.main.sb -rel sunk -command ".timebook.main.body yview" pack .timebook.main.body -in .timebook.main -side right -fill both -expand 1 pack .timebook.main.sb -in .timebook.main -side right -fill y -expand 1 pack .timebook.main -fill both -expand 1 # puts [.timebook.main.body configure] frame .timebook.bot button .timebook.bot.ok -text OK -command { doCancel .timebook } button .timebook.bot.mail -text "Mail..." -command { mailTimeBookings } button .timebook.bot.saveas -text [mc "Save As..."] -command { saveTimeBookings } pack .timebook.bot.ok .timebook.bot.mail .timebook.bot.saveas -side left -in .timebook.bot pack .timebook.bot for { set weekinc 0 } { $weekinc < $timebook_numweeks } { incr weekinc } { # work out which files we need - how do we convert a week number into # a set of days ? set thisweek [expr $timebook_weekno + $weekinc] set startday [firstDayOfWeek $thisweek $timebook_year] .timebook.main.body insert end "\t\t[mc {Time Bookings for week}] $thisweek [mc of] $timebook_year\n\n" # initialize totals variables used for this loop set booked_projects {} set total_overheads "00:00:00" set nonbreakstotal "00:00:00" set breakstotal "00:00:00" set immutabletotal "00:00:00" # Clear all the arrays used for totals if [ info exists projtotals ] { unset projtotals } if [ info exists dayoverheads ] { unset dayoverheads } if [ info exists daytotal ] { unset daytotal } if [ info exists dayimmutable] { unset dayimmutable } # Work out the times for all the projects in all the files set projtotals(empty) "00:00" for { set day $startday } {$day < [expr { $startday+7}] } { incr day } { if [ info exists projtimes${day} ] { unset projtimes${day} } # FRINK: nocheck set projtimes${day}(empty) "00:00" set daytotal($day) "00:00" # Open the file for this day (if possible) set filename1 [ clock format [clock scan "1 jan $timebook_year $day days"] -format "%m%d"] set filename "$rootdir/log$timebook_year/$filename1.tag" if [file exists $filename] { if { $newway } { ### # for testing # Clear the thisnames array set thisday(empty) "00:00" foreach el [array names thisday] { unset thisday($el) } getProjectTimes $filename thisday booked_projects puts "thisday is $day" foreach el [array names thisday] { puts "thisday($el) = $thisday($el)" } # Process thisday array to roll discovered totals into the week totals, also # spread overheads by day if required. foreach el [array names thisday] { set duration [timediff "00:00:00" $thisday($el)] if { [isbreak $el ]} { inctime breakstotal $duration } else { inctime nonbreakstotal $duration inctime daytotal($day) $duration } if { [isimmutable $el] } { inctime immutabletotal $duration inctime dayimmutable($day) $duration } if { [isoverhead $el] } { inctime dayoverheads($day) $duration inctime totaloverheads $duration } } # Having been through the whole day - spread overheads by day if required. if { $showtime_spreadoverheads == "byday" } { if { [info exist dayoverheads($day) ] } { if { $dayoverheads($day) != "00:00:00" } { set secstospread [timediff "00:00:00" $dayoverheads($day)] puts "we have overheads on $day of $dayoverheads($day) = $secstospread secs" set totalsecs [timediff "00:00" $daytotal($day)] set immutablesecs [timediff "00:00" dayimmutable($day)] set totalsecs [expr { $totalsecs - $immutablesecs - $secstospread } ] puts "we have $totalsecs seconds of todays projects" puts "which are [array names thisday]" foreach pr [array names thisday] { # puts "looking at project $pr" if { [isoverhead $pr] || [isimmutable $pr] || [isbreak $pr ] } { # puts "ignore $pr" } else { set projsecs [timediff "00:00:00" $thisday($pr)] set projfraction [expr ($projsecs * 1.0) / $totalsecs] puts "Time for $pr was $thisday($pr) - $projsecs - fraction is $projfraction" set extratime [ expr { round($projfraction * $secstospread)} ] inctime thisday($pr) $extratime puts "Add $extratime seconds to $pr - now $thisday($pr)" # Now convert projects to displayed names, or codes - note that this might # compress several projects with the same code into one entry # Deal with different ways to set up the project if { $showtime_bookbycode == 0 } { set displayname [getprojcode $pr] } elseif { $showtime_bookbycode == 1 } { set displayname $pr } elseif { $showtime_bookbycode == 2 } { set displayname [getprojcode $pr] set displayname "$displayname ($pr)" } else { error "showtime_bookbycode has invalid value $showtime_bookbycode" } # add the project to booked_projects if we have not seen it before if { [lsearch -exact $booked_projects $displayname ] == -1 } { lappend booked_projects $pr set projtotals($displayname) "00:00" } inctime projtimes${day}($displayname) $duration inctime projtotals($displayname) $duration } } # end of foreach pr } } } # End of if showtime_spreadoverheads == byday } else { # Oldway set logs [ tag readfile $filename ] set logs [ lrange $logs 1 end ] set thisproject unknown foreach entry $logs { set starttime 0 set endtime 0 foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } { # Because this is the end tag we should have all the values we are going # to get set duration [timediff $starttime $endtime] # Deal with different ways to set up the project if { $showtime_bookbycode == 0 } { set displayname [getprojcode $thisproject] } elseif { $showtime_bookbycode == 1 } { set displayname $thisproject } elseif { $showtime_bookbycode == 2 } { set displayname [getprojcode $thisproject] set displayname "$displayname ($thisproject)" } else { error "showtime_bookbycode has invalid value $showtime_bookbycode" } # puts "duration is $duration - project is $thisproject day is $day" # Is is a breaks project ? if { [isbreak $thisproject ] } { inctime breakstotal $duration } elseif { ( $showtime_spreadoverheads != "off") && ( [isoverhead $thisproject]) } { inctime daytotal($day) $duration inctime nonbreakstotal $duration inctime total_overheads $duration inctime dayoverheads($day) $duration } else { # add the project to booked_projects if we have not seen it before if { [lsearch -exact $booked_projects $displayname ] == -1 } { lappend booked_projects $displayname set projtotals($displayname) "00:00" } inctime projtimes${day}($displayname) $duration inctime projtotals($displayname) $duration inctime daytotal($day) $duration inctime nonbreakstotal $duration if { [isimmutable $thisproject] } { inctime immutabletotal $duration inctime dayimmutable($day) $duration } } set thisproject unknown } elseif { $tagname == "StartTime" } { set starttime $tagvalue } elseif { $tagname == "EndTime" } { set endtime $tagvalue } elseif { $tagname == "Project" } { set thisproject $tagvalue } else { } } } } # end of oldway } else { # want to warn if we cant open the file (unless it is Sat or Sun) if {[ clock format [clock scan "1 jan $timebook_year $day days"] -format "%u"] <6 } { .timebook.errors.body insert end "[mc {Warning - cant open}] $filename\n" if { ! $display_errors } { pack .timebook.errors -side top set display_errors 1 } } } } if { $showtime_spreadoverheads == "byweek" } { #puts "Total of overheads is $total_overheads" # Work through the days, adjusting the times for the non-overheads projects, # so as to keep the total constant, # First work out the percentage of the time spent on each non-overheads project. set totalmins [ timediff "00:00" $nonbreakstotal ] set overheadmins [ timediff "00:00" $total_overheads ] set immutablemins [ timediff "00:00" $immutabletotal ] set totalmins [ expr { $totalmins - $overheadmins - $immutablemins } ] # puts "Total mins is $totalmins" foreach thisproject $booked_projects { if { ! [isimmutable $thisproject ] } { # puts "project is $thisproject Total time is $projtotals($thisproject)" set projmins [ timediff "00:00" $projtotals($thisproject) ] # puts "Projmins is $projmins" set projfraction($thisproject) [expr { ( $projmins * 1.0) / $totalmins } ] # puts "Fraction of the time spent on this project is $projfraction($thisproject)" } } } # print headers for the different days .timebook.main.body insert end "[mc Project]\t[mc Total]\t" for { set day $startday } {$day < [expr {$startday+7} ]} { incr day } { .timebook.main.body insert end [mc [clock format [clock scan "1 jan $timebook_year $day days"] -format "%a"]] .timebook.main.body insert end " \t" } .timebook.main.body insert end "\n" .timebook.main.body insert end "[mc Day]\t " .timebook.main.body insert end "\t" bodydata .timebook.main.body insert end " " for { set day $startday } {$day < [expr {$startday+7} ]} { incr day } { .timebook.main.body insert end [clock format [clock scan "1 jan $timebook_year $day days"] -format "%d/%m"] bodydata if { $day < [expr {$startday+6}]} { .timebook.main.body insert end " " .timebook.main.body insert end "\t" bodydata } } .timebook.main.body insert end "\n\n" bodydata # work through the booked projects foreach thisproject $booked_projects { # puts "project is $thisproject Total time is $projtotals($thisproject)" # write out the projects as constant width set displayproj [string range $thisproject 0 18] .timebook.main.body insert end "$displayproj\t" bodydata for { set day $startday } {$day < [expr {$startday+7}]} { incr day } { if { ($showtime_spreadoverheads == "byweek") && [ info exists dayoverheads($day)] } { if { ! [isimmutable $thisproject]} { # redistribute the spare minutes (or seconds now that we work in them) set secstospread [timediff "00:00" $dayoverheads($day)] set secsthisproj [ expr { round( $secstospread * $projfraction($thisproject))}] # puts "We have $dayoverheads($day) = $minstospread minutes to spread _ $minsthisproj" inctime projtimes${day}($thisproject) $secsthisproj inctime projtotals($thisproject) $secsthisproj } } } DisplayTime .timebook.main.body projtotals($thisproject) bold .timebook.main.body insert end "\t" for { set day $startday } {$day < [expr {$startday+7}]} { incr day } { DisplayTime .timebook.main.body projtimes${day}($thisproject) bodydata if { $day < [expr {$startday+6}]} { .timebook.main.body insert end " " .timebook.main.body insert end "\t" bodydata } } .timebook.main.body insert end "\n" bodydata } .timebook.main.body insert end "\n" bodydata # write the totals for all days .timebook.main.body insert end "\t" DisplayTime .timebook.main.body nonbreakstotal bold .timebook.main.body insert end "\t" for { set day $startday } {$day < [expr {$startday+7}]} { incr day } { DisplayTime .timebook.main.body daytotal($day) bold .timebook.main.body insert end " \t" } .timebook.main.body insert end "\n" .timebook.main.body insert end "[mc {Breaks total}]\t" DisplayTime .timebook.main.body breakstotal bold .timebook.main.body insert end "\n" } tkwait window .timebook } proc doWeeklyTimeBookingsByProject {} { global year timebook_year timebook_weekno showtime_format showtime_spreadoverheads showtime_bookbycode timebook_numweeks global timebook_startlastweek toplevel .timebooksel wm title .timebooksel [mc "Select Time Period"] frame .timebooksel.top menubutton .timebooksel.top.label -text [mc "Time Format"] -menu .timebooksel.top.label.m menu .timebooksel.top.label.m .timebooksel.top.label.m add command -label [mc Help] -command "taghelp timebooksel_timeformat" radiobutton .timebooksel.top.hhmm -text "hh:mm" -relief flat -variable showtime_format -value 0 radiobutton .timebooksel.top.decimalhours -text [mc "Decimal hours"] -relief flat -variable showtime_format -value 1 radiobutton .timebooksel.top.decimaldays -text [mc "Decimal days"] -relief flat -variable showtime_format -value 2 pack .timebooksel.top.label .timebooksel.top.hhmm .timebooksel.top.decimalhours .timebooksel.top.decimaldays -side left -in .timebooksel.top pack .timebooksel.top if { $showtime_spreadoverheads == 0 } { set showtime_spreadoverheads off } if { $showtime_spreadoverheads == 1 } { set showtime_spreadoverheads byweek } frame .timebooksel.spread_overheads menubutton .timebooksel.spread_overheads.l -text [mc "Spread overhead projects"] -menu .timebooksel.spread_overheads.l.m menu .timebooksel.spread_overheads.l.m .timebooksel.spread_overheads.l.m add command -label [mc Help] -command "taghelp timebooksel_spreadoverheads" radiobutton .timebooksel.spread_overheads.off -variable showtime_spreadoverheads -value off -text [mc Off] radiobutton .timebooksel.spread_overheads.byday -variable showtime_spreadoverheads -value byday -text [mc Day] -state disabled radiobutton .timebooksel.spread_overheads.byweek -variable showtime_spreadoverheads -value byweek -text [mc Week] pack .timebooksel.spread_overheads.l .timebooksel.spread_overheads.off .timebooksel.spread_overheads.byday .timebooksel.spread_overheads.byweek -in .timebooksel.spread_overheads -side left pack .timebooksel.spread_overheads frame .timebooksel.t2 label .timebooksel.t2.bookas -text [mc "Book by Project"] radiobutton .timebooksel.t2.bookcode -text "Code" -relief flat -variable showtime_bookbycode -value 0 radiobutton .timebooksel.t2.bookname -text "Name" -relief flat -variable showtime_bookbycode -value 1 radiobutton .timebooksel.t2.bookcodename -text "Code+Name" -relief flat -variable showtime_bookbycode -value 2 pack .timebooksel.t2.bookas .timebooksel.t2.bookcode .timebooksel.t2.bookname .timebooksel.t2.bookcodename -in .timebooksel.t2 -side left pack .timebooksel.t2 set timebook_year $year frame .timebooksel.m frame .timebooksel.m.year menubutton .timebooksel.m.year.l -text [mc Year] -menu .timebooksel.m.year.l.m menu .timebooksel.m.year.l.m .timebooksel.m.year.l.m add command -label [mc Help] -command "taghelp timebook_year" entry .timebooksel.m.year.e -textvariable timebook_year -width 4 pack .timebooksel.m.year.l .timebooksel.m.year.e -in .timebooksel.m.year -side left bind .timebooksel.m.year.e "setWeekRange .timebooksel.wrange" set timebook_numweeks 1 frame .timebooksel.m.numweeks entry .timebooksel.m.numweeks.e -textvariable timebook_numweeks -width 1 menubutton .timebooksel.m.numweeks.l -text [mc "weeks"] -menu .timebooksel.m.numweeks.l.m menu .timebooksel.m.numweeks.l.m .timebooksel.m.numweeks.l.m add command -label [mc Help] -command "taghelp timebook_numweeks" pack .timebooksel.m.numweeks.e .timebooksel.m.numweeks.l -in .timebooksel.m.numweeks -side left bind .timebooksel.m.numweeks.e "setWeekRange .timebooksel.wrange" # we need to trimleft to deal with the week 8 problem (08 is not a valid number) set timebook_weekno [ string trimleft [ clock format [clock seconds] -format "%W"] 0] # This will give us null string for week 0 - pick that up as well if {$timebook_weekno == ""} {set timebook_weekno 0} # incr timebook_weekno -1 if { ! $timebook_startlastweek } { incr timebook_weekno } frame .timebooksel.m.week menubutton .timebooksel.m.week.l -text [mc "starting at number"] -menu .timebooksel.m.week.l.m menu .timebooksel.m.week.l.m .timebooksel.m.week.l.m add command -label [mc Help] -command "taghelp timebook_weekno" button .timebooksel.m.week.minus -text "-" -command { incr timebook_weekno -1; setWeekRange .timebooksel.wrange} entry .timebooksel.m.week.e -textvariable timebook_weekno -width 3 bind .timebooksel.m.week.e "setWeekRange .timebooksel.wrange" button .timebooksel.m.week.plus -text "+" -command { incr timebook_weekno; setWeekRange .timebooksel.wrange} pack .timebooksel.m.week.l .timebooksel.m.week.minus .timebooksel.m.week.e .timebooksel.m.week.plus -in .timebooksel.m.week -side left pack .timebooksel.m.year .timebooksel.m.numweeks .timebooksel.m.week -side left -in .timebooksel.m pack .timebooksel.m # widget to display the range of days entry .timebooksel.wrange -width 32 -state disabled -relief groove pack .timebooksel.wrange -side top # fill the widget .timebooksel.wrange setWeekRange .timebooksel.wrange frame .timebooksel.bot button .timebooksel.bot.ok -text OK -command showTimeBookings button .timebooksel.bot.cancel -text [mc Cancel] -command {doCancel .timebooksel} button .timebooksel.bot.help -text [mc Help] -command "taghelp timebooksel" pack .timebooksel.bot.ok .timebooksel.bot.cancel .timebooksel.bot.help -in .timebooksel.bot -side left pack .timebooksel.bot -side bottom tkwait window .timebooksel } proc doTimeByActivityOK {} { global timebyact_start timebyact_end global GL_tableFont toplevel .tba wm title .tba [mc "Time by Activity"] set activities {} set acttotal "00:00" set fileslist [dateRangeToLogfileList $timebyact_start $timebyact_end] foreach filename $fileslist { set logs [tag readfile $filename] foreach entry $logs { set starttime 0 set endtime 0 set activity unknown foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } { set duration [timediff $starttime $endtime] # more to do here inctime acttotal $duration if { [lsearch -exact $activities $activity] == -1 } { lappend activities $activity set acttime($activity) "00:00" } inctime acttime($activity) $duration } elseif { $tagname == "StartTime" } { set starttime $tagvalue } elseif { $tagname == "EndTime" } { set endtime $tagvalue } elseif { $tagname == "Activity" } { set activity $tagvalue } else { } } } } set resultheight [expr {[array size acttime] + 3} ] frame .tba.results if { $resultheight > 20 } { text .tba.results.body -rel sunk -yscrollcommand ".tba.results.sb set" -height $resultheight \ -font $GL_tableFont -tabs { 5c left 2c 2c left } pack .tba.results.body -in .tba.results -side right -fill y scrollbar .tba.results.sb -rel sunk -command ".tba.results.body yview" pack .tba.results.sb -in .tba.results -side right -fill y } else { text .tba.results.body -rel sunk -height $resultheight \ -font $GL_tableFont -tabs { 5c left 2c 2c left } pack .tba.results.body -in .tba.results -side right -fill y } pack .tba.results .tba.results.body insert end "[mc Activity]\t[mc {Total time}]\n\n" foreach act [array names acttime] { .tba.results.body insert end "$act\t$acttime($act)\n" } frame .tba.bot button .tba.bot.ok -text OK -command {doCancel .tba } #button .tba.graph -text Graph -command graphTimeByActivity pack .tba.bot.ok -in .tba.bot pack .tba.bot tkwait window .tba } proc doTimeByActivity {} { global timebyact_start timebyact_end toplevel .timebyact wm title .timebyact [mc "Select date range"] frame .timebyact.start menubutton .timebyact.start.b -text [mc "Start Date"] -menu .timebyact.start.b.m menu .timebyact.start.b.m calUtil_win .timebyact.start.e "" timebyact_start pack .timebyact.start.b .timebyact.start.e -in .timebyact.start -side left pack .timebyact.start frame .timebyact.end menubutton .timebyact.end.b -text [mc "End Date"] -menu .timebyact.end.b.m menu .timebyact.end.b.m calUtil_win .timebyact.end.e "" timebyact_end pack .timebyact.end.b .timebyact.end.e -in .timebyact.end -side left pack .timebyact.end frame .timebyact.bot button .timebyact.bot.ok -text OK -command doTimeByActivityOK button .timebyact.bot.cancel -text [mc Cancel] -command { doCancel .timebyact } pack .timebyact.bot.ok .timebyact.bot.cancel -in .timebyact.bot -side left pack .timebyact.bot tkwait window .timebyact } proc doProjectProgressReport {} { global projrepinfosel_project projrepinfosel_start projrepinfosel_end toplevel .projrepinfo wm title .projrepinfo [mc "Enter information for Project Progress Report"] frame .projrepinfo.selproj frame .projrepinfo.selproj.p menubutton .projrepinfo.selproj.p.project -text [mc Project] -menu .projrepinfo.selproj.p.project.m menu .projrepinfo.selproj.p.project.m setupProjMenu .projrepinfo.selproj.p.project.m projrepinfosel_project "all" "" entry .projrepinfo.selproj.p.projectentry -textvariable projrepinfosel_project -width 20 pack .projrepinfo.selproj.p.project .projrepinfo.selproj.p.projectentry -in .projrepinfo.selproj.p -side left pack .projrepinfo.selproj.p pack .projrepinfo.selproj frame .projrepinfo.start menubutton .projrepinfo.start.l -text [mc "Start Date"] -menu .projrepinfo.start.l.m menu .projrepinfo.start.l.m set md [clock format [clock scan "last month"] -format "%Y-%m-01"] .projrepinfo.start.l.m add command -label "$md [mc {Start of last month}]" -command "set projrepinfosel_start $md" calUtil_win .projrepinfo.start.e "" projrepinfosel_start pack .projrepinfo.start.l .projrepinfo.start.e -in .projrepinfo.start -side left pack .projrepinfo.start frame .projrepinfo.end menubutton .projrepinfo.end.l -text [mc "End Date"] -menu .projrepinfo.end.l.m menu .projrepinfo.end.l.m set md [clock format [clock seconds] -format "%Y-%m-01"] .projrepinfo.end.l.m add command -label "$md [mc {Start of this month}]" -command "set projrepinfosel_end $md" calUtil_win .projrepinfo.end.e "" projrepinfosel_end pack .projrepinfo.end.l .projrepinfo.end.e -in .projrepinfo.end -side left pack .projrepinfo.end frame .projrepinfo.bot button .projrepinfo.bot.ok -text OK -command { doProjectReportOK $projrepinfosel_project $projrepinfosel_start $projrepinfosel_end } button .projrepinfo.bot.cancel -text [mc Cancel] -command { doCancel .projrepinfo } pack .projrepinfo.bot.ok .projrepinfo.bot.cancel -in .projrepinfo.bot -side left pack .projrepinfo.bot tkwait window .projrepinfo } proc doProjectReportOK { proj start end { mode screen } } { global allact allactstate global scrollside global GL_tableFont global html_public_dir if { $mode == "screen" } { toplevel .projrep wm title .projrep "[mc {Project Progress Report for}] $proj" } else { set fn [tk_getSaveFile -defaultextension ".html" -initialdir $html_public_dir] if { $fn != "" } { set f [open $fn w] puts $f "" puts $f "[mc {Project Progress Report for}] $proj" } else { return } } getallact if { $mode == "screen" } { frame .projrep.main text .projrep.main.body -rel sunk -wrap word -yscrollcommand ".projrep.main.sb set" \ -font $GL_tableFont -tabs { 12c left 3c 3c } scrollbar .projrep.main.sb -rel sunk -command ".projrep.main.body yview" pack .projrep.main.body -side $scrollside -in .projrep.main -fill both -expand 1 pack .projrep.main.sb -side $scrollside -fill y -in .projrep.main pack .projrep.main -fill both -expand 1 frame .projrep.bot button .projrep.bot.ok -text OK -command { doCancel .projrep } button .projrep.bot.save -text "[mc {SaveAs Html}]" -command "doProjectReportOK \"$proj\" \"$start\" \"$end\" html" pack .projrep.bot.ok -side left pack .projrep.bot.save -side left pack .projrep.bot # Now fill the window .projrep.main.body insert end [mc "Project Progress Report"]\n .projrep.main.body insert end [mc "Project"]\t$proj\n .projrep.main.body insert end "[mc {Progress from}] $start[mc { to }]$end\n\n" .projrep.main.body insert end [mc Achievements]\n .projrep.main.body insert end [mc "Tasks completed since last report"]\n .projrep.main.body insert end "[mc Title]\t[mc Expected]\t[mc Actual]\t\n\t[mc Date]\t[mc Date]\n" } else { puts $f "

[mc "Project Progress Report"]

" puts $f "

[mc "Project"]\t$proj

" puts $f "[mc {Progress from}] $start[mc { to }]$end

" puts $f "

[mc Achievements]

" puts $f "[mc "Tasks completed since last report"]" puts $f "" } if { $proj != "" } { set test [list Project == $proj] lappend tests $test set actions [ tag extract $allact $tests ] } else { set actions $allact } # looking for tasks completed since the last report foreach entry $actions { set test [list Completed-date -later $start] if [ tag matchcond $entry $test ] { set title "" set expected_completed_date "" set completed_date "" foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Title" } { set title $tagvalue } elseif { $tagname == "Expected-completed-date" } { set expected_completed_date $tagvalue } elseif { $tagname == "Completed-date" } { set completed_date $tagvalue } } if { $mode == "screen" } { .projrep.main.body insert end "$title\t$expected_completed_date\t$completed_date\n" } else { puts $f "" } } } # looking for tasks started since the last report if { $mode =="screen" } { .projrep.main.body insert end "\n\n[mc {Tasks started since last report}]\n" .projrep.main.body insert end "[mc Title]\t[mc Expected]\t[mc Actual]\t\n\t[mc Date]\t[mc Date]\n" } else { puts $f "
[mc Title][mc Expected] [mc Date][mc Actual] [mc Date]
$title$expected_completed_date$completed_date

[mc {Tasks started since last report}]

" puts $f "" puts $f "" } foreach entry $actions { set test [list Active-date -later $start] if [ tag matchcond $entry $test ] { set title "" set expected_started_date "" set started_date "" foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Title" } { set title $tagvalue } elseif { $tagname == "Expected-start-date" } { set expected_started_date $tagvalue } elseif { $tagname == "Active-date" } { set started_date $tagvalue } } if { $mode == "screen"} { .projrep.main.body insert end "$title\t$expected_started_date\t$started_date\n" } else { puts $f "" } } } # looking for tasks slipped since the last report # - slipped tasks will have a Revised-expected-start-date or a revised-expected-completed-date # also tasks which are still pending, even though they have reached their # expected start date must have slipped. # Not quite sure how to do this if { $mode == "screen" } { .projrep.main.body insert end "\n\n[mc {Tasks slipped since last report}]\n" .projrep.main.body insert end "[mc Title]\t[mc Expected]\t[mc Actual]\t\n\t[mc Date]\t[mc Date]\n" } else { puts $f "
[mc Title][mc Expected] [mc Date][mc Actual] [mc Date]
$title$expected_started_date$started_date
" puts $f "

[mc {Tasks slipped since last report}]

" puts $f "" puts $f "" } foreach entry $actions { set test [list Active-date -later $start] if [ tag matchcond $entry $test ] { set title "" set expected_started_date "" set started_date "" foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Title" } { set title $tagvalue } elseif { $tagname == "Expected-start-date" } { set expected_started_date $tagvalue } elseif { $tagname == "Active-date" } { set started_date $tagvalue } } if { $mode == "screen" } { .projrep.main.body insert end "$title\t$expected_started_date\t$started_date\n" } else { puts $f "" } } } # looking for active tasks if { $mode == "screen" } { .projrep.main.body insert end "\n\n[mc {Active tasks}]\n" .projrep.main.body insert end "[mc Title]\t[mc Scheduled]\t[mc Forecast]\t\n\t[mc Completion]\t[mc Completion]\n" } else { puts $f "
[mc Title][mc Expected] [mc Date][mc Actual] [mc Date]
$title$expected_started_date$started_date
" puts $f "

[mc {Active tasks}]

" puts $f "" puts $f "" } foreach entry $actions { set test [list Status == Active] if [ tag matchcond $entry $test ] { set title "" set expected_completed_date "" set started_date "" foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Title" } { set title $tagvalue } elseif { $tagname == "Expected-completed-date" } { set expected_completed_date $tagvalue } elseif { $tagname == "Active-date" } { set started_date $tagvalue } } if { $mode == "screen" } { .projrep.main.body insert end "$title\t$expected_completed_date\t$started_date\n" } else { puts $f "" } } } if { $mode == "screen" } { tkwait window .projrep } else { puts $f "
[mc Title][mc Scheduled] [mc Completion][mc Forecast] [mc Completion]
$title$expected_completed_date$started_date
" puts $f "" close $f } } # fills the range of days into the widget $wRange proc setWeekRange {wRange} { global timebook_year timebook_numweeks timebook_weekno global dateformat_view if {[winfo exists $wRange]} { if {![catch { # check year, execute illegal command if year is out of range if {$timebook_year < 1970 || $timebook_year > 2100} {$xxxx} if {$dateformat_view == "DD/MM/YYYY" } { set dForm "%d/%m/%Y" set dLen 30 } elseif {$dateformat_view == "MM/DD/YYYY" } { set dForm "%m/%d/%Y" set dLen 30 } else { set dForm "%Y-%m-%d" set dLen 32 } set startday [firstDayOfWeek $timebook_weekno $timebook_year] set startStr [ clock format \ [clock scan "1 jan $timebook_year $startday days"] -format $dForm] set endday [expr {$startday + $timebook_numweeks * 7 - 1}] set endStr [ clock format \ [clock scan "1 jan $timebook_year $endday days"] -format $dForm] } ]} { # insert the text $wRange configure -state normal -width $dLen $wRange delete 0 end $wRange insert 0 "[mc Mon] $startStr ... [mc Sun] $endStr" $wRange configure -state disabled } } return True } proc doInterruptionsReport {} { global intrepask_start intrepask_end toplevel .intrepask wm title .intrepask [mc "Interruptions Report setup"] frame .intrepask.start menubutton .intrepask.start.b -text [mc "Start Date"] -menu .intrepask.start.b.m menu .intrepask.start.b.m calUtil_win .intrepask.start.e "" intrepask_start pack .intrepask.start.b .intrepask.start.e -in .intrepask.start -side left pack .intrepask.start frame .intrepask.end menubutton .intrepask.end.b -text [mc "End Date"] -menu .intrepask.end.b.m menu .intrepask.end.b.m calUtil_win .intrepask.end.e "" intrepask_end pack .intrepask.end.b .intrepask.end.e -in .intrepask.end -side left pack .intrepask.end frame .intrepask.bot button .intrepask.bot.ok -text OK -command doInterruptionsReportOK button .intrepask.bot.cancel -text [mc Cancel] -command { doCancel .intrepask } pack .intrepask.bot.ok .intrepask.bot.cancel -in .intrepask.bot -side left pack .intrepask.bot tkwait window .intrepask } proc doInterruptionsReportOK {} { global intrepask_start intrepask_end global GL_tableFont toplevel .intrep wm title .intrep [mc "Interruptions Report"] set totalInterrupts 0 set numdays 0 set peakipd 0 set fileslist [dateRangeToLogfileList $intrepask_start $intrepask_end] foreach filename $fileslist { set dayInterrupts 0 incr numdays set logs [tag readfile $filename] foreach entry $logs { foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Stack-info" } { if { [string range $tagvalue 0 0] == "!" } { incr dayInterrupts incr totalInterrupts } } } } if { $dayInterrupts > $peakipd } { set peakipd $dayInterrupts } } frame .intrep.results text .intrep.results.body -rel sunk -height 10 -font $GL_tableFont -tabs { 5c left 2c 2c left } pack .intrep.results.body -in .intrep.results -side right -fill y pack .intrep.results .intrep.results.body insert end "[mc {There were a total of}] $totalInterrupts [mc {interruptions in}] $numdays [mc days.]\n" set avg [expr $totalInterrupts/$numdays] .intrep.results.body insert end "[mc {The average number of interruptions in a day was}] $avg\n" .intrep.results.body insert end "[mc {The peak number of interruptions per day was}] $peakipd\n" frame .intrep.bot button .intrep.bot.ok -text OK -command {doCancel .intrep } pack .intrep.bot.ok -in .intrep.bot pack .intrep.bot tkwait window .intrep } proc doActiveAndPendingReport {} { # Report on active and pending actions. global actsel_project actsel_st_any actsel_st_unclaimed actsel_st_pending actsel_st_active actsel_st_blocked actsel_st_delegated actsel_st_completed actsel_st_aborted actsel_showfields actsel_maxpriority actsel_expected_start actsel_expected_completed actsel_expected_start_test actsel_expected_completed_test actsel_filename actsel_sortby global actsel_id actsel_title global actsel_filename actionsfilename set actsel_project "" set actsel_st_any 0 set actsel_st_unclaimed 0 set actsel_st_pending 1 set actsel_st_active 1 set actsel_st_blocked 1 set actsel_st_delegated 0 set actsel_st_compeleted 0 set actsel_st_aborted 0 set actsel_showfields(all) 1 set actsel_maxpriority "" set actsel_expected_start "" set actsel_expected_completed "" set actsel_sortby "Priority" set actsel_id "" set actsel_title "" set actsel_filename $actionsfilename displayActions } proc doActiveActionsReview {} { global allact activeactions global GL_tableFont global CALIMAGE global expectedTime expectedCompleted set w .actrev toplevel $w wm title $w [mc "Active Actions Review"] frame $w.main text $w.main.body -rel sunk -wrap word -yscrollcommand "$w.main.sb set" -font $GL_tableFont scrollbar $w.main.sb -rel sunk -command "$w.main.body yview" pack $w.main.body -side right -in $w.main -fill both -expand 1 pack $w.main.sb -fill y -side right -in $w.main pack $w.main -expand 1 -fill both set titlewidth 40 $w.main.body insert end "Title\tTime\tExpected\n\n" # Note that we need to work with allact as it has all fields set test [list Status "-in" { Active } ] lappend tests $test set sortactiveactions [ tag extract $allact $tests ] # If an action was added directly as active then it may not have an Active-date # Set all the field for such actions to the date they were entered. # set idx -1 foreach act $sortactiveactions { incr idx if {[tag_entryVal $act Active-date] == "" } { set cdate [tag_entryVal $act Date] tag setorreplace act Active-date $cdate set sortactiveactions [lreplace $sortactiveactions $idx $idx $act] } } for {set i 0} {$i < [llength $activeactions]} {incr i} { set actionTime($i) "00:00:00" } set sortactiveactions [tag sort $sortactiveactions Active-date -ascii] set earliestDate [tag_entryVal [lindex $sortactiveactions 0] Active-date] set fileslist [dateRangeToLogfileList $earliestDate ""] foreach filename $fileslist { set logs [tag readfile $filename] foreach entry $logs { set entryaction [tag_entryVal $entry Action] if {$entryaction != ""} { for {set i 0} {$i < [llength $activeactions]} {incr i} { if { [lindex [lindex $activeactions $i] 0] == $entryaction } { set duration [timediff [tag_entryVal $entry StartTime] [tag_entryVal $entry EndTime]] # puts "Duration is $duration" inctime actionTime($i) $duration # and set other things for this entry } } } } } set i 0 foreach action $activeactions { set title [format "%*s" $titlewidth [string range [lindex $action 1] 0 $titlewidth]] button $w.main.body.title$i -text $title -command "editaction [lindex $action 0]" -width $titlewidth $w.main.body window create end -window $w.main.body.title$i $w.main.body insert end "$actionTime($i)\t" set expectedTime($i) [tag_entryVal [lindex $allact [lindex $action 4]] Expected-time] entry $w.main.body.eTime$i -textvariable expectedTime($i) -width 5 $w.main.body window create end -window $w.main.body.eTime$i if { $expectedTime($i) != "" } { if {[expr [timediff $actionTime($i) $expectedTime($i)] < 0] } { $w.main.body.eTime$i configure -background coral1 } } set expectedCompleted($i) [tag_entryVal [lindex $allact [lindex $action 4]] Expected-completed-date] entry $w.main.body.ecDate$i -textvariable expectedCompleted($i) -width 16 button $w.main.body.ecCal$i -bitmap @$CALIMAGE \ -command "calUtil_open $w.main.body.ecDate$i" $w.main.body window create end -window $w.main.body.ecDate$i $w.main.body window create end -window $w.main.body.ecCal$i if { $expectedCompleted($i) != "" } { if { [clock scan $expectedCompleted($i)] < [clock seconds] } { $w.main.body.ecDate$i configure -background coral1 } } $w.main.body insert end "\n" incr i } frame $w.bot button $w.bot.ok -text OK -command "doActiveActionsReviewOK $w" button $w.bot.cancel -text [mc Cancel] -command "doCancel $w" button $w.bot.help -text [mc Help] -command "taghelp activeActionsReview" pack $w.bot.ok $w.bot.cancel $w.bot.help -in $w.bot -side left pack $w.bot tkwait window $w } proc doActiveActionsReviewOK { w } { global allact activeactions global expectedTime expectedCompleted set i 0 foreach action $activeactions { set revised 0 if { $expectedTime($i) != [tag_entryVal [lindex $allact [lindex $action 4]] Expected-time]} { set revised 1 } if { $expectedCompleted($i) != [tag_entryVal [lindex $allact [lindex $action 4]] Expected-completed-date] } { set revised 1 } if { $revised } { doReviseAction [lindex $allact [lindex $action 4]] $expectedCompleted($i) $expectedTime($i) "" } incr i } doCancel $w } taglog-0.2.6/src/taglog.10000644000175000017500000000060713534701742013611 0ustar johnjohn.TH tag 1 "2001-11-7" .SH NAME taglog \- Time Management and Recording system .SH SYNOPSIS .B taglog .SH DESCRIPTION Taglog allows you to keep an online daybook, recording what you have done, and to plan your future actions. It produces reports on how your time was spent. For further information see the tutorial, and the built in help. .SH AUTHOR John Lines (john+taglog@paladyn.org) taglog-0.2.6/src/taglog0000755000175000017500000012621413534752765013473 0ustar johnjohn#!/usr/bin/env wish # # This program gives a combined electronic diary and time clock. # Copyright John Lines (john+taglog@paladyn.org) November 1999 # # This program is released under the terms of the GNU Public Licence # set version 0.2.6 proc sourcelibs {} { global libsdir auto_path # we will look for tag.tcl in the same directory as this script. # and in /usr/local/lib/taglog, and /usr/lib/taglog, and /usr/lib/tag set scriptdir [file dirname [info script]] # If this is the development version it works from the .taglog in the # scriptdir # # else Source ~/.taglog early if {[file readable "$scriptdir/.taglog"] } { # Note that we use catch as there may be undefined items in it. catch { source "$scriptdir/.taglog" } } elseif {[file readable "~/.taglog"] } { catch { source "~/.taglog" } } if { [info exist libsdir ] && [file readable "$libsdir/taglog_help.tcl"]} { # Dont need to set libsdir - it is already OK # I will use taglog_help.tcl as the file to indicate where the library # files are. } elseif { [file readable "$scriptdir/taglog_help.tcl"] } { set libsdir $scriptdir } elseif { [file readable "~/lib/taglog/taglog_help.tcl"] } { set libsdir ~/lib/taglog } elseif { [file readable "/usr/lib/taglog/taglog_help.tcl"] } { set libsdir /usr/lib/taglog } elseif { [file readable "/usr/share/taglog/taglog_help.tcl"] } { set libsdir /usr/share/taglog } elseif { [file readable "/usr/local/lib/taglog/taglog_help.tcl"] } { set libsdir /usr/local/lib/taglog } else { error [mc "Unable to find library directory containing taglog_help.tcl"] } # In order to be wrappable with sdx we need to require Tk package require Tk # append the libsdir directory to the auto_path lappend auto_path $libsdir # These may be in some real library location as they may not be exclusive # to taglog package require tag package require smtpclient # These are local taglog packages package require taglog_help package require taglog_report package require taglog_init package require taglog_util package require taglog_project package require taglog_action package require taglog_contact package require taglog_widgets package require logEdit package require mainwin package require taglog_stack if { [file readable "$libsdir/cal2.xbm"] } { global CALIMAGE set CALIMAGE $libsdir/cal2.xbm } else { error "Can not find $libsdir/cal2.xbm" } } proc gettime {} { global hh mm ss tcl_platform if { [info tclversion] >=8.0 } { set d [clock format [clock seconds] -format "%H:%M:%S"] scan $d "%d:%d:%d" hh mm ss } else { if {$tcl_platform(platform) == "unix"} { catch {exec date +%H:%M } d scan $d "%d:%d" hh mm } elseif {$tcl_platform(platform) == "windows"} { puts "Cant handle Windows yet - coming soon" exit } else { puts "Unknown platform $tcl_platform(platform) - please report to john+taglog@paladyn.org" exit } } # leave them as numbers, so currentTimeFormat can be used to format them # set hh [format "%02d" $hh] # set mm [format "%02d" $mm] # set ss [format "%02d" $ss] } proc getdate {} { global year month day # catch {exec date +%Y-%m-%d } d set d [clock format [clock seconds] -format "%Y-%m-%d"] scan $d "%d-%d-%d" year month day set month [format "%02d" $month] set day [format "%02d" $day] } proc logfilename2date { filename args } { global year dateformat_tcl dateformat_view # Improved version thanks to Bruce Gingery if { $filename == "" } { return "" } if {[lindex $args 0] == "-iso" } { set mydateformat "YYYY-MM-DD" } elseif { [lindex $args 0] == "-us" } { set mydateformat "MM/DD/YYYY" } else { set mydateformat $dateformat_view } set mmdd [file rootname [file tail $filename]] set mm [ string range $mmdd 0 1] set dd [string range $mmdd 2 3] set logyear $year regexp {^log(\d+)$} [file tail [file dirname $filename]] {} logyear if { $mydateformat == "DD/MM/YYYY" } { set result "$dd/$mm/$logyear" } elseif { $mydateformat == "MM/DD/YYYY" } { set result "$mm/$dd/$logyear" } else { # default to ISO format set result "$logyear-$mm-$dd" } return $result } proc fieldname2index { fn } { # take in a field name such as Email-status-to and return a value suitable # for an array index - I think I can just change - to _ regsub -all -- "-" $fn _ result return $result } proc index2fieldname { index } { regsub -all _ $index "-" result return $result } proc dologedit { entrynum } { global logentries global logedit_id logedit_start logedit_end logedit_description logedit_project logedit_action logedit_actiontitle logedit_activity logedit_contact logedit_rate logedit_stack_info set entry "" set logedit_description($entrynum) [string trim [.logedit$entrynum.description.v get 1.0 end]] set entry [tagappend $entry Id $logedit_id($entrynum)] set entry [tagappend $entry StartTime $logedit_start($entrynum)] set entry [tagappend $entry EndTime $logedit_end($entrynum)] set entry [tagappend $entry Project $logedit_project($entrynum)] set entry [tagappend $entry Action $logedit_action($entrynum)] set entry [tagappend $entry ActionTitle $logedit_actiontitle($entrynum)] set entry [tagappend $entry Activity $logedit_activity($entrynum)] set entry [tagappend $entry Contact $logedit_contact($entrynum)] set entry [tagappend $entry Rate $logedit_rate($entrynum)] set entry [tagappend $entry Stack-info $logedit_stack_info($entrynum)] set entry [tagappend $entry Description $logedit_description($entrynum) END_D] set endpair [list End ] lappend entry $endpair set logentries [lreplace $logentries $entrynum $entrynum $entry] writelog -modify # readlogentries fillpreventries .preventries.body destroy .logedit$entrynum } proc editpreventry { entrynum } { global logentries global logedit_id logedit_start logedit_end logedit_description logedit_project logedit_action logedit_actiontitle logedit_activity logedit_contact logedit_rate logedit_stack_info set thisentry [lindex $logentries $entrynum] toplevel .logedit$entrynum wm title .logedit$entrynum "[mc {Edit log entry}] $entrynum" frame .logedit$entrynum.id menubutton .logedit$entrynum.id.n -text "Id" -menu .logedit$entrynum.id.n.m menu .logedit$entrynum.id.n.m .logedit$entrynum.id.n.m add command -label [mc Help] -command "taghelp logedit_id" entry .logedit$entrynum.id.v -width 20 -textvariable logedit_id($entrynum) pack .logedit$entrynum.id.n .logedit$entrynum.id.v -in .logedit$entrynum.id -side left pack .logedit$entrynum.id frame .logedit$entrynum.start menubutton .logedit$entrynum.start.n -text [mc "Start Time"] -menu .logedit$entrynum.start.n.m menu .logedit$entrynum.start.n.m .logedit$entrynum.start.n.m add command -label [mc Help] -command "taghelp logedit_start" entry .logedit$entrynum.start.v -width 10 -textvariable logedit_start($entrynum) pack .logedit$entrynum.start.n .logedit$entrynum.start.v -in .logedit$entrynum.start -side left pack .logedit$entrynum.start frame .logedit$entrynum.end menubutton .logedit$entrynum.end.n -text [mc "End Time"] -menu .logedit$entrynum.end.n.m menu .logedit$entrynum.end.n.m .logedit$entrynum.end.n.m add command -label [mc Help] -command "taghelp logedit_end" entry .logedit$entrynum.end.v -width 10 -textvariable logedit_end($entrynum) pack .logedit$entrynum.end.n .logedit$entrynum.end.v -in .logedit$entrynum.end -side left pack .logedit$entrynum.end set logedit_project($entrynum) "" frame .logedit$entrynum.project menu_create .logedit$entrynum.project.n [mc Project] logedit_project 1 projAll menu_setText .logedit$entrynum.project.v entry .logedit$entrynum.project.v -width 20 -textvariable logedit_project($entrynum) pack .logedit$entrynum.project.n .logedit$entrynum.project.v -in .logedit$entrynum.project -side left pack .logedit$entrynum.project set logedit_action($entrynum) "" frame .logedit$entrynum.action menubutton .logedit$entrynum.action.n -text [mc "Action"] -menu .logedit$entrynum.action.n.m menu .logedit$entrynum.action.n.m .logedit$entrynum.action.n.m add command -label [mc Help] -command "taghelp logedit_action" entry .logedit$entrynum.action.v -width 20 -textvariable logedit_action($entrynum) pack .logedit$entrynum.action.n .logedit$entrynum.action.v -in .logedit$entrynum.action -side left pack .logedit$entrynum.action set logedit_actiontitle($entrynum) "" frame .logedit$entrynum.actiontitle menubutton .logedit$entrynum.actiontitle.n -text [mc ActionTitle] -menu .logedit$entrynum.actiontitle.n.m menu .logedit$entrynum.actiontitle.n.m .logedit$entrynum.actiontitle.n.m add command -label [mc Help] -command "taghelp logedit_actiontitle" entry .logedit$entrynum.actiontitle.v -width 20 -textvariable logedit_actiontitle($entrynum) pack .logedit$entrynum.actiontitle.n .logedit$entrynum.actiontitle.v -in .logedit$entrynum.actiontitle -side left pack .logedit$entrynum.actiontitle set logedit_activity($entrynum) "" frame .logedit$entrynum.activity menu_create .logedit$entrynum.activity.n [mc "Activity"] logedit_activity 1 acties menu_setText .logedit$entrynum.activity.v entry .logedit$entrynum.activity.v -width 20 -textvariable logedit_activity($entrynum) pack .logedit$entrynum.activity.n .logedit$entrynum.activity.v -in .logedit$entrynum.activity -side left pack .logedit$entrynum.activity getallcontacts set logedit_contact($entrynum) "" frame .logedit$entrynum.contact menu_create .logedit$entrynum.contact.n [mc "Contact"] logedit_contact 1 cont menu_setText .logedit$entrynum.contact.v entry .logedit$entrynum.contact.v -width 20 -textvariable logedit_contact($entrynum) pack .logedit$entrynum.contact.n .logedit$entrynum.contact.v -in .logedit$entrynum.contact -side left pack .logedit$entrynum.contact set logedit_rate($entrynum) "" frame .logedit$entrynum.rate menubutton .logedit$entrynum.rate.n -text [mc Rate] -menu .logedit$entrynum.rate.n.m menu .logedit$entrynum.rate.n.m .logedit$entrynum.rate.n.m add command -label "--" -command "set logedit_rate($entrynum) \"\"" .logedit$entrynum.rate.n.m add command -label [mc Overtime] -command "set logedit_rate($entrynum) Overtime" .logedit$entrynum.rate.n.m add separator .logedit$entrynum.rate.n.m add command -label [mc Help] -command "taghelp logedit_rate" entry .logedit$entrynum.rate.v -width 10 -textvariable logedit_rate($entrynum) pack .logedit$entrynum.rate.n .logedit$entrynum.rate.v -in .logedit$entrynum.rate -side left pack .logedit$entrynum.rate set logedit_stack_info($entrynum) "" set logedit_description($entrynum) "" frame .logedit$entrynum.description menubutton .logedit$entrynum.description.n -text [mc Description] -menu .logedit$entrynum.description.n.m menu .logedit$entrynum.description.n.m .logedit$entrynum.description.n.m add command -label [mc Help] -command "taghelp logedit_description" text .logedit$entrynum.description.v -rel sunk -wrap word -yscrollcommand ".logedit$entrynum.description.sb set" -width 40 -height 5 scrollbar .logedit$entrynum.description.sb -rel sunk -command ".logedit$entrynum.description.v yview" pack .logedit$entrynum.description.n -in .logedit$entrynum.description -side left pack .logedit$entrynum.description.v -side right -in .logedit$entrynum.description -expand 1 -fill both pack .logedit$entrynum.description.sb -side left -fill y -in .logedit$entrynum.description pack .logedit$entrynum.description -expand 1 -fill both frame .logedit$entrynum.bot button .logedit$entrynum.bot.ok -text [mc "Save"] -command "dologedit $entrynum" button .logedit$entrynum.bot.cancel -text [mc "Cancel"] -command "doCancel .logedit$entrynum" button .logedit$entrynum.bot.help -text [mc "Help"] -command "taghelp logedit" pack .logedit$entrynum.bot.ok .logedit$entrynum.bot.cancel .logedit$entrynum.bot.help -side left -in .logedit$entrynum.bot pack .logedit$entrynum.bot foreach item $thisentry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Id" } { set logedit_id($entrynum) $tagvalue } elseif { $tagname == "StartTime" } { set logedit_start($entrynum) $tagvalue } elseif { $tagname == "EndTime" } { set logedit_end($entrynum) $tagvalue } elseif { $tagname == "Project" } { set logedit_project($entrynum) $tagvalue } elseif { $tagname == "Description" } { set logentry_description($entrynum) $tagvalue .logedit$entrynum.description.v insert end "$tagvalue" } elseif { $tagname == "Action" } { set logedit_action($entrynum) $tagvalue } elseif { $tagname == "ActionTitle" } { set logedit_actiontitle($entrynum) $tagvalue } elseif { $tagname == "Activity" } { set logedit_activity($entrynum) $tagvalue } elseif { $tagname == "Contact" } { set logedit_contact($entrynum) $tagvalue } elseif { $tagname == "Rate" } { set logedit_rate($entrynum) $tagvalue } elseif { $tagname == "Stack-info" } { set logedit_stack_info($entrynum) $tagvalue } } tkwait window .logedit$entrynum } proc readlogentries {} { # Get the log entries from the logfile in logfilename # and put them into logentries global logfilename logentries global log_summary num_today_actions set logentries [tag readfile $logfilename] set header [lindex $logentries 0] # puts "in readlogentries header is $header" # From 0.1.53 the summary and actions are held in the header # The log_summary_temp bit is because the summary could be attached to # an log item in an old file and we dont want to destroy it here. set log_summary [tag_entryVal $header Summary] for {set i 1} { $i<= $num_today_actions } { incr i} { set a [tag_entryVal $header Action-title.$i] .actions.a$i.title insert 0 $a } } proc fillpreventries { w } { global logentries global projTimes # zero all the project times foreach index [array names projTimes] { set projTimes($index) "00:00" } .preventries.body configure -state normal .preventries.body delete 1.0 end # Get rid of the header set realentries [lrange $logentries 1 end ] set entrynum 0 .preventries.body mark set prevmark 1.0 .preventries.body mark gravity prevmark left foreach entry $realentries { # .preventries.body mark set prevmark 1.0 set starttime 0 set endtime 0 set thisproject [mc "unknown"] incr entrynum set itemnum -1 # The entry should be a list of tag-value pairs foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] incr itemnum if { $tagname == "End" } { # Because this is the end tag we should have all the values we are going # to get set duration [timediff $starttime $endtime] if { [info exists projTimes($thisproject)] } { inctime projTimes($thisproject) $duration } else { set projTimes($thisproject) "00:00" inctime projTimes($thisproject) $duration } # The following does not work on TCL v8 (OK on 8.2) - hardwire for portability # .preventries.body insert end [string repeat _ 40] .preventries.body insert end "_______________________________________" .preventries.body insert end "\n" .preventries.body tag add tag_$entrynum prevmark insert # .preventries.body tag add tag_$entrynum 1.0 1.end # puts "Added tag called tag_$entrynum " # puts [.preventries.body tag ranges tag_$entrynum] # puts [.preventries.body mark names] # puts [.preventries.body dump -all 1.0 end] .preventries.body tag bind tag_$entrynum "editpreventry $entrynum" .preventries.body mark set prevmark insert # puts "set prevmark - it is now" # puts [.preventries.body dump -mark 1.0 end] # puts "Tag values are now" # puts [.preventries.body dump -tag 1.0 end] } elseif { $tagname == "Id" } { # Dont bother to display Id's set thisentryid $tagvalue } elseif { $tagname == "StartTime" } { .preventries.body insert end "Start " .preventries.body insert end "$tagvalue " set starttime $tagvalue } elseif { $tagname == "EndTime" } { .preventries.body insert end "[mc End] " .preventries.body insert end "$tagvalue\n" set endtime $tagvalue } elseif { $tagname == "Project" } { .preventries.body insert end "[mc Project]: $tagvalue\n" set thisproject $tagvalue } else { .preventries.body insert end "[mc $tagname]: " .preventries.body insert end "$tagvalue" .preventries.body insert end "\n" } } } .preventries.body yview moveto 1 .preventries.body configure -state disabled } proc FindDefaultPrevday {} { global prevdayfilename year month day rootdir # The whole way this works is flawed - I think I need to just use glob to # look at the files return getdate set logdir "$rootdir/log$year" # puts "day is $day" set numday [ e $day ] set prevday [format "%02d" [incr numday -1 ]] set prevdayfilename "$logdir/$month$prevday.tag" if { ! [ file exists $prevdayfilename ]} { set prevdayfilename "" } } proc fillprevday {} { global prevdayfilename display_prevday if { $display_prevday } { if { $prevdayfilename !="" } { # Fill the prevday.body window .prevday.body delete 1.0 end set f [open $prevdayfilename] while { ![eof $f]} { .prevday.body insert end [read $f 1000] } close $f .prevday.body yview moveto 1 } } } proc openlogfile { args } { # Opens the logfile in the ~/diary/logyyy directory, named after the month and day global logfile year month day logfilename rootdir global logentries # args can be -write set dowrite 0 foreach arg $args { switch -- $arg { "-write" { set dowrite 1 } } } getdate set logdir "$rootdir/log$year" # create the directory if it does not already exist (with a prompt box) if { ! [ file isdirectory $logdir ] } { # mkdir does not like ~/diary - it needs a shell to expand it - work around set currentdir [ pwd ] # we may not even have rootdir if { ! [ file isdirectory $rootdir ] } { file mkdir $rootdir } cd $rootdir # catch {exec mkdir log$year } d file mkdir "$rootdir/log$year" cd $currentdir # note that this does not work under Windows } set logfilename "$logdir/$month$day.tag" # create the file if it does not exist if [ file exists $logfilename ] { set mode a if { $dowrite } { set mode w } set logfile [open $logfilename $mode ] # Fill the preventries.body window readlogentries fillpreventries .preventries.body } else { set logfile [openNewLogFile $logfilename] # tag writefile $logfilename $logentries } fillprevday } proc closelogfile {} { global logfile close $logfile } proc dosummaryOK {} { # Now no longer writes a summary record where it happens to be, write # the summary in writelog global log_summary global logentries set log_summary [.summaryBox.entry.body get 1.0 end] # # but do update the header set header [lindex $logentries 0] tag setorreplace header Summary $log_summary END_S set logentries [lreplace $logentries 0 0 $header] writelog -modify destroy .summaryBox } proc dosummary {} { global log_summary toplevel .summaryBox wm title .summaryBox "Summary of the day" frame .summaryBox.top -relief raised pack .summaryBox.top -side top -fill both frame .summaryBox.entry pack .summaryBox.entry frame .summaryBox.bot pack .summaryBox.bot -side bottom -fill both message .summaryBox.top.msg -text \ "Enter the summary of what you did today" pack .summaryBox.top.msg -side right -expand 1 -fill both -padx 3m -pady 3m text .summaryBox.entry.body -rel sunk -wrap word -yscrollcommand ".summaryBox.entry.sb set" scrollbar .summaryBox.entry.sb -rel sunk -command ".summaryBox.entry.body yview" pack .summaryBox.entry.body -side right -in .summaryBox.entry pack .summaryBox.entry.sb -side right -fill y -in .summaryBox.entry button .summaryBox.bot.ok -text "Save" -command dosummaryOK button .summaryBox.bot.cancel -text [mc Cancel] -command { doCancel .summaryBox } button .summaryBox.bot.help -text [mc Help] -command "taghelp summarybox" pack .summaryBox.bot.ok .summaryBox.bot.cancel .summaryBox.bot.help -side left .summaryBox.entry.body insert end $log_summary # grab set .summaryBox focus .summaryBox tkwait window .summaryBox } proc pickMonth { { funct { doMonthSummary }} { win {.pickmonth} } } { # pick a year and execute the procedure in the argument global year month picked_month_year picked_month_month toplevel $win wm title $win [mc "Choose a month"] set picked_month_year $year set picked_month_month $month label $win.label -text [mc "Choose a month"] pack $win.label -side top frame $win.year label $win.year.ml -text [mc "Month"] button $win.year.mminus -text "-" -command {incr picked_month_month -1 } entry $win.year.me -width 4 -textvariable picked_month_month button $win.year.mplus -text "+" -command {incr picked_month_month } label $win.year.l -text [mc "Year"] button $win.year.minus -text "-" -command {incr picked_month_year -1 } entry $win.year.e -width 4 -textvariable picked_month_year button $win.year.plus -text "+" -command {incr picked_month_year } pack $win.year.ml $win.year.mminus $win.year.me $win.year.mplus $win.year.l $win.year.minus $win.year.e $win.year.plus -side left pack $win.year frame $win.bot button $win.bot.ok -text OK -command { doMonthSummary $picked_month_month $picked_month_year ; destroy .pickmonth } button $win.bot.cancel -text [mc Cancel] -command "destroy $win" pack $win.bot.ok $win.bot.cancel -side left -fill x pack $win.bot } proc doMonthSummaryOK { smonth syear win } { global rootdir # if { $syear == "" } { set syear $year } set logdir "$rootdir/log$syear" set msfile "$logdir/${smonth}.tag" if { ! [file isdirectory $logdir ] } { # mkdir does not like ~/diary - it needs a shell to expand it - work around set currentdir [ pwd ] # we may not even have rootdir if { ! [ file isdirectory $rootdir ] } { file mkdir $rootdir } cd $rootdir # catch {exec mkdir log$year } d file mkdir "$rootdir/log$syear" cd $currentdir # note that this does not work under Windows } # We will overwrite the month summary every time. set ysentries "" set hdr "" set header [list Tag-worklog-version 1.0] lappend hdr $header set header [list End] lappend hdr $header lappend ysentries $hdr set hdr "" set thisDescription [string trim [$win.entry.body get 1.0 end]] set hdr [tagappend $hdr Description $thisDescription END_D] # header is still the End entry lappend hdr $header lappend ysentries $hdr tag writefile $msfile $ysentries destroy $win } proc doMonthSummary { smonth syear } { # Month summaries are of the form nn.tag global year rootdir set monthsumm "" # Make sure smonth is two digit set smonth [format "%02d" [string trimleft $smonth 0]] set logdir "$rootdir/log$syear" set msfile "$logdir/$smonth.tag" # I probably should check for logdir existing and create if required but # this really should go into a common procedure. # And the month and annual summary stuff should also be common. if [ file exists $msfile ] { set monthsumm [tag readfile $msfile] set monthsumm [ lrange $monthsumm 1 end] set monthsumm [ lindex $monthsumm 0] set monthsumm [tag_entryVal $monthsumm Description] } set win .monthsumm$syear$smonth set wintitle [mc "Monthly Summary for "]$syear$smonth toplevel $win wm title $win $wintitle frame $win.entry text $win.entry.body -rel sunk -wrap word -yscrollcommand "$win.entry.sb set" scrollbar $win.entry.sb -rel sunk -command "$win.entry.body yview" pack $win.entry.body -side right -in $win.entry pack $win.entry.sb -side right -fill y -in $win.entry pack $win.entry frame $win.bot button $win.bot.ok -text [mc OK] -command "doMonthSummaryOK $smonth $syear $win" pack $win.bot.ok -side left pack $win.bot # insert the summary in here if there is one. $win.entry.body insert end $monthsumm } proc doYearSummaryOK { {syear {}} } { global year rootdir set win .yearsumm$syear if { $syear == "" } { set syear $year } set logdir "$rootdir/log$syear" set ysfile "$logdir/yearsumm$syear.tag" if { ! [file isdirectory $logdir ] } { # mkdir does not like ~/diary - it needs a shell to expand it - work around set currentdir [ pwd ] # we may not even have rootdir if { ! [ file isdirectory $rootdir ] } { file mkdir $rootdir } cd $rootdir # catch {exec mkdir log$year } d file mkdir "$rootdir/log$syear" cd $currentdir # note that this does not work under Windows } # We will overwrite the year summary every time. set ysentries "" set hdr "" set header [list Tag-worklog-version 1.0] lappend hdr $header set header [list End] lappend hdr $header lappend ysentries $hdr set hdr "" set thisDescription [string trim [$win.entry.body get 1.0 end]] set hdr [tagappend $hdr Description $thisDescription END_D] # header is still the End entry lappend hdr $header lappend ysentries $hdr tag writefile $ysfile $ysentries destroy $win } proc pickYear { { funct { doYearSummary }} { win {.pickyear} } } { # pick a year and execute the procedure in the argument global year picked_year toplevel $win wm title $win [mc "Choose a year"] set picked_year $year label $win.label -text [mc "Choose a year"] pack $win.label -side top frame $win.year label $win.year.l -text [mc "Year"] button $win.year.minus -text "-" -command {incr picked_year -1 } entry $win.year.e -width 4 -textvariable picked_year button $win.year.plus -text "+" -command {incr picked_year } pack $win.year.l $win.year.minus $win.year.e $win.year.plus -side left pack $win.year frame $win.bot #button $win.bot.ok -text OK -command {$funct $picked_year} button $win.bot.ok -text OK -command "$funct $picked_year ; destroy .pickyear" button $win.bot.cancel -text [mc Cancel] -command "destroy $win" pack $win.bot.ok $win.bot.cancel -side left -fill x pack $win.bot } proc doYearSummary { {syear {}} } { # Year summaries live in the directory which belongs to the year (logyyyy) # and are called yearsummyyyy.tag global year rootdir global picked_year set yearsumm "" if { ! [info exist picked_year] } { set picked_year "" } if { $picked_year != "" } { set syear $picked_year } if { $syear == "" } { set syear $year } set ysfile "$rootdir/log$syear/yearsumm$syear.tag" if [ file exists $ysfile ] { set yearsumm [tag readfile $ysfile] set yearsumm [ lrange $yearsumm 1 end] set yearsumm [ lindex $yearsumm 0] set yearsumm [tag_entryVal $yearsumm Description] } toplevel .yearsumm$syear wm title .yearsumm$syear [mc "Annual Summary for "]$syear frame .yearsumm$syear.entry text .yearsumm$syear.entry.body -rel sunk -wrap word -yscrollcommand ".yearsumm$syear.entry.sb set" scrollbar .yearsumm$syear.entry.sb -rel sunk -command ".yearsumm$syear.entry.body yview" pack .yearsumm$syear.entry.body -side right -in .yearsumm$syear.entry pack .yearsumm$syear.entry.sb -side right -fill y -in .yearsumm$syear.entry pack .yearsumm$syear.entry frame .yearsumm$syear.bot button .yearsumm$syear.bot.ok -text [mc OK] -command "doYearSummaryOK $syear" pack .yearsumm$syear.bot.ok -side left pack .yearsumm$syear.bot # insert the summary in here if there is one. .yearsumm$syear.entry.body insert end $yearsumm } proc getlogentry {} { # Get the values for a log entry from the display and return them as a list global logfile hh mm ss year month day currentStart currentEnd currentProject currentActivity actionTitle logfilename logentries currentAction currentActionTitle rate currentContact stack_info # set up variables where required set logid "$year$month$day$hh$mm$ss" # Get the contents of the Description window set thisdescription [string trim [.description.body get 1.0 end]] # Set up thisentry set tagnamelist { Id StartTime EndTime Project Rate Contact Action ActionTitle \ Activity Stack-info Description } set thisentry "" set thisentry [tagappend $thisentry Id $logid] set thisentry [tagappend $thisentry StartTime $currentStart] set thisentry [tagappend $thisentry EndTime $currentEnd] set thisentry [tagappend $thisentry Project $currentProject] set thisentry [tagappend $thisentry Rate $rate] set thisentry [tagappend $thisentry Contact $currentContact] set thisentry [tagappend $thisentry Action $currentAction] set thisentry [tagappend $thisentry ActionTitle $currentActionTitle] set thisentry [tagappend $thisentry Activity $currentActivity] set thisentry [tagappend $thisentry Stack-info $stack_info] set thisentry [tagappend $thisentry Description $thisdescription END_D] set endpair [list End ] lappend thisentry $endpair return $thisentry } proc writetodayactions {} { # Write the today actions into the header global num_today_actions actionTitle logentries set header [lindex $logentries 0] foreach i [array names actionTitle] { if { $actionTitle($i) != "" } { tag setorreplace header Action-title.$i $actionTitle($i) } } set logentries [lreplace $logentries 0 0 $header] } proc writelog { args } { global logfile hh mm ss year month day logfilename logentries # args can be -writeactions -modify set dowriteactions 0 set domodify 0 foreach arg $args { switch -- $arg { "-writeactions" { set dowriteactions 1 } "-modify" { set domodify 1 } } } # If we are modifying then we will have to close the log file and open # it for writing if { $domodify } { #closelogfile tag writefile $logfilename $logentries #openlogfile # for now if we have written the logfile we will not do any more return } set logid "$year$month$day$hh$mm$ss" set thisentry [getlogentry] # append the entry to logentries lappend logentries $thisentry if { $dowriteactions } { writetodayactions } tag writefile $logfilename $logentries return $logid } proc doquit {} { wm protocol . WM_DELETE_WINDOW if {[tk_messageBox -icon warning -title "Quit TAGLOG" -type yesno \ -message "Quit without saving?" -default no] == "yes"} { closelogfile writeallact exit } wm protocol . WM_DELETE_WINDOW doquit } proc doexit {} { dosummary writelog -writeactions writeallact closelogfile exit } proc doCancel { w } { destroy $w } proc refreshLog {} { closelogfile openlogfile } proc dologviewSaveAsOK {} { global SaveAsFilename lvsa_dirname set filename "$lvsa_dirname/$SaveAsFilename" set f [ open $filename w ] puts $f [ .logview.main.body get 1.0 end ] close $f destroy .lvsa } proc dologviewSaveAs {} { global html_public_dir html_private_dir lvsa_dirname SaveAsFilename toplevel .lvsa wm title .lvsa [mc "Save Log View Display As ..."] if { $lvsa_dirname=="" } { set lvsa_dirname . } frame .lvsa.dirname menubutton .lvsa.dirname.l -text [mc "Directory"] -menu .lvsa.dirname.l.m menu .lvsa.dirname.l.m .lvsa.dirname.l.m add command -label [mc "Current Directory"] -command "set lvsa_dirname \".\"" .lvsa.dirname.l.m add command -label "$html_public_dir" -command "set lvsa_dirname \"$html_public_dir\"" .lvsa.dirname.l.m add command -label "$html_private_dir" -command "set lvsa_dirname \"$html_private_dir\"" .lvsa.dirname.l.m add separator .lvsa.dirname.l.m add command -label [mc "Help"] -command "taghelp lvsa_dirname" entry .lvsa.dirname.e -textvariable lvsa_dirname -width 20 pack .lvsa.dirname.l .lvsa.dirname.e -in .lvsa.dirname -side left pack .lvsa.dirname if { ! [info exists SaveAsFilename] } { set SaveAsFilename "logsave" } if { $SaveAsFilename == "" } { set SaveAsFilename "logsave" } frame .lvsa.filename label .lvsa.filename.label -text [mc "File name :"] entry .lvsa.filename.name -relief sunken -textvariable SaveAsFilename pack .lvsa.filename.label .lvsa.filename.name -side left -in .lvsa.filename pack .lvsa.filename frame .lvsa.bot button .lvsa.bot.ok -text [mc "Save Text"] -command dologviewSaveAsOK button .lvsa.bot.savehtml -text [mc "Save HTML"] -command dologviewSaveHtml button .lvsa.bot.cancel -text [mc Cancel] -command { doCancel .lvsa } pack .lvsa.bot.ok .lvsa.bot.savehtml .lvsa.bot.cancel -side left pack .lvsa.bot tkwait window .lvsa } proc dologviewSaveHtml {} { global SaveAsFilename lvsa_dirname logsel_project logsel_descrString logsel_activity logsel_contact if { [regexp -nocase { (.*\.html$)|(.*\.htm$) } $SaveAsFilename] } { set extension "" } else { set extension ".html" } set filename "$lvsa_dirname/$SaveAsFilename$extension" set f [ open $filename w ] puts $f "Saved log file" puts $f "" set filenames [logselfilenames] foreach logfile $filenames { set logs [getlogselection $logfile $logsel_project $logsel_descrString $logsel_activity $logsel_contact] set dateseperator 0 if { [llength $logs] > 0 } { set headerdate [logfilename2date $logfile] puts $f "

$headerdate

" tag writehtml dlist $f $logs } } puts $f "" close $f destroy .lvsa } proc getlogselection { logfile logsel_project logsel_descrString logsel_activity logsel_contact } { set logs [ tag readfile $logfile ] # set logs [lrange $logs 1 end ] set tests "" if { $logsel_project != "" } { set test [list Project == $logsel_project ] lappend tests $test } if { $logsel_descrString != ""} { set test [list Description -contains $logsel_descrString] lappend tests $test } if { $logsel_activity != "" } { set test [list Activity == $logsel_activity] lappend tests $test } if { $logsel_contact != "" } { set test [list Contact == $logsel_contact] lappend tests $test } if { $tests != "" } { set logs [ tag extract $logs $tests ] } return $logs } proc fillLogWin { win filenames logsel_project logsel_descrString logsel_activity logsel_contact {logsel_daysumm {}} } { # Fill the window $win delete 1.0 end foreach logfile $filenames { set logs [getlogselection $logfile $logsel_project $logsel_descrString $logsel_activity $logsel_contact] # puts "logs is $logs" set dateseperator 0 foreach entry $logs { foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { ! $dateseperator } { set dateseperator 1 set headerdate [logfilename2date $logfile] $win insert end "\n\n $headerdate\n\n" } if { $logsel_daysumm } { if {$tagname == "Summary"} { $win insert end "$tagvalue\n" } } else { if { $tagname == "End" } { $win insert end "_______________________________\n" } elseif { $tagname == "Id" } { # dont do anything } elseif { $tagname == "Tag-worklog-version" } { } elseif { $tagname == "Date" } { } else { $win insert end "$tagname: " $win insert end "$tagvalue" $win insert end "\n" } } } } } } proc logselfilenames {} { global logsel_years rootdir foreach year $logsel_years { set decade [expr $year / 10] set fileselection [.logsel.fileselect.d$decade.y$year.files curselection] foreach selfile $fileselection { set fn [.logsel.fileselect.d$decade.y$year.files get $selfile] lappend filenames "$rootdir/log$year/$fn.tag" } } return $filenames } proc displayLogs {} { global logsel_project logsel_years logsel_descrString logsel_activity logsel_contact global logsel_daysumm set filenames [logselfilenames] toplevel .logview wm title .logview [mc "Log view"] frame .logview.main text .logview.main.body -rel sunk -wrap word -yscrollcommand ".logview.main.sb set" scrollbar .logview.main.sb -rel sunk -command ".logview.main.body yview" pack .logview.main.body -side right -fill both -expand 1 -in .logview.main pack .logview.main.sb -side right -fill y -in .logview.main pack .logview.main -fill both -expand 1 frame .logview.bot button .logview.bot.ok -text OK -command { doCancel .logview } button .logview.bot.saveas -text [mc "Save As..."] -command dologviewSaveAs button .logview.bot.savehtml -text [mc "Save HTML..."] -command dologviewSaveHtml pack .logview.bot.ok .logview.bot.saveas -side left pack .logview.bot # Fill the window fillLogWin .logview.main.body $filenames $logsel_project $logsel_descrString $logsel_activity $logsel_contact $logsel_daysumm tkwait window .logview } proc logSelect {} { global rootdir activities allcontacts logsel_years logsel_activity logsel_contact logsel_projstat global logsel_daysumm toplevel .logsel wm title .logsel [mc "Select Log Files ..."] frame .logsel.fileselect set decade 0 set newdecade 0 # Find all the available years foreach yeardir [lsort [glob "$rootdir/log*/"]] { set year [string range [file tail [string trimright $yeardir / ]] 3 end] lappend logsel_years $year set thisdecade [expr $year / 10] if { $thisdecade > $decade } { set decade $thisdecade frame .logsel.fileselect.d$decade set newdecade 1 } frame .logsel.fileselect.d$decade.y$year button .logsel.fileselect.d$decade.y$year.name -text $year -command " doYearSummary $year " pack .logsel.fileselect.d$decade.y$year.name -in .logsel.fileselect.d$decade.y$year listbox .logsel.fileselect.d$decade.y$year.files -relief raised -borderwidth 2 -width 7 -yscrollcommand ".logsel.fileselect.d$decade.y$year.scroll set" -selectmode extended -exportselection false pack .logsel.fileselect.d$decade.y$year.files -in .logsel.fileselect.d$decade.y$year -side left scrollbar .logsel.fileselect.d$decade.y$year.scroll -command ".logsel.fileselect.d$decade.y$year.files yview" pack .logsel.fileselect.d$decade.y$year.scroll -in .logsel.fileselect.d$decade.y$year -side right -fill y pack .logsel.fileselect.d$decade.y$year -in .logsel.fileselect.d$decade -side left set filepat {[0-9]*.tag} foreach filename [lsort [ glob -nocomplain $yeardir/$filepat ]] { set filebase [ file rootname [file tail $filename]] .logsel.fileselect.d$decade.y$year.files insert end $filebase } if { $newdecade } { pack .logsel.fileselect.d$decade -in .logsel.fileselect set newdecade 0 } } pack .logsel.fileselect set logsel_projstat "" frame .logsel.tagselect menu_create .logsel.tagselect.project [mc Project] logsel_project 1 proj menu_setText .logsel.tagselect.projectentry entry .logsel.tagselect.projectentry -textvariable logsel_project -width 10 pack .logsel.tagselect.project .logsel.tagselect.projectentry -in .logsel.tagselect -side left label .logsel.tagselect.descrl -text [mc "Description contains"] entry .logsel.tagselect.descre -textvariable logsel_descrString pack .logsel.tagselect.descrl .logsel.tagselect.descre -in .logsel.tagselect -side left pack .logsel.tagselect frame .logsel.nextsel set logsel_activity "" menubutton .logsel.nextsel.activity -text [mc Activity] -menu .logsel.nextsel.activity.m menu .logsel.nextsel.activity.m .logsel.nextsel.activity.m add command -label "--" -command "set logsel_activity \"\"" foreach activity $activities { .logsel.nextsel.activity.m add command -label "$activity" -command "set logsel_activity \"$activity\"" } .logsel.nextsel.activity.m add separator .logsel.nextsel.activity.m add command -label [mc Help] -command "taghelp logsel_activity" entry .logsel.nextsel.activentry -textvariable logsel_activity pack .logsel.nextsel.activity .logsel.nextsel.activentry -in .logsel.nextsel -side left getallcontacts set logsel_contact "" menubutton .logsel.nextsel.contact -text [mc Contact] -menu .logsel.nextsel.contact.m menu .logsel.nextsel.contact.m .logsel.nextsel.contact.m add command -label "--" -command "set logsel_contact \"\"" foreach contact $allcontacts { foreach item $contact { if { [lindex $item 0] == "Id" } { .logsel.nextsel.contact.m add command -label [lindex $item 1] -command "set logsel_contact \"[lindex $item 1]\"" } } } .logsel.nextsel.contact.m add separator .logsel.nextsel.contact.m add command -label [mc Help] -command "taghelp logsel_contact" entry .logsel.nextsel.contacte -textvariable logsel_contact pack .logsel.nextsel.contact .logsel.nextsel.contacte -in .logsel.nextsel -side left pack .logsel.nextsel frame .logsel.summsel checkbutton .logsel.summsel.daysumm -text [mc "Show day summaries only"] -relief flat -variable logsel_daysumm pack .logsel.summsel.daysumm -in .logsel.summsel -side left pack .logsel.summsel frame .logsel.bot button .logsel.bot.ok -text OK -command displayLogs button .logsel.bot.cancel -text [mc Cancel] -command { doCancel .logsel } button .logsel.bot.help -text [mc Help] -command "taghelp logsel" pack .logsel.bot.ok .logsel.bot.cancel .logsel.bot.help -side left pack .logsel.bot tkwait window .logsel } proc openNewLogFile {logfilename} { global logentries rootdir # opens a log file with mode "w" and writes the header lines # Note that this should only be called if the file really is new. # and that it should only set the global logentries on todays file. if { [file readable $logfilename] } { set logfile [open $logfilename w] return $logfile } set date [clock format [clock scan [logfilename2date $logfilename -us]] -format "%Y-%m-%d"] set weekday [clock format [clock scan [logfilename2date $logfilename -us]] -format "%A"] set istoday 0 if { $date == [clock format [clock seconds] -format "%Y-%m-%d"] } { set istoday 1 } set hdr "" set header [list Tag-worklog-version 1.0] lappend hdr $header set header [list Date $date] lappend hdr $header set header [list WeekDay $weekday] lappend hdr $header set header [list End] lappend hdr $header # If we got through all the preparation OK then open the log file set logfile [open $logfilename w] if { $istoday } { lappend logentries $hdr tag writefile $logfilename $logentries } else { lappend dummy $hdr tag writefile $logfilename $dummy } return $logfile } proc doadjstartOK {} { global currentStart logentries adjPrevEnd NewStart if { $adjPrevEnd } { # put the value of currentStart into the previous end time set lastitem [expr { [llength $logentries] - 1}] set preventry [lindex $logentries $lastitem ] tag replace preventry EndTime $NewStart set logentries [lreplace $logentries $lastitem $lastitem $preventry] writelog -modify # readlogentries fillpreventries .preventries.body } set currentStart $NewStart destroy .adjstart } proc adjNewStart value { global NewStart currentStart set NewStart $currentStart inctime NewStart [expr { - $value * 60 }] } proc adjustStart {} { global currentStart logentries adjPrevEnd NewStart set prevend "" set prevstart "" toplevel .adjstart wm title .adjstart [mc "Adjust start time"] set preventry [lindex $logentries [expr { [llength $logentries] -1} ]] foreach item $preventry { if { [lindex $item 0 ] == "StartTime" } { set prevstart [lindex $item 1 ] } if { [lindex $item 0 ] == "EndTime" } { set prevend [lindex $item 1 ] } } frame .adjstart.top if { $prevstart != ""} { message .adjstart.top.msg -width 200 -text \ "[mc {Adjust start time back towards previous start time of}] $prevstart" } else { message .adjstart.top.msg -text [mc "Adjust start time back towards the start of the day"] } pack .adjstart.top.msg pack .adjstart.top if { $prevstart == "" } { set prevstart "00:00:00" } set adjPrevEnd 0 if { $prevend != ""} { set adjPrevEnd 1 checkbutton .adjstart.adjprev -text [mc "Adjust previous end time"] -variable adjPrevEnd pack .adjstart.adjprev } set NewStart $currentStart frame .adjstart.newstart label .adjstart.newstart.l -text [mc "New Start Time"] entry .adjstart.newstart.e -width 10 -textvariable NewStart pack .adjstart.newstart.l .adjstart.newstart.e -side left -in .adjstart.newstart pack .adjstart.newstart set adjTimeDiff [expr { [timediff $prevstart $currentStart] / 60 } ] scale .adjstart.scale -label [mc "Minutes to Subtract from StartTime"] -orient horizontal -from 0 -to $adjTimeDiff -command adjNewStart -length 220 pack .adjstart.scale frame .adjstart.bot button .adjstart.bot.ok -text [mc "Set"] -command doadjstartOK button .adjstart.bot.cancel -text [mc Cancel] -command { doCancel .adjstart } button .adjstart.bot.help -text [mc Help] -command "taghelp adjstart" pack .adjstart.bot.ok .adjstart.bot.cancel .adjstart.bot.help -side left pack .adjstart.bot tkwait window .adjstart } sourcelibs initialise wm protocol . WM_DELETE_WINDOW doquit # protect against mc being set on first initialise if { [ llength [ info procs mc ]] == 0 } { if { [info tclversion] >= 8.2 } { package require msgcat namespace import msgcat::mc msgcat::mclocale $language msgcat::mcload $libsdir } else { proc mc { msg } { return $msg } } } setupdisplay openlogfile minuteTimer setupHandleMidnight activate_timeblocked displayPeriodicActions if { [llength start_procs] !=0 } { foreach p $start_procs { catch { eval $p } mesg if { $mesg != "" } { global errorInfo tk_messageBox -icon error -title [mc "Error in startprocs"] -type ok -message $errorInfo } } } taglog-0.2.6/src/install.tcl0000755000175000017500000001741513550071213014423 0ustar johnjohn#!/usr/bin/env tclsh # Script to install taglog - this is under development. # Inoke as wish install.tcl (for Unix) or by clicking on the install icon # (for Windows) proc do_install {} { global bindir taglogbin libfiles libdir docdir helpfiles msgfiles mandir man1files man3files removeold activitiesfile global rootdir tcl_platform global activitiesdir global userinstall global system global srcdir global srcdocdir global isAndroid # srcdir should be the same as the directory we are currently in set srcdir [file dirname [info script]] # srcdocdir should be $srcdir/../doc/ set srcdocdir "$srcdir/../doc/" # Make the directories follow the libdir in windows if they were changed # by the user. if {$tcl_platform(platform) == "windows" } { set bindir $libdir set docdir $libdir set mandir $libdir set rootdir $libdir set activitiesdir $libdir } # if { ! [ file isdirectory $bindir ] } { file mkdir $bindir } file copy -force $srcdir/taglog $taglogbin puts "Installed taglog into $taglogbin" if { $tcl_platform(platform) == "unix" } { # make it executable by user and group file attributes $taglogbin -permissions ug+rx } if { ! [ file isdirectory $libdir ] } { file mkdir $libdir } foreach libfile $libfiles { file copy -force $srcdir/$libfile $libdir if {$system} { file attributes $libfile -permissions +r } } #puts "Installed library files into $libdir" # set up package index file copy -force $srcdir/pkgIndex.tcl $libdir if { $removeold } { file delete $bindir/taglog_help.tcl # we might want to delete other old library files } foreach helpfile $helpfiles { file copy -force $srcdir/$helpfile $libdir } foreach msgfile $msgfiles { file copy -force $srcdir/$msgfile $libdir } if { $mandir != "" } { foreach man1file $man1files { file copy -force $srcdir/$man1file $mandir/man1 } foreach man3file $man3files { file copy -force $srcdir/$man3file $mandir/man3 } } # Copy the documentation files (everything in the doc directory) if { $docdir !="" } { if { ! [ file isdirectory $docdir ] } { file mkdir $docdir } foreach docfile [ glob $srcdocdir/* ] { if { $docfile != "INSTALL" } { file copy -force $docfile $docdir } } if { ! [file isdirectory $activitiesdir]} { file mkdir $activitiesdir } file copy -force $srcdir/$activitiesfile $activitiesdir/$activitiesfile } exit } proc choose_dir {var label} { upvar #0 $var dir set dir [tk_chooseDirectory -title $label -parent .] } proc directory_chooser {path label var} { frame $path label $path.l -text $label -width 30 -anchor w entry $path.e -textvariable $var -width 30 button $path.c -text "..." -command [list choose_dir $var $label] grid $path.l $path.e $path.c -sticky w grid columnconfigure $path 1 -weight 1 return $path } proc choose_file {var label} { upvar #0 $var file set file [tk_getOpenFile -title $label -parent .] } proc file_chooser {path label var} { frame $path label $path.l -text $label -anchor w -width 30 entry $path.e -textvariable $var -width 30 button $path.c -text "..." -command [list choose_file $var $label] grid $path.l $path.e $path.c -sticky w grid columnconfigure $path 1 -weight 1 return $path } proc setup_display {} { global bindir taglogbin libfiles libdir docdir removeold userinstall global isAndroid package require Tk wm title . "Install Taglog" set bin [directory_chooser .bindir "Binary Directory" ::bindir] set tagbin [file_chooser .taglogbin "Taglog executable" ::taglogbin] set lib [directory_chooser .libdir "Library Directory" ::libdir] set man [directory_chooser .mandir "Manpage dir" ::mandir] set doc [directory_chooser .docdir "Documentation Directory" ::docdir] set root [directory_chooser .datadir "Data Directory" ::rootdir] grid $bin -sticky w grid $tagbin -sticky w grid $lib -sticky w grid $man -sticky w grid $doc -sticky w grid $root -sticky w # For the case where the library files have moved we want to issue a # warning (and remove the old files set removeold 0 if { $bindir != $libdir } { if { [file readable $bindir/taglog_help.tcl] } { if {[tk_messageBox -icon warning -title "Library has moved" -message \ "The library files are now in $libdir - the old taglog_help.tcl has been removed - you may wish to tidy up the other files in $bindir" \ -type yesno] == "yes"} { set removeold 1 } else { exit } } } frame .bot button .bot.ok -text OK -command do_install button .bot.cancel -text Cancel -command exit grid .bot.ok .bot.cancel -sticky w -padx 3 grid .bot -sticky w if { $isAndroid } { # wm attributes . -fullscreen 1 # It looks as if the size is pixels rather than characters. wm geometry . 200x300 focus . } tkwait window . } global bindir taglogbin libfiles libdir argv docdir helpfiles destdir mandir removeold system global activitiesdir isAndroid set quiet 0 set debian 0 set system 0 set destdir "" set mandir "" set vfs 0 set userinstall 1 set isAndroid 0 if { [info commands sdltk] ne "" } { set isAndroid [sdltk android] puts "running on Android - $isAndroid" } set usage "install.tcl ?-quiet? ?-debian path|-system|-vfs?" set skipnext 0 set nextispath 0 foreach arg $argv { if {$skipnext} {set skipnext 0 continue } if {$nextispath} { set destdir $arg continue } switch -- $arg { "-quiet" { set quiet 1 } "-debian" { set debian 1 set quiet 1 set userinstall 0 set nextispath 1 } "-system" { set system 1 set userinstall 0 set quiet 1 } "-vfs" { set vfs 1 set quiet 1 set userinstall 0 } default { return -code error "Unknown option \"$arg\"\n $usage" } } } # It only deals with the install as normal user under Unix at present. # amd possibly under Windows. set removeold 0 if { $tcl_platform(platform) == "unix" } { # Work out where the wish executable is. set wishexec [info nameofexecutable] # if { $tcl_platform(user) == "root" } if { $system } { # Install into /usr/local by default set instroot "/usr/local" set libdir "$instroot/lib/taglog" set bindir "$instroot/bin" set docdir "$instroot/doc/taglog" set mandir "$instroot/man" set rootdir "~/diary" set activitiesdir "$libdir" set taglogbin $bindir/taglog } elseif { $debian } { set libdir "$destdir/usr/share/taglog" set bindir "$destdir/usr/bin" set docdir "$destdir/usr/share/doc/taglog" set mandir "$destdir/usr/share/man" set taglogbin $destdir/usr/bin/taglog set rootdir "~/diary" set activitiesdir "$libdir" } elseif { $vfs } { set destdir taglog.vfs set libdir "$destdir" set bindir "$destdir" set docdir "" set mandir "" set activitiesdir "$libdir" set taglogbin "$destdir/main.tcl" } else { # Unix non-root install set libdir "~/lib/taglog" set bindir "~/bin" set docdir "~/bin" set mandir "~/bin" set taglogbin $bindir/taglog if { $isAndroid } { set taglogbin $bindir/taglog.tag } set rootdir "~/diary" set activitiesdir "$rootdir" } } elseif { $tcl_platform(platform) == "windows" } { set libdir "C:/Program Files/taglog" set bindir $libdir set docdir $libdir set mandir $libdir set rootdir $libdir set activitiesdir $rootdir set taglogbin $bindir/taglog.tcl } else { error "Unknown platform $tcl_platform(platform) - cant automatically install" } # Languages, other than English, supported # Each must have a taglog_help_xx.tag and an xx.msg file set languages { de fr nl } set libfiles { tag.tcl taglog_action.tcl taglog_report.tcl taglog_init.tcl smtp.tcl taglog_help.tcl taglog_contact.tcl taglog_util.tcl taglog_project.tcl cal2.xbm logEdit.tcl taglog_widgets.tcl mainwin.tcl taglog_stack.tcl } set binfiles { taglog } set helpfiles { taglog_help_en.tag taglog_help_de.tag taglog_help_fr.tag taglog_help_nl.tag } set msgfiles { de.msg fr.msg nl.msg } set man1files { taglog.1 } set man3files { tag.3 } set activitiesfile {activities} if { $quiet } { do_install } else { setup_display } exit taglog-0.2.6/src/smtp.tcl0000644000175000017500000001057113534701742013742 0ustar johnjohnpackage provide smtpclient 0.1 # SMTP mailer support for tcl # # This defines a new command smtp # # smtp send message recipient [filename] # # sends a file (read from filename) to the recpient(s) specified in # recipient, which is a list of email addresses # # send takes parameters # -attachtag tagfilelist # attach the given list (which must be a tagged file) to the # message # # -attachname name # associate a name with the attachment # # -header typename # Add a tag header tag-typename-version # # # smtp reads from a file called ~/.smtp (for unix) or ~/smtp.cfg (for Windows) # to initialise its variables. # It needs to know # thishost - what it should put in the HELO part of the SMTP dialogue # mailhost - what system to connect to # myemail - the current user's email address (for MAIL FROM) # proc smtp { action args } { global smtpv tcl_platform if {$action == "init" } { global env # initialise if { [file readable "~/.smtp"]} { source "~/.smtp" set smtpv(prefsfile) "~/.smtp" } elseif { [ file readable "~/smtp.cfg"]} { source "~/smtp.cfg" set smtpv(prefsfile) "~/smtp.cfg" } else { set smtpv(thishost) [info hostname] set smtpv(mailhost) "localhost" if { ($tcl_platform(platform) == "unix") && ([info exists env(USER)])} { set smtpv(myemail) "$env(USER)@$smtpv(thishost)" } else { set smtpv(myemail) "someuser@$smtpv(thishost)" } set smtpv(port) 25 # could be 587 if we are a Mail Submission Agent set smtpv(prefsfile) "" set smtpv(initialised) 1 } return 1 } elseif {$action == "send" } { if { ! [info exists smtpv(initialised) ] } { smtp init } set subject "" set numattach 0 # look for switches while { [ string index [lindex $args 0] 0] == "-" } { set flag [lindex $args 0] set args [lrange $args 1 end] if { $flag == "-subject"} { set subject [lindex $args 0] set args [lrange $args 1 end] } elseif { $flag == "-attachtag"} { incr numattach set attachment($numattach) [lindex $args 0] set attachmentname($numattach) "noname.tag" set attachmentheader($numattach) "" set args [lrange $args 1 end] } elseif { $flag == "-attachname"} { set attachmentname($numattach) [lindex $args 0] set args [lrange $args 1 end] } elseif { $flag == "-header" } { set attachmentheader($numattach) [lindex $args 0] set args [lrange $args 1 end] } else { error "smtp send - unknown switch $flag" } } set message [lindex $args 0] set recipient [lindex $args 1] if {[llength $args ] > 2 } { set filename [lindex $args 2] } # Open a connection set mc [socket $smtpv(mailhost) $smtpv(port) ] set reply [gets $mc ] # puts "reply is $reply" puts $mc "HELO $smtpv(thishost)" flush $mc set reply [gets $mc ] # puts "reply is $reply" puts $mc "Mail From: $smtpv(myemail)" flush $mc set reply [gets $mc ] # puts "reply is $reply" puts $mc "Rcpt to: $recipient" flush $mc set reply [gets $mc] # puts "reply (rcpt to) is $reply" puts $mc "DATA" flush $mc set reply [gets $mc] # puts "reply (data) is $reply" puts $mc "To: $recipient" if {$subject != ""} { puts $mc "Subject: $subject" } puts $mc "Mime-version: 1.0" if { $numattach > 0 } { set boundary "----=zzz12345split" puts $mc "Content-type: Multipart/mixed; boundary=\"$boundary\"" } puts $mc "" flush $mc # set reply [gets $mc] # puts "reply is $reply" if { $numattach > 0 } { puts $mc "This is a MIME message" puts $mc "" puts $mc "--$boundary" puts $mc "Content-type: text/plain" puts $mc "" } puts $mc $message puts $mc "" puts $mc "" flush $mc # set reply [gets $mc] # puts "reply (message) is $reply" for {set a 1} {$a <= $numattach} { incr a} { puts $mc "--$boundary" if { $attachmentname($numattach) != "" } { set nf "; name=\"$attachmentname($numattach)\"" } else { set nf "" } puts $mc "Content-type: text/prs.lines.tag $nf" if { $attachmentname($numattach) != "" } { puts $mc "Content-disposition: attachment; filename=\"$attachmentname($numattach)\"" } puts $mc "" # puts $mc $attachment($a) if { $attachmentheader($numattach) != ""} { puts $mc "Tag-$attachmentheader($numattach)-version; 1.0" puts $mc "End:" puts $mc "" } tag writeentry $mc $attachment($a) puts $mc "" } if { $numattach > 0 } { # put on the final boundary puts $mc "--$boundary--" } puts $mc "." flush $mc set reply [gets $mc] # puts "reply (dot) is $reply" puts $mc "QUIT" flush $mc set reply [gets $mc] # puts "reply is $reply" } return 0 } taglog-0.2.6/src/tag.tcl0000644000175000017500000006342113534701742013534 0ustar johnjohnpackage provide tag 0.1 # # This defines a set of operations on tag type data files, all accessed # through one master tag procedure. # # This will probably be rewritten as a loadable set of extensions. # # tag open # tag getheader # tag getnext # returns a list, where each list item is a pair of values, # of the form {tagname value} # (or for multiline values the items are a triplet of the # form {tagname value endlabel} # # tag readfile # returns a list, where each list item is a tag record as # above # # tag readselected # reads a file and returns all those entries which match the # in a similar maner to doing a # 'tag readfile' followed by a 'tag extract' # # tag writehtml dlist [options] # write the taglist to the specified file (appending to it) # a list of html elements as a definition list # # tag writehtml tlist [options] # write the taglist to the file as two column tables, the # first column being the values, and the second being the # valuse # # tag writehtml table [options] # write the taglist to the spedified file (appending to it) # as a table. The columns of the table are given by the # -fields option # # tag sort [options] # return a list of tagrecords, sorted in order of the value # of fieldname. It tekes the same options as the lsort command # proc tag_entryVal { entry attribName } { # return the value of a given item out of a tag entry # # entry - an entry in a tag file as a TCL list # attribName - the name of the attribute to be returned # # Based on logEdit_tagVal by Alexander Spanke foreach i $entry { if {[lindex $i 0] == $attribName} { return [lindex $i 1] } } return "" } proc tag { action args } { proc tag__readitem { buffervar indexvar } { # Read an item from a buffer which contains a tagged file # buffervar - the name of the buffer to read from # indexvar - the name of the variable containing the index into that # buffer - will be incremented # The result is a TCL list of either a label and a value, or a label, # value and endlabel # upvar $buffervar tagbuf upvar $indexvar i set l [string length $tagbuf] set tagendlabel "" set tagname "" set tagvalue "" # puts "tag__readitem (start) i is $i" # Skip leading white space (note requires TCL 8.1.1) while { $i < $l && [string is space [string index $tagbuf $i]]} { incr i # puts "in loop i is $i, tagbuf i is [string index $tagbuf $i]" } # puts "tag__readline (afterspaces) i is $i" # Pick up characters into the label set start $i while { $i < $l && [ string index $tagbuf $i ] != ":" } { incr i } set tagname [string range $tagbuf $start [ expr $i-1]] incr i # We need to know if this was a multiline tag or not if {[ string index $tagbuf $i] == ":" } { # puts "Multiline tag" incr i set start $i while { $i < $l && [string index $tagbuf $i] != "\n" } { incr i} set tagendlabel [string trim [string range $tagbuf $start [expr $i-1]]] # puts "Endlabel is $tagendlabel" incr start [expr [string length $tagendlabel]+2] # Now we have the harder task to find the end of this block, by finding the # endlabel, set e [string first "$tagendlabel\n" [string range $tagbuf $i end]] # puts "Endlabel found at $e" incr i $e set tagvalue [string range $tagbuf $start [expr $i-2]] # puts "tagvalue is $tagvalue" incr i [string length $tagendlabel] # puts "buffer pointer is now [string index $tagbuf $i]" } else { # puts "Single line tag" if { [string index $tagbuf $i ] == " " } { incr i } set start $i while { $i < $l && [string index $tagbuf $i] != "\n" } { incr i} set tagvalue [string range $tagbuf $start [expr $i-1]] } # We now have a tagname and value pair - append them to thisentry set thispair [list $tagname $tagvalue] # if there is an endlabel then we ought to append it to thispair if { $tagendlabel != "" } { lappend thispair $tagendlabel } # puts "thispair is $thispair" if { $tagname == "" && $tagvalue == "" } { return "" } return $thispair } proc tag__readentry { buffervar indexvar } { # Read an entry from a buffer which contains a tagged file # buffervar - the name of the buffer to read from # indexvar - the name of the variable containing the index into that # buffer - will be incremented # The result is a TCL list of items, as returned by tag__readitem # upvar $buffervar tagbuf upvar $indexvar i set thisentry "" set endseen 0 while { !$endseen } { set thisitem [tag__readitem tagbuf i] # puts "tag__readentry - thisitem is $thisitem, i is $i" if { $thisitem == "" } { break } if {[llength $thisentry] == 0 } { set thisentry [list $thisitem] } else { # set thisentry [list $thisentry $thispair] lappend thisentry $thisitem } # puts "thisentry is $thisentry" # if the tagname is End then we should append thisentry to the result and # clear it if {[lindex $thisitem 0] == "End"} { set endseen 1 } } return $thisentry } proc tag__skip2end { buffervar indexvar} { # Call as tag_skip2end buf index # Moves the index variable forward until it is pointing just beyond an End: # upvar $buffervar tagbuf upvar $indexvar i set e [string first "End:" [string range $tagbuf $i end]] incr i $e set l [string length $tagbuf] while { $i < $l && [string index $tagbuf $i] != "\n" } { incr i} # puts "Rest of buffer is [string range $tagbuf $i end]" } proc tag__findsorted { filename searchval } { set h [tag readheader $filename] set sortkey "" foreach item $h { if {[lindex $item 0] == "Sort-key" } { set sortkey [lindex $item 1] break } } set minptr 0 set maxptr [file size $filename] # bufsize must be large enough to hold the largest record set bufsize 1000 set f [open $filename] set lc 0 while { $lc < 10 } { set ptr [expr int(($maxptr - $minptr)/2) + $minptr] set searchspace [expr $maxptr - $ptr] seek $f $ptr set buf [read $f $bufsize] set i 0 # puts "buf is $buf" tag__skip2end buf i set start $i # Really want a repeat until here - in case the index variable is not the # next in the record. set thisitem [tag__readitem buf i] set thisval [lindex $thisitem 1] set t [string compare -nocase $thisval $searchval] if { $t== -1 } { # too early set minptr $ptr # puts "Too early - $searchval $thisval look now between $minptr $maxptr ($searchspace)" # break } elseif { $t == 1 } { # Too late # puts "ptr is now $ptr" set maxptr $ptr # set minptr [expr $ptr - $bufsize] # if { $minptr <0 } { set minptr 0 } # puts "too late - $searchval $thisval look now between $minptr $maxptr ($searchspace)" } elseif { $t == 0 } { # Found it ! # puts "Found it !" seek $f [expr $ptr + $start] set buf [read $f $bufsize] # puts "found buf is $buf" set i 0 close $f return [tag__readentry buf i] } else { error "Error - t is $t !!!" exit } incr lc } close $f return "" } proc tag_find { taglist test {startindex 0}} { # taglist is a list of tag entries # test is a list of tests # startindex is the first place to start in the taglist # - returns the index to where the next matching entry or -1 if not found # for {set i $startindex } {$i <= [llength $taglist]} {incr i} { set item [lindex $taglist $i] if {[tag matchall $item $test ]} { return $i } } return -1 } proc tag_findval { taglist field value {startindex 0}} { # like tag_find, but takes a field and value as a common operation for {set i $startindex } {$i <= [llength $taglist]} {incr i} { set item [lindex $taglist $i] if { [tag_entryVal $item $field] == $value } { return $i } } return -1 } if { $action == "readfile0" } { set result {} if { ! [file readable [lindex $args 0]]} { return $result } set f [open [lindex $args 0]] # ought to check that it opened OK - if not then return an empty list # This is not the most efficient way to do it - read the whole file into # a single variable - then split up that variable - but will work on # reading it in chunks later while { ![eof $f]} { set tagbuf [read $f] } close $f set finished 0 set thisentry {} while { [string length $tagbuf] >0 } { set tagendlabel "" set tagindex [ string first : $tagbuf ] # puts "tagindex is $tagindex" incr tagindex -1 set tagname [ string range $tagbuf 0 $tagindex ] # puts "tagname is $tagname" incr tagindex 2 set tagbuf [string range $tagbuf $tagindex end ] # puts "tagbuf is now $tagbuf" if { [string index $tagbuf 0] == ":" } { set tagindex [string first \n $tagbuf ] incr tagindex -1 set tagendlabel [string trimleft [ string range $tagbuf 1 $tagindex ]] # puts "tagendlabel is $tagendlabel" incr tagindex 2 set tagbuf [string range $tagbuf $tagindex end] # puts "Tagbuf (ML) is $tagbuf" set tagindex [string first "$tagendlabel\n" $tagbuf] # puts "tagindex is $tagindex" incr tagindex -2 set tagvalue [string range $tagbuf 0 $tagindex] # puts "tagvalue is $tagvalue" incr tagindex 2 incr tagindex [string length $tagendlabel] set tagbuf [string range $tagbuf $tagindex end ] set tagbuf [string trimleft $tagbuf] # puts "tagbuf is now $tagbuf" } else { set tagindex [ string first \n $tagbuf ] incr tagindex -1 # puts "tagindex is $tagindex" set tagvalue [string range $tagbuf 0 $tagindex ] set tagvalue [string trimleft $tagvalue] # puts "tagvalue is $tagvalue" incr tagindex 2 set tagbuf [string range $tagbuf $tagindex end ] set tagbuf [string trimleft $tagbuf] # puts "tagbuf is now $tagbuf" } # We now have a tagname and value pair - append them to thisentry set thispair [list $tagname $tagvalue] # if there is an endlabel then we ought to append it to thispair if { $tagendlabel != "" } { lappend thispair $tagendlabel } # puts "thispair is $thispair" if {[llength $thisentry] == 0 } { set thisentry [list $thispair] } else { # set thisentry [list $thisentry $thispair] lappend thisentry $thispair } # puts "thisentry is $thisentry" # if the tagname is End then we should append thisentry to the result and # clear it if {$tagname == "End"} { if {[llength $result] == 0 } { set result [list $thisentry] } else { lappend result $thisentry } # puts "result is $result" set thisentry "" } } return $result } elseif { $action == "readfile" } { if { [info tclversion] < 8.2 } { return [tag readfile0 [lindex $args 0]] } set result {} if { ! [file readable [lindex $args 0]]} { return $result } set f [open [lindex $args 0]] # ought to check that it opened OK - if not then return an empty list # This is not the most efficient way to do it - read the whole file into # a single variable - then split up that variable - but will work on # reading it in chunks later while { ![eof $f]} { set tagbuf [read $f] } close $f set tagindex 0 while { $tagindex < [string length $tagbuf] } { set thisentry [tag__readentry tagbuf tagindex] # puts "thisentry is $thisentry" if {[llength $result] == 0 } { set result [list $thisentry] } else { # puts "Length of thisentry is [llength $thisentry]" if {[llength $thisentry] !=0} { lappend result $thisentry } } # puts "result is $result" } # puts "result is $result" return $result } elseif { $action == "readheader" } { set result {} if { ! [file readable [lindex $args 0]]} { return $result } set f [open [lindex $args 0]] # ought to check that it opened OK - if not then return an empty list # Note that we assume the header will be contained in 1000 bytes. set headbuf [read $f 1000] close $f set finished 0 set tagindex 0 return [ tag__readentry headbuf tagindex] } elseif { $action == "readbuf" } { # Return a tagged list in internal format from a buffer which contains # tagged data. set result {} # This is not the most efficient way to do it - read the whole file into # a single variable - then split up that variable - but will work on # reading it in chunks later set inbuf [lindex $args 0] upvar $inbuf tagbuf set finished 0 set thisentry {} while { [string length $tagbuf] >0 } { set tagendlabel "" set tagindex [ string first : $tagbuf ] # puts "tagindex is $tagindex" incr tagindex -1 set tagname [ string range $tagbuf 0 $tagindex ] # puts "tagname is $tagname" incr tagindex 2 set tagbuf [string range $tagbuf $tagindex end ] # puts "tagbuf is now $tagbuf" if { [string index $tagbuf 0] == ":" } { set tagindex [string first \n $tagbuf ] incr tagindex -1 set tagendlabel [string trimleft [ string range $tagbuf 1 $tagindex ]] # puts "tagendlabel is $tagendlabel" incr tagindex 2 set tagbuf [string range $tagbuf $tagindex end] # puts "Tagbuf (ML) is $tagbuf" set tagindex [string first "$tagendlabel\n" $tagbuf] # puts "tagindex is $tagindex" incr tagindex -2 set tagvalue [string range $tagbuf 0 $tagindex] # puts "tagvalue is $tagvalue" incr tagindex 2 incr tagindex [string length $tagendlabel] set tagbuf [string range $tagbuf $tagindex end ] set tagbuf [string trimleft $tagbuf] # puts "tagbuf is now $tagbuf" } else { set tagindex [ string first \n $tagbuf ] incr tagindex -1 # puts "tagindex is $tagindex" set tagvalue [string range $tagbuf 0 $tagindex ] set tagvalue [string trimleft $tagvalue] # puts "tagvalue is $tagvalue" incr tagindex 2 set tagbuf [string range $tagbuf $tagindex end ] set tagbuf [string trimleft $tagbuf] # puts "tagbuf is now $tagbuf" } # We now have a tagname and value pair - append them to thisentry set thispair [list $tagname $tagvalue] # if there is an endlabel then we ought to append it to thispair if { $tagendlabel != "" } { lappend thispair $tagendlabel } # puts "thispair is $thispair" if {[llength $thisentry] == 0 } { set thisentry [list $thispair] } else { # set thisentry [list $thisentry $thispair] lappend thisentry $thispair } # puts "thisentry is $thisentry" # if the tagname is End then we should append thisentry to the result and # clear it if {$tagname == "End"} { if {[llength $result] == 0 } { set result [list $thisentry] } else { lappend result $thisentry } # puts "result is $result" set thisentry {} } } return $result } elseif { $action == "findsorted" } { # # tag findsorted tagfile value # return [tag__findsorted [lindex $args 0] [lindex $args 1]] } elseif { $action == "writefile" } { # # Write out a whole file 'tag writefile filename list [mode]' # set filename [lindex $args 0] set tlist [lindex $args 1] set mode [lindex $args 2] if {$mode == ""} {set mode w} # puts "tag writefile $filename $tlist" set f [open $filename $mode] foreach entry $tlist { # the entry should be a list of tag-value pairs (except multiline which have # a third element, which is the delimiter foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if {[llength $item] == 3 } { set delimiter [lindex $item 2] puts $f "${tagname}:: $delimiter" puts $f $tagvalue puts $f $delimiter } else { puts $f "$tagname: $tagvalue" } } } close $f } elseif { $action == "writeentry" } { # tag writeentry filechannel entry # set f [lindex $args 0] set entry [lindex $args 1] foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if {[llength $item] == 3 } { set delimiter [lindex $item 2] puts $f "${tagname}:: $delimiter" puts $f $tagvalue puts $f $delimiter } else { puts $f "$tagname: $tagvalue" } } } elseif { $action == "matchcond" } { # Take a single tag entry and return 1 if it matches the criteria or 0 if not # set entry [lindex $args 0 ] set test [lindex $args 1] foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] set testlabel [lindex $test 0] set testop [lindex $test 1] if { $testop == "=="} { set testvalue [lindex $test 2] if { (($testlabel == $tagname) && ($tagvalue == $testvalue ))} { return 1 } } elseif { $testop == "!="} { set testvalue [lindex $test 2] if { (($testlabel == $tagname) && ($tagvalue != $testvalue ))} { return 1 } } elseif { $testop == "<="} { set testvalue [lindex $test 2] if { (($testlabel == $tagname) && ($tagvalue <= $testvalue ))} { return 1 } } elseif { $testop == "-in"} { # return true if the tagvalue is a member of the list given as the testvalue if { $testlabel == $tagname } { set testvalue [lindex $test 2] foreach listval $testvalue { if { $tagvalue == $listval } { return 1 } } } } elseif { $testop == "-contains"} { # return true if the tagvalue contains the string given as a testvalue # Note - Do not optimise this by an early return if the label is found # but the value does not match, as it could be that the label occurs # more than once (is used that way in taglog_project # for the flags if { $testlabel == $tagname } { set testvalue [lindex $test 2] if { [string match -nocase *$testvalue* $tagvalue] } { return 1 } } } elseif { $testop == "-later" } { if { $testlabel == $tagname } { set testvalue [lindex $test 2] if { [clock scan $tagvalue] > [clock scan $testvalue] } { return 1 } } } elseif { $testop == "-earlier" } { if { $testlabel == $tagname } { set testvalue [lindex $test 2] if { [clock scan $tagvalue] < [clock scan $testvalue] } { return 1 } } } elseif { $testop == "-datebetween"} { # return true if the tagvalue (which must be a date) is between the *two* # dates given as testvalues if { $testlabel == $tagname } { set startdate [lindex $test 2] set enddate [lindex $test 3] error "Not yet implemented" } } elseif { $testop == "-exists"} { # return true if the testlabel is found in the current record # puts "Exists - checking to see if testlabel $testlabel = tagname $tagname" if { $testlabel == $tagname } { return 1 } } else { error "Invalid operator $testop in tag matchcond" } } # We never found what we were looking for return 0 } elseif { $action == "matchall" } { # does a tag item match *all* the criteria in a list set entry [lindex $args 0 ] set criteria [lindex $args 1] foreach test $criteria { if { ! [ tag matchcond $entry $test ]} { # puts "matchall found that $entry did not match $test - returning 0" return 0 } } # puts "matchall found that all the criteria matched - returning 1" return 1 } elseif { $action == "matchany" } { # does a tag item match *any* of the creteria in a list of conditions set entry [lindex $args 0 ] set criteria [lindex $args 1] foreach test $criteria { if { [ tag matchcond $entry $test ]} { return 1 } } return 0 } elseif { $action == "extract" } { # Takes a list of tag items and returns those which match the criteria in # the selection list # i.e. tag extract list list-of-criteria # where list of criteria is a list of lists of the form { label op [value] } # set tlist [lindex $args 0] set criteria [lindex $args 1] foreach entry $tlist { if { [ tag matchall $entry $criteria ] } { lappend result $entry } } if { [info exists result] } { return $result } else { return {} } } elseif { $action == "replace" } { # Returns a new value for the entry - call as # tag replace entryvar name newvalue set entryvar [lindex $args 0 ] set name [lindex $args 1 ] set newvalue [lindex $args 2 ] upvar $entryvar entry set i 0 foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $name == $tagname } { set newitem [list $tagname $newvalue] set entry [ lreplace $entry $i $i $newitem ] return 0 } incr i } error "No tag named $name in $entry to replace" } elseif {$action == "setorreplace" } { # tag setorreplace entryvar name newvalue set entryvar [lindex $args 0 ] set name [lindex $args 1 ] set newvalue [lindex $args 2 ] set endlabel "" if {[llength $args] == 4 } { set endlabel [lindex $args 3] } upvar $entryvar entry if {$endlabel == "" } { set newitem [list $name $newvalue] } else { set newitem [list $name $newvalue $endlabel] } set i 0 foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $name == $tagname } { set entry [ lreplace $entry $i $i $newitem ] return 0 } incr i } # we got here and we did not find the tag we wanted - add it to the end set len [llength $entry] incr len -1 set entry [linsert $entry $len $newitem] return 0 } elseif {$action == "setorreplaceflags" } { # Similar to setorreplace, but the entryvar points to a set of flags # tag setorreplaceflags entryvar name flag value # e.g. tag setorrplaceflags proj Flags Active 0 # # If value is set to 1 then works like addorreplace and will add a Flags # entry set to Active (or not if not needed) # If value is set to 0 then remove any Flags entries which only contain # the Active value (and later will remove it from comma seperated list) # set entryvar [lindex $args 0 ] set name [lindex $args 1 ] set flag [lindex $args 2] set newvalue [lindex $args 3 ] upvar $entryvar entry set i 0 foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { (( $name == $tagname) && ( $tagvalue == $flag)) } { if { $newvalue } { # We want the value to exist # It already exists - return return 0 } else { # We want to take it out if it matches this entry set entry [lreplace $entry $i $i] return 0 } } incr i } # we got here and we did not find the tag we wanted - add it to the end # but only if newvalue is true if { $newvalue } { set newitem [list $name $flag] set len [llength $entry] incr len -1 set entry [linsert $entry $len $newitem] } return 0 } elseif { $action == "update" } { # # tag update filename replacement_entry id_field # # Read a tagged file until we come across one where the id_field in the # replacement_entry matches that in the file, replace that entry with # the replacement - if no match then the file is unchanged. It always # copies to a file named after the input file with a .tmp suffix, which is # renamed to the original if the replacemnt succeeds # # For now use readfile to read in the whole lot - and not use a temp file set filename [lindex $args 0] set replacementEntry [lindex $args 1] set idField [lindex $args 2] foreach item $replacementEntry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == $idField } { set idvalue $tagvalue } } set tmplist [tag readfile $filename] set test [list $idField "==" $idvalue] set f [open $filename w] foreach entry $tmplist { if [tag matchcond $entry $test] { tag writeentry $f $replacementEntry } else { tag writeentry $f $entry } } close $f } elseif { $action == "readselected" } { # tag readselected # reads a file and returns all those entries which match the # in a similar maner to doing a # 'tag readfile' followed by a 'tag extract' # # For now we can implement it exactly like that set tmplist [tag readfile [lindex $args 0]] return [tag extract $tmplist [lindex $args 1]] } elseif { $action == "writehtml" } { set isurlcall "" set fieldslist "" set hformat [lindex $args 0] set f [lindex $args 1] set taglist [lindex $args 2] set n 3 while { $n < [llength $args] } { # for now should only be one optional argument - really ned to do this better if { [lindex $args $n] == "-isurlcall"} { incr n set isurlcall [lindex $args $n] incr n } elseif { [lindex $args $n] == "-fields" } { incr n set fieldslist [lindex $args $n] incr n } else { error "unknown option [lindex $args $n]" } } if { $hformat == "dlist" } { foreach entry $taglist { puts $f "
" foreach item $entry { set delimiter "" set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname != "End" } { puts $f "
$tagname
" if { [llength $item] == 3 } { puts $f "
$tagvalue\n
" } else { # only worry about URLs on single lines if { $isurlcall != "" } { set isurl [$isurlcall $tagname $tagvalue] if { $isurl } { puts $f "$tagvalue" } else { puts $f "$tagvalue" } } else { puts $f "$tagvalue" } } } } puts $f "
" puts $f "
" } } elseif { $hformat == "table" } { } else { error "bad argument to'tag writehtml' expected dlist or table" } } elseif { $action == "sort" } { set tags [lindex $args 0] set indexfield [lindex $args 1] set listops [lrange $args 2 end] # create a temporary list consisting of the values of the sort elements for { set i 0 } { $i < [llength $tags] } { incr i} { set entry [lindex $tags $i] set l [list $i {}] if { [lsearch $listops "-integer"] >=0 } { # Need to make the default value an integer if we do an integer sort set l [list $i 0] } foreach item $entry { if { [lindex $item 0] == $indexfield } { set l [list $i [lindex $item 1]] break } } lappend sortlist $l } set listcmd [list lsort -index 1 $listops $sortlist] set sortlist [eval $listcmd] # work through the sortlist - appending values to the result for { set i 0 } { $i < [llength $sortlist] } { incr i} { set te [lindex $tags [lindex [lindex $sortlist $i] 0 ]] lappend result $te } return $result } elseif { $action == "findval" } { set startindex 0 if { [llength $args] > 3 } { set startindex [lindex $args 3] } return [tag_findval [lindex $args 0] [lindex $args 1] [lindex $args 2] $startindex] } elseif { $action == "find" } { set startindex 0 if { [llength $args] > 2 } { set startindex [lindex $args 2] } return [tag_find [lindex $args 0] [lindex $args 1] $startindex] } else { error "Unknown first argument to tag - must be 'readfile' or 'writefile'" } } taglog-0.2.6/src/taglog_help.tcl0000644000175000017500000000502413534701742015241 0ustar johnjohn# # taglog_help.tcl - routines providing the help system for taglog # Copyright John Lines (john+taglog@paladyn.org) November 2000 # # This program is released under the terms of the GNU Public Licence # # Note that only one argument will be substituted at present. package provide taglog_help 0.1 proc taghelp { subject args } { global language helpdir helpsorted proc gethelp_for { helpfile subject } { global helpsorted set description "" if { ! $helpsorted } { set test [list Id "==" $subject] lappend tests $test set helpentries [tag readselected $helpfile $tests] foreach entry $helpentries { foreach item $entry { if { [lindex $item 0] == "Description" } { set description [lindex $item 1] } } } } else { # puts "Sorted help file" set description "" set entry [ tag findsorted $helpfile $subject ] foreach item $entry { if { [lindex $item 0] == "Description" } { set description [lindex $item 1] } } } return $description } set description "" set helpfile "$helpdir/taglog_help_$language.tag" if { ! [file exists $helpfile] } { set description "Help text not found for item $subject in language $language - please check that $helpfile exists" } # From now on we can only work with sorted helpfiles - they will have to # be sorted before installation. if { [info tclversion] < 8.2 } { set helpsorted 0 } else { set helpsorted 1 if {! [info exists helpsorted] } { set helpsorted 0 set h [tag readheader $helpfile] foreach item $h { if { [lindex $item 0] == "Sorted-date" } { set sd [lindex $item 1] set fd [clock format [file mtime $helpfile] -format "%Y-%m-%d %H:%M:%S"] # compare as strings # puts " sd is $sd - fd is $fd" if { [string compare $sd $fd] >= 0 } { set helpsorted 1 } } } # puts "helpsorted is $helpsorted" } } set description [gethelp_for $helpfile $subject] if { $description == "" } { set description [gethelp_for $helpfile UNKNOWN] } # if args is non empty then perform argument substitution set i 1 for { set i 1 } { $i <= [ llength $args] } { incr i } { set thisarg [lindex $args [expr $i - 1]] regsub {\$1} $description $thisarg description } toplevel .taghelp_$subject wm title .taghelp_$subject "Help on $subject" frame .taghelp_$subject.body message .taghelp_$subject.body.msg -text $description -width 7i pack .taghelp_$subject.body.msg pack .taghelp_$subject.body frame .taghelp_$subject.bot button .taghelp_$subject.bot.ok -text OK -command "doCancel .taghelp_$subject" pack .taghelp_$subject.bot.ok pack .taghelp_$subject.bot tkwait window .taghelp_$subject } taglog-0.2.6/src/activities0000644000175000017500000000022513534701742014335 0ustar johnjohnphone-in phone-out meeting meeting-preparation meeting-review email reading programming writing thinking service-break informal-discussion taglog-0.2.6/src/taglog_project.tcl0000644000175000017500000007460213534701742015767 0ustar johnjohn# # This program gives a combined electronic diary and time clock. # This module deals with projects - which for taglog purposes are entities # to which you book time. # Copyright John Lines (john+taglog@paladyn.org) January 2003 # # This program is released under the terms of the GNU Public Licence # package provide taglog_project 0.1 proc proj_testflag { projname flagname } { # Test if a particular flag is set for a particular project global allproj set test [list Flags "-contains" $flagname] foreach proj $allproj { if { [tag_entryVal $proj Name] == $projname } { if { [tag matchcond $proj $test]} { return 1 } else { return 0 } } } return 0 } proc isbreak { projname } { # return true if the given project is a break project return [proj_testflag $projname Breaks] } proc isoverhead { projname } { # return true if the give project is an overhead project return [proj_testflag $projname Overheads] } proc isactive { projname } { # return true if the give project is an active project return [proj_testflag $projname Active] } proc isimmutable { projname } { # return true if the given project is immutable return [proj_testflag $projname Immutable] } proc getprojcode { projname } { # returns the project code asociated with the given project global allproj foreach proj $allproj { if { [tag_entryVal $proj Name] == $projname } { return [tag_entryVal $proj Code] } } return "" } proc getprojstart { projname } { global allproj foreach proj $allproj { if { [tag_entryVal $proj Name] == $projname } { return [tag_entryVal $proj StartDate] } } return "" } proc getprojend { projname } { global allproj foreach proj $allproj { if { [tag_entryVal $proj Name] == $projname } { return [tag_entryVal $proj EndDate] } } return "" } proc proj_getExpectedTime { projname } { global allproj foreach proj $allproj { if { [tag_entryVal $proj Name] == $projname } { return [tag_entryVal $proj ExpectedTime] } } return "" } proc projclosed { projname } { set enddate [getprojend $projname] if { $enddate != "" } { # check the date - there is probably some clever way of doing this with the # tcl clock command but they should just compare as strings set now [clock format [clock seconds] -format "%Y-%m-%d"] if { [string compare $enddate $now] <=0 } { return 1 } } return 0 } proc incprojactindex { projname } { global allproj # increment the current actions index for a project and return the new value set n 0 foreach proj $allproj { if { [tag_entryVal $proj Name] == $projname } { set t [tag_entryVal $proj NextActionId] if { $t == "" } { set t 0 } incr t tag setorreplace proj NextActionId $t set allproj [lreplace $allproj $n $n $proj] writeprojects return $t } incr n } return "" } proc proj_getDescription { projname } { global allproj } proc proj_setDescription { projname description } { global allproj } proc proj_isImmutable { proj } { global allproj return 0 } proc getProjTimes { files } { # Read the given files and return a list of arrays giving the project times for# all the projects, with an extra array (first element ?) with the totals. set a(unknown) "00:00" set tot(unknown) "00:00" set results {} set index 0 foreach filename $files { incr index # FRINK: nocheck set a$index(unknown) "00:00" if [file exists $filename] { # FRINK: nocheck set tot$index "00:00" set entries [tag readfile $filename] foreach entry $entries { set starttime 0 set endtime 0 set thisproject "unknown" # The entry should be a list of tag-value pairs foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } { # Because this is the end tag we should have all the values we are going # to get set duration [timediff $starttime $endtime] if { [info exists a($thisproject)] } { inctime a($thisproject) $duration } else { set a($thisproject) "00:00" inctime a($thisproject) $duration } } elseif { $tagname == "StartTime" } { set starttime $tagvalue } elseif { $tagname == "EndTime" } { set endtime $tagvalue } elseif { $tagname == "Project" } { set thisproject $tagvalue } else { } } } } else { # we cant read the file #FRINK: nocheck set tot$index "-" } } return $results } proc addProjectOK {} { global addproject_name addproject_breaks addproject_overheads addproject_bookas addproject_active addproject_immutable addproject_startdate addproject_enddate addproject_expectedtime global allproj set endflag 1 set thisproj "" set thisproj [tagappend $thisproj Name $addproject_name] set thisproj [tagappend $thisproj NextActionId 1] set thisproj [tagappend $thisproj Code $addproject_bookas] set thisproj [tagappend $thisproj StartDate $addproject_startdate] set thisproj [tagappend $thisproj EndDate $addproject_enddate] set thisproj [tagappend $thisproj ExpectedTime $addproject_expectedtime] if { $addproject_overheads } { set thisproj [tagappend $thisproj Flags Overheads] } if { $addproject_breaks } { set thisproj [tagappend $thisproj Flags Breaks] } if { $addproject_active } { set thisproj [tagappend $thisproj Flags Active] } if { $addproject_immutable } { set thisproj [tagappend $thisproj Flags Immutable] } if { $endflag } { set endpair [list End ] lappend thisproj $endpair } lappend allproj $thisproj # Also need to manually add a new projects menu entry .currentbar.project.menu add command -label $addproject_name \ -command "set currentProject \"$addproject_name\"" writeprojects destroy .addProject } proc inputProjectOK { w mode winnum pindex } { global projin_f_a allproj set proj [lindex $allproj $pindex] tag setorreplaceflags proj Flags Breaks $projin_f_a($winnum,Breaks) tag setorreplaceflags proj Flags Overheads $projin_f_a($winnum,Overheads) tag setorreplace proj Code $projin_f_a($winnum,Code) tag setorreplace proj StartDate $projin_f_a($winnum,StartDate) tag setorreplace proj EndDate $projin_f_a($winnum,EndDate) tag setorreplaceflags proj Flags Active $projin_f_a($winnum,Active) tag setorreplaceflags proj Flags Immutable $projin_f_a($winnum,Immutable) tag setorreplace proj ExpectedTime $projin_f_a($winnum,ExpectedTime) set allproj [lreplace $allproj $pindex $pindex $proj] destroy $w } proc projInputWindow { mode {winnum 0} {pindex -1} } { # At present only used to edit a project, but will merge doAddProject global projin_f_a set w .inpProj$winnum toplevel $w if { $mode == "input" } { wm title $w [mc "Add Project"] } else { wm title $w "[mc {Edit project}] $projin_f_a($winnum,Name)" } wm minsize $w 200 200 frame $w.entry label $w.entry.l -text [mc "Project name"] entry $w.entry.e -width 20 -textvariable projin_f_a($winnum,Name) pack $w.entry.l $w.entry.e -side left -in $w.entry pack $w.entry frame $w.flags set addproject_breaks 0 checkbutton $w.flags.breaks -text [mc "Book as breaks"] -variable projin_f_a($winnum,Breaks) set addproject_overheads 0 checkbutton $w.flags.overheads -text [mc "Book as overheads"] -variable projin_f_a($winnum,Overheads) set addproject_active 1 checkbutton $w.flags.active -text [mc "Project is active"] -variable projin_f_a($winnum,Active) set addproject_immutable 0 checkbutton $w.flags.immutable -text [mc "Project is immutable"] -variable projin_f_a($winnum,Immutable) pack $w.flags.breaks $w.flags.overheads $w.flags.active $w.flags.immutable -in $w.flags pack $w.flags frame $w.projcode label $w.projcode.project -text [mc "Booking Code"] entry $w.projcode.projentry -width 20 -textvariable projin_f_a($winnum,Code) pack $w.projcode.project $w.projcode.projentry -in $w.projcode -side left pack $w.projcode #set addproject_startdate [clock format [clock seconds] -format "%Y-%m-%d"] frame $w.start label $w.start.label -text [mc "Start Date"] calUtil_win $w.start.e "" projin_f_a($winnum,StartDate) pack $w.start.label $w.start.e -in $w.start -side left pack $w.start frame $w.end button $w.end.label -text [mc "End Date"] -command "taghelp project_enddate" calUtil_win $w.end.e "" projin_f_a($winnum,EndDate) pack $w.end.label $w.end.e -in $w.end -side left pack $w.end frame $w.expectedTime button $w.expectedTime.label -text [mc "Expected-time"] -command "taghelp project_expectedtime" entry $w.expectedTime.e -width 10 -textvariable projin_f_a($winnum,ExpectedTime) pack $w.expectedTime.label $w.expectedTime.e -in $w.expectedTime -side left pack $w.expectedTime frame $w.bot button $w.bot.ok -text OK -command "inputProjectOK $w edit $winnum $pindex" button $w.bot.cancel -text [mc Cancel] -command "doCancel $w" button $w.bot.help -text [mc Help] -command "taghelp addproject" pack $w.bot.ok $w.bot.cancel $w.bot.help -in $w.bot -side left pack $w.bot tkwait window $w } proc doAddProject {} { global addproject_overheads addproject_breaks addproject_bookas addproject_startdate addproject_enddate addproject_active addproject_immutable addproject_expectedtime toplevel .addProject wm title .addProject [mc "Add a new project"] frame .addProject.entry label .addProject.entry.l -text [mc "Project name"] entry .addProject.entry.e -width 20 -textvariable addproject_name pack .addProject.entry.l .addProject.entry.e -side left -in .addProject.entry pack .addProject.entry frame .addProject.flags set addproject_breaks 0 checkbutton .addProject.flags.breaks -text [mc "Book as breaks"] -variable addproject_breaks set addproject_overheads 0 checkbutton .addProject.flags.overheads -text [mc "Book as overheads"] -variable addproject_overheads set addproject_active 1 checkbutton .addProject.flags.active -text [mc "Project is active"] -variable addproject_active set addproject_immutable 0 checkbutton .addProject.flags.immutable -text [mc "Project is immutable"] -variable addproject_immutable pack .addProject.flags.breaks .addProject.flags.overheads .addProject.flags.active .addProject.flags.immutable -in .addProject.flags pack .addProject.flags frame .addProject.projcode label .addProject.projcode.project -text [mc "Booking Code"] entry .addProject.projcode.projentry -width 20 -textvariable addproject_bookas pack .addProject.projcode.project .addProject.projcode.projentry -in .addProject.projcode -side left pack .addProject.projcode set addproject_startdate [clock format [clock seconds] -format "%Y-%m-%d"] frame .addProject.start label .addProject.start.label -text [mc "Start Date"] calUtil_win .addProject.start.e "" addproject_startdate pack .addProject.start.label .addProject.start.e -in .addProject.start -side left pack .addProject.start frame .addProject.end label .addProject.end.label -text [mc "End Date"] calUtil_win .addProject.end.e "" addproject_enddate pack .addProject.end.label .addProject.end.e -in .addProject.end -side left pack .addProject.end frame .addProject.expectedTime button .addProject.expectedTime.label -text [mc "Expected-time"] -command "taghelp project_expectedtime" entry .addProject.expectedTime.e -width 10 -textvariable addproject_expectedtime pack .addProject.expectedTime.label .addProject.expectedTime.e -in .addProject.expectedTime -side left pack .addProject.expectedTime frame .addProject.bot button .addProject.bot.ok -text OK -command addProjectOK button .addProject.bot.cancel -text [mc Cancel] -command {doCancel .addProject } button .addProject.bot.help -text [mc Help] -command "taghelp addproject" pack .addProject.bot.ok .addProject.bot.cancel .addProject.bot.help -in .addProject.bot -side left pack .addProject.bot tkwait window .addProject } proc doEditProjectsOK {} { global allproj global epbreaks epoverheads epbookas epdelete epstart epend epactive epimmutable set n 0 set projindex 0 foreach proj $allproj { if {$epdelete($n)} { set allproj [lreplace $allproj $projindex $projindex] incr n } else { # The tricky part about the flags is that we do not want to keep # adding to them, and we want to be able to unset them too # tag setorreplaceflags proj Flags Breaks $epbreaks($n) tag setorreplaceflags proj Flags Overheads $epoverheads($n) tag setorreplace proj Code $epbookas($n) tag setorreplace proj StartDate $epstart($n) tag setorreplace proj EndDate $epend($n) tag setorreplaceflags proj Flags Active $epactive($n) tag setorreplaceflags proj Flags Immutable $epimmutable($n) set allproj [lreplace $allproj $projindex $projindex $proj] incr n incr projindex } } #writeprojects_old writeprojects destroy .ep } proc doEditProj { pname } { global projin_f_a global allproj set winnum 0 set projin_f_a($winnum,Name) $pname set projin_f_a($winnum,Breaks) [isbreak $pname] set projin_f_a($winnum,Overheads) [isoverhead $pname] set projin_f_a($winnum,Active) [isactive $pname] set projin_f_a($winnum,Immutable) [isimmutable $pname] set projin_f_a($winnum,Code) [getprojcode $pname] set projin_f_a($winnum,StartDate) [getprojstart $pname] set projin_f_a($winnum,EndDate) [getprojend $pname] set pindex -1 foreach proj $allproj { incr pindex if { [tag_entryVal $proj Name] == $pname } { set projin_f_a($winnum,ExpectedTime) [tag_entryVal $proj ExpectedTime] break } } projInputWindow edit $winnum $pindex } proc doEditProjects {} { global allproj global epbreaks epoverheads epbookas epdelete epstart epend epactive epimmutable toplevel .ep wm title .ep [mc "Edit Projects"] wm minsize .ep 200 200 frame .ep.top label .ep.top.title -width 20 -text [mc Title] frame .ep.top.flags label .ep.top.flags.breaks -text [mc Breaks] label .ep.top.flags.overheads -text [mc Overheads] label .ep.top.flags.active -text [mc Active] label .ep.top.flags.immutable -text [mc Immutable] pack .ep.top.flags.breaks -in .ep.top.flags -anchor w pack .ep.top.flags.overheads -in .ep.top.flags pack .ep.top.flags.active -in .ep.top.flags -anchor e pack .ep.top.flags.immutable -in .ep.top.flags -anchor e label .ep.top.code -text [mc Code] label .ep.top.dates -text [mc Dates] -width 45 label .ep.top.delete -text [mc Delete] pack .ep.top.title .ep.top.flags .ep.top.code .ep.top.dates .ep.top.delete -in .ep.top -side left pack .ep.top frame .ep.m -bd 4 -relief sunken canvas .ep.m.c -yscrollcommand ".ep.m.scroll set" -scrollregion {0 0 0 650} -relief raised -confine false -yscrollincrement 25 scrollbar .ep.m.scroll -command ".ep.m.c yview" -relief raised pack .ep.m.scroll -side right -fill y pack .ep.m.c -side left -fill both -expand true pack .ep.m -fill both -expand 1 set f [frame .ep.m.c.f -bd 0] .ep.m.c create window 0 0 -anchor nw -window $f set n 0 foreach proj $allproj { set pname [tag_entryVal $proj Name] frame .ep.m.c.f.p$n button .ep.m.c.f.p$n.p -text $pname -width 20 -command "doEditProj \"$pname\"" set epbreaks($n) 0 if { [isbreak $pname] } { set epbreaks($n) 1 } checkbutton .ep.m.c.f.p$n.breaks -variable epbreaks($n) pack .ep.m.c.f.p$n.p -side left pack .ep.m.c.f.p$n.breaks -side left -fill x set epoverheads($n) 0 if { [isoverhead $pname] } { set epoverheads($n) 1 } checkbutton .ep.m.c.f.p$n.overheads -variable epoverheads($n) pack .ep.m.c.f.p$n.overheads -side left -fill x set epactive($n) 0 if {[isactive $pname] } { set epactive($n) 1 } checkbutton .ep.m.c.f.p$n.active -variable epactive($n) pack .ep.m.c.f.p$n.active -side left -fill x set epimmutable($n) 0 if {[isimmutable $pname] } { set epimmutable($n) 1 } checkbutton .ep.m.c.f.p$n.immutable -variable epimmutable($n) pack .ep.m.c.f.p$n.immutable -side left -fill x set epbookas($n) [getprojcode $pname] label .ep.m.c.f.p$n.bookasmenu -text "Code" pack .ep.m.c.f.p$n.bookasmenu -side left -fill x entry .ep.m.c.f.p$n.bookas -width 10 -textvariable epbookas($n) pack .ep.m.c.f.p$n.bookas -side left -fill x set epstart($n) [getprojstart $pname] menubutton .ep.m.c.f.p$n.startlab -text [mc "Start"] -menu .ep.m.c.f.p$n.startlab.m menu .ep.m.c.f.p$n.startlab.m calUtil_menu .ep.m.c.f.p$n.startlab.m .ep.m.c.f.p$n.starten pack .ep.m.c.f.p$n.startlab -side left -fill x entry .ep.m.c.f.p$n.starten -width 10 -textvariable epstart($n) pack .ep.m.c.f.p$n.starten -side left -fill x set epend($n) [getprojend $pname] menubutton .ep.m.c.f.p$n.endlab -text [mc "End "] -menu .ep.m.c.f.p$n.endlab.m menu .ep.m.c.f.p$n.endlab.m set todayiso [clock format [clock seconds] -format "%Y-%m-%d"] set todaydisp [dateiso2disp $todayiso] .ep.m.c.f.p$n.endlab.m add command -label "[mc Today] ($todaydisp)" -command "set epend($n) $todayiso" calUtil_menu .ep.m.c.f.p$n.endlab.m .ep.m.c.f.p$n.enden .ep.m.c.f.p$n.endlab.m add separator .ep.m.c.f.p$n.endlab.m add command -label [mc Help] -command "taghelp ep_enddate" pack .ep.m.c.f.p$n.endlab -side left -fill x entry .ep.m.c.f.p$n.enden -width 10 -textvariable epend($n) pack .ep.m.c.f.p$n.enden -side left -fill x set epdelete($n) 0 checkbutton .ep.m.c.f.p$n.delete -text [mc "Delete"] -variable epdelete($n) pack .ep.m.c.f.p$n.delete -side left -fill x pack .ep.m.c.f.p$n -side top -fill x incr n } set child [lindex [pack slaves $f] 0] if { $child != ""} { tkwait visibility $child set incr [winfo height $child] set width [winfo width $f] set height [winfo height $f] .ep.m.c config -scrollregion "0 0 $width $height" .ep.m.c config -yscrollincrement $incr set epmaxrows 12 if { $height > $epmaxrows * $incr } { set height [expr $epmaxrows * $incr] } .ep.m.c config -width $width -height $height } frame .ep.bot button .ep.bot.ok -text OK -command {doEditProjectsOK} button .ep.bot.cancel -text [mc Cancel] -command {doCancel .ep} button .ep.bot.help -text [mc Help] -command "taghelp editproject" pack .ep.bot.ok .ep.bot.cancel .ep.bot.help -in .ep.bot -side left pack .ep.bot tkwait window .ep } proc initProjTimes {} { global projTimes projTimesTotal projTimesTotalNonBreaks global allproj set projTimesTotal "00:00" set projTimesTotalNonBreaks "00:00" # initialise the projTimes array foreach proj $allproj { set projname [tag_entryVal $proj Name] if {[isactive $projname] } { if { ![info exists projTimes($projname)] } { set projTimes($projname) "00:00" } } } } proc highlightActiveProjButton { varname index op } { global projTimes currentProject for { set i 1 } { $i <= [array size projTimes] } { incr i } { if { [winfo exists .projwin.$i.b] } { set bn [.projwin.$i.b cget -text] # puts "bn $i is $bn" if { $bn == $currentProject } { .projwin.$i.b configure -background yellow } else { .projwin.$i.b configure -background grey } } } } proc doShowProjects {} { global projTimes projTimesTotal projTimesTotalNonBreaks currentProject toplevel .projwin wm title .projwin [mc "Project Times"] initProjTimes set projlabelwidth 20 set totallabelwidth [expr $projlabelwidth + 2 ] set i 1 # work through projTimes in sorted order foreach project [lsort [array names projTimes]] { frame .projwin.$i set projTxt $project if {$projTxt == "unknown"} {set projTxt [mc unknown]} button .projwin.$i.b -text "$projTxt" -width $projlabelwidth -command "donext \"\" \"$project\"" entry .projwin.$i.e -width 10 -textvariable projTimes($project) -state disabled pack .projwin.$i.b .projwin.$i.e -in .projwin.$i -side left pack .projwin.$i set duration [timediff "00:00:00" $projTimes($project)] inctime projTimesTotal $duration if { ! [isbreak $project ]} { inctime projTimesTotalNonBreaks $duration } incr i } frame .projwin.projtimestotal label .projwin.projtimestotal.b -text [mc "Total"] -width $totallabelwidth entry .projwin.projtimestotal.e -textvariable projTimesTotal -state disabled -width 10 pack .projwin.projtimestotal.b .projwin.projtimestotal.e -in .projwin.projtimestotal -side left pack .projwin.projtimestotal frame .projwin.projtimestotalnonbreaks label .projwin.projtimestotalnonbreaks.b -text [mc "Total (non breaks)"] -width $totallabelwidth entry .projwin.projtimestotalnonbreaks.e -textvariable projTimesTotalNonBreaks -state disabled -width 10 pack .projwin.projtimestotalnonbreaks.b .projwin.projtimestotalnonbreaks.e -in .projwin.projtimestotalnonbreaks -side left pack .projwin.projtimestotalnonbreaks frame .projwin.bot button .projwin.bot.ok -text OK -command {doCancel .projwin} button .projwin.bot.help -text [mc Help] -command "taghelp viewproject" pack .projwin.bot.ok .projwin.bot.help -in .projwin.bot -side left pack .projwin.bot highlightActiveProjButton currentProject index w trace variable currentProject w highlightActiveProjButton tkwait window .projwin trace vdelete currentProject w highlightActiveProjButton } # -- setupProjMenu # # Set up a tk menu, which will present a set of projects and allow a variable # to be set according to the project which is selected. # # Arguments # menuname: the name of the menu (e.g. .winname.select.proj # varname: the name of the variable receive the project name # projstat: "all" if all projects are to be returned, otherwise "" for # active projects only. # helpdest: Id of the help entry or "" for no help entry. # proc setupProjMenu { menuname varname projstat helpdest } { global allproj $menuname delete 1 end $menuname add command -label "--" -command "set $varname \"\"" foreach proj $allproj { set pname [tag_entryVal $proj Name] if {$pname != ""} { if { $projstat == "all" || ! [projclosed $pname] } { $menuname add command -label $pname \ -command "set $varname \"$pname\"" } } } if { $helpdest != "" } { $menuname add separator $menuname add command -label [mc Help] -command "taghelp $helpdest" } } proc writeprojects {} { global allproj projectsfilename tag writefile $projectsfilename $allproj } proc writeprojects_old {} { global projects projectsfilename # for now this is more complex than writeactions because we have the projects # in a tcl list which is not in tagged format. set f [open $projectsfilename w] puts $f "Tag-accountproj-version: 1.0" puts $f "End:" puts $f "" foreach proj $projects { set projname [lindex $proj 0] puts $f "Name: $projname" set projnextact [lindex $proj 1] puts $f "NextActionId: $projnextact" set projcode [lindex $proj 2] puts $f "Code: $projcode" if {[lindex $proj 3] == 1} { puts $f "Flags: Overheads" } if {[lindex $proj 4] == 1} { puts $f "Flags: Breaks" } if {[lindex $proj 7]== 1} { puts $f "Flags: Active" } set projstart [lindex $proj 5] puts $f "StartDate: $projstart" set projend [lindex $proj 6] if { $projend != ""} { puts $f "EndDate: $projend" } puts $f "End:" } close $f } proc allproj2projects {} { # transitional routine - set the projects global from the allproj global global projects allproj if {[info exists projects] } { unset projects } # set projects to match allproj for transition foreach entry $allproj { set thisproj_name "" set thisproj_actidx 0 set thisproj_code "" set thisproj_isoverhead 0 set thisproj_isbreak 0 set thisproj_isactive 0 set thisproj_start "" set thisproj_end "" foreach item $entry { if {[lindex $item 0 ] == "Name" } { set thisproj_name [lindex $item 1]} if {[lindex $item 0 ] == "NextActionId" } { set thisproj_actidx [lindex $item 1]} if {[lindex $item 0 ] == "Code" } { set thisproj_code [lindex $item 1]} if {[lindex $item 0 ] == "Flags" } { if { [string match Overheads [lindex $item 1]]} { set thisproj_isoverhead 1} if { [string match Breaks [lindex $item 1]]} { set thisproj_isbreak 1} if { [string match Active [lindex $item 1]]} { set thisproj_isactive 1} } if {[lindex $item 0 ] == "StartDate" } { set thisproj_start [lindex $item 1]} if {[lindex $item 0 ] == "EndDate" } { set thisproj_end [lindex $item 1]} } if { $thisproj_name != ""} { set thisproj [list $thisproj_name $thisproj_actidx $thisproj_code $thisproj_isoverhead $thisproj_isbreak $thisproj_start $thisproj_end $thisproj_isactive] lappend projects $thisproj } } # puts "projects is $projects" # If we have no projects yet we will create an empty list if { ![info exists projects] } { set projects {} } } proc readprojects {} { global projects projectsfilename allproj # Note that projects is not in tagged list format, but allproj is. set allproj [tag readfile $projectsfilename] if { [ llength $allproj] == 0 } { set hdr "" set header [list Tag-accountproj-version 1.0] lappend hdr $header set endpair [list End ] lappend hdr $endpair lappend allproj $hdr } # puts "allproj is $allproj" # projects may have been read in from preferences # if they have then exit for now if {[info exists projects] } { # puts "projects is $projects" if { [llength $projects] != 0 } { writeprojects_old savePrefs return } unset projects } # set projects to match allproj for transition allproj2projects } proc can_get_httprojects {} { global projects_url # return true if we can get projects information by http if { [info tclversion] >= 8.0 } { package require http if { $projects_url == "" } { return 0 } return 1 } return 0 } proc update_projects_ok {} { global allproj update_projects_allproj set allproj $update_projects_allproj allproj2projects destroy .update_info } proc doUpdateProjects {} { global projects_url allproj update_projects_allproj toplevel .update_info wm title .update_info "Projects HTTP update report" text .update_info.text -width 60 -height 20 frame .update_info.bot button .update_info.bot.ok -text "OK" -command update_projects_ok button .update_info.bot.cancel -text "Cancel" -command "destroy .update_info" button .update_info.bot.help -text "Help" -command "taghelp project_update" pack .update_info.text pack .update_info.bot.ok .update_info.bot.cancel .update_info.bot.help -side left -in .update_info.bot pack .update_info.bot set p [::http::geturl $projects_url] set body [::http::data $p] # set newproj [tag readbuf body] #.update_info.text insert end $newproj set today [clock format [clock seconds] -format "%Y-%m-%d"] # Go through allproj and compare to newproj to find projects which # have been closed - write the info to a global array called update_projects_allproj foreach proj $allproj { set thisproj_name [logEdit_tagVal $proj Name] set found 0 foreach newp $newproj { if { [logEdit_tagVal $newp Name] == $thisproj_name } { # This project still exists - just copy it across lappend update_projects_allproj $proj set found 1 break } } if { !$found } { # This project is now closed - set the enddate to today # unless the project was already closed if { ! [ projclosed $thisproj_name ] } { tag setorreplace proj EndDate $today .update_info.text insert end "Closed $thisproj_name\n" lappend update_projects_allproj $proj } } } # Go through newproj and find all the projects which are not already in update_projects_allproj # and add them foreach newp $newproj { set thisproj_name [logEdit_tagVal $newp Name] set found 0 foreach proj $update_projects_allproj { if { [logEdit_tagVal $proj Name] == $thisproj_name } { # This project has already been found set found 1 break } } if { !$found } { # We have a new project - append its details to update_projects_allpoj .update_info.text insert end "Added $thisproj_name\n" lappend update_projects_allproj $newp } } tkwait window .update_info unset update_projects_allproj } proc doArchiveProjects {} { global archiveProjectCloseDate archiveProjectCheckActions archiveProjectFile global rootdir toplevel .archiveProject wm title .archiveProject [mc "Archive old projects"] frame .archiveProject.closedate menubutton .archiveProject.closedate.l -text [mc "Archive projects closed before"] -menu .archiveProject.closedate.l.m menu .archiveProject.closedate.l.m set todayiso [clock format [clock seconds ] -format "%Y-%m-%d"] set todaydisp [dateiso2disp $todayiso] .archiveProject.closedate.l.m add command -label "[mc Today] ($todaydisp)" -command "set archiveProjectCloseDate $todayiso" pack .archiveProject.closedate.l -side left -fill x calUtil_win .archiveProject.closedate.d "" archiveProjectCloseDate pack .archiveProject.closedate.d .archiveProject.closedate.l.m add separator .archiveProject.closedate.l.m add command -label [mc Help] -command "taghelp archproj_closedate" entry .archiveProject.closedate.v -width 10 -textvariable archiveProjectCloseDate pack .archiveProject.closedate.l -side left -fill x pack .archiveProject.closedate set archiveProjectFile "$rootdir/projects-archive-$todayiso.tag" frame .archiveProject.filename menubutton .archiveProject.filename.l -text [mc "Archive projects to filename"] -menu .archiveProject.filename.l.m menu .archiveProject.filename.l.m entry .archiveProject.filename.v -width 20 -textvariable archiveProjectFile pack .archiveProject.filename.l .archiveProject.filename.v -side left -fill x pack .archiveProject.filename set archiveProjectCheckActions 1 frame .archiveProject.checkActions checkbutton .archiveProject.checkActions.c -text [mc "Do not archive projects with active or pending actions"] -variable archiveProjectCheckActions pack .archiveProject.checkActions.c pack .archiveProject.checkActions frame .archiveProject.file # set up the archive file name here - with a widget ? frame .archiveProject.bot button .archiveProject.bot.ok -text OK -command {doArchiveProjectsOK} button .archiveProject.bot.cancel -text [mc Cancel] -command {destroy .archiveProject} button .archiveProject.bot.help -text [mc Help] -command "taghelp archiveproject" pack .archiveProject.bot.ok .archiveProject.bot.cancel .archiveProject.bot.help -side left -in .archiveProject.bot pack .archiveProject.bot tkwait window .archiveProject } proc doArchiveProjectsOK {} { global archiveProjectCloseDate archiveProjectCheckActions archiveProjectFile global allproj allact set needMessageBox 0 # Find all the projects which closed before the close date set tests "" set test [list EndDate -earlier $archiveProjectCloseDate] lappend tests $test set archiveProjects [lrange $allproj 1 end] set archiveProjects [tag extract $archiveProjects $tests] if { $archiveProjectCheckActions } { foreach action $allact { # check to see if if is active or pending, then check to see if the project # is in the archiveProjects. If it is then remove it. set st [tag_entryVal $action Status] if { $st == "Pending" || $st == "Active" } { set prj [tag_entryVal $action Project] # Find out if that project is in our list of Projects to archive. set i -1 foreach tproj $archiveProjects { incr i if { [tag_entryVal $tproj Name] == $prj } { if { ! $needMessageBox } { set needMessageBox 1 set messages "" } set messages "$messages Project $prj removed from archive list as it has Pending or Active actions\n" set archiveProjects [lreplace $archiveProjects $i $i] break } } } } } if { $needMessageBox } { tk_messageBox -title [mc "Archive projects notifications"] -message $messages } tag writefile $archiveProjectFile $archiveProjects # remove all the projects which were in archiveProjects from allproj set i -1 foreach proj $allproj { incr i set pn [tag_entryVal $proj Name] foreach tproj $archiveProjects { if { [tag_entryVal $tproj Name] == $pn } { set allproj [lreplace $allproj $i $i] incr i -1 break } } } writeprojects } taglog-0.2.6/src/taglog_util.tcl0000644000175000017500000001357513534701742015300 0ustar johnjohn # # taglog_util.tcl - utility routines for taglog # Copyright John Lines (john+taglog@paladyn.org) August 2001 # # This program is released under the terms of the GNU Public Licence # package provide taglog_util 0.1 proc inctime { var duration } { # increment a time in hh:mm (or just mm) by some time in seconds upvar $var vtime global currentTimeFormat if { ! [ info exist vtime] } { set vtime "00:00:00" } set ss 0 set hh 0 set mm 0 scan $vtime "%d:%d:%d" hh mm ss set mins [expr {$hh*60 + $mm} ] set secs [expr {$hh*3600 + $mm*60 + $ss}] incr mins $duration incr secs $duration set hh [expr { $secs/3600} ] incr secs [ expr {- $hh * 3600} ] set mm [ expr { $secs/60} ] set ss [ expr { $secs%60} ] set vtime [format $currentTimeFormat $hh $mm $ss ] } proc timediff { start end } { # return the time difference in seconds between 2 times specified in hh:mm set starth 0 set startm 0 set starts 0 set endh 0 set endm 0 set ends 0 scan $start "%d:%d:%d" starth startm starts scan $end "%d:%d:%d" endh endm ends set startmins [expr {$starth*60 + $startm}] set startsecs [expr {$starth*3600 + $startm*60 + $starts}] set endmins [expr { $endh*60 + $endm} ] set endsecs [expr {$endh*3600 + $endm*60 + $ends}] # return [expr $endmins - $startmins] return [expr {$endsecs - $startsecs} ] } ######## dateiso2disp # convert an ISO date into the current display format # # Arguments: # date - the date, in internal format, to be displayed # # Results: # returns a string containing the date in the format specified # by the global variable dateformat_view # proc dateiso2disp { date } { global dateformat_view scan $date "%d-%d-%d" year mm dd set mm [format "%02d" $mm] set dd [format "%02d" $dd] if { $dateformat_view == "DD/MM/YYYY" } { return "$mm/$dd/$year" } elseif { $dateformat_view== "MM/DD/YYYY" } { return "$dd/$mm/$year" } else { # default to ISO format return $date } } # datedisp2iso proc datedisp2iso { date } { global dateformat_view } proc tagappend { taglist tagname tagvalue args } { # take a list of tagname and value pairs and append the new name and # value pair if the value part is not empty set result $taglist if { $tagvalue != "" } { if { $args != ""} { set newpair [list $tagname $tagvalue $args] } else { set newpair [list $tagname $tagvalue] } lappend result $newpair } return $result } # ---------------------- taglog_getList --------------------------------- # provides a simple list extracted from a complex list stored in a global # variable # # lType switch for the list to create # projAll provide all project names from list in global variable allproj # proj provide project names from list in global variable allproj, # which are not closed # actAct provide actions from the list in global variable activeactions # acties provide activities from the list in global variable activities # cont provide contacts from the list in global variable allcontacts # # # return: output list or "" proc taglog_getList {lType} { global activeactions global activities global allcontacts global allproj switch $lType { projAll { # all projects # foreach i $projects { # lappend iList [lindex $i 0] # } foreach proj $allproj { lappend iList [tag_entryVal $proj Name] } } proj { # projects which are not closed # now we return the active projects first by making two passes # through the projects list foreach proj $allproj { set pname [tag_entryVal $proj Name] if { (![projclosed $pname]) && ( [isactive $pname])} { lappend iList $pname } } foreach proj $allproj { set pname [tag_entryVal $proj Name] if { (![projclosed $pname]) && ( ![isactive $pname])} { lappend iList $pname } } } cont { # contacts foreach i $allcontacts { set val [tag_entryVal $i Id] if {$val != ""} { lappend iList $val } } } actAct { # actions foreach i $activeactions { lappend iList [lindex $i 1] } } # activities acties { set iList $activities } } if {[info exists iList]} {return $iList} return "" } # ---------------------- taglog_getMaxMembLen --------------------------- # provides the maximum string length of members of a global list # # lType type of the global list (see "taglog_getList" for the types) # minLen if the max. length is less than minLen, minLen is returned # limit If this is not zero then it is the maximum length to return # # return: the maximum string length of members of "minLen" proc taglog_getMaxMembLen {lType minLen { limit 0 }} { set maxLen $minLen set lst [taglog_getList $lType] foreach i $lst { set strLen [string length $i] if {$strLen > $maxLen} {set maxLen $strLen} } if { $limit != 0 } { if { $maxLen > $limit} { set maxLen $limit} } return $maxLen } proc dateRangeToLogfileList { startdate enddate } { global rootdir # return a list of all the log files which can be found on disk between the # start and end dates. Either date as null string means first or last available # (which will include today) if { $startdate == "" } { set startdate "2000-01-01" } if { $enddate == "" } { set enddate [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S"] } set result {} for { set thisdate $startdate } { [clock scan "$thisdate"] <= [clock scan "$enddate"] } { set thisdate [clock format [ clock scan "$thisdate 1 day" ] -format "%Y-%m-%d"] } { # turn the date into a filename scan $thisdate "%d-%d-%d" thisyear thismonth thisday set thismonth [format "%02d" $thismonth] set thisday [format "%02d" $thisday] set filename "$rootdir/log$thisyear/$thismonth$thisday.tag" if [file exists $filename] { lappend result $filename } } return $result } taglog-0.2.6/src/taglog_help_fr.tag0000644000175000017500000000116413603645471015725 0ustar johnjohnTag-help-version: 1.0 Translated-by: John Lines Sorted-date: 2020-01-03 14:10:11 Sort-key: Id End: Id: prefs_language Description:: END_D Cette zone indique votre langage préféré, comme code de langage d'ISO 639. Actuellement seulement l'information d'aide est disponible est disponible en plus d'un langage. L'aide avec de meilleures traductions et plus de langages est toujours appréciée END_D End: Id: UNKNOWN Description:: END_D Il n'y a aucune aide pour cet élément en francais. Je serais très reconnaissant si vous pourriez fournir une traduction à john+taglog@paladyn.org END_D End: taglog-0.2.6/src/taglog_help_de.tag0000644000175000017500000012220413603645471015705 0ustar johnjohnTag-help-version: 1.0 Translated-by: John Lines Sorted-date: 2020-01-03 14:10:11 Sort-key: Id End: Id: About Description:: END_D Dies ist Version $1 Copyright 2000 John Lines Taglog ist freie Software und steht unter der GNU Public License. Taglog Home Page: https://github.com/JohnLines/taglog/wiki END_D End: Id: actinput Description:: END_D Eine Aktion sollte ein klar definiertes Arbeitspaket sein, das Sie oder jemand anderes ausführen soll. In den Feldern des Aktions-Eingabefensters können Sie Schlüsselatribute für die Aktion angeben. Jedes Feld hat seinen eigenen Hilfetext. Bevor Sie eine neue Aktion definieren sollten Sie überlegen, ob sie über- haupt durchgeführt werden sollte. Bedenken Sie Stephen R Coveys "Circle of Concern and Circle of Influence from the 7 Habits of Highly Effective People". Wenn eine Aktion nicht in Ihren Einflussbereich fällt, sollten Sie sie lieber sein lassen und etwas anderes tun, wo Sie mehr bewirken können. END_D End: Id: actinput_abort_action Description:: END_D Dieses Feld enthält die Id einer Aktion, die gestartet wird, wenn die Aktion, die gerade eingegeben wird, abgebrochen wird. END_D End: Id: actinput_active_after Description:: END_D Wenn Sie hier ein Datum (und optional eine Zeit) einsetzen, wird die Aktion so lange als "Blockiert" markiert, bis der angegebene Zeitpunkt erreicht ist oder Taglog das nächste Mal nach der angegebenen Zeit gestartet wurde. Dann wird die Aktion automatisch auf "Aktiv" gesetzt. Wenn die Aktion auf "Aktiv" gesetzt wird, erscheint ein Fenster, das die Überschrift und die Beschreibung der Aktion enthält. Damit kann man zeit- gesteuerte Erinnerungen veranlassen. END_D End: Id: actinput_date Description:: END_D Dieses Feld enthält das Datum, an dem die Aktion hinzu- gefügt wurde. Es wird automatisch vom Programm besetzt. END_D End: Id: actinput_delegated_to Description:: END_D Dieses Feld enthält die Kontakt-Id (oder den Namen, falls Sie die Kontakte nicht nutzen) der Person, der die Aktion übertragen wurde. Momentan benach- richtigt taglog nicht diese Person, so dass Sie das selbst tun müssen. END_D End: Id: actinput_deliverable Description:: END_D Mit diesem Feld können Sie genau definieren, wie der Endzustand der Aktion aussehen muss. Falls sich die unerledigten Aktionen anhäufen, kann es sein, dass sie genauere Angeben in diesem Feld machen müssen (bessere Zielbestimmung). Falls sich die Ziele ändern, kann es besser sein, die Aktion abzubrechen (Status Aborted) und neue Aktionen mit passenderen Zielen zu definieren. END_D End: Id: actinput_description Description:: END_D Hier können Sie eine längere Beschreibung zu der geplanten Tätigkeit geben. Falls Sie z.B. über eine EMail zu einer Tätigkeit aufgefordert wurden, können Sie die wesentlichen Teile mit "cut & paste" aus der EMail in dieses Feld kopieren. END_D End: Id: actinput_difficulty Description:: END_D Der Schwierigkeitsgrad kann dazu genutzt werden, Aktionen herauszusuchen, die leichter als ein bestimmter Grad sind. Zum Beispiel wollen Sie sich für das Ende der Arbeitstages eine leichte Aktion heraussuchen oder zu einem günstigen Zeitpunkt eine anspruchsvolle Aktion in Angriff nehmen. END_D End: Id: actinput_email_status_to Description:: END_D Wenn Sie dieses Feld anwählen und Ihre EMail-Einstellung ist vorbelegt, wird jedesmal, wenn sich der Status einer Aktion ändert, eine EMail an die angegebene Adresse ge- sendet. Das schließt die Erzeugung der Aktion ein. Die EMail enthält alle Felder der Aktion. Dadurch können Sie ohne weiteres Zutun jemanden auf dem Laufenden halten. END_D End: Id: actinput_expected_completed_date Description:: END_D Geben Sie das Datum für die erwartete Erledigung der Aktion an. Das Datum sollte im ISO-Format (JJJJ-MM-TT) angegeben werden. Das Datum kann auch aus dem Kalender ausgewählt werden (Knopf rechts neben dem Datum-Feld). Durch die Speicherung des Ende-Datums können sie leicht prüfen, welche Aktionen zu einer bestimmten Zeit erledigt sein müssen. END_D End: Id: actinput_expected_cost Description:: END_D Geben Sie einen Geldbetrag beliebiger Währung an, der die erwarteten Kosten (ohne die Kosten für die Arbeitszeit) der Aktion darstellt. Der Wert sollte als reelle Zahl eingegeben werden. END_D End: Id: actinput_expected_start_date Description:: END_D Geben Sie das Datum für die erwartete Startzeit der Aktion an. Also das Datum, an dem voraussichtlich der Status von "Wartend" auf "Aktiv" geändert wird. Das Datum sollte im ISO-Format (JJJJ-MM-TT) angegeben werden. Es kann auch aus dem Kalender ausgewählt werden (Knopf rechts neben dem Datum-Feld). END_D End: Id: actinput_expected_time Description:: END_D Geben Sie die erwartete effektive Arbeitszeit in Stunden und Minuten an. Sie können eine Wert aus dem Menü auswählen, oder einen Wert in das Text- feld eingeben, z.B. 3:15 für 3 Stunden und 15 Minuten. END_D End: Id: actinput_id Description:: END_D Jeder Aktion ist eine eindeutige Identifizierung (Id) zugeordnet. Diese wird automatisch generiert, wenn Sie das Id-Feld auf "*Auto*" belassen. Wenn Sie ein Id-Präfix in Datei/Einstellungen angegeben haben, bildet dieses den ersten Teil der Id. Wenn die Aktion mit einem Projekt verknüpft ist, wird die Id aus dem Projekt- namen und einer fortlaufenden Nummer erzeugt. Diese Nummer wird für jede Aktion in einem Projekt hochgezählt - z.B. jlines.test_projekt.57 Falls die Aktion nicht mit einem Projekt verknüpft ist, wird die Identifizie- rung in der Form "taglog.JJJJMMTThhmm" aus dem aktuellen Datum und der Uhr- zeit gebildet - z.B. jlines.taglog.200011190945 Beachten Sie, dass das Präfix mit dem Urheber der Aktion verbunden ist und nicht notwendigerweise mit dem, der die Aufgabe ausführen wird. Es wird be- nutzt, damit eine Aktion eindeutig ist - so gibt es keine Unklarheit, wenn jemand fragt - 'Haben Sie das Projekt jlines.test_projekt.57 beendet?' END_D End: Id: actinput_next_action Description:: END_D Dieses Feld enthält die Id einer Aktion, die gestartet wird, sobald die aktuelle Aktion abgeschlossen ist. END_D End: Id: actinput_precursor Description:: END_D Das Vorgänger-Feld blockiert eine Aktion so lange, bis eine andere (Vorgänger-)Aktion beendet ist. Dieses Attribut wird noch nicht benutzt. END_D End: Id: actinput_priority Description:: END_D Taglog verwendet Prioritäten im Bereich von 0 bis 100. 0 = höchste Priorität (eilig) 100 = niedrigste Priorität Der Standardwert ist 50. END_D End: Id: actinput_project Description:: END_D Taglog benutzt den Begriff Projekt als Verrechnungsstelle (Kostenstelle) für die Zeiterfassung. Wenn Sie eine Aktion ausführen, die mit einem Projekt verbunden ist, wird die aufgewandte Zeit für dieses Projekt verbucht. Falls Sie noch keine Projekte definiert haben, können Sie diese unter Projects/add (Option in der Menüleiste) hinzufügen. END_D End: Id: actinput_reason Description:: END_D Manchmal weiß man nicht, aus welchem Grund man eine Aktion begonnen hat. Hier kann dieses Feld helfen und einen motivieren. Falls das nicht der Fall ist (z.B. der Grund ist 'Der Chef hat mir aufgetragen...') vergessen Sie dieses Feld. END_D End: Id: actinput_status Description:: END_D Aktionen ist ein Bearbeitungsstatus zugeordnet. Folgende Status sind möglich: "Wartend" ("pending") Normalerweise der Status beim Start einer Aktion. (wartet auf Ausführung, noch nicht begonnen) "Aktiv" ("active") Momentan in Bearbeitung "Abgeschlossen" ("completed") Bearbeitet "Abgebrochen" ("aborted") Abgebrochen "Delegiert" ("delegated") an eine andere Person delegiert "Blockiert" ("blocked") Aktive Aktionen können als blockiert markiert werden, wenn man an ihrer Ausführung gehindert ist. "Unveranlagt" ("unclaimed") Besitzerlose Aktionen, die (noch) keinem Be- arbeiter zugeordnet sind, sondern einer gesamten Gruppe von Personen zur Verfügung stehen. Sie können einem Bearbeiter zu- geordnet werden, indem er den Status auf "Wartend" oder "Aktiv" setzt. END_D End: Id: actinput_subtask_of Description:: END_D "Unteraufgabe-von" bedeutet, dass eine Aufgabe eine Unter- aufgabe einer anderen Aufgabe ist. Diese Funktionalität ist noch nicht implementiert. END_D End: Id: actinput_title Description:: END_D Wählen Sie eine kurze Überschrift für diese Aktion. An vielen Stellen können Sie die Aktion durch diese Überschrift identifizieren, ohne weitere Informationen zu dieser Aufgabe (z.B. die Beschreibung oder das Projekt) angeben zu müssen. Wählen Sie deshalb eine aussagekräftige Überschrift. END_D End: Id: actions Description:: END_D Aktionen helfen Ihnen Ihre 'Todo'-Liste zu verwalten. Hat man einmal Aktionen eingegeben, kann man eine aus den momentan aktiven Aktionen auswählen indem man auf 'Aktion' in der mittleren Menüleiste klickt. Hinzufügen... Hier kann eine neue Aktion erzeugt werden. Ansicht Zeigt ausgewählte Aktionen in einer Liste an. Mit einem rechten Mausklick kann man einen Eintrag editieren. Historie Liefert alle Log-Einträge, die mit einer Aktion verknüpft sind und zeigt diese an. Zusätzlich summiert es alle Zeiten, die für diese Aktion aufgewendet wurden, auf und erlaubt so eine Abschätzung der zeitlichen Aufwände und des Erledigungsdatums. Diese Werte können hier auch geändert werden. Abschließen Hier kann man eine aktive Aktion auswählen und als erledigt markieren. Das Erledigungsdatum wird automatisch gespeichert. Zusätzlich kann noch ein Erledigungsvermerk eingegeben werden. Aktivieren Hier kann man eine 'wartende' Aktion auswählen und als aktiv markieren. Abbruch Aktiv Hier kann man eine aktive Aktion auswählen und als abgebrochen markieren. Abbruch Wartend Hier kann man eine 'wartende' Aktion auswählen und als abgebrochen markieren. Reaktivieren Hier kann man eine als erledigt markierte Aktion auswählen und als aktiv markieren. Extra... Hier können Änderungen an Aktionen vorgenommen werden, die normalerweise nicht notwendig sind. END_D End: Id: actmail_message Description:: END_D Geben Sie den Text ein, der als Beschreibung zu dieser Aktion mit versendet werden soll. END_D End: Id: actmail_to Description:: END_D Geben Sie die EMail-Adresse der Person an, an die die Nachricht geschickt werden soll, oder wählen Sie deren Ansprechpartner Id aus der Liste, um die EMail-Adresse automatisch zu besetzen. END_D End: Id: actreminder Description:: END_D Benutzen Sie dieses Feld, wenn Sie sich an Aktionen, die Sie heute vorhaben, erinnern lassen möchten. Momentan ist es nur ein gewöhnliches Textfeld, das nicht mit den Aktions-Daten verbunden ist. Wenn Sie das Programm verlassen, wird der Inhalt der Felder gespeichert, so dass Sie zurückschauen und sich erinnern können, was Sie gestern getan haben. (Momentan allerdings nur in einer Datei.) END_D End: Id: actsel Description:: END_D In diesem Fenster können Sie auswählen, welche Aktion Sie sich anzeigen lassen möchten. Es gibt viele Arten eine Aktion auszuwählen. Hier können Sie Attribute setzen, die die auszuwählenden Aktionen haben müssen. Diese Attribute werden durch ein "logisches UND" verknüpft, d.h. alle gesetzten Attribute müssen für eine Aktion zutreffen. Die "Refresh"-Schaltfläche baut die Liste der Aktionen in den "drop down" Menüs für Id (Identifikation) und Überschrift anhand der ausgewählten Attribute neu auf. END_D End: Id: actsel_expected_completed Description:: END_D Hier kann man Aktionen mit einem erwarteten Erledigungsdatum auswählen. END_D End: Id: actsel_expected_start Description:: END_D Hier kann man Aktionen mit einem erwarteten Startdatum auswählen. END_D End: Id: actsel_filename Description:: END_D Wählen Sie den Namen einer Datei aus, in der Aktionen gespeichert sind, die Sie anzeigen lassen wollen. Vor- besetzt ist die Datei, in der sich die momentane Aktion befindet. END_D End: Id: actsel_id Description:: END_D Wenn sie die "Aktualisieren"-Schaltfläche links vom "Id"-Feld betätigen, wird das "Id"-Menü mit Ids der Aktionen gefüllt, die den anderen ausgewählten Feldern entsprechen. Sie können dann das "Id"-Feld nutzen, um eine spezielle Aktion auszuwählen. END_D End: Id: actsel_maxpriority Description:: END_D Aktionen, deren Priorität kleiner oder gleich dem hier angegebenen Wert sind, werden berücksichtigt. Prioritäten reichen von 1 (höchste Priorität) bis 100 (niedrigste Pr.). Der Standardwert ist 50. Diese Option erlaubt es, Aktionen auszuwählen, die mindestens eine bestimmte Wichtigkeit haben. END_D End: Id: actsel_project Description:: END_D Wählen Sie ein Projekt aus, für das Sie Aktionen auswählen. Es werden nur Aktionen berücksichtigt, die mit diesem Projekt verbunden sind. END_D End: Id: actsel_showfields Description:: END_D Sie können die Felder auswählen, die in der Liste der Aktionen angezeigt werden sollen. Ist der "Alle"-Schalter gesetzt, werden alle Felder auswählt, ansonsten werden nur die Felder angezeigt, deren Schalter aktiviert sind. END_D End: Id: actsel_sortby Description:: END_D Die Liste der Aktionen kann nach verschiedenen Feldern sortiert werden. Wählen Sie hier einen Wert, um die ausgewählten Aktionen nach diesem Wert zu sortieren. END_D End: Id: actsel_st Description:: END_D Wenn der "Beliebig"-Schalter gesetzt, ist werden alle Aktionen ungeachtet ihrer Status berücksichtigt. Die Anderen Status-Schalter spielen dann keine Rolle. Ist der "Beliebig"-Schalter nicht gesetzt, werden nur Aktionen berücksichtigt, die den selektierten Status-Schaltern entsprechen. END_D End: Id: actsel_title Description:: END_D Wenn Sie die "Refresh"-Schaltfläche links vom "Id"-Feld betätigen, wird das "Titel"-Menü mit Überschriften der Aktionen gefüllt, die den anderen ausgewählten Feldern entsprechen. Sie können dann das "Titel"-Feld nutzen, um eine spezielle Aktion auszuwählen. END_D End: Id: add_old_log Description:: END_D Hier können Sie einen alten Log-Eintrag auswählen. Der Eintrag wird immer an die Log-Datei angefügt, auch wenn er schon existiert, der Zeitbereich früher ist als alle Zeiten in der Datei oder Bereiche überlappen. Das bringt die Programmteile durcheinander, die Reports erstellen. Diese Funktionaltiät ist hauptsächlich dafür gedacht, dass man Zeiten nach- tragen kann, wenn man ein oder mehrere Tage nicht an seinem Computer ge- arbeitet hat. END_D End: Id: addcontact Description:: END_D Füllen Sie diese Felder aus, um einen neuen Ansprechpartner hinzuzufügen. Sie können diesen Kontakt nutzen, um das Versenden von Mails zu ver- einfachen, um Telefonanrufe nachzuvollziehen, die Sie machen müssen, oder um eine Historie von Kontakten mit einer bestimmten Person zu erhalten. END_D End: Id: addcontact_address Description:: END_D Geben Sie hier Teile der Adresse ein, die in keinem anderen Feld unter- zubringen sind. END_D End: Id: addcontact_country Description:: END_D Geben Sie das Land an, in dem die Person wohnt. Ich schlage vor, den ISO- Ländercode zu verwenden, um konsistent zu bleiben, aber das ist nicht erforderlich. END_D End: Id: addcontact_default_as Description:: END_D Dieser Parameter ist bisher nur experimentell. In Zukunft wird man hier eine Id eines anderen Kontakts angeben können, wodurch alle Felder des Kontakts bis auf diejenigen, die den Kontakt umfangreicher beschreiben, durch Werte des hier ausgewählten Kontakts gefüllt werden. In dieser Version ist es nur ein Platzhalter und bewirkt nichts. END_D End: Id: addcontact_email Description:: END_D Geben Sie die EMail-Adresse des Kontakts an. END_D End: Id: addcontact_fax Description:: END_D Geben Sie die Fax-Nummer des Kontakts an. END_D End: Id: addcontact_forename Description:: END_D Geben Sie den Vornamen des Kontakts an. END_D End: Id: addcontact_id Description:: END_D Geben Sie eine Identifizierung (ID) für diesen neuen Kontakt (Person) an. Diese ID sollte kurz und gut zu merken sein, da sie in Auswahlmenüs von Kontakten verwendet wird. Je nachdem wieviele Personen Sie speichern wollen, können Sie nur die Initialen oder auch den gesamten Namen hier angeben. END_D End: Id: addcontact_ldap Description:: END_D Geben Sie die LDAP URL (wie in RFC 2255 beschrieben) für den Kontakt ein. z.B. ldap://ldap.example.com/cn=smith,dc=example,dc=com Das kann möglicherweise dazu benutzt werden, um die Details dieser Person beim LDAP Server zu bekommen oder zu überprüfen. END_D End: Id: addcontact_mobilephone Description:: END_D Geben Sie die Mobilfunknummer des Kontakts an. END_D End: Id: addcontact_organisation Description:: END_D Geben Sie die Organisation an, die mit der Person verbunden ist (z.B die Firma, in der sie arbeitet). END_D End: Id: addcontact_phone Description:: END_D Geben Sie die Telefonnummer des Kontakts an. END_D End: Id: addcontact_postcode Description:: END_D Geben Sie die Postleitzahl (oder den zip code) des Kontakts an. END_D End: Id: addcontact_short_id Description:: END_D Geben Sie eine kurze (2 bis 3 Zeichen) Identifizierung für diesen Kontakt an. Sie wird für Berichte genutzt, bei denen eine Aktion mit einer oder mehreren Personen verbunden ist, und soll dort nicht viel Raum einnehmen. Dieses Feld ist (momentan) nur für Mitarbeiter von bedeutung. Wenn es nicht besetzt ist, wird die normale ID angezeigt. END_D End: Id: addcontact_surname Description:: END_D Geben Sie den Nachnamen des Kontakts an. END_D End: Id: addcontact_title Description:: END_D Geben Sie den Titel der Person an oder wählen Sie Ihn vom "drop down" Menü. Bitte bedenken Sie, dass es so viele Titel gibt, dass sie nicht alle aufgeführt werden können. END_D End: Id: addcontact_type Description:: END_D Wählen sie einen Typ aus dem "drop down"-Menü. Diese Typen können Sie in der Datei für die Voreinstellungen ändern. END_D End: Id: addcontact_web Description:: END_D Geben Sie die HTTP-URL für die Homepage dieser Person an. END_D End: Id: addproject Description:: END_D In taglog ist ein Projekt etwas, auf dem man Arbeitszeit verbuchen kann. Der Projektname sollte eine einfach zu merkende Bezeichnung des Projekts sein. Der Buchungs-Code wird benutzt als Identifizierung des Projekts in Ihrem Abrechnungssystem, das vielleicht keine Buchstaben für Kostenstellen ver- arbeiten kann. Man kann Projekte haben, die als "Pausen" (Unterbrechungen, Pausen) gekenn- zeichnet sind. Ihre Zeit kann nicht verbucht werden. Es gibt sogenannte "Overhead" Projekte, die bei der Generierung von Reports genutzt werden, wobei Zeiten, die in diesen Projekten verbraucht wurden, auf wirkliche Projekte verteilt werden. Die Hauptprojekte, an denen Sie momentan arbeiten, sollten als "Aktiv" markiert sein. Sie erscheinen immer in Projekt/Ansicht Darstellung, auch wenn für sie keine Zeit verbucht wurde. Das Erzeugungsdatum des Projekts wird automatisch vom System gesetzt und Sie können das Datum des voraussichtlichen Endes angeben, oder sie geben es später über die Option "Projekte/Bearbeiten" ein. Das System nutzt die Datumeinträge um schneller die verbrachte Zeit in einem Projekt berechnen zu können, da nur Log-Dateien durchsucht werden müssen, die ab dem Erzeugungsdatum des Projekts erstellt wurden. Wenn das Beendigungsdatum überschritten wurde, wird Ihnen das zugehörige Projekt nicht mehr angeboten, um darauf Zeit zu verbuchen. END_D End: Id: adjstart Description:: END_D Die Möglichkeit, die Startzeit eines Log-Eintrags anzupassen, ist z.B. dann nützlich, wenn Sie für "kurze" Zeit Ihren Arbeitsplatz verlassen, während das Logging zu einem Projekt läuft, und Sie von Jemandem länger als erwartet durch eine Diskussion zu einem anderen Projekt aufgehalten werden. Sie können die Startzeit für die aktuelle Aktion (die, deren Beschreibung Sie in das untere große Fenster eingeben) durch das Betätigen der "Start"- Schaltfläche ändern. Dabei können Sie entweder die geänderte Zeit in das Feld mit der Beschriftung "Neue Startzeit" eintragen, oder Sie können mit dem Schieberegler die Anzahl der Minuten einstellen, die Sie abziehen möchten. Falls Sie nicht die Startzeit des ersten Eintrags an diesem Tag ändern, haben Sie die Möglichkeit das Ende des vorhergehenden Eintrags an die geänderte Zeit anzupassen. Das ist die Voreinstellung. Wenn Sie diese Anpassung nicht vornehmen, wird für die Zeitdifferenz das Zeitkonto doppelt belastet. END_D End: Id: alwin_project Description:: END_D Der Projektname, der mit der alten Log-Datei verbunden ist, kann hier ein- gegeben werden oder aus dem "drop down"-Menü ausgewählt werden. Man kann alle Projekte auswählen, auch solche, deren Beendigungszeit schon über- schritten wurde. END_D End: Id: contacts Description:: END_D Die Verwaltung von Kontakten ist nicht die Hauptaufgabe von taglog, aber diese Möglichkeit ist vorhanden und erlaubt Ihnen Log-Einträge mit Personen zu verknüpfen oder Einträge zu suchen, die mit bestimmten Personen verknüpft sind. Es können auch Email-Adressen gespeichert werden und zusammen mit der EMail Funktion von taglog verwendet werden. END_D End: Id: contactview Description:: END_D Benutzen Sie diese Felder zur Auswahl von Informationen zu Ansprech- partnern, die sie sehen möchten, und klicken Sie 'Ansicht'. END_D End: Id: cview_forename Description:: END_D Geben Sie den Vornamen (oder einen Teil davon) der Person ein, die Sie suchen. END_D End: Id: cview_organisation Description:: END_D Geben Sie die Organisation (oder einen Teil davon) ein, die Sie suchen. END_D End: Id: cview_phone Description:: END_D Geben Sie die Telefonnummer (oder einen Teil davon) ein, die Sie suchen. END_D End: Id: cview_surname Description:: END_D Geben Sie den Nachnamen (oder einen Teil davon) der Person ein, die Sie suchen. END_D End: Id: cview_type Description:: END_D Wählen Sie einen Kontakt-Typ aus, um das Suchergebnis auf Kontakte mit diesen Typ zu beschränken. END_D End: Id: editprefs Description:: END_D Hier können Sie einige Merkmale festlegen, die die Arbeitsweise des Programms beeinflussen. Jeder Eintrag hat seinen eigenen Hilfetext (linker Maus-Klick auf die jeweilige Beschriftung). Taglog speichert diese Einstellungen in einer Datei, deren Name in der Kopfzeile zu finden ist. Mit Ok werden die neuen Einstellungen in die Datei geschrieben. END_D End: Id: editprefs_current_win_depth Description:: END_D Hier können Sie die Anzahl der Zeilen für das aktuelle Log-Fenster ein- stellen. (Das ist das untere Fenster im Hauptfenster). Allerdings ändert sich die Fenstergröße, wenn Sie das Hauptfenster in seiner Größe verändern. END_D End: Id: editprefs_history_win_depth Description:: END_D Hier geben Sie die Anzahl der Zeilen für das "History"-Fenster an. (Das ist das Fenster, das die bisherigen Log-Einträge des Tages enthält.) Damit kann man auf kleinen Bildschirmen Platz sparen. END_D End: Id: editprefs_id_prefix Description:: END_D Dieses Präfix wird verwendet, um Aktionen, die Sie neu definieren, ein- deutig zu machen (innerhalb einer Arbeitsgruppe). Falls ein Präfix gesetzt ist, wird dieses jeder neuen Aktions-ID vorangestellt. END_D End: Id: editprefs_num_today_actions Description:: END_D Hier können Sie die Anzahl der Felder für Aktionen auswählen, an die Sie erinnert werden wollen. Diese Felder werden unter der Menüleiste im Haupt- fenster angezeigt. Mit 0 können Sie alle Felder ausblenden. END_D End: Id: editprefs_projects_url Description:: END_D Geben Sie eine URL zu einer Web-Seite an, die eine Liste von Projekten liefert, auf die Zeit gebucht werden kann. Beispiel: http://projects.example.com/projects-list.php?jl END_D End: Id: editprefs_start_procs Description:: END_D Alle hier angegebenen Prozeduren werden beim Start von taglog gestartet. Wenn Sie mit einem ikonifizierten Hauptfenster und einem Fenster, das die momentan aktiven Projekte und die für diesen Tag darauf verbuchten Zeiten anzeigt, starten möchten, wählen Sie 'iconify_mainwin doShowProjects'. END_D End: Id: editproject Description:: END_D In taglog ist ein Projekt etwas, auf dem man Arbeitszeit verbuchen kann. Jedes Projekt hat einen Namen, einige Kennzeichnungen, wie Zeiten, die für dieses Projekt verbucht werden können, einen Buchungs-Code und das Start- und Beendigungsdatum. Die Kennzeichnungen sind: Pausen Diese Projekte haben keine normale Arbeitszeit. Ihre Zeiten werden bei Berichten anders behandelt. 'Overhead'-Zeiten werden nicht auf sie verteilt. Overhead Zeiten, für solche Projekte werden bei den Berichten gleichmäßig auf die anderen projekte verteilt (mit Ausnahme von 'Pausen') Aktiv Solche Projekte sind in der Bearbeitung (im Gegensatz zu nur offen). Sie werden immer in Projekte/Ansicht mit aufgeführt, auch wenn keine Zeit für sie verbucht wurde. Wenn Sie vermeiden wollen, dass ein Projekt in der Projektauswahl erscheint, geben Sie diesem ein Beendigungsdatum, das älter als der heutige Tag ist. END_D End: Id: endbutton Description:: END_D Die Punkte unter dem 'Ende'-Knopf behandeln verschiedene Eigenschaften des Log- eintrags. Sie können die aktuelle Aktion abschließen. Sie können die aktuelle Aktion abbrechen. Sie können einen Ansprechpartner mit dem aktuellen Log-Eintrag verknüpfen. Die Verknüpfung wird zurückgesetzt, wenn Sie zum nächsten Eintrag übergehen. Sie können eine Rate mit dem aktuellen Log-Eintrag verknüpfen. Diese Verknüpfung bleibt bestehen, bis Sie das Programm verlassen oder die Rate löschen. END_D End: Id: ep_enddate Description:: END_D Geben Sie das Beendigungsdatum für das Projekt an. END_D End: Id: file Description:: END_D 'Öffnen' erlaubt Ihnen Einträge von vorangegengenen Tagen anzuschauen. Man kann Einträge aufgrund verschiedener Kriterien suchen (z.B. Projektbezeichnung oder Aktivität) 'Ende' Beendigung des Programmes am Ende des Tages 'Abbruch' Beendet das Programm ohne den letzten Eintrag zu speichern 'Log hinzufügen/ändern Erlaubt Eintraäg von vorhergehenden Tagen zu ändern oder neu zu erzeugen. Um einen Eintrag des aktuellen Tages zu ändern sollte man mit der rechten Maustaste diesen Eintrag auswählen. 'Anhalten' Hält die Buchungsuhr an (z.B. wegen Pausen) 'Fortfahren' Läßt die angehaltene Buchungsuhr wieder weiterlaufen. 'Einstellungen' Erlaubt benutzerdefinierte Einstellungen. END_D End: Id: hint_activity_pre_meeting Description:: END_D Besprechungen können eine große Zeitverschwendung oder extrem produktiv sein. Wesentlich ist die Vorbereitung. Bedenken Sie folgendes vor einer besprechung: Weshalb sind Sie dabei? Bereiten Sie die besprechung vor? Falls ja, haben Sie eine Agenda mit Ihren persönlichen Leitlinien und der dazugehörigen Zeitplanung? Sollen Sie technische Informationen dazu beitragen? Falls ja, haben Sie die notwendigen Hintergrundinformationen gesammelt? Welche Fragen können Inhen gestellt werden? Sind Sie dabei, um Informationen zu bekommen? Was sind Ihre Ziele? Wenn Sie wissen, was für Sie bei der Besprechung herauskommen soll und die anderen Teilnehmer sind nicht vorbereitet, werden Sie wahrscheinlich Ihre Ziele erreichen. END_D End: Id: hint_help Description:: END_D Dieser Abschnitt enthält Hintergrundinformationen zum Zeit-Management. Einige davon enthalten Vorschläge, wie man Zeit-Management-Probleme mit taglog löst, aber es sind auch allgemeinere Hilfen enthalten. Weitere Zusätze sind willkommen. Wenn Sie einen guten Tip zum Zeit-Management haben, schicken Sie ihn bitte an den Author. END_D End: Id: hint_problem_actions_overrun Description:: END_D Wenn Sie meinen, dass Aktionen länger dauern als ursprünglich erwartet, waren Sie wahrscheinlich bei zu Beginn zu optimistisch. Falls Sie es nicht schon tun, versuchen Sie zu Beginn einer Aktion die erwartete Zeit anzugeben. Prüfen Sie regelmäßig Ihre aktiven Aktionen indem Sie den Menüpunkt Aktionen/Historie aufrufen und passen Sie gegebenenfalls die Daten an. Die Zusammenfassung von Aktionen/Historie zeigen den Unterschied zwischen der letzten und der ursprünglichen Schätzung. Verwenden Sie diese Information um künftig bessere Anfangsabschätzungen machen zu können. END_D End: Id: hint_problem_interruptions Description:: END_D Fall Sie durch Unterbrechungen zu sehr gestört werden, legen Sie Zeiten fest, an denen Sie nicht zu sprechen sind und machen Sie diese durch eine Notiz an Ihrer Tür oder auf Ihrem Schreibtisch (falls Sie in einem Großraumbüro arbeiten) bekannt. Ihr Anrufbeantworter sollte Zeiten angeben, zu denen Sie bevorzugr Gespräche annehmen. END_D End: Id: introduction Description:: END_D Taglog erlaubt es zu messen, wie Sie Ihre Zeit verwenden und hilft Ihnen bei der planung von Aktionen (Aufgaben). Sie können Peiten auf Projekte buchen. Projekte werden in taglog dazu verwendet um die Arbeitszeit in buchbare Einheiten aufzuteilen. Wenn Sie Zeiten zu Projekten buchen wollen, dann legen Sie im nächsten Schritt Projekte an. Die Hauptfunktion von taglog ist es, Anmerkungen zur verbrachten Zeit zu machen. Diese werden im größeren Fenster unten eingegeben. Wenn Sie zur nächsten Aktivität wechseln, klicken Sie auf 'Weiter'. Damit wird die Start- und Beendigungszeit der Aktivität protokolliert. Viele der Beschriftungen haben eine Online-Hilfe und/oder erlauben Ihnen Werte aus einer Liste auszuwählen. Dazu klicken Sie einfach auf die Be- schriftung. Um das Programm zu verlassen verwendet man den Menüeintrag Datei/Ende. END_D End: Id: led_calendar Description:: END_D Drücken Sie einen Knopf im Kalender, um Log-Einträge für den zugehörigen Tag auszuwählen. Mit ">>" und "<<" kann man den nächsten oder vorherigen Monat auswählen. Wenn zu einem Tag eine Log-Datei existiert, ist der zugehörige Knopf gelb dargestellt. END_D End: Id: led_ediEnt Description:: END_D Dieses Fenster erlaubt die Parameter eines Log-Eintrages zu verändern. END_D End: Id: led_entList Description:: END_D Dieses Fenster zeigt die Liste aller Log-Einträge für einen ausgewählten Tag. Einträge mit Startzeiten, die früher als die End-Zeit des vorhergehenden Ein- trags sind, sind mit ">" gekennzeichnet. Falls die Startzeit eines Eintrags größer als dessen End-Zeit ist, wird der Eintrag mit "!" markiert. Die markierten Einträge sind auch farbig hervorgehoben, wenn das die TCL/TK- Version unterstützt. Folgende Bearbeitungsoptionen sind vorhanden: Bearbeiten... Diese Option ist nur aktiviert, wenn Einträge in der Liste ausgewählt wurden. Für jeden ausgewählten Eintrag wird ein Fenster geöffnet, das alle Parameter zu diesem Log-Eintrag enthält. Hinzufügen... Es wird ein Eingabefenster geöffnet, in dem man einen neuen Log-Eintrag hinzu- fügen kann. Löschen Die ausgewählten Einträge werden gelöscht. Importieren... Diese Option erlaubt es Log-Einträge aus Dateien zu übernehmen. Zusätzlich besteht die Möglichkeit, Start- oder End-Zeiten an die Zeit des vorherigen oder nächsten Eintrages anzupassen. Dazu wählt man den zu ändernden Eintrag mit der rechten Maustaste aus. Es erscheint ein Menü, in dem Sie die gewünschte Operation ausführen können. END_D End: Id: led_impList Description:: END_D Diese Liste enthält alle Log-Einträge der ausgewählten Datei. Einträge mit Startzeiten, die früher als die End-Zeit des vorhergehenden Eintrags sind, sind mit ">" gekennzeichnet. Falls die Startzeit eines Eintrags größer als dessen End-Zeit ist, wird der Eintrag mit "!" markiert. Die markierten Ein- träge sind auch farbig hervorgehoben, wenn das Ihre TCL/TK-Version unterstützt. Mit "Importieren" kann man selektierte Einträge übernehmen. "Alle" erlaubt es, die gesamte Liste zu importieren. END_D End: Id: led_newEnt Description:: END_D Hier können Sie die Parameter für einen neuen Log-Eintrag eingeben. END_D End: Id: logedit Description:: END_D Gemäß 'The Rubaiyat' von Omar Khayyam (ins Englische übersetzt von Edward Fitzgerald) The Moving Finger writes; and, having writ, Moves on; nor all thy Piety nor Wit Shall lure it back to cancel half a Line, Nor all thy Tears wash out a Word of it. Taglog gibt ihnen allerdings die Möglichkeit, mit der rechten Maustaste einen Eintrag anzuklicken und Ihn zu editieren. END_D End: Id: logedit_action Description:: END_D Sie können die mit diesem Eintrag verbundene Aktion ändern. Momentan kön- nen Sie die Aktion nicht einer Auswahlliste entnehmen. Seien Sie vorsichtig, die Aktions-Id wird nicht geprüft. Sie sollten das 'Titel der Aktion' Feld anpassen, wenn Sie eine Änderung vornehmen. END_D End: Id: logedit_actiontitle Description:: END_D Sie können die Überschrift der Aktion für diesen Eintrag ändern. Momentan kön- nen Sie die Überschrift nicht einer Auswahlliste entnehmen. Sie müssen diese Änderung zusammen mit dem Aktions-Feld durchführen, was Sie zur Zeit noch von Hand ausführen müssen. END_D End: Id: logedit_activity Description:: END_D Sie können hier die mit dem Eintrag verbundene Aktivität ändern. END_D End: Id: logedit_contact Description:: END_D Sie können hier den mit dem Eintrag verbundenen Kontakt ändern. END_D End: Id: logedit_description Description:: END_D Sie können hier die mit dem Eintrag verbundene Beschreibung ändern. END_D End: Id: logedit_end Description:: END_D Sie können die Beendigungszeit dieses Eintrags ändern. Beachten Sie aber, dass die Startzeit des vorhergehenden Eintrags momentan nicht angepasst wird. Diese Anpassung müssen Sie selbst durchführen, wenn Sie Ihre Logs konsistent halten wollen. END_D End: Id: logedit_id Description:: END_D Dieses Feld zeigt die Identifizierung, die mit dem Log-Eintrag verbunden ist. Man kann dieses Feld nicht ändern. END_D End: Id: logedit_project Description:: END_D Ändern Sie das Projekt, das mit diesem Eintrag verbunden ist. END_D End: Id: logedit_rate Description:: END_D Sie können hier die mit dem Eintrag verbundene Rate ändern. END_D End: Id: logedit_start Description:: END_D Sie können die Startzeit dieses Eintrags ändern. Beachten Sie aber, dass die Beendigungszeit des vorhergehenden Eintrags momentan nicht angepasst wird. Diese Anpassung müssen Sie selbst durchführen, wenn Sie Ihre Logs konsistent halten wollen. END_D End: Id: logsel Description:: END_D Der obere Teil des Fensters enthält eine Liste der Log-Dateien, deren Inhalt Sie sich anschauen können. Einträge in der Liste setzen sich zusammen aus dem Monat und dem Tag (z.B. 0102 bedeutet 2. Januar). Die Felder unter der Liste dienen zur Einschränkung dessen, was angezeigt werden soll. END_D End: Id: logsel_activity Description:: END_D Wenn Sie hier einen Typ eine Aktivität auswählen, dann werden nur Einträge mit diesem Aktivitätstyp angezeigt. END_D End: Id: logsel_contact Description:: END_D Wenn Sie hier einen Kontakt wählen, dann werden nur Einträge angezeigt, die mit diesem Kontakt verbunden sind. Das kann z.B dazu genutzt werden, um Themen, die Sie mit einer bestimmten Person in den letzten Monaten diskutiert haben, zu suchen und anzuzeigen. END_D End: Id: lvsa_dirname Description:: END_D Der Name des Verzeichnisses, wo die zu sichernde Datei gespeichert werden soll, kann hier eingegeben oder ausgewählt werden. END_D End: Id: prefs_dateformat Description:: END_D Wählen Sie von den gegebenen Optionen Ihr bevorzugtes Format zur Eingabe und Darstellung von Datumwerten. Taglog arbeitet intern immer im ISO 8601 Format, aber einige Teile des Programms erlauben Ihr bevorzugtes Format. Beachten Sie, dass die Unterstützung der anderen Formate momentan noch unvollständig ist. END_D End: Id: prefs_docdir Description:: END_D Taglog speichert seine Dokumentation in diesem Verzeichnis. Wenn Sie diesen Text lesen, ist der Pfadname für das Dokumentationsverzeichnis wahrscheinlich richtig. Falls Sie also diesen Text lesen können, sollten Sie den Pfadnamen NICHT ändern. END_D End: Id: prefs_language Description:: END_D Dieses Feld zeigt Ihre bevorzugte Sprache als ISO 639 Sprachen-Code an. Momentan ist nur die Hilfe-Information in mehreren Sprachen vorhanden. Hilfe bei einer besseren Übersetzung und bei der Erweiterung auf mehr Sprachen ist erwünscht und wird dankbar angenommen. END_D End: Id: prefs_rootdir Description:: END_D Dateien mit den Daten für taglog sind in diesem Verzeichnis oder dessen Unterverzeichnis gespeichert. Bitte beachten Sie, dass Sie bei Änderung dieses Verzeichnisses die schon existierenden Dateien umkopieren müssen. END_D End: Id: prefs_showtime_hours_per_day Description:: END_D Geben Sie die Länge Ihres Arbeitstages in Stunden (Dezimalschreibweise) an. Diese Angabe wird im wöchentlichen Zeitbuchungs-Report genutzt, wenn sie eine Abfrage nach Zeiten in Tagen mit Dezimalschreibweise starten. END_D End: Id: prefs_showtime_spreadoverheads Description:: END_D Wählen Sie diese Option aus, wenn Sie die Zeiten von 'Overhead"-Projekten standardmäßig auf alle buchbare Projekte verteilen möchten. END_D End: Id: projects Description:: END_D Projekte werden in taglog dazu verwendet um die Arbeitszeit in buchbare Einheiten aufzuteilen. Die Möglichkeit zur Planung und Kontrolle von Aktivitäten finden Sie unter 'Aktionen'. Hinzufügen Erzeugt ein neues projekt Bearbeiten Editieren und Löschen von Projekten Aktualisieren Laden von Projektinformationen über eine URL. Diese kann in Datei/Einstellungen angegeben werden. Ansicht Zeigt an, wie sich die Arveitszeit des aktuellen Tages über die Projekte verteilt. Außerdem ist diese Projektansicht bei ikonisiertem Hauptfenster vorhanden. END_D End: Id: reports Description:: END_D Taglog kann eine Vielzahl von Berichten aus den gesammelten Informationen erzeugen. END_D End: Id: smtp_mailhost Description:: END_D Geben Sie den Namen des Rechners an, der als "Mailhost" verwendet werden soll. Das ist der Rechner, der Ihre Mails an die Empfänger weiterleitet. Die Vorbesetzung unter UNIX ist hierbei "localhost". END_D End: Id: smtp_myemail Description:: END_D Geben Sie hier Ihre EMail-Adresse an. Diese Adresse wird in den "Von:"-Teil der EMail eingesetzt. END_D End: Id: smtp_port Description:: END_D SMTP an andere Rechner benutzt normalerweise den Port 25. Auf einigen Systemen wird der Port 587 für die Versendung lokaler Mails verwendet. END_D End: Id: smtp_prefsfile Description:: END_D Die Einstellungen für die Mail-Konfiguration sind in einer gesonderten Datei gespeichert: UNIX: ~/.smtp Windows: ~/smtp.cfg Falls keiner dieser Dateien gefunden wird, werden die Parameter mit im Programm vordefinierten Einstellungen initialisiert. END_D End: Id: smtp_thishost Description:: END_D Geben Sie den Namen dieses Rechners an. Er wird für den HELO-Teil des SMTP verwendet. END_D End: Id: summarybox Description:: END_D Geben Sie eine Zusammenfassung der Ereignisse dieses Tages. Wenn Sie hier 'Abbruch' klicken, wird das Programm trotzdem beendet. Es wird nur keine Zusammenfassung gespeichert. END_D End: Id: timebook_numweeks Description:: END_D Geben Sie die Anzahl der Wochen an, für die Sie einen Report wünschen. Damit können Sie Reports für mehrere Wochen gleichzeitig erzeugen. END_D End: Id: timebook_weekno Description:: END_D Geben Sie die Kalenderwoche an. Als Vorgabe ist die aktuelle Kalenderwoche eingegeben. Mit den Schaltflächen "+" und "-" können Sie diese ändern. END_D End: Id: timebook_year Description:: END_D Wählen Sie das Jahr, in dem die Zeitbuchung beginnt. Beachten Sie, dass Reports, die sich über Jahre ausdehnen, wahrscheinlich nicht erzeugt werden können. END_D End: Id: timebooksel Description:: END_D Hier können Sie Einstellung zur Berichtgenerierung bearbeiten. Die Zeiten können in Stunden und Minuten, Stunden in Dezimalschreibweise oder Tage in Dezimalschreibweise ausgegeben werden. Der Auswahlwert 'Stunden pro Tag' bestimmt die Umrechnung von Tagen in Dezimalschreibweise. Die Vorgabe 'Stunden pro Tag' aus Datei/Einstellungen bestimmt die Derzimal- darstellung der Tage. Wenn sie die Option 'Overhead-Projekte aufteilen' wählen, dann werden die Zeiten, die auf die Projekte, die mit 'overhead' markiert sind, auf alle übrigen Projekte (mit Ausnahme der Projekte, die mit 'Pause' markiert sind) verteilt. Die 'overhead'-Zeiten für jeden Tag werden nach der Zeitaufteilung der buchbaren Projekte einer Woche verteilt. Sie können auswählen, ob die Projekte anhand des Buchungscodes, des Namens oder beider Kriterien dargestellt werden sollen. Wenn Sie den Buchungscode wählen und mehr als ein Projekt mit dem gleichen Buchungscode existiert, dann werden deren Gesamtsummen dargestellt. Geben Sie ein Jahr an, wenn sie nicht das aktuelle Jahr auswählen wollen. Die Kalenderwoche für den Report können Sie eingeben oder mit den Schalt- flächen "+" und "-" verändern. END_D End: Id: timebooksel_timeformat Description:: END_D Zeiten könne ausgegeben werden als: . Stunden und Minuten . Stunden in Dezimalschreibweise . Tagen in Dezimalschreibweise Der Auswahlwert 'Stunden pro Tag' in Datei/Einstellungen bestimmt die Umrechnung von Tagen in Dezimalschreibweise. END_D End: Id: UNKNOWN Description:: END_D Zu diesem Thema gibt es keinen Hilfetext. Ich wäre sehr dankbar, wenn Sie eine Übersetzung an john+taglog@paladyn.org senden könnten. END_D End: Id: viewc Description:: END_D Mit der rechten Maustaste können Sie einen Kontakt auswählen, um ihn zu editieren. END_D End: Id: viewproject Description:: END_D Die Darstellung 'Projektzeiten' zeigt die kumulative Zeit für alle Projekte an, die für den aktuellen Tag Zeit verbucht haben. Außerdem wird die Gesamtzeit für alle Projekte und für alle Projekte, die nicht mit 'Pause' bezeichnet sind, aufgführt. Projekte, für die die Zeiten beim Öffnen dieses Fensters noch nicht ver- bucht waren, werden nicht angezeigt. Erst wenn Sie die Schaltfläche OK be- tätigen und dann nochmal 'Projekte/Ansicht' auswählen, erscheinen sie. Sie können durch Klicken auf 'Projekt' zu anderen Projekten wechseln. END_D End: taglog-0.2.6/src/taglog_tmp.tcl0000644000175000017500000000160113534701742015106 0ustar johnjohnproc dateRangeToLogfileList { startdate enddate } { global rootdir # return a list of all the log files which can be found on disk between the # start and end dates. Either date as null string means first or last available # (which will include today) if { $startdate == "" } { set startdate "2000-01-01" } if { $enddate == "" } { set enddate [clock format [clock seconds] -format "%Y-%m-%d"] } set result {} for { set thisdate $startdate } { [clock scan "$thisdate"] <= [clock scan "$enddate"] } { set thisdate [clock format [ clock scan "$thisdate 1 day" ] -format "%Y-%m-%d"] } { # turn the date into a filename scan $thisdate "%d-%d-%d" thisyear thismonth thisday set thismonth [format "%02d" $thismonth] set thisday [format "%02d" $thisday] set filename "$rootdir/log$thisyear/$thismonth$thisday.tag" if [file exists $filename] { lappend result $filename } } return $result } taglog-0.2.6/src/mainwin.tcl0000644000175000017500000004323013550071213014406 0ustar johnjohn# # This program gives a combined electronic diary and time clock. # Copyright John Lines (john+taglog@paladyn.org) October 2001 # # This program is released under the terms of the GNU Public Licence # package provide mainwin 0.1 proc donext { activity { proj ""} } { global hh mm ss currentStart currentEnd currentActivity currentProject global currentAction currentActionTitle currentContact stack_info global currentTimeFormat gettime set currentEnd [format $currentTimeFormat $hh $mm $ss] set lastId [writelog] .description.body delete 1.0 end # Cleanup variable which should be cleaned at the end # always set currentAction to null after write as we are almost certainly # changing what we do set currentAction "" set currentActionTitle "" set currentContact "" # If the stack_info was an interupt make it into a normal push after it # has been written if { [string index $stack_info 0] == "!" } { set stack_info "+[string range $stack_info 1 end]" } # readlogentries fillpreventries .preventries.body gettime set currentStart [format $currentTimeFormat $hh $mm $ss] set currentEnd [format $currentTimeFormat $hh $mm $ss] set currentActivity $activity if { $proj != "" } { set currentProject $proj } return $lastId } proc dopause {} { global hh mm ss currentStart currentEnd state writelog .description.body delete 1.0 end set currentStart "pause" set currentEnd "pause" set state "paused" } proc doresume {} { global hh mm ss currentStart currentEnd state day month year global currentTimeFormat # We need to check on a resume to see if we are now in a different day # actually we may not need to - I think we can just always close and open # the log file - it will handle being a new day. #set prevday $day #set prevmonth $month #set prevyear $year #getdate # if { ( $prevday == $day ) && ( $prevmonth == $month ) && ( $prevyear == $year ) ) } { # we are just resuming on the same day - probably dont need to do much #} else { # closelogfile openlogfile #} set state "running" gettime set currentStart [format $currentTimeFormat $hh $mm $ss] set currentEnd [format $currentTimeFormat $hh $mm $ss] } proc doabout {} { global version toplevel .aboutBox -class Dialog wm title .aboutBox "About taglog" wm iconname .aboutBox Dialog frame .aboutBox.top -relief raised -bd 1 pack .aboutBox.top -side top -fill both frame .aboutBox.bot -relief raised -bd 1 pack .aboutBox.bot -side bottom -fill both message .aboutBox.top.msg -width 4i -text \ "About Taglog: This is version $version Copyright 2019 John Lines \nTaglog is Free Software, released under the terms of the GNU Public License.\nSee https://github.com/JohnLines/taglog/wiki for the taglog home page" pack .aboutBox.top.msg -side right -expand 1 -fill both -padx 3m -pady 3m set oldFocus [focus] button .aboutBox.bot.button -text OK -command "destroy .aboutBox" pack .aboutBox.bot.button grab set .aboutBox focus .aboutBox } proc display_today_actions {} { global num_today_actions frame .actions getactiveactions for { set i 1 } { $i <= $num_today_actions } { incr i } { frame .actions.a$i menu_create .actions.a$i.id [mc Action]$i actreminder 0 actAct menu_setText .actions.a$i.title entry .actions.a$i.title -width 40 -textvariable actionTitle($i) pack .actions.a$i.id .actions.a$i.title -in .actions.a$i -side left pack .actions.a$i -in .actions } pack .actions } proc setupdisplay {} { global activities display_prevday activeactions global allcontacts global num_today_actions history_win_depth current_win_depth global version global month year global debug global isAndroid set winwid 60 #if {[winfo screenmmwidth .] > 100 } { set winwid 30 } if { $isAndroid } { set winwid 30 } # # Set up basic display structure # frame .mBar -relief raised -bd 2 pack .mBar -side top -fill x # Create menu buttons and menus menubutton .mBar.file -text [mc File] -underline 0 -menu .mBar.file.m menu .mBar.file.m .mBar.file.m add command -label [mc "Open..."] -underline 0 -command logSelect .mBar.file.m add command -label [mc "Exit"] -underline 0 -command doexit .mBar.file.m add command -label [mc "Quit"] -underline 0 -command doquit .mBar.file.m add command -label [mc "Add/Edit Log"] -underline 0 \ -command "logEdit_selDay .lgedit" .mBar.file.m add command -label [mc "Today's Summary"] -underline 0 -command dosummary .mBar.file.m add command -label [mc "This month's Summary"] -command "doMonthSummary $month $year" .mBar.file.m add command -label [mc "This year's Summary"] -command "doYearSummary \"\"" .mBar.file.m add command -label [mc "Other month's Summary"] -command "pickMonth doMonthSummary" .mBar.file.m add command -label [mc "Other year's Summary..."] -command "pickYear doYearSummary" .mBar.file.m add command -label [mc "Pause"] -command dopause .mBar.file.m add command -label [mc "Resume"] -command doresume # .mBar.file.m add cascade -label "Refresh" -menu .mBar.file.m.r #menu .mBar.file.m.r #.mBar.file.m.r add command -label "Log" -command refreshLog #.mBar.file.m.r add command -label "Actions" -command refreshActions .mBar.file.m add command -label [mc Preferences] -command editPrefs if { $debug } { .mBar.file.m add command -label [mc "Debug"] -command debugWindow } .mBar.file.m add separator .mBar.file.m add command -label [mc "Help"] -command "taghelp file" menubutton .mBar.actions -text [mc Actions] -underline 0 -menu .mBar.actions.m menu .mBar.actions.m .mBar.actions.m add command -label [mc "Add..."] -underline 0 -command "actionInputWindow input" .mBar.actions.m add command -label [mc "View"] -underline 0 -command { actSelect displayActions } .mBar.actions.m add command -label [mc "History"] -underline 0 -command { actSelect displayHistory } .mBar.actions.m add command -label [mc "Complete"] -command { doNewState Active Completed } .mBar.actions.m add command -label [mc "Activate"] -command { doNewState Pending Active } .mBar.actions.m add command -label [mc "Abort Active"] -command { doNewState Active Aborted } .mBar.actions.m add command -label [mc "Abort Pending"] -command { doNewState Pending Aborted } .mBar.actions.m add command -label [mc "Reactivate"] -command { doNewState Completed Active } .mBar.actions.m add cascade -label [mc "Extra..."] -menu .mBar.actions.m.e menu .mBar.actions.m.e .mBar.actions.m.e add command -label [mc "Refresh Active"] -command setactionsmenu .mBar.actions.m.e add command -label [mc "Active Time Blocked"] -command activate_timeblocked .mBar.actions.m.e add command -label [mc "Archive Old Actions"] -command archiveOldActions .mBar.actions.m.e add command -label [mc "Update All Subtasks"] -command Update_all_subtasks .mBar.actions.m.e add command -label [mc "Display Periodic Actions"] -command displayPeriodicActions .mBar.actions.m add separator .mBar.actions.m add command -label [mc "Help"] -command "taghelp actions" menubutton .mBar.projects -text [mc Projects] -underline 0 -menu .mBar.projects.m menu .mBar.projects.m .mBar.projects.m add command -label [mc Add] -underline 0 -command doAddProject .mBar.projects.m add command -label [mc Edit] -underline 0 -command doEditProjects .mBar.projects.m add command -label [mc "Update"] -underline 0 -command doUpdateProjects -state disabled if { [can_get_httprojects] } { .mBar.projects.m entryconfigure 3 -state normal } .mBar.projects.m add command -label [mc "View"] -underline 0 -command doShowProjects .mBar.projects.m add command -label [mc "Archive"] -underline 0 -command doArchiveProjects .mBar.projects.m add separator .mBar.projects.m add command -label [mc "Help"] -command "taghelp projects" menubutton .mBar.reports -text [mc Reports] -underline 0 -menu .mBar.reports.m menu .mBar.reports.m .mBar.reports.m add command -label [mc "Weekly time bookings by project"] -underline 0 -command doWeeklyTimeBookingsByProject .mBar.reports.m add command -label [mc "Time by activity"] -command doTimeByActivity .mBar.reports.m add command -label [mc "Total time for a project"] -command doTotalTimeForProject .mBar.reports.m add command -label [mc "Project Progress Report"] -command doProjectProgressReport .mBar.reports.m add command -label [mc "Interruptions Report"] -command doInterruptionsReport .mBar.reports.m add command -label [mc "Active and Pending Actions"] -command doActiveAndPendingReport .mBar.reports.m add command -label [mc "Active Actions Review"] -command doActiveActionsReview .mBar.reports.m add separator .mBar.reports.m add command -label [mc "Help"] -command "taghelp reports" menubutton .mBar.contacts -text [mc Contacts] -underline 0 -menu .mBar.contacts.m menu .mBar.contacts.m .mBar.contacts.m add command -label [mc Add] -underline 0 -command "addContact input" .mBar.contacts.m add command -label [mc View] -underline 0 -command viewContacts .mBar.contacts.m add command -label [mc Import] -underline 0 -command importContacts .mBar.contacts.m add separator .mBar.contacts.m add command -label [mc "Help"] -command "taghelp contacts" menubutton .mBar.help -text [mc "Help"] -menu .mBar.help.m menu .mBar.help.m .mBar.help.m add command -label [mc "About"] -command "taghelp About $version" .mBar.help.m add command -label [mc "Introduction"] -command "taghelp introduction" .mBar.help.m add cascade -label [mc "Hints"] -menu .mBar.help.m.h menu .mBar.help.m.h .mBar.help.m.h add cascade -label [mc Activity] -menu .mBar.help.m.h.a menu .mBar.help.m.h.a .mBar.help.m.h.a add command -label [mc "meeting-preparation"] -command "taghelp hint_activity_pre_meeting" .mBar.help.m.h.a add command -label [mc "meeting"] -command "taghelp hint_activity_meeting" .mBar.help.m.h.a add command -label [mc "email"] -command "taghelp hint_activity_email" .mBar.help.m.h add cascade -label [mc "Problem"] -menu .mBar.help.m.h.p menu .mBar.help.m.h.p .mBar.help.m.h.p add command -label [mc "Actions overrun"] -command "taghelp hint_problem_actions_overrun" .mBar.help.m.h.p add command -label [mc "Actions not completed"] -command "taghelp hint_problem_actions_not_completed" .mBar.help.m.h.p add command -label [mc "Interruptions"] -command "taghelp hint_problem_interruptions" .mBar.help.m.h add separator .mBar.help.m.h add command -label [mc "Help"] -command "taghelp hint_help" # Normally only show this if debug is enabled, but for now show it all the time .mBar.help.m add command -label [mc "Debug"] -command "showDebug" pack .mBar.file .mBar.actions .mBar.projects .mBar.reports .mBar.contacts -side left pack .mBar.help -side right tk_menuBar .mBar .mBar.file if { $num_today_actions != 0 } { display_today_actions } if { $display_prevday } { frame .prevday text .prevday.body -rel sunk -width $winwid -height 15 -wrap word -yscrollcommand ".prevday.sb set" scrollbar .prevday.sb -rel sunk -command ".prevday.body yview" pack .prevday.body -side right -in .prevday -fill both -expand 1 pack .prevday.sb -side right -fill y -in .prevday pack .prevday -fill both -expand 1 } frame .preventries text .preventries.body -rel sunk -width $winwid -height $history_win_depth -wrap word -yscrollcommand ".preventries.sb set" -state disabled scrollbar .preventries.sb -rel sunk -command ".preventries.body yview" pack .preventries.body -side right -in .preventries -fill both -expand 1 pack .preventries.sb -side right -fill y -in .preventries pack .preventries -fill x frame .currentbar button .currentbar.nextbutton -text [mc "Next"] -command { donext "" } bind .currentbar.nextbutton {.currentbar.nextbutton.m post [winfo pointerx .currentbar] [winfo pointery .currentbar]} menu .currentbar.nextbutton.m .currentbar.nextbutton.m add command -label "--" -command "set currentActivity \"\"" for { set i 0 } {$i < [llength $activities]} { incr i} { .currentbar.nextbutton.m add command -label [lindex $activities $i ] \ -command "donext [lindex $activities $i]" } button .currentbar.startbutton -text [mc "Start"] -command adjustStart entry .currentbar.starttime -textvariable currentStart -width 6 menubutton .currentbar.endbutton -text [mc "End "] -menu .currentbar.endbutton.m -relief raised menu .currentbar.endbutton.m .currentbar.endbutton.m add command -label [mc Complete] -command actCompleteCurrent .currentbar.endbutton.m add command -label [mc Abort] -command actAbortCurrent # .currentbar.endbutton.m add command -label "Complete and NextSequence" .currentbar.endbutton.m add cascade -label [mc Contact] -menu .currentbar.endbutton.m.contact menu .currentbar.endbutton.m.contact setcontactsmenu .currentbar.endbutton.m add cascade -label Rate -menu .currentbar.endbutton.m.rate menu .currentbar.endbutton.m.rate .currentbar.endbutton.m.rate add command -label "--" -command "set rate \"\"" .currentbar.endbutton.m.rate add command -label Overtime -command "set rate Overtime" .currentbar.endbutton.m add command -label [mc Help] -command "taghelp endbutton" entry .currentbar.endtime -textvariable currentEnd -width 6 set mWid [menu_create .currentbar.project [mc "Project"] "" 1 proj menu_setText .currentbar.projectentry] $mWid add cascade -label [mc Activity] -menu $mWid.menu menu_create $mWid [mc "Activity"] "" 1 acties menu_setText .currentbar.activityentry entry .currentbar.projectentry -textvariable currentProject \ -width [taglog_getMaxMembLen proj 10 18] entry .currentbar.activityentry -textvariable currentActivity \ -width [taglog_getMaxMembLen acties 10 18] pack .currentbar.nextbutton .currentbar.startbutton .currentbar.starttime .currentbar.endbutton .currentbar.endtime .currentbar.project .currentbar.projectentry .currentbar.activityentry -side left pack .currentbar frame .actionbar frame .actionbar.stack button .actionbar.stack.interrupt -text "!" -command "stack_push \"!\"" button .actionbar.stack.push -text "+" -command "stack_push \"+\"" button .actionbar.stack.pop -text "-" -command stack_pop -state disabled pack .actionbar.stack.interrupt .actionbar.stack.push .actionbar.stack.pop -side left -in .actionbar.stack pack .actionbar.stack -side left -anchor w menubutton .actionbar.action -text [mc "Action"] -menu .actionbar.action.m bind .actionbar.action {editaction $currentAction} menu .actionbar.action.m # Add the active actions to the actions menubar. # activeactions is a list of triples of actionID,action title and project, set up # by getactiveactions setactionsmenu entry .actionbar.actionentry -textvariable currentActionTitle -width 40 pack .actionbar.action .actionbar.actionentry -side left pack .actionbar frame .description frame .description.textf text .description.body -rel sunk -width $winwid -height $current_win_depth \ -wrap word -yscrollcommand ".description.sb set" scrollbar .description.sb -rel sunk -command ".description.body yview" pack .description.body -side right -in .description.textf -expand 1 -fill both pack .description.sb -side right -fill y -in .description.textf pack .description.textf -fill both -expand 1 pack .description -fill both -expand 1 } proc iconify_mainwin {} { # Make main window an icon wm iconify . } # Update the displayed end time every minute for the current record proc minuteTimer {} { # This is run once a minute to update the screen # Set the displayed end time to the current time global hh mm ss currentEnd state currentProject projTimes projTimesTotal projTimesTotalNonBreaks global currentTimeFormat if { $state == "running" } { set oldmm $mm gettime set currentEnd [format $currentTimeFormat $hh $mm $ss] if {$oldmm != $mm } { if { $currentProject == "" } { set cproj "unknown" } else { set cproj $currentProject } inctime projTimes($cproj) 60 inctime projTimesTotal 60 if { ! [isbreak $cproj ] } { inctime projTimesTotalNonBreaks 60 } } } after 30000 { minuteTimer } } proc handleMidnight {} { global logentries currentStart # Called at midnight to switch to a new log file #puts "handleMidnight called" donext "" writelog -writeactions writeallact closelogfile set logentries "" fillpreventries .preventries.body after 2000 openlogfile set currentStart "00:00:00" } proc setupHandleMidnight {} { set timeToMidnight [expr { [clock scan "23:59:59" ] - [clock seconds]} ] set timeToMidnight [ expr {$timeToMidnight * 1000 }] after $timeToMidnight { handleMidnight } } proc debugWindow {} { toplevel .debugwin wm title .debugwin "Enter tcl commands" frame .debugwin.main entry .debugwin.main.c -textvariable debugCommand -width 60 button .debugwin.main.go -text Exec -command doDebugCommand pack .debugwin.main.c .debugwin.main.go -in .debugwin.main -side left pack .debugwin.main } proc doDebugCommand {} { global debugCommand eval $debugCommand } proc showDebug {} { global tcl_platform set info "Debug information\n" append info "Platform " $tcl_platform(platform) "\nUser " $tcl_platform(user) # These Variables are only available on Android if { [catch {package require Borg}]} { # Borg package not available set android_something "not available" # puts "Not on android" } else { append info "\nAndroid user data directory " [borg osenvironment datadir] append info "\nAndroid displaymetrics " [borg displaymetrics] } if { [info commands sdltk] ne "" } { append info "\nRunning on android " [sdltk android] append info "\nMaxroot width " [lindex [sdltk maxroot] 0] " height " [lindex [sdltk maxroot] 1] append info "\nroot width " [lindex [sdltk root] 0] " height " [lindex [sdltk root] 1] append info "\nsdltk root size width " [lindex [sdltk root] 0] " height " [lindex [sdltk root] 1] } toplevel .showdebug wm title .showdebug "Debugging information" append info "\nGeometry of showdebug " [winfo geometry .showdebug] append info "\nGeometry of . " [winfo geometry .] append info "\nScreen name " [winfo screen .showdebug] append info "\nScreen width " [winfo screenwidth .showdebug] " height " [winfo screenheight .showdebug] append info "\nScreen mm width " [winfo screenmmwidth .] " height " [winfo screenmmwidth .] frame .showdebug.main -width 200 message .showdebug.info -text $info pack .showdebug.info .showdebug.main } taglog-0.2.6/src/logEdit.tcl0000644000175000017500000010116113534701742014342 0ustar johnjohnpackage provide logEdit 0.1 # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # This file contains functions for editing of log entries # # The global variable "LGL_Shell" is only used in this file # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # ---------------------- logEdit_selDay --------------------------------- # creates shell to select the date of the log file to be input/edited # if the shell already exists it will be raised # # win name of the shell to be created proc logEdit_selDay {win} { global CALIMAGE global dateformat_view if {[winfo exists $win]} { # popup the shell if it exists raise $win return } toplevel $win -class "logEdit" wm title $win [mc "Log edit"] label $win.lab1 -text "[mc {Input and editing of log entries}]\n" label $win.lab2 -text "[mc {Please select the date of log}]\n[mc {entries to be input or edited}]\n" pack $win.lab1 $win.lab2 -side top frame $win.date -borderwidth 10 entry $win.date.e -width 10 focus $win.date.e button $win.date.b -bitmap @$CALIMAGE -command \ "calUtil_open $win.date.e $dateformat_view logEdit_setCalCol {} led_calendar" pack $win.date.e $win.date.b -side left pack $win.date -side top frame $win.frm -relief sunken -borderwidth 2 button $win.frm.ok -text OK -width 7 \ -command "logEdit_selOk $win $win.date.e $dateformat_view" button $win.frm.cancel -text [mc Cancel] -width 7 -command "destroy $win" pack $win.frm.ok $win.frm.cancel -side left -fill x pack $win.frm -side top -expand 1 -fill x } # ---------------------- logEdit_selOk ---------------------------------- # INTERNAL USE ONLY # OK callback for the date selection, destroys the selection shell after # creation of the shell containing the log entries for one day # # win the date selection shell # eWin the entry widget containing the date string # dateFormat format of the date string in the entry widget # three formats are available: # DD/MM/YYYY (e.g. 24/01/2001 or 24/1/01) # MM/DD/YYYY (e.g. 01/24/2001 or 1/24/01) # YYYY-MM-DD (e.g. 2001-01-24 or 01-1-24) DEFAULT proc logEdit_selOk {win eWin dateFormat} { set date [string trim [$eWin get]] # check parameterinput if {$date == ""} { tk_messageBox -icon error -title [mc "Date selection"] -type ok \ -message [mc "No date selected"] return } if {[calUtil_parse $dateFormat $date] == ""} { tk_messageBox -icon error -title [mc "Date selection"] -type ok \ -message [mc "Invalid date format"] return } # create the shell containing the log entries for the selected day logEdit_dayShell $date $dateFormat # destroy the date selection shell destroy $win } # ---------------------- logEdit_dayShell ------------------------------- # creates an editing shell containing the log entries for one day # # date the shell will contain log entries for this day # default: the current day # dateFormat format of the date string in the entry widget # three formats are available: # DD/MM/YYYY (e.g. 24/01/2001 or 24/1/01) # MM/DD/YYYY (e.g. 01/24/2001 or 1/24/01) # YYYY-MM-DD (e.g. 2001-01-24 or 01-1-24) DEFAULT proc logEdit_dayShell {{date ""} {dateFormat "YYYY-MM-DD"}} { global LGL_Shell global rootdir if {$date == ""} { # set default date set date [clock format [clock seconds] -format "%Y-%m-%d"] } # parse/check the date string set dateStr [calUtil_parse $dateFormat $date] if {$dateStr == ""} return set mmddStr [lindex $dateStr 1][lindex $dateStr 2] set yyyyStr [lindex $dateStr 0] # this is an unique ID for the global array "LGL_Shell" set idx "$yyyyStr$mmddStr" # shell already opened? if {[array get LGL_Shell $idx-shell] != ""} { if {[winfo exists $LGL_Shell($idx-shell)]} { raise $idx-shell return } logEdit_unset $idx } set LGL_Shell($idx-file) $rootdir/log$yyyyStr/$mmddStr.tag set LGL_Shell($idx-shell) ".log$idx" set LGL_Shell($idx-date) "$date" # load the log entries into "LGL_Shell($idx-entries)" logEdit_loadFile $idx # build the shell logEdit_shell date $idx [mc "Editing of log file"] "[mc Day]: $date" \ "led_entList" } # ---------------------- logEdit_fileShell ------------------------------ # creates a shell containing a list of all log entries of a log file # # filenam full path name of the log file # pIdx index for "LGL_Shell" of the parent shell proc logEdit_fileShell {filename pIdx} { global LGL_Shell if {! [file exists $filename]} return # get a new name for the shell set i 0 while {[array get LGL_Shell F$i-shell] != ""} {incr i} set idx F$i set LGL_Shell($idx-sensWid) "" set LGL_Shell($idx-file) $filename set LGL_Shell($idx-shell) "$LGL_Shell($pIdx-shell).file$idx" set LGL_Shell($idx-pIdx) $pIdx # load entries off the file if {[logEdit_loadFile $idx] > 0} { # create the shell logEdit_shell file $idx [mc "Import of log entries"] \ "[mc File]: $filename" "led_impList" } else { logEdit_unset $idx tk_messageBox -icon warning -title "Import" -type ok \ -message "[mc {No entries found in file}] [file tail $filename]" } } # ---------------------- logEdit_shell ---------------------------------- # INTERNAL USE ONLY # creates a shell widget containing a list with log entries for # input, editing or import # # type the shell type: # file for import of log entries from a file # date for input and editing of log entries # idx unique identification used for "LGL_Shell" # title the shell title # header the top label in the shell # helpid a HELP-button is created which calls "taghelp helpid" proc logEdit_shell {type idx title header helpid} { global LGL_Shell global GL_tableFont # create a new shell set win $LGL_Shell($idx-shell) toplevel $win -class "logEdit" wm title $win $title wm protocol $win WM_DELETE_WINDOW "logEdit_unset $idx" label $win.date -text $header -relief groove -padx 5 -pady 3 pack $win.date -side top # list with log entries frame $win.body -relief sunken -borderwidth 2 frame $win.body.frm label $win.body.frm.lab -text " Start [mc {End }] [mc Project]" \ -font $GL_tableFont -anchor w -padx 2 listbox $win.body.frm.listw -height 20 -width 40 -selectmode extended \ -font $GL_tableFont -yscroll "$win.body.vscr set" -setgrid 1 bind $win.body.frm.listw <> "logEdit_setSens $idx" bind $win.body.frm.listw "logEdit_edit $idx" scrollbar $win.body.vscr -orient vertical -command "$win.body.frm.listw yview" pack $win.body.frm.lab -side top -fill x -expand 1 pack $win.body.frm.listw -side top -fill both -expand 1 set LGL_Shell($idx-listw) $win.body.frm.listw pack $win.body.frm -side left -fill both -expand 1 pack $win.body.vscr -side left -fill y if {$type == "date"} { # build popup menu for adjustment of time ranges logEdit_menu $win.body.frm.listw $idx # action buttons for editing of log entries set aButton [logEdit_eButtons $win.body $idx] pack $aButton -side left -fill y } pack $win.body -side top -fill both -expand 1 logEdit_fill $idx # control buttons frame $win.control -relief sunken -borderwidth 2 if {$type == "date"} { button $win.control.ok -text OK -width 10 \ -command "logEdit_shellOK $idx" pack $win.control.ok -side left -fill y -expand 1 } else { # import buttons logEdit_iButtons $win.control $idx } button $win.control.cancel -text [mc Cancel] -width 10 \ -command "logEdit_destroy $idx" button $win.control.help -text [mc Help] -width 10 \ -command "taghelp $helpid" pack $win.control.cancel $win.control.help \ -side left -fill y -expand 1 pack $win.control -side top -fill y -expand 1 } # ---------------------- logEdit_iButtons ------------------------------- # INTERNAL USE ONLY # creates additional buttons for the import # # parent the name of the parent widget of the buttons # idx unique identification used for "LGL_Shell" proc logEdit_iButtons {parent idx} { global LGL_Shell button $parent.impall -text [mc "Import all"] -width 10 \ -command "logEdit_impAll $idx" button $parent.impsel -text [mc "Import"] -width 10 \ -command "logEdit_impSel $idx" \ -state disabled pack $parent.impall $parent.impsel -side left -fill y -expand 1 set LGL_Shell($idx-sensWid) "$parent.impsel" } # ---------------------- logEdit_eButtons ------------------------------- # INTERNAL USE ONLY # creates additional buttons for the input and editing # # parent the name of the parent widget of the buttons # idx unique identification used for "LGL_Shell" proc logEdit_eButtons {parent idx} { global LGL_Shell # action buttons frame $parent.action button $parent.action.edit -text "[mc Edit]..." \ -command "logEdit_edit $idx" \ -state disabled button $parent.action.add -text [mc Add...] \ -command "logEdit_edShell $idx -1" button $parent.action.delete -text [mc Delete] \ -command "logEdit_delete $idx" \ -state disabled button $parent.action.import -text "[mc Import]..." \ -command "logEdit_impFile $idx" set LGL_Shell($idx-sensWid) "$parent.action.edit $parent.action.delete" pack $parent.action.edit \ $parent.action.add \ $parent.action.delete \ $parent.action.import \ -side top -fill x return $parent.action } # ---------------------- logEdit_setSens -------------------------------- # INTERNAL USE ONLY # changes the sensitivity of buttons which are only active if item(s) are # selected in the list of log entries # # idx unique identification used for "LGL_Shell" proc logEdit_setSens {idx} { global LGL_Shell if {[llength [$LGL_Shell($idx-listw) curselection]] > 0} { # item(s) selected, activate the button set status normal } else { # NO item selected, disable the button set status disabled } # loop over button widgets foreach wid $LGL_Shell($idx-sensWid) { if {[winfo exists $wid]} { $wid configure -state $status } } } # ---------------------- logEdit_edit ----------------------------------- # INTERNAL USE ONLY # callback function to start the editing of selected log entries # # idx unique identification used for "LGL_Shell" proc logEdit_edit idx { global LGL_Shell set sel [$LGL_Shell($idx-listw) curselection] # entries selected? if {$sel == ""} return # loop over selected items and create an edit shell for each item foreach ipos $sel { logEdit_edShell $idx $ipos } } # ---------------------- logEdit_delete --------------------------------- # INTERNAL USE ONLY # callback function to delete selected log entries # # idx unique identification used for "LGL_Shell" proc logEdit_delete idx { global LGL_Shell set sel [$LGL_Shell($idx-listw) curselection] # entries selected? if {$sel == ""} return set sel [lsort -integer -decreasing $sel] # loop over selected items and delete them foreach i $sel { set LGL_Shell($idx-entries) [lreplace $LGL_Shell($idx-entries) $i $i] } # update the display of the list logEdit_fill $idx # disable editing buttons logEdit_setSens $idx } # ---------------------- logEdit_impFile -------------------------------- # INTERNAL USE ONLY # callback function to select a file for import and to open the import shell # # idx unique identification used for "LGL_Shell" proc logEdit_impFile idx { # file types for the file selection set types { {"Tag Files" .tag} {"Text Files" .txt} {"All Files" *} } # file selection shell set filename [tk_getOpenFile -filetypes $types -title "Import of log file"] if {$filename != ""} { # file selected, open the import shell logEdit_fileShell $filename $idx } } # ---------------------- logEdit_impSel --------------------------------- # INTERNAL USE ONLY # callback function to add the selected entries to the parent list # # idx unique identification used for "LGL_Shell" proc logEdit_impSel idx { global LGL_Shell set sel [$LGL_Shell($idx-listw) curselection] # entries selected? if {$sel == ""} return set pIdx $LGL_Shell($idx-pIdx) # loop over selected items and add them to the parent list foreach i $sel { lappend LGL_Shell($pIdx-entries) [lindex $LGL_Shell($idx-entries) $i] } # sort the parent list set LGL_Shell($pIdx-entries) \ [lsort -command logEdit_sTimeSort $LGL_Shell($pIdx-entries)] # update the display of the list logEdit_fill $pIdx # destroy the selection shell logEdit_destroy $idx } # ---------------------- logEdit_impAll --------------------------------- # INTERNAL USE ONLY # callback function to add all entries to the parent list # # idx unique identification used for "LGL_Shell" proc logEdit_impAll idx { global LGL_Shell set pIdx $LGL_Shell($idx-pIdx) if {[info exists LGL_Shell($pIdx-entries)]} { append LGL_Shell($pIdx-entries) " " $LGL_Shell($idx-entries) } else { set LGL_Shell($pIdx-entries) $LGL_Shell($idx-entries) } # sort the parent list set LGL_Shell($pIdx-entries) \ [lsort -command logEdit_sTimeSort $LGL_Shell($pIdx-entries)] # update the display of the list logEdit_fill $pIdx # destroy the selection shell logEdit_destroy $idx } # ---------------------- logEdit_sTimeSort ------------------------------ # compare function used in "lsort" to sort log entries according to their # StartTime # # tagList1 first taglist # tagList2 second taglist # # return: 1 first StartTime greater than second StartTime # -1 first StartTime less than second StartTime # 0 first StartTime equal to second StartTime proc logEdit_sTimeSort {tagList1 tagList2} { set t1 [logEdit_tagVal $tagList1 StartTime] set t2 [logEdit_tagVal $tagList2 StartTime] if {[catch {set s1 [clock scan $t1]}]} {set s1 -99999} if {[catch {set s2 [clock scan $t2]}]} {set s2 -99999} if {$s1 > $s2} {return 1} if {$s1 < $s2} {return -1} return -1 } # ---------------------- logEdit_tagVal --------------------------------- # provides the value for a given tag out of a tag list # # tagList the tag list # tagName the name of the tag # # return: the value associated with the tag "tagName" # or "" if there is no tag with that name proc logEdit_tagVal {tagList tagName} { foreach i $tagList { if {[lindex $i 0] == $tagName} { return [lindex $i 1] } } return "" } # ---------------------- logEdit_tagSet --------------------------------- # sets/deletes the value for a given tag in a tag list, if the tag doesn't # exist, it will be appended to the list, an empty tag value will cause # the deletion of this tag # # tagList the tag list (MDOIFIED) # tagName the name of the tag # tagVal value to be set # endFlag termination flag for a multy line tag proc logEdit_tagSet {tagList tagName tagVal {endFlag ""}} { upvar $tagList tList set ipos [logEdit_tagPos $tList $tagName] if {$ipos < 0} { # new tag if {$tagVal != ""} { if {$endFlag == ""} { # normal tag lappend tList "$tagName [list $tagVal]" } else { # multy line tag lappend tList "$tagName [list $tagVal] $endFlag" } } } else { # modify existing tag if {$tagVal != ""} { # replace entry if {$endFlag == ""} { # normal tag set tList [lreplace $tList $ipos $ipos "$tagName [list $tagVal]"] } else { # multy line tag set tList \ [lreplace $tList $ipos $ipos "$tagName [list $tagVal] $endFlag"] } } else { # delete entry set tList [lreplace $tList $ipos $ipos] } } } # ---------------------- logEdit_tagPos --------------------------------- # provides the position of a tag in a tag list # # tagList the tag list # tagName the name of the tag # # return: the position of the tag in the list # or -1 if not found proc logEdit_tagPos {tagList tagName} { set j 0 foreach i $tagList { if {[lindex $i 0] == $tagName} { return $j } incr j } return "-1" } # ---------------------- logEdit_loadFile ------------------------------- # INTERNAL USE ONLY # reads a log file and fills "LGL_Shell($idx-entries)" (the list of taglists) # # idx unique identification used for "LGL_Shell" # # return: number of tag lists in "LGL_Shell($idx-entries)" proc logEdit_loadFile idx { global LGL_Shell # read the tag file set entries [tag readfile $LGL_Shell($idx-file)] # Seperate out the header record set hdr [lindex $entries 0] # Check that it is a header if { [lindex [lindex $hdr 0] 0] == "Tag-worklog-version" } { # preserve the header set LGL_Shell($idx-header) $hdr } set count 0 if {$entries != ""} { set defSec [clock scan "00:00:00"] # loop over tag lists and select only tag lists which contain the # tag "Id" foreach tagList $entries { if {[string compare [logEdit_tagVal $tagList Id] ""]} { foreach i "StartTime EndTime" { # replace invalid times by "00:00:00" set xTime [logEdit_tagVal $tagList $i] if {$xTime == ""} {set xTime "00:00:00"} if {[catch {set sec [clock scan $xTime]}]} {set sec $defSec} set xTime [clock format $sec -format "%H:%M:%S"] logEdit_tagSet tagList $i $xTime } lappend entr $tagList incr count } } if {$count > 0} { # sort the list according to the StartTime set LGL_Shell($idx-entries) [lsort -command logEdit_sTimeSort $entr] } } return $count } # ---------------------- logEdit_fill ----------------------------------- # INTERNAL USE ONLY # fills a list widget with log entries (StartTime, EndTime and project name) # # idx unique identification used for "LGL_Shell" proc logEdit_fill idx { global LGL_Shell if {[info tclversion] >= 8.3} { # colors for list entries possible set colAllow 1 } else { set colAllow 0 } set listW $LGL_Shell($idx-listw) # unset error flags catch "unset LGL_Shell($idx-errOv)" catch "unset LGL_Shell($idx-errIn)" # delete old list $listW delete 0 end logEdit_setSens $idx if {! [info exists LGL_Shell($idx-entries)]} return set lastEnd "00:00:00" # loop over entries and create a list item foreach tagList $LGL_Shell($idx-entries) { set sTime [logEdit_tagVal $tagList StartTime] set eTime [logEdit_tagVal $tagList EndTime] set proj [logEdit_tagVal $tagList Project] if {$proj == ""} {set proj [mc "unknown"]} set errFlg "" if {$sTime < $lastEnd} { # overlapping time range set errFlg ">" set color orange set LGL_Shell($idx-errOv) 1 } if {$sTime > $eTime} { # StartTime is greater than the EndTime set errFlg "!" set lastEnd $sTime set color red set LGL_Shell($idx-errIn) 1 } else { set lastEnd $eTime } # add to the list widget $listW insert end \ [format "%-2.2s %8.8s %8.8s %s" $errFlg $sTime $eTime $proj] if {$errFlg != "" && $colAllow} { $listW itemconfigure end -background $color } } } # ---------------------- logEdit_destroy -------------------------------- # INTERNAL USE ONLY # un-sets the members of the array "LGL_Shell" associated with a list shell # and destroys it # # idx unique identification used for "LGL_Shell" proc logEdit_destroy idx { global LGL_Shell set win $LGL_Shell($idx-shell) logEdit_unset $idx destroy $win } # ---------------------- logEdit_unset ---------------------------------- # INTERNAL USE ONLY # un-sets the members of the array "LGL_Shell" associated with a list shell # # idx unique identification used for "LGL_Shell" proc logEdit_unset idx { global LGL_Shell foreach i [array names "$idx-*"] { unset LGL_Shell($i) } # only for higher tcl version #array unset LGL_Shell "$idx-*" } # ---------------------- logEdit_edShell -------------------------------- # INTERNAL USE ONLY # creates a shell for input or editing of one log entry # # idx unique identification used for "LGL_Shell" # ipos the position of the entry in the list of olog entries proc logEdit_edShell {idx ipos} { global LGL_Shell set win $LGL_Shell($idx-shell).ed$ipos if {[winfo exists $win]} { raise $win return } toplevel $win -class "logEdit" if {$ipos > -1} { # edit existing entry wm title $win [mc "Edit log entry"] set helpid "led_ediEnt" set tagList [lindex $LGL_Shell($idx-entries) $ipos] } else { # add a new entry wm title $win [mc "Add a new entry"] set helpid "led_newEnt" if {[info exists LGL_Shell($idx-entries)]} { set tagList [lindex $LGL_Shell($idx-entries) $ipos] } else { set tagList "" } } label $win.lab -text "\n$LGL_Shell($idx-date)\n" pack $win.lab -side top frame $win.body -relief sunken -borderwidth 2 set irow 0 # loop over the items of a log entry and create the widgets # one member of the following list has the following members: # button label, tag name, menu list, switch for menu list, helpId foreach lst \ "{Id Id 0 logedit_id} {\"[mc {Start Time}]\" StartTime 0 logedit_start} {\"[mc {End Time}]\" EndTime 0 logedit_end} {[mc Project] Project projAll logedit_project} {Rate Rate 0 logedit_rate} {[mc Action] Action 0 logedit_action} {[list [mc {ActionTitle}]] ActionTitle 0 logedit_actiontitle} {[mc Activity] Activity acties logedit_activity} {[mc Contact] Contact cont logedit_contact}" { set lab [lindex $lst 0] set i [lindex $lst 1] set ind [lindex $lst 2] set helpId [lindex $lst 3] set blankSw 0 if {"$ind" != "0"} {set blankSw 1} menu_create $win.body.l$i $lab $helpId $blankSw $ind \ menu_setText $win.body.e$i grid $win.body.l$i -row $irow -column 0 -sticky e entry $win.body.e$i -width 15 lappend winList "$i $win.body.e$i" grid $win.body.e$i -row $irow -column 1 -sticky w if {$ipos > -1} { $win.body.e$i insert 0 [logEdit_tagVal $tagList $i] } incr irow } menu_create $win.body.lDescription [mc Description] logedit_description frame $win.body.frm text $win.body.frm.txt -height 5 -width 40 \ -yscroll "$win.body.frm.vscr set" lappend winList "Description $win.body.frm.txt" scrollbar $win.body.frm.vscr -orient vertical \ -command "$win.body.frm.txt yview" pack $win.body.frm.txt -side left -fill both -expand 1 if {$ipos > -1} { $win.body.frm.txt insert 1.0 [logEdit_tagVal $tagList Description] } else { # create a new Id $win.body.eId insert 0 \ [clock format [clock seconds] -format %Y%m%d%H%M%S] } grid $win.body.lDescription -row $irow -column 0 -sticky ensw pack $win.body.frm.vscr -side left -fill y -expand 1 grid $win.body.frm -row $irow -column 1 -sticky nsew pack $win.body -side top -fill both -expand 1 frame $win.control -relief sunken -borderwidth 2 button $win.control.ok -text OK -width 10 \ -command "logEdit_editOK $idx $win [list $tagList] [list $winList]" button $win.control.cancel -text [mc Cancel] -width 10 \ -command "destroy $win" button $win.control.help -text [mc Help] -width 10 \ -command "taghelp $helpid" pack $win.control.ok $win.control.cancel $win.control.help \ -side left -fill x pack $win.control -side top } # ---------------------- logEdit_menu ----------------------------------- # INTERNAL USE ONLY # creates a menu with buttons to adjust times # # parent the parent widget of the menu # idx unique identification used for "LGL_Shell" proc logEdit_menu {parent idx} { set menuW $parent.menu menu $menuW -tearoff False $menuW add command -label "Adjust to previous EndTime" \ -command "logEdit_adjust -1 $idx" $menuW add command -label "Adjust to following Startime" \ -command "logEdit_adjust 1 $idx" #...popup the menu with mouse button 3 #bind $parent "tk_popup $menuW %X %Y" bind $parent "logEdit_popup $parent $menuW %X %Y $idx" } # ---------------------- logEdit_popup ---------------------------------- # INTERNAL USE ONLY # pops up the menu for time adjustment # # listW list widget, it is used to check which entry is selected # menuW the menu widget # X x-coordinate of the cursor position # Y x-coordinate of the cursor position # idx unique identification used for "LGL_Shell" proc logEdit_popup {listW menuW X Y idx} { global LGL_Shell if {[array get LGL_Shell $idx-entries] == ""} return # last index in the list set maxPos [expr [llength $LGL_Shell($idx-entries)] - 1] if {$maxPos < 0} return # get list entry which is closest to the y-position of the cursor set listPos [$listW nearest [expr $Y - [winfo rooty $listW]]] # de-select all entries in the list $listW selection clear 0 end # select entry at opsition"listPos" $listW selection set $listPos logEdit_setSens $idx if {$listPos == 0} { # selected entry is the first in the list, # adjustment to prev. EndTime not possible $menuW entryconfigure 0 -state disabled } else { $menuW entryconfigure 0 -state normal } if {$listPos == $maxPos} { # selected entry is the last in the list, # adjustment to next StartTime not possible $menuW entryconfigure 1 -state disabled } else { $menuW entryconfigure 1 -state normal } #popup the menu tk_popup $menuW $X $Y } # ---------------------- logEdit_adjust --------------------------------- # INTERNAL USE ONLY # does the adjustment of times # # adjSw offset from the selected position, the time will be adjusted # to the time of the entry with that offset # idx unique identification used for "LGL_Shell" proc logEdit_adjust {adjSw idx} { global LGL_Shell set iAct [$LGL_Shell($idx-listw) curselection] set entries $LGL_Shell($idx-entries) if {[llength $iAct] != 1} return set actEnt [lindex $entries $iAct] set ipos [expr $iAct + $adjSw] if {$ipos < 0 || $ipos >= [llength $entries]} return set setEnt [lindex $entries $ipos] if {$adjSw == -1} { # source entry = previous entry set tgTag StartTime set srTag EndTime } else { # source entry = following entry set tgTag EndTime set srTag StartTime } set ipos [logEdit_tagPos $actEnt $tgTag] if {$ipos > -1} { # get the time from the source entry set time [logEdit_tagVal $setEnt $srTag] # replace in target tag set actEnt [lreplace $actEnt $ipos $ipos "$tgTag $time"] # replace in target entry set LGL_Shell($idx-entries) [lreplace $entries $iAct $iAct $actEnt] logEdit_fill $idx } } # ---------------------- logEdit_editOK --------------------------------- # INTERNAL USE ONLY # OK callback for the input/editing of a log entry # # idx unique identification used for "LGL_Shell" # shell name of the editing shell # tagList the tag list of the log entry # winList list of pairs {tagName widget}, the "widget"s contain # the edited values proc logEdit_editOK {idx shell tagList winList} { global LGL_Shell # get the Id of the edited log entry set tagVal [logEdit_tagVal $tagList Id] set ipos -1 set j 0 # find the position of the log entry in the list of entries if {[info exists LGL_Shell($idx-entries)]} { foreach i $LGL_Shell($idx-entries) { if {$tagVal == [logEdit_tagVal $i Id]} { set ipos $j break } incr j } } set j [logEdit_tagPos $tagList "End"] if {$j > 0} { # remove "End" tag set tagList [lreplace $tagList $j $j] } foreach i $winList { set tagName [lindex $i 0] set win [lindex $i 1] if {[winfo class $win] == "Entry"} { # for entry widgets set tagVal [$win get] } else { # for text widgets set tagVal [$win get 1.0 end] # remove trailing "newlines" while {[string index $tagVal end] == "\n"} { set iEnd [expr [string length $tagVal] - 2] if {$iEnd >= 0} { set tagVal [string range $tagVal 0 $iEnd] } else { set tagVal "" } } } if {$tagName == "StartTime" || $tagName == "EndTime"} { # in case of times, check the format if {[logEdit_chkSetTime tagVal $tagName]} return if {$tagName == "StartTime"} { set sTime $tagVal } else { set eTime $tagVal } } if {$tagName == "Description"} { # update the tag value logEdit_tagSet tagList $tagName $tagVal "END_D" } else { # update the tag value logEdit_tagSet tagList $tagName $tagVal } } lappend tagList "End {}" # check time range if {$sTime > $eTime} { tk_messageBox -icon error -title [mc "Invalid date range"] -type ok \ -message [mc "The StartTime is greater\nthan the EndTime"] return } if {$ipos < 0} { # new entry, append it lappend LGL_Shell($idx-entries) $tagList } else { # replace the existing entry set LGL_Shell($idx-entries) \ [lreplace $LGL_Shell($idx-entries) $ipos $ipos $tagList] } # sort the entries according to the StartTime set LGL_Shell($idx-entries) \ [lsort -command logEdit_sTimeSort $LGL_Shell($idx-entries)] logEdit_fill $idx destroy $shell } # ---------------------- logEdit_chkSetTime ----------------------------- # checks a string containing a time value and re-formats it # # tStr time string (MODIFIED) # tagName name of the tag to be checked # # return: 0 OK # 1 invalid time proc logEdit_chkSetTime {tStr tagName} { upvar $tStr timeStr if {$timeStr == "" } { tk_messageBox -icon error -title [mc "Invalid date"] -type ok \ -message "[mc {Please enter a value for}] $tagName" return 1 } if {[catch {set sec [clock scan $timeStr]}]} { tk_messageBox -icon error -title [mc "Invalid date"] -type ok \ -message "'$timeStr' [{is not a valid\ntime value for}] $tagName" return 1 } set timeStr [clock format $sec -format "%H:%M:%S"] return 0 } # ---------------------- logEdit_shellOK -------------------------------- # INTERNAL USE ONLY # OK callbak for the editing of log entries of one day # # idx unique identification used for "LGL_Shell" proc logEdit_shellOK {idx} { global LGL_Shell global rootdir global logfilename global prevdayfilename display_prevday set msg "" if {[info exists LGL_Shell($idx-errOv)]} { if {[info exists LGL_Shell($idx-errIn)]} { set msg [mc "There are overlapping (marked with '>')\nand inconsistent (marked with '!') time ranges."] } else { set msg [mc "There are overlapping time ranges (marked with '>')."] } } elseif {[info exists LGL_Shell($idx-errIn)]} { set msg [mc "There are inconsistent time ranges (marked with '!')."] } if {$msg != "" && \ [tk_messageBox -icon error -title "Log edit" -type yesno -default no \ -message "$msg\n\n[mc {Do you want to save?}]"] == "no"} { return } # get the date set yy [string range $idx 0 3] set mm [string range $idx 4 5] set dd [string range $idx 6 7] set weekday [clock format [clock scan "$mm/$dd/$yy"] -format "%A"] # build the file name from the date information set fName "$mm$dd.tag" set dName "$rootdir/log$yy" set fullName $dName/$fName if {$logfilename == $fullName} { # close the log file of the actual day closelogfile } # open the log file and write the header set logfile [openNewLogFile $fullName] close $logfile if {[info exists LGL_Shell($idx-entries)]} { # output the entries to the log file if {[info exists LGL_Shell($idx-header)]} { set entries "" lappend entries $LGL_Shell($idx-header) tag writefile $fullName $entries } tag writefile $fullName $LGL_Shell($idx-entries) "a" } if {$logfilename == $fullName} { if {[winfo exists .preventries.body]} { # update the display of previous entries readlogentries fillpreventries .preventries.body } # open the log file of the actual day openlogfile } if { $display_prevday && $prevdayfilename == $fullName} { # update the display of entries of the previous day fillprevday } logEdit_destroy $idx } # ---------------------- logEdit_setCalCol ------------------------------ # checks wether a log file exists for a given date # this function is used as argument in "calUtil_open" # # year the year, four digits # month the month, 1,2,...,11,12 # day the day, 1,2,...30,31 # data unused # # return: "yellow" if the file exists, otherwise "" proc logEdit_setCalCol {year month day data} { global rootdir set fName [format "%s/log%s/%02d%02d.tag" $rootdir $year $month $day] if {[file exists $fName]} {return yellow} return "" } taglog-0.2.6/src/taglog_contact.tcl0000644000175000017500000004531613534701742015754 0ustar johnjohn# # taglog_contact.tcl - contact management routines for taglog # Copyright John Lines (john+taglog@paladyn.org) December 2000 # # This program is released under the terms of the GNU Public Licence # package provide taglog_contact 0.1 proc get_contact_input_fields { args } { global contactsfilename allcontacts allcontactsstate global addcontact_id addcontact_forename addcontact_surname addcontact_email addcontact_phone addcontact_mobilephone addcontact_fax addcontact_organisation addcontact_type addcontact_note addcontact_title addcontact_address addcontact_short_id addcontact_postcode addcontact_country addcontact_web addcontact_ldap addcontact_default_as if { [llength $args] > 0 } { set endflag 0 } else { set endflag 1 } set thiscontact "" set thiscontact [tagappend $thiscontact Id $addcontact_id] set thiscontact [tagappend $thiscontact Forename $addcontact_forename] set thiscontact [tagappend $thiscontact Surname $addcontact_surname] set thiscontact [tagappend $thiscontact Title $addcontact_title] set thiscontact [tagappend $thiscontact Default-as $addcontact_default_as] set thiscontact [tagappend $thiscontact Email $addcontact_email] set thiscontact [tagappend $thiscontact Web $addcontact_web] set thiscontact [tagappend $thiscontact Ldap $addcontact_ldap] set thiscontact [tagappend $thiscontact Phone $addcontact_phone] set thiscontact [tagappend $thiscontact MobilePhone $addcontact_mobilephone] set thiscontact [tagappend $thiscontact Fax $addcontact_fax] set thiscontact [tagappend $thiscontact Address $addcontact_address END_D] set thiscontact [tagappend $thiscontact Postcode $addcontact_postcode] set thiscontact [tagappend $thiscontact Country $addcontact_country] set thiscontact [tagappend $thiscontact Organisation $addcontact_organisation] set thiscontact [tagappend $thiscontact Type $addcontact_type] set thiscontact [tagappend $thiscontact Note $addcontact_note END_D] set thiscontact [tagappend $thiscontact Short-id $addcontact_short_id] if { $endflag } { set endpair [list End ] lappend thiscontact $endpair } return $thiscontact } proc addcontactOK {} { global contactsfilename allcontacts allcontactsstate global addcontact_id addcontact_forename addcontact_surname addcontact_email addcontact_phone addcontact_mobilephone addcontact_fax addcontact_organisation addcontact_type addcontact_note addcontact_title addcontact_address addcontact_short_id addcontact_postcode addcontact_country addcontact_web addcontact_ldap addcontact_default_as getallcontacts set addcontact_note [string trim [.addcontact.note.e get 1.0 end]] set addcontact_address [string trim [.addcontact.address.e get 1.0 end]] set thiscontact [get_contact_input_fields ] lappend allcontacts $thiscontact set allcontactsstate modified writeallcontacts setcontactsmenu destroy .addcontact } proc editcontactOK {} { global addcontact_note addcontact_address global allcontacts allcontactsstate set thiscontact "" set addcontact_note [string trim [.addcontact.note.e get 1.0 end]] set addcontact_address [string trim [.addcontact.address.e get 1.0 end]] set thiscontact [get_contact_input_fields -noend] foreach field [array names editcontact_fields] { set thiscontact [tagappend $thiscontact [index2fieldname $field] $editcontact_fields($field)]] } set endpair [list End ] lappend thiscontact $endpair set allcontactststate modified foreach item $thiscontact { if { [lindex $item 0] == "Id" } { set thisid [lindex $item 1] } } set test [ list Id "==" $thisid ] set idx 0 foreach entry $allcontacts { if [ tag matchcond $entry $test] { set allcontacts [lreplace $allcontacts $idx $idx $thiscontact] } incr idx } set allcontactsstate modified writeallcontacts setcontactsmenu destroy .addcontact } proc addContact { mode } { global contactsfilename contacttypes global addcontact_id addcontact_forename addcontact_surname addcontact_email addcontact_phone addcontact_mobilephone addcontact_fax addcontact_organisation addcontact_type addcontact_note addcontact_title addcontact_address addcontact_short_id addcontact_postcode addcontact_country addcontact_web addcontact_ldap addcontact_default_as proc addcontactfield { name label width mode } { global addcontact_$name if { $mode == "input" } { set addcontact_$name "" } frame .addcontact.$name menubutton .addcontact.$name.l -text "$label" -menu .addcontact.$name.l.m menu .addcontact.$name.l.m .addcontact.$name.l.m add command -label [mc "Help"] -command "taghelp addcontact_$name" entry .addcontact.$name.v -textvariable addcontact_$name -width $width pack .addcontact.$name.l .addcontact.$name.v -side left -in .addcontact.$name pack .addcontact.$name } toplevel .addcontact if { $mode == "input" } { wm title .addcontact [mc "Input a contact"] } else { wm title .addcontact "[mc {Edit contact}] $addcontact_id" } addcontactfield id Id 20 $mode addcontactfield forename [mc Forename] 20 $mode addcontactfield surname [mc Surname] 20 $mode if { $mode == "input" } { set addcontact_title "" } frame .addcontact.title menubutton .addcontact.title.l -text [mc Title] -menu .addcontact.title.l.m menu .addcontact.title.l.m .addcontact.title.l.m add command -label "--" -command "set addcontact_title \"\"" .addcontact.title.l.m add command -label [mc "Mr"] -command "set addcontact_title Mr" .addcontact.title.l.m add command -label [mc "Mrs"] -command "set addcontact_title Mrs" .addcontact.title.l.m add command -label [mc "Ms"] -command "set addcontact_title Ms" .addcontact.title.l.m add command -label "Dr" -command "set addcontact_title Dr" .addcontact.title.l.m add separator .addcontact.title.l.m add command -label [mc "Help"] -command "taghelp addcontact_title" entry .addcontact.title.v -textvariable addcontact_title -width 10 pack .addcontact.title.l .addcontact.title.v -side left -in .addcontact.title pack .addcontact.title addcontactfield default_as [mc "Default-as"] 20 $mode addcontactfield email Email 35 $mode addcontactfield web Web 30 $mode addcontactfield ldap Ldap 30 $mode addcontactfield phone [mc Phone] 20 $mode addcontactfield mobilephone [mc "Mobile Phone"] 20 $mode addcontactfield fax Fax 20 $mode if { $mode == "input"} { set addcontact_address "" } frame .addcontact.address menubutton .addcontact.address.l -text [mc Address] -menu .addcontact.address.l.m menu .addcontact.address.l.m .addcontact.address.l.m add command -label [mc "Help"] -command "taghelp addcontact_address" text .addcontact.address.e -rel sunk -wrap word -yscrollcommand ".addcontact.address.s set" -width 40 -height 5 scrollbar .addcontact.address.s -rel sunk -command ".addcontact.address.e yview" pack .addcontact.address.l -side left -in .addcontact.address pack .addcontact.address.e -side right -in .addcontact.address pack .addcontact.address.s -side right -fill y -in .addcontact.address pack .addcontact.address if { $mode == "edit" } { .addcontact.address.e insert end $addcontact_address } addcontactfield postcode [mc Postcode] 10 $mode addcontactfield country [mc Country] 20 $mode addcontactfield organisation Organisation 30 $mode if { $mode == "input" } { set addcontact_type "" } frame .addcontact.type menubutton .addcontact.type.l -text [mc "Type"] -menu .addcontact.type.l.m menu .addcontact.type.l.m .addcontact.type.l.m add command -label "--" -command "set addcontact_type \"\"" foreach type $contacttypes { .addcontact.type.l.m add command -label [mc "$type"] -command "set addcontact_type \"[mc $type]\"" } .addcontact.type.l.m add separator .addcontact.type.l.m add command -label [mc "Help"] -command "taghelp addcontact_type" entry .addcontact.type.v -textvariable addcontact_type -width 12 pack .addcontact.type.l .addcontact.type.v -side left -in .addcontact.type pack .addcontact.type addcontactfield short_id [mc "Short-id"] 3 $mode if { $mode == "input" } { set addcontact_note "" } frame .addcontact.note menubutton .addcontact.note.l -text [mc Note] -menu .addcontact.note.l.m menu .addcontact.note.l.m .addcontact.note.l.m add command -label [mc "Help"] -command "taghelp addcontact_note" text .addcontact.note.e -rel sunk -wrap word -yscrollcommand ".addcontact.note.s set" -width 40 -height 5 scrollbar .addcontact.note.s -rel sunk -command ".addcontact.note.e yview" pack .addcontact.note.l -side left -in .addcontact.note pack .addcontact.note.e -side right -in .addcontact.note pack .addcontact.note.s -side right -fill y -in .addcontact.note pack .addcontact.note if { $mode == "edit" } { .addcontact.note.e insert end $addcontact_note } frame .addcontact.bot if {$mode == "input" } { button .addcontact.bot.ok -text [mc "Add"] -command addcontactOK } elseif { $mode == "edit" } { button .addcontact.bot.ok -text [mc "Edit"] -command editcontactOK } button .addcontact.bot.cancel -text [mc Cancel] -command { doCancel .addcontact } button .addcontact.bot.help -text [mc Help] -command "taghelp addcontact" pack .addcontact.bot.ok .addcontact.bot.cancel .addcontact.bot.help -side left -in .addcontact.bot pack .addcontact.bot tkwait window .addcontact } proc editcontact { contactid } { global allcontacts global contactsfilename global addcontact_id addcontact_forename addcontact_surname addcontact_email addcontact_phone addcontact_mobilephone addcontact_fax addcontact_organisation addcontact_type addcontact_note addcontact_title addcontact_address addcontact_short_id addcontact_postcode addcontact_country addcontact_web addcontact_ldap addcontact_default_as global editcontact_fields getallcontacts set addcontact_note "" set addcontact_address "" if { [info exist editcontact_fields] } { unset editcontact_fields } set addcontact_id $contactid set test [list Id "==" $contactid] lappend tests $test set thiscontact [tag extract $allcontacts $tests] foreach contact $thiscontact { foreach item $contact { if { [lindex $item 0] == "Forename" } { set addcontact_forename [lindex $item 1] } elseif { [lindex $item 0] == "Surname" } { set addcontact_surname [lindex $item 1] } elseif { [lindex $item 0] == "Title" } { set addcontact_title [lindex $item 1] } elseif { [lindex $item 0] == "Default-as" } { set addcontact_default_as [lindex $item 1] } elseif { [lindex $item 0] == "Email"} { set addcontact_email [lindex $item 1] } elseif { [lindex $item 0] == "Phone" } { set addcontact_phone [lindex $item 1] } elseif { [lindex $item 0] == "Web" } { set addcontact_web [lindex $item 1] } elseif { [lindex $item 0] == "Ldap" } { set addcontact_ldap [lindex $item 1] } elseif { [lindex $item 0] == "MobilePhone" } { set addcontact_mobilephone [lindex $item 1] } elseif { [lindex $item 0] == "Fax" } { set addcontact_fax [lindex $item 1] } elseif { [lindex $item 0] == "Note" } { set addcontact_note [lindex $item 1] } elseif { [lindex $item 0] == "Organisation"} { set addcontact_organisation [lindex $item 1] } elseif { [lindex $item 0] == "Type"} { set addcontact_type [lindex $item 1] } elseif { [lindex $item 0] == "Address"} { set addcontact_address [lindex $item 1] } elseif { [lindex $item 0] == "Short-id"} { set addcontact_short_id [lindex $item 1] } elseif { [lindex $item 0] == "Postcode"} { set addcontact_postcode [lindex $item 1] } elseif { [lindex $item 0] == "Country"} { set addcontact_country [lindex $item 1] } elseif { [lindex $item 0] == "Id" } { # dont do anything } else { set fieldname [fieldname2index [lindex $item 0]] set editcontact_fields($fieldname) [lindex $item 1] } } } set contact [ addContact edit] } proc getallcontacts {} { global contactsfilename allcontacts allcontactsstate if { $allcontactsstate == "closed" } { set allcontacts [tag readfile $contactsfilename] set allcontactsstate open if { [llength $allcontacts] == 0 } { set hdr "" set header [ list Tag-contact-version 1.0 ] lappend hdr $header set endpair [list End ] lappend hdr $endpair lappend allcontacts $hdr } } } proc writeallcontacts {} { global contactsfilename allcontacts allcontactsstate if { $allcontactsstate == "modified" } { tag writefile $contactsfilename $allcontacts set allcontactsstate open } } proc setcontactsmenu {} { global allcontacts getallcontacts .currentbar.endbutton.m.contact delete 1 end .currentbar.endbutton.m.contact add command -label "--" -command "set currentContact \"\"" foreach contact $allcontacts { foreach item $contact { if { [lindex $item 0] == "Id" } { .currentbar.endbutton.m.contact add command -label [lindex $item 1] -command "set currentContact \"[lindex $item 1]\"" } } } } proc viewContactsOK {} { global allcontacts global cview_phone cview_organisation cview_type cview_forename cview_surname toplevel .viewc wm title .viewc [mc "Contacts Display"] getallcontacts frame .viewc.main text .viewc.main.body -rel sunk -wrap word -yscrollcommand ".viewc.main.sb set" scrollbar .viewc.main.sb -rel sunk -command ".viewc.main.body yview" pack .viewc.main.body -side right -in .viewc.main pack .viewc.main.sb -side right -fill y -in .viewc.main pack .viewc.main frame .viewc.bot button .viewc.bot.ok -text [mc "Close"] -command { doCancel .viewc } button .viewc.bot.help -text [mc "Help"] -command "taghelp viewc" pack .viewc.bot.ok .viewc.bot.help -in .viewc.bot -side left pack .viewc.bot .viewc.main.body delete 1.0 end set tests "" if { $cview_phone != "" } { set test [list Phone -contains $cview_phone ] lappend tests $test } if { $cview_organisation != "" } { set test [list Organisation -contains $cview_organisation ] lappend tests $test } if { $cview_type != ""} { set test [list Type == $cview_type] lappend tests $test } if {$cview_forename != ""} { set test [list Forename -contains $cview_forename] lappend tests $test } if {$cview_surname != ""} { set test [list Surname -contains $cview_surname] lappend tests $test } set contacts [lrange $allcontacts 1 end] set contacts [tag extract $contacts $tests ] set entrynum 0 .viewc.main.body mark set prevmark 1.0 .viewc.main.body mark gravity prevmark left foreach entry $contacts { incr entrynum foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } { .viewc.main.body insert end "_______________________________________\n" .viewc.main.body tag add tag_$entryid prevmark insert .viewc.main.body tag bind tag_$entryid "editcontact \"$entryid\"" .viewc.main.body mark set prevmark insert } elseif { $tagname == "Id" } { set entryid $tagvalue } else { .viewc.main.body insert end "[mc $tagname]: " .viewc.main.body insert end "$tagvalue" .viewc.main.body insert end "\n" } } } tkwait window .viewc } proc viewContacts {} { global cview_phone cview_organisation cview_type cview_forename cview_surname global contacttypes toplevel .cview wm title .cview [mc "Select Contacts to view"] frame .cview.main frame .cview.main.forename menubutton .cview.main.forename.l -text [mc Forename] -menu .cview.main.forename.l.m menu .cview.main.forename.l.m .cview.main.forename.l.m add command -label [mc Help] -command "taghelp cview_forename" entry .cview.main.forename.e -textvariable cview_forename -width 20 pack .cview.main.forename.l .cview.main.forename.e -side left -in .cview.main.forename pack .cview.main.forename frame .cview.main.surname menubutton .cview.main.surname.l -text [mc Surname] -menu .cview.main.surname.l.m menu .cview.main.surname.l.m .cview.main.surname.l.m add command -label [mc Help] -command "taghelp cview_surname" entry .cview.main.surname.e -textvariable cview_surname -width 20 pack .cview.main.surname.l .cview.main.surname.e -side left -in .cview.main.surname pack .cview.main.surname frame .cview.main.phone menubutton .cview.main.phone.l -text [mc Phone] -menu .cview.main.phone.l.m menu .cview.main.phone.l.m .cview.main.phone.l.m add command -label [mc Help] -command "taghelp cview_phone" entry .cview.main.phone.e -textvariable cview_phone -width 12 pack .cview.main.phone.l .cview.main.phone.e -side left -in .cview.main.phone pack .cview.main.phone frame .cview.main.organisation menubutton .cview.main.organisation.l -text Organisation -menu .cview.main.organisation.l.m menu .cview.main.organisation.l.m .cview.main.organisation.l.m add command -label [mc Help] -command "taghelp cview_organisation" entry .cview.main.organisation.e -textvariable cview_organisation -width 20 pack .cview.main.organisation.l .cview.main.organisation.e -side left -in .cview.main.organisation pack .cview.main.organisation frame .cview.main.type menubutton .cview.main.type.l -text [mc Type] -menu .cview.main.type.l.m menu .cview.main.type.l.m .cview.main.type.l.m add command -label "--" -command "set cview_type \"\"" foreach type $contacttypes { .cview.main.type.l.m add command -label [mc "$type"] -command "set cview_type \"[mc $type]\"" } .cview.main.type.l.m add separator .cview.main.type.l.m add command -label [mc "Help"] -command "taghelp cview_type" entry .cview.main.type.e -textvariable cview_type -width 10 pack .cview.main.type.l .cview.main.type.e -side left -in .cview.main.type pack .cview.main.type pack .cview.main frame .cview.bot button .cview.bot.ok -text [mc "View"] -command viewContactsOK button .cview.bot.cancel -text [mc "Cancel"] -command { doCancel .cview } button .cview.bot.help -text [mc "Help"] -command "taghelp contactview" pack .cview.bot.ok .cview.bot.cancel .cview.bot.help -in .cview.bot -side left pack .cview.bot tkwait window .cview } proc importContacts {} { set types [list "[list [mc "vCard Files"]] .vcf"] set filename [tk_getOpenFile -filetypes $types -title [mc " vCard files to Import"]] if {$filename !=""} { set imported_contacts [read_vcard $filename] } } proc read_vcard { filename } { # # Read one or more contacts from the given file and return them as a list of # contacts # set result "" set f [open $filename] while { [gets $f line] >= 0 } { # Lines should consist of a label and a value set ll [split $line :] if { [llength $ll] ==2 } { set label [lindex $ll 0] set value [lindex $ll 1] puts "label is $label - value is $value" if { $label == "END"} [ set thiscontact "" if { $imp_id==""} { set imp_id Import.$now } set thiscontact [tagappend $thiscontact Id $imp_id] set thiscontact [tagappend $thiscontact Email $imp_email] set thiscontact [tagappend $thiscontact Web $imp_web] set thiscontact [tagappend $thiscontact Phone $imp_phone] set thiscontact [tagappend $thiscontact MobilePhone $imp_mobilephone] set thiscontact [tagappend $thiscontact Fax $imp_fax] set thiscontact [tagappend $thiscontact Organisation $imp_org] set endpair [list End ] lappend thiscontact $endpair lappend result $thiscontact } elseif { $label == "BEGIN" } { set imp_id "" set imp_email "" set imp_web "" set imp_phone "" set imp_mobilephone "" set imp_fax "" set imp_org "" } elseif { $label == "ORG" } { set imp_org $value } elseif { $label == "URL"} { set imp_web $value } elseif { $label == "TEL;WORK;VOICE" } { set imp_phone $value } elseif { $label == "TEL;WORK;FAX" } { set imp_fax $value } else { puts "llength of $ll is not 2" } } close $f return $result } taglog-0.2.6/src/tag.30000644000175000017500000000303213534701742013104 0ustar johnjohn.TH tag 3tcl "July 3, 2000 .SH NAME tag \- Manipulate tagged files .SH SYNOPSIS .B tag option ?arg arg ...? .SH DESCRIPTION The tag procedure provides a number of options for manipulating tagged files. .SH COMMANDS .TP tag readfile filename Reads the file with the given filename and returns a list where each list element is a tag record, which is represented by a list of label-value pairs, or label-value-endlabel triples. The tag header is the first element returned. .TP tag writefile filename list Takes a list in the format used internally in tcl programs for tagged data and writes it as a tagged file. .TP tag extract list tests Takes a list in tagged format, and a list of conditions, and returns a new list in tagged format which contains those tag records which match the conditions. The tests is a list of test items, each of which is a list of the form { labelname condition matchvalue } The conditions are .TP .I == String equals .TP .I != String not equal .TP .I <= Less than or equal .TP .I -in Is the test value a member of the list given as the matchvalue .TP .I -contains Does the match value contain the test value as a case insensitive substring. .TP .I -earlier Date earlier .TP .I -later Date later - dates are in ISO format (yyyy-mm-dd [hh:mm:ss]). .TP .I -exists Does the label exist in this record. .SH BUGS tag readfile reads the whole file into memory before turning it into a list. Should be more memory efficient. The -earlier and -later comparisons require TCL8.3 .SH AUTHOR John Lines (john+taglog@paladyn.org) taglog-0.2.6/src/nl.msg0000644000175000017500000003050213534701742013370 0ustar johnjohn# namespace import -force msgcat::mcset mcset nl Help Hulp #mcset nl Cancel Abbruch mcset nl Quit {Houd met op} mcset nl Exit Uitgang #mcset nl Next Weiter #mcset nl Action Aktion #mcset nl Actions Aktionen #mcset nl actions Aktionen #mcset nl Reports Berichte mcset nl Preferences Voorkeur #mcset nl Open... ffnen #mcset nl Pause Anhalten #mcset nl Resume Fortfahren #mcset nl {Add/Edit Log} {Log Hinzufgen/ndern} #mcset nl Add... Hinzufgen... #mcset nl View Ansicht #mcset nl Complete Abschlieen #mcset nl Activate Aktivieren #mcset nl {Abort Active} {Abbruch Aktiv} #mcset nl {Abort Pending} {Abbruch Wartend} #mcset nl Abort Abbrechen #mcset nl Reactivate Reaktivieren #mcset nl Projects Projekte #mcset nl Add Hinzufgen #mcset nl Edit Bearbeiten #mcset nl About ber #mcset nl {Please select the date of log} {Bitte das Datum fr Logeintrge auswhlen,} #mcset nl {entries to be input or edited} {die bearbeitet oder neu eingegeben werden sollen} #mcset nl {Input and editing of log entries} {Eingabe und Bearbeitung von Logeintrgen} #mcset nl "Log edit" Log-Bearbeitung #mcset nl "Date selection" "Datumauswahl" #mcset nl "No date selected" "Kein Datum ausgewhlt" #mcset nl "Invalid date format" "Ungltiges Datumsformat" #mcset nl "Editing of log file" "Bearbeitung einer Log-Datei" mcset nl Day Jour mcset nl day jour mcset nl days jours #mcset nl week Woche #mcset nl "Import of log entries" "Import von Logeintrgen" #mcset nl File Datei #mcset nl {No entries found in file} {Keine Eintrge gefunden in Datei} #mcset nl "Import all" "Alles" #mcset nl Import Importieren #mcset nl Project Projekt #mcset nl "End " Ende #mcset nl End Ende #mcset nl Delete Lschen #mcset nl "Edit log entry" "Bearbeitung eines Log-Eintrages" #mcset nl "Add a new entry" "Neuer Log-Eintrag" #mcset nl {Start Time} Startzeit #mcset nl {End Time} Ende #mcset nl {ActionTitle} {Titel der Aktion} #mcset nl Activity Aktivitt #mcset nl Contact Kontakt #mcset nl Contacts Kontakte #mcset nl Save Speichern #mcset nl "Save As..." "Speichern unter..." #mcset nl Description Beschreibung #mcset nl "Adjust to previous EndTime" "Zeit an vorheriges Ende anpassen" #mcset nl "Adjust to following Startime" "An nchste Startzeit anpassen" #mcset nl "Invalid date range" "Zeitbereich ungltig" #mcset nl "The StartTime is greater\nthan the EndTime" "Startzeit grer als Endzeit" #mcset nl "Invalid date" "Ungltiges Datum" #mcset nl {Please enter a value for} {Bitte einen Wert eingeben fr:} #mcset nl {is not a valid\ntime value for} {ist keine gltige\nZeit fr Tag} #mcset nl "There are overlapping (marked with '>')\nand inconsistent (marked with '!') time ranges." "Es existieren berlappende ('>')\nund inkonsistente '(!)' Zeitbereiche." #mcset nl "There are overlapping time ranges (marked with '>')." "Es existieren berlappende Zeitbereiche." #mcset nl "There are inconsistent time ranges (marked with '!')." "Es existieren inkonsistente Zeitbereiche." #mcset nl {Do you want to save?} {Wollen Sie trotzdem abspeichern?} #mcset nl "Weekly time bookings by project" "Projekte: Wchentliche Zeitbuchungen" #mcset nl "Time by activity" "Gesamtzeit je Aktivitt" #mcset nl "Total time for a project" "Gesamtzeit fr ein Projekt" #mcset nl "Project Progress Report" "Projektfortschritt" #mcset nl Directory Verzeichnis #mcset nl "Current Directory" "Aktuelles Verzeichnis" #mcset nl "File name :" "Dateiname:" #mcset nl "Save Text" "Speichern als Text" #mcset nl "Save HTML" "Speichern als HTML" #mcset nl "Save HTML..." "Speichern als HTML ..." #mcset nl "Description contains" "Beschreibung enthlt" #mcset nl "Documentation Directory" "Dokumentationsverzeichnis" #mcset nl "Data directory root" "Wurzelverzeichnis fr Daten" #mcset nl Language Sprache #mcset nl "Hours Worked per Day (decimal)" "Arbeitsstunden pro Tag (dezimal)" #mcset nl "Date Format" Datumsformat #mcset nl "European (DD/MM/YYYY)" "Europisch (DD/MM/YYYY)" #mcset nl "American (MM/DD/YYYY)" "Amerikanisch (MM/DD/YYYY)" #mcset nl "History Window Depth" {Zeilen fr Historien-Fenster} #mcset nl "Current Window Depth" "Zeilen fr Log-Fenster" #mcset nl "Number of 'Today' actions" "Anzahl der 'Heute'-Aktionen" #mcset nl Prefix Prfix #mcset nl "SMTP Preferences filename" "Dateiname fr SMTP-Einstellungen" #mcset nl "email address" "EMail-Adresse" #mcset nl traditional traditionell #mcset nl "local mail submission port" "lokaler Mail-Port" #mcset nl "Input an action" "Eingabe einer Aktion" #mcset nl {Edit action} "Bearbeite Aktion" #mcset nl Title Titel #mcset nl Date Datum #mcset nl Priority Prioritt #mcset nl Expected-cost "Erwartete Kosten" #mcset nl Expected-time "Erwartete Zeit" #mcset nl Expected-Time "Erwartete Zeit" #mcset nl Revised-expected-time "Gend. Erwartete Zeit" #mcset nl Expected-start-date "Erwartete Startzeit" #mcset nl Completed-date "Fertigstellungsdatum" #mcset nl Active-date "Aktivierungsdatum" #mcset nl Aborted-date "Abbruchdatum" #mcset nl Expected-completed-date "Erw-Fertigstellungsdatum" #mcset nl Expected-Completed-Date "Erw-Fertigstellungsdatum" #mcset nl Revised-expected-completed-date "Gend. Erw-Fertigstellungsdatum" #mcset nl Revised-date Gend-Datum #mcset nl Precursor Vorgnger #mcset nl Active-after "Aktiv nach" #mcset nl Subtask-of "Unteraufgabe von" #mcset nl Next-action "Nchste Aktion" #mcset nl Abort-action Abbruch-Aktion #mcset nl Difficulty Schwierigkeit #mcset nl nobrainer simpel #mcset nl trivial trivial #mcset nl easy leicht #mcset nl tricky anspruchsvoll #mcset nl hard schwer #mcset nl "very hard" "sehr schwer" #mcset nl Email-status-to "Sende-Status an" #mcset nl Deliverable Auslieferbar #mcset nl Reason Grund #mcset nl Message Nachricht #mcset nl "Mail to" "Sende an" #mcset nl "Mail an action" "Sende eine Aktion" #mcset nl "Add a new project" "Neues Projekt" #mcset nl "Project name" Projektname #mcset nl "Book as breaks" "Als Pause buchen" #mcset nl "Book as overheads" "Als Overhead buchen" #mcset nl "Booking Code" "Buchungs-Code" #mcset nl "Start Date" "Startdatum" #mcset nl "End Date" "Beendigungsdatum" #mcset nl "Edit Projects" "Projekte bearbeiten" #mcset nl Breaks Pausen #mcset nl "Project Times" Projektzeiten #mcset nl Total Gesamt #mcset nl "Total (non breaks)" "Gesamt (ohne Pausen)" #mcset nl Today Heute #mcset nl "Select date range" "Zeitbereich" #mcset nl "Enter Project details" Projektdetails #mcset nl "Enter information for Project Progress Report" "Projektfortschritt" #mcset nl "Select Time Period" "Auswahl der Zeitbereichs" #mcset nl "Time Format" Zeitformat #mcset nl "Decimal hours" "Stunden dezimal" #mcset nl "Decimal days" "Tage dezimal" #mcset nl "Spread overhead projects" "Overhead Projekte aufteilen" #mcset nl "Book by Project" "Sortieren nach Projekt" #mcset nl Year Jahr #mcset nl weeks Wochen #mcset nl "starting at number" "Start bei" #mcset nl "Time by Activity" "Gesamtzeit je Aktivitt" #mcset nl "Project Progress Report for" "Projektfortschrittsbericht fr" #mcset nl "Total Times for" "Gesamtzeit fr" #mcset nl "Time Bookings" "Zeitbuchungen" mcset nl Sun "Dim" mcset nl Mon "Lun" mcset nl Tue "Mar" mcset nl Wed "Mer" mcset nl Thu "Jeu" mcset nl Fri "Ven" mcset nl Sat "Sam" #mcset nl "Breaks total" "Pausen gesamt" #mcset nl "Time Bookings for week" "Zeitbuchungen fr Kalenderwoche" #mcset nl of von #mcset nl "Warning - cant open" "Warnung - folgende Datei kann nicht geffnet werden:" #mcset nl "Total time" Gesamtzeit #mcset nl "Total time for" "Die Gesamtzeit fr" #mcset nl is ist #mcset nl "decimal days" "dezimale Tage" #mcset nl Examined "Untersucht wurden" #mcset nl "files and found entries for" "Dateien. Gefunden wurden Eintrge fr" #mcset nl "of them" "von ihnen" #mcset nl "First date was" "Erstes Datum:" #mcset nl "last date was" "Letztes Datum:" #mcset nl "Adjust start time" "Startzeit anpassen" #mcset nl "Adjust start time back towards previous start time of" "Startzeit anpassen in Richtung auf vorherige Startzeit von" #mcset nl "Adjust start time back towards the start of the day" "Startzeit an Tagesbeginn anpassen" #mcset nl "Adjust previous end time" "Vorherige End-Zeit anpassen" #mcset nl "New Start Time" "Neue Startzeit" #mcset nl "Minutes to Subtract from StartTime" "Zu subtrahierende Minuten" #mcset nl Set "Startzeit setzen" #mcset nl calendar Kalender #mcset nl Calendar Kalender #mcset nl Su So #mcset nl Tu Di #mcset nl We Mi #mcset nl Th Do #mcset nl January Januar #mcset nl February Februar #mcset nl March Mrz #mcset nl April April #mcset nl May Mai #mcset nl June Juni #mcset nl July Juli #mcset nl August August #mcset nl September September #mcset nl October Oktober #mcset nl November November #mcset nl December Dezember #mcset nl "Select Contacts to view" "Auswahl zum Anzeigen von Kontakten" #mcset nl Forename Vorname #mcset nl Phone Telefon #mcset nl Type Typ #mcset nl Surname Nachname #mcset nl "Contacts Display" "Anzeige der Kontakte" #mcset nl Close Schlieen #mcset nl Address Adresse #mcset nl Short-id Kurz-Id #mcset nl "Input a contact" "Kontakt eingeben" #mcset nl "Edit contact" "Bearbeite Kontakt" #mcset nl Mr Herr #mcset nl Ms Frulein #mcset nl Mrs Frau #mcset nl "Default-as" "Vorbesetzen mit" #mcset nl "Mobile Phone" Mobiltelefon #mcset nl Postcode Postleitzahl #mcset nl Country Land #mcset nl Note Bemerkung #mcset nl "Select Actions ..." "Aktionen auswhlen ..." #mcset nl Filename Dateiname #mcset nl All Alle #mcset nl Any Beliebig #mcset nl Unclaimed Unveranlagt #mcset nl Pending Wartend #mcset nl Active Aktiv #mcset nl Blocked Blockiert #mcset nl Completed Abgeschlossen #mcset nl Aborted Abgebrochen #mcset nl "Date Expected" "Erwartetes Datum" #mcset nl Tomorrow Morgen #mcset nl Later Spter #mcset nl Earlier Frher #mcset nl "Show Fields" "Felder anzeigen" #mcset nl "Due Date" "Flligkeitsdatum" #mcset nl Refresh Aktualisieren #mcset nl "Sort by" "Sortieren nach" #mcset nl "Actions view of" "Aktionen, Sicht von:" #mcset nl "Save Action History As ..." "Speichere Aktions-Historie unter..." #mcset nl "Action history" "Historie fr Aktion" #mcset nl Revise ndern #mcset nl History Historie #mcset nl Duration Dauer #mcset nl "Total duration" Gesamtdauer #mcset nl "Save Actions Display As ..." "Speichere Aktionsanzeige unter ..." #mcset nl "Save Log View Display As ..." "Speichere Log-Anzeige unter ..." #mcset nl "Select Log Files ..." "Auswahl von Log-Dateien" #mcset nl "Log view" "Log-Anzeige" #mcset nl "Edit Preferences" "Bearbeite Einstellungen" #mcset nl Displayed Angezeigt: #mcset nl "Total expected time" "Gesamte erwartete Zeit:" #mcset nl unknown unbekannt #mcset nl "Pick an action to move from" "Wechsel des Status einer Aktion von" #mcset nl to nach #mcset nl "Refresh Active" "Liste der aktiven Akt. neu aufbauen" #mcset nl "Active Time Blocked" "Aktiviere fllige Aktionen" #mcset nl "Archive Old Actions" "Archiviere alte Aktionen" #mcset nl colleague Kollege #mcset nl customer Kunde #mcset nl supplier Lieferant #mcset nl contact Kontakt #mcset nl friend Privat #mcset nl "Interruptions Report" "Unterbrechungen" #mcset nl "There were a total of" "Es gibt insgesamt" #mcset nl "interruptions in" "Unterbrechungen in" #mcset nl "days." "Tagen." #mcset nl "The average number of interruptions in a day was" "Die durchschnittliche Anzahl von Unterbrechungen pro Tag war" #mcset nl "The peak number of interruptions per day was" "Die Spitzen-Anzahl von Unterbrechungen pro Tag war" #mcset nl "vCard Files" "vCard Dateien" #mcset nl " vCard files to Import" " Zu importierende vCard Dateien" #mcset nl "Introduction" "Einfhrung" #mcset nl "Hints" "Hinweise" #mcset nl "Actions overrun" "berschreitung der geplanten Zeiten" #mcset nl "Actions not completed" "Aktivitten nicht beendet" #mcset nl "Interruptions" "Unterbrechungen" #mcset nl "Progress from" "Fortschritt von" #mcset nl " to " " bis " #mcset nl "Achievements" "Erreichtes" #mcset nl "Tasks completed since last report" "Seit letztem Bericht erledigte Aufgaben" #mcset nl "Expected" "Erwartet" #mcset nl "Actual" "Tatschlich" #mcset nl "Tasks started since last report" "Seit letztem Bericht gestartete Aufgaben" #mcset nl "Tasks slipped since last report" "Aufgaben, die die Zeit berschreiten werden" #mcset nl "Active tasks" "Aktive Aufgaben" #mcset nl "Scheduled" "Geplant" #mcset nl "Forecast" "Prognose" #mcset nl "Completion" "Erledigung" #mcset nl "Delegated-to" "Delegiert an" #mcset nl "Delegated" "Delegiert" #mcset nl "delegated" "delegiert" #mcset nl "Pick" "Auswahl" #mcset nl "Update" "Aktualisierung" #mcset nl "meeting-preparation" "Besprechungsvorbereitung" #mcset nl "meeting" "Besprechung" #mcset nl "email" "EMail" taglog-0.2.6/src/taglog_init.tcl0000644000175000017500000010066613550071213015253 0ustar johnjohn# # taglog_init.tcl - initialisation routines for taglog # Copyright John Lines (john+taglog@paladyn.org) July 2000, January 2003 # # This program is released under the terms of the GNU Public Licence # package provide taglog_init 0.1 proc initialise {} { global tcl_platform env global hh mm ss year month day currentStart currentEnd currentProject currentActivity logfilename \ actionsfilename state projectsfilename activities rootdir currentAction global currentContact global contactsfilename global contacttypes global currentActionTitle global actinput_project global actinput_f_a0 global projTimes projTimesTotal projTimesTotalNonBreaks global logentries global validStates global libsdir prefsfile display_prevday global actsel_project actsel_st_any actsel_st_unclaimed actsel_st_pending actsel_st_active actsel_st_blocked actsel_st_completed actsel_st_aborted actsel_st_periodic actsel_filename actsel_filenames actsel_projstat actsel_sortby global showtime_format showtime_spreadoverheads showtime_bookbycode showtime_hours_per_day global timebook_startlastweek global actsel_maxpriority actsel_showfields global docdir global helpdir global scrollside global allactstate global language global allcontactsstate global rate global dateformat_view dateformat_tcl global num_today_actions history_win_depth current_win_depth global html_public_dir html_private_dir global lvsa_dirname global id_prefix global action_textarea_fields global GL_tableFont global GL_autoComCase global GL_autoComMsec global argv global start_procs exit_procs global stackdepth stack_info global projects_url global log_summary global activitiesfilename global debug global isAndroid global currentTimeFormat set currentTimeFormat "%d:%02d:%02d" # Initialise common variables set hh 0 set mm 0 set ss 0 gettime set year 0 set month 0 set day 0 getdate set currentStart [format $currentTimeFormat $hh $mm $ss] set currentEnd [format $currentTimeFormat $hh $mm $ss] set currentProject "" set currentContact "" set currentAction "" set currentActionTitle "" set currentActivity "" set logfilename "" set prevdayfilename "" set state "running" set logentries {} set projTimes(unknown) "00:00" set projTimesTotal "00:00" set projTimesTotalNonBreaks "00:00" set validStates { Unclaimed Pending Active Blocked Delegated Completed Aborted Periodic} set prefsfile "" set actsel_st_any 1 set actsel_st_unclaimed 1 set actsel_st_pending 1 set actsel_st_active 1 set actsel_st_blocked 0 set actsel_st_completed 0 set actsel_st_aborted 0 set actsel_st_periodic 0 set actsel_maxpriority "" set actsel_showfields(all) 1 set actsel_showfields(id) 0 set actsel_showfields(title) 1 set actsel_showfields(priority) 0 set actsel_showfields(project) 1 set actsel_showfields(status) 1 set actsel_showfields(summary) 1 set actsel_projstat all set actsel_sortby "" set stackdepth 0 set stack_info "" set log_summary "" # parameters for auto completion of entry widgets # case ignore case? 0=no, 1=yes set GL_autoComCase 1 # delay in milliseconds, 0 means autocompletion only with key set GL_autoComMsec 300 set allactstate closed set allcontactsstate closed set id_prefix "" set GL_tableFont "-*-courier-medium-r-normal--*-120-*" set action_textarea_fields { Description Deliverable Reason Summary} # The following items are likely to be customised by the user set dateformat_view "YYYY-MM-DD" set dateformat_tcl "%Y-%m-%d" set debug 0 set rootdir "~/diary" if { $tcl_platform(platform) == "windows" } { if [ info exists env(USERPROFILE)] { set df [file join $env(USERPROFILE) diary] if { [file isdirectory $env(USERPROFILE)] } { set rootdir $df } } } set start_procs {} set exit_procs {} set projects_url "" # delay setting the following until after the preferences file has been read set actionsfilename "" set projectsfilename "" set html_public_dir "" set html_private_dir "" set lvsa_dirname "" set activitiesfilename "" set contactsfilename "" set contacttypes { colleague customer supplier contact friend } set rate "" set activities { phone-in phone-out meeting meeting-preparation meeting-review email reading programming writing thinking service-break informal-discussion } set showtime_format 1 set showtime_spreadoverheads byweek set showtime_bookbycode 0 set showtime_hours_per_day 7.58 set timebook_startlastweek 1 set isAndroid 0 if { [info commands sdltk] ne "" } { set isAndroid [sdltk android] } # which side the scroll bars are, in windows with scroll bars set scrollside left set history_win_depth 15 set current_win_depth 15 set num_today_actions 3 if { $isAndroid } { set history_win_depth 10 set current_win_depth 10 set num_today_actions 0 } # How often (in minutes) do we want to be reminded to take a break - 0 disables set breakRemindInterval 0 # do we display the previous day window set display_prevday 0 # where do we find our preferences # this is now set in sourcelibs # set libsdir "" # where do we keep the help files - default to the same place as the # taglog main script set scriptdir [file dirname [info script]] set helpdir $scriptdir if { [ file readable $scriptdir/taglog_help_en.tag] } { set helpdir $scriptdir } elseif { [file readable ~/lib/taglog/taglog_help_en.tag] } { set helpdir ~/lib/taglog } elseif { [file readable /usr/lib/taglog/taglog_help_en.tag] } { set helpdir /usr/lib/taglog } elseif { [file readable /usr/local/lib/taglog/taglog_help_en.tag] } { set helpdir /usr/local/lib/taglog } elseif { [file readable /usr/share/taglog/taglog_help_en.tag] } { set helpdir /usr/share/taglog } elseif { [ file readable /usr/share/doc/taglog/taglog_help_en.tag] } { set helpdir /usr/share/doc/taglog } elseif { [ file readable /usr/local/doc/taglog_help_en.tag] } { set helpdir /usr/local/doc } set docdir $helpdir # preferred language set language en if { [llength $argv] >0} { while {[string match -* [lindex $argv 0]]} { switch -exact -- [lindex $argv 0] { -c { set prefsfile [lindex $argv 1] set argv {} } } } } # Having set the defaults we will source /etc/taglog.conf if it exists if {[file readable "/etc/taglog.conf"] } { source /etc/taglog.conf } if { $prefsfile == "" } { # This is for Unix if {[file readable "~/.taglog"] } { source "~/.taglog" set prefsfile "~/.taglog" } # If c:\Documents and Settings\username\taglog.cfg exists then use that. if { $tcl_platform(platform) == "windows" } { if [ info exists env(USERPROFILE)] { set tf [file join $env(USERPROFILE) taglog.cfg] if { [file readable $tf] } { source $tf set prefsfile $tf } } } # This is a Windows fallback if { [file readable "~/taglog.cfg"] } { source "~/taglog.cfg" set prefsfile "~/taglog.cfg" } } else { # prefs must have been set from command line if { [file readable $prefsfile] } { source $prefsfile } } # If the preferences were not found then we should initialise then if { $prefsfile == "" } { initprefs } # The following are automatically set, but depend on things from the user # preferences if { $actionsfilename == "" } { set actionsfilename "$rootdir/actions.tag" } if { $projectsfilename == "" } { set projectsfilename "$rootdir/projects.tag" } if { $html_public_dir == "" } { set html_public_dir "~/public_html" } if { $html_private_dir == "" } { set html_private_dir "$rootdir/html" } if { $contactsfilename == "" } { set contactsfilename "$rootdir/contacts.tag" } if { $activitiesfilename == ""} { set activitiesfilename "$rootdir/activities" } lappend actsel_filenames $actionsfilename lappend actsel_filenames "$docdir/taglog_todo.tag" set actsel_filename $actionsfilename if { $dateformat_view=="DD/MM/YYYY" } { set dateformat_tcl "%d/%m/%Y" } elseif { $dateformat_view=="MM/DD/YYYY" } { set dateformat_tcl "%m/%d/%Y" } else { set dateformat_tcl "%Y-%m-%d" } # Reset current start and end using time format from preferences, # so they appear correctly on boot set currentStart [format $currentTimeFormat $hh $mm $ss] set currentEnd [format $currentTimeFormat $hh $mm $ss] # Post initialisation procedures FindDefaultPrevday #fill up the activities list from file # if {[file readable $activitiesfilename] } { set fileid [open $activitiesfilename r+] seek $fileid 0 start set buffer [read $fileid]; close $fileid set activities [split $buffer "\n"]; } # read the projects file readprojects } proc initprefs {} { global tcl_platform rootdir env prefsfile # initialise the preferences file # We should be able to just display the prefs dialog to let the user confirm # Since we are in the first time we dont really know what the users language # should be - default to the minimal mc so it exists when we call editPrefs proc mc { msg } { return $msg } wm iconify . if {$tcl_platform(platform) == "unix"} { set prefsfile "~/.taglog" } if { $tcl_platform(platform) == "windows" } { if [ info exists env(USERPROFILE)] { set tf [file join $env(USERPROFILE) taglog.cfg] if { [file isdirectory $env(USERPROFILE)] } { set prefsfile $tf } } if { $prefsfile == "" } { set prefsfile "~/taglog.cfg"} } # Create a blank preferences file set header "# Preferences for taglog" set marker "# above this line is automatically saved - put your changes below here" set f [open $prefsfile w] puts $f "$header" puts $f "$marker" close $f editPrefs wm deiconify . } proc editprefsOK {} { global docdir language editprefs_docdir editprefs_language global editprefs_showtime_hours_per_day showtime_hours_per_day global editprefs_showtime_spreadoverheads showtime_overheads global editprefs_timebook_startlastweek timebook_startlastweek global smtpv editprefs_smtp_thishost editprefs_smtp_mailhost editprefs_smtp_myemail editprefs_smtp_port editprefs_smtp_prefsfile global editprefs_dateformat dateformat_view dateformat_tcl global editprefs_rootdir rootdir global editprefs_history_win_depth editprefs_current_win_depth editprefs_num_today_actions global history_win_depth current_win_depth num_today_actions global id_prefix editprefs_id_prefix global helpdir editprefs_helpdir global start_procs editprefs_start_procs exit_procs editprefs_exit_procs global projects_url editprefs_projects_url global editprefs_activitiesFile global activities global activitiesfilename global libsdir editprefs_libsdir global editprefs_timeformat currentTimeFormat set activitiesfilename $editprefs_activitiesFile set docdir $editprefs_docdir set rootdir $editprefs_rootdir set libsdir $editprefs_libsdir # set helpdir $editprefs_helpdir set language $editprefs_language if { ( $showtime_hours_per_day < 24 ) && ( $editprefs_showtime_hours_per_day > 0) } { set showtime_hours_per_day $editprefs_showtime_hours_per_day } set showtime_spreadoverheads $editprefs_showtime_spreadoverheads set timebook_startlastweek $editprefs_timebook_startlastweek set dateformat_view $editprefs_dateformat if { $dateformat_view=="DD/MM/YYYY" } { set dateformat_tcl "%d/%m/%Y" } elseif { $dateformat_view=="MM/DD/YYYY" } { set dateformat_tcl "%m/%d/%Y" } else { set dateformat_tcl "%Y-%m-%d" } set currentTimeFormat $editprefs_timeformat if { ($history_win_depth > 1) && ( $history_win_depth <80) } { set history_win_depth $editprefs_history_win_depth } if { ($current_win_depth >1) && ( $current_win_depth <80) } { set current_win_depth $editprefs_current_win_depth } if { ($editprefs_num_today_actions >=0) && ($editprefs_num_today_actions <21) } { set num_today_actions $editprefs_num_today_actions } set id_prefix $editprefs_id_prefix set start_procs [split [string trim $editprefs_start_procs]] set projects_url $editprefs_projects_url if { [can_get_httprojects] } { catch {.mBar.projects.m entryconfigure 3 -state normal} } #fill up the activity list if {[file readable $activitiesfilename]} { set fileid [open $activitiesfilename r+] seek $fileid 0 start set buffer [read $fileid]; close $fileid set activities [split $buffer "\n"]; } savePrefs # save smtp preferences if { $editprefs_smtp_prefsfile != "" } { set f [open $editprefs_smtp_prefsfile w] puts $f "# Preferences for smtp.tcl - created by taglog" puts $f "set smtpv(thishost) $editprefs_smtp_thishost" puts $f "set smtpv(mailhost) $editprefs_smtp_mailhost" puts $f "set smtpv(myemail) \"$editprefs_smtp_myemail\"" puts $f "set smtpv(port) $editprefs_smtp_port" puts $f "set smtpv(initialised) 1" close $f } destroy .editprefs } proc editPrefs {} { global tcl_platform env global docdir language editprefs_docdir editprefs_language global rootdir editprefs_rootdir libsdir editprefs_libsdir global editprefs_showtime_hours_per_day showtime_hours_per_day global editprefs_showtime_spreadoverheads showtime_spreadoverheads global editprefs_timebook_startlastweek timebook_startlastweek global smtpv editprefs_smtp_thishost editprefs_smtp_mailhost editprefs_smtp_myemail editprefs_smtp_port editprefs_smtp_prefsfile global editprefs_dateformat dateformat_view dateformat_tcl global editprefs_rootdir rootdir global prefsfile global editprefs_history_win_depth editprefs_current_win_depth editprefs_num_today_actions global history_win_depth current_win_depth num_today_actions global id_prefix editprefs_id_prefix global helpdir editprefs_helpdir global start_procs editprefs_start_procs exit_procs editprefs_exit_procs global projects_url editprefs_projects_url global activitiesfilename global editprefs_activitiesFile global editprefs_timeformat currentTimeFormat set realprefs [file nativename $prefsfile] toplevel .editprefs wm title .editprefs "[mc {Edit Preferences}] in $realprefs" frame .editprefs.f text .editprefs.c -width 40 -height 20 -xscrollcommand ".editprefs.xscroll set" -yscrollcommand ".editprefs.yscroll set" scrollbar .editprefs.xscroll -orient horizontal -command ".editprefs.c xview" scrollbar .editprefs.yscroll -command ".editprefs.c yview" pack .editprefs.xscroll -side bottom -fill x -in .editprefs.f pack .editprefs.yscroll -side right -fill y -in .editprefs.f pack .editprefs.c -expand yes -fill both -side top -in .editprefs.f pack .editprefs.f -expand yes # Files set editprefs_docdir $docdir frame .editprefs.c.docdir menubutton .editprefs.c.docdir.l -text [mc "Documentation Directory"] -menu .editprefs.c.docdir.l.m menu .editprefs.c.docdir.l.m .editprefs.c.docdir.l.m add command -label [mc Help] -command "taghelp prefs_docdir" entry .editprefs.c.docdir.v -textvariable editprefs_docdir -width 30 pack .editprefs.c.docdir.l .editprefs.c.docdir.v -side left -in .editprefs.c.docdir pack .editprefs.c.docdir set editprefs_libsdir $libsdir frame .editprefs.c.libsdir menubutton .editprefs.c.libsdir.l -text [mc "Library Directory"] -menu .editprefs.c.libsdir.l.m menu .editprefs.c.libsdir.l.m .editprefs.c.libsdir.l.m add command -label [mc Help] -command "taghelp prefs_libsdir" entry .editprefs.c.libsdir.v -textvariable editprefs_libsdir -width 30 pack .editprefs.c.libsdir.l .editprefs.c.libsdir.v -side left -in .editprefs.c.libsdir pack .editprefs.c.libsdir set editprefs_rootdir $rootdir frame .editprefs.c.rootdir menubutton .editprefs.c.rootdir.l -text [mc "Data directory root"] -menu .editprefs.c.rootdir.l.m menu .editprefs.c.rootdir.l.m if { $tcl_platform(platform) == "windows" } { if [ info exists env(USERPROFILE)] { set df [file join $env(USERPROFILE) diary] if { [file isdirectory $env(USERPROFILE)] } { .editprefs.c.rootdir.l.m add command -label $df -command "set editprefs_rootdir \"$df\"" } } } .editprefs.c.rootdir.l.m add command -label "~/diary" -command "set editprefs_rootdir \"~/diary\"" .editprefs.c.rootdir.l.m add command -label "~/.taglog-diary" -command "set editprefs_rootdir \"~/.taglog-diary\"" .editprefs.c.rootdir.l.m add separator .editprefs.c.rootdir.l.m add command -label [mc "Help"] -command "taghelp prefs_rootdir" entry .editprefs.c.rootdir.v -textvariable editprefs_rootdir -width 40 if { [info tclversion] >= 8.3 } { button .editprefs.c.rootdir.pick -text [mc "Pick"] -command { set editprefs_rootdir [tk_chooseDirectory -title [mc "Data directory root"] -mustexist 0 -initialdir $editprefs_rootdir -parent .editprefs] } } pack .editprefs.c.rootdir.l .editprefs.c.rootdir.v -side left -in .editprefs.c.rootdir if { [info tclversion] >= 8.3 } { pack .editprefs.c.rootdir.pick -side left -in .editprefs.c.rootdir } pack .editprefs.c.rootdir # Activities file set editprefs_activitiesFile "$activitiesfilename" frame .editprefs.c.activitiesFile menubutton .editprefs.c.activitiesFile.l -text [mc "Activities File"] -menu .editprefs.c.activitiesFile.l.m menu .editprefs.c.activitiesFile.l.m if { $tcl_platform(platform) == "windows" } { if [ info exists env(USERPROFILE)] { set df [file join $env(USERPROFILE) diary] if { [file isdirectory $env(USERPROFILE)] } { .editprefs.c.activitiesFile.l.m add command -label $df -command "set editprefs_activitiesFile \"$df\"" } } } .editprefs.c.activitiesFile.l.m add command -label "~/diary/activities" -command "set editprefs_activitiesFile \"~/diary/activities\"" .editprefs.c.activitiesFile.l.m add command -label "~/.taglog_actvities" -command "set editprefs_activitiesFile \"~/.taglog_activities\"" .editprefs.c.activitiesFile.l.m add separator .editprefs.c.activitiesFile.l.m add command -label [mc "Help"] -command "taghelp prefs_activitiesfile" entry .editprefs.c.activitiesFile.v -textvariable editprefs_activitiesFile -width 40 if { [info tclversion] >= 8.3 } { button .editprefs.c.activitiesFile.pick -text [mc "Pick"] -command { set editprefs_activitiesFile [tk_getOpenFile -title [mc "Activities File"] -initialdir $editprefs_rootdir -parent .editprefs] } } pack .editprefs.c.activitiesFile.l .editprefs.c.activitiesFile.v -side left -in .editprefs.c.activitiesFile if { [info tclversion] >= 8.3 } { pack .editprefs.c.activitiesFile.pick -side left -in .editprefs.c.activitiesFile } pack .editprefs.c.activitiesFile # Language set editprefs_language $language frame .editprefs.c.language menubutton .editprefs.c.language.l -text [mc Language] -menu .editprefs.c.language.l.m menu .editprefs.c.language.l.m .editprefs.c.language.l.m add command -label "English (en)" -command "set editprefs_language en" .editprefs.c.language.l.m add command -label "Deutsch (de)" -command "set editprefs_language de" .editprefs.c.language.l.m add command -label "Español (es) (minimal)" -command "set editprefs_language es" .editprefs.c.language.l.m add command -label "Francais (fr) (minimal)" -command "set editprefs_language fr" .editprefs.c.language.l.m add command -label "Ελληνικά (el) (minimal)" -command "set editprefs_language el" .editprefs.c.language.l.m add command -label "Italiano (it) (minimal)" -command "set editprefs_language it" .editprefs.c.language.l.m add command -label "Nederlands (nl) (minimal)" -command "set editprefs_language nl" .editprefs.c.language.l.m add separator .editprefs.c.language.l.m add command -label [mc Help] -command "taghelp prefs_language" entry .editprefs.c.language.v -textvariable editprefs_language pack .editprefs.c.language.l .editprefs.c.language.v -side left -in .editprefs.c.language pack .editprefs.c.language set editprefs_showtime_spreadoverheads $showtime_spreadoverheads frame .editprefs.c.spreadoverheads menubutton .editprefs.c.spreadoverheads.l -text [mc "Spread Overheads"] -menu .editprefs.c.spreadoverheads.l.m menu .editprefs.c.spreadoverheads.l.m .editprefs.c.spreadoverheads.l.m add command -label [mc Help] -command "taghelp prefs_showtime_spreadoverheads" radiobutton .editprefs.c.spreadoverheads.off -relief flat -variable showtime_spreadoverheads -value off -text [mc Off] radiobutton .editprefs.c.spreadoverheads.byday -relief flat -variable showtime_spreadoverheads -value byday -text [mc Day] radiobutton .editprefs.c.spreadoverheads.byweek -relief flat -variable showtime_spreadoverheads -value byweek -text [mc Week] # Put the Default time bookings report starts last week flag here too set editprefs_timebook_startlastweek $timebook_startlastweek menubutton .editprefs.c.spreadoverheads.l2 -text [mc "Time Bookings starts"] -menu .editprefs.c.spreadoverheads.l2.m menu .editprefs.c.spreadoverheads.l2.m .editprefs.c.spreadoverheads.l2.m add command -label [mc Help] -command "taghelp prefs_timebook_startlastweek" radiobutton .editprefs.c.spreadoverheads.r1 -text [mc "last week"] -variable editprefs_timebook_startlastweek -value 1 radiobutton .editprefs.c.spreadoverheads.r2 -text [mc "this week"] -variable editprefs_timebook_startlastweek -value 0 pack .editprefs.c.spreadoverheads.l .editprefs.c.spreadoverheads.off .editprefs.c.spreadoverheads.byday .editprefs.c.spreadoverheads.byweek .editprefs.c.spreadoverheads.l2 .editprefs.c.spreadoverheads.r1 .editprefs.c.spreadoverheads.l2 .editprefs.c.spreadoverheads.r1 .editprefs.c.spreadoverheads.r2 -in .editprefs.c.spreadoverheads -side left pack .editprefs.c.spreadoverheads set editprefs_showtime_hours_per_day $showtime_hours_per_day frame .editprefs.c.hours menubutton .editprefs.c.hours.l -text [mc "Hours Worked per Day (decimal)"] -menu .editprefs.c.hours.l.m menu .editprefs.c.hours.l.m .editprefs.c.hours.l.m add command -label [mc Help] -command "taghelp prefs_showtime_hours_per_day" entry .editprefs.c.hours.e -textvariable editprefs_showtime_hours_per_day -width 6 pack .editprefs.c.hours.l .editprefs.c.hours.e -side left -in .editprefs.c.hours pack .editprefs.c.hours set editprefs_dateformat $dateformat_view frame .editprefs.c.dateformat menubutton .editprefs.c.dateformat.l -text [mc "Date Format"] -menu .editprefs.c.dateformat.l.m menu .editprefs.c.dateformat.l.m .editprefs.c.dateformat.l.m add command -label "ISO (YYYY-MM-DD)" -command "set editprefs_dateformat \"YYYY-MM-DD\"" .editprefs.c.dateformat.l.m add command -label [mc "European (DD/MM/YYYY)"] -command "set editprefs_dateformat \"DD/MM/YYYY\"" .editprefs.c.dateformat.l.m add command -label [mc "American (MM/DD/YYYY)"] -command "set editprefs_dateformat \"MM/DD/YYYY\"" .editprefs.c.dateformat.l.m add separator .editprefs.c.dateformat.l.m add command -label [mc "Help"] -command "taghelp prefs_dateformat" entry .editprefs.c.dateformat.e -textvariable editprefs_dateformat pack .editprefs.c.dateformat.l .editprefs.c.dateformat.e -side left -in .editprefs.c.dateformat pack .editprefs.c.dateformat set editprefs_timeformat $currentTimeFormat frame .editprefs.c.timeformat menubutton .editprefs.c.timeformat.l -text [mc "Time Format"] -menu .editprefs.c.timeformat.l.m menu .editprefs.c.timeformat.l.m .editprefs.c.timeformat.l.m add command -label [mc "Default (HH:MM:SS)"] -command "set editprefs_timeformat \"%d:%02d:%02d\"" .editprefs.c.timeformat.l.m add command -label [mc "No seconds (HH:MM)"] -command "set editprefs_timeformat \"%d:%02d\"" .editprefs.c.timeformat.l.m add separator .editprefs.c.timeformat.l.m add command -label [mc "Help"] -command "taghelp prefs_timeformat" entry .editprefs.c.timeformat.e -textvariable editprefs_timeformat pack .editprefs.c.timeformat.l .editprefs.c.timeformat.e -side left -in .editprefs.c.timeformat pack .editprefs.c.timeformat set editprefs_history_win_depth $history_win_depth frame .editprefs.c.history_win_depth menubutton .editprefs.c.history_win_depth.l -text [mc "History Window Depth"] -menu .editprefs.c.history_win_depth.l.m menu .editprefs.c.history_win_depth.l.m .editprefs.c.history_win_depth.l.m add command -label [mc "Help"] -command "taghelp editprefs_history_win_depth" entry .editprefs.c.history_win_depth.e -textvariable editprefs_history_win_depth pack .editprefs.c.history_win_depth.l .editprefs.c.history_win_depth.e -side left -in .editprefs.c.history_win_depth pack .editprefs.c.history_win_depth set editprefs_current_win_depth $current_win_depth frame .editprefs.c.current_win_depth menubutton .editprefs.c.current_win_depth.l -text [mc "Current Window Depth"] -menu .editprefs.c.current_win_depth.l.m menu .editprefs.c.current_win_depth.l.m .editprefs.c.current_win_depth.l.m add command -label [mc "Help"] -command "taghelp editprefs_current_win_depth" entry .editprefs.c.current_win_depth.e -textvariable editprefs_current_win_depth pack .editprefs.c.current_win_depth.l .editprefs.c.current_win_depth.e -side left -in .editprefs.c.current_win_depth pack .editprefs.c.current_win_depth set editprefs_num_today_actions $num_today_actions # If we are on a small screen default to 0 if { [winfo screenmmheight .] < 150 } { set editprefs_num_today_actions 0 } frame .editprefs.c.num_today_actions menubutton .editprefs.c.num_today_actions.l -text [mc "Number of 'Today' actions"] -menu .editprefs.c.num_today_actions.l.m menu .editprefs.c.num_today_actions.l.m .editprefs.c.num_today_actions.l.m add command -label "0" -command "set editprefs_num_today_actions 0" .editprefs.c.num_today_actions.l.m add command -label "1" -command "set editprefs_num_today_actions 1" .editprefs.c.num_today_actions.l.m add command -label "2" -command "set editprefs_num_today_actions 2" .editprefs.c.num_today_actions.l.m add command -label "3" -command "set editprefs_num_today_actions 3" .editprefs.c.num_today_actions.l.m add separator .editprefs.c.num_today_actions.l.m add command -label [mc "Help"] -command "taghelp editprefs_num_today_actions" entry .editprefs.c.num_today_actions.e -textvariable editprefs_num_today_actions pack .editprefs.c.num_today_actions.l .editprefs.c.num_today_actions.e -side left -in .editprefs.c.num_today_actions pack .editprefs.c.num_today_actions set editprefs_id_prefix $id_prefix frame .editprefs.c.id_prefix menubutton .editprefs.c.id_prefix.l -text "Id [mc Prefix]" -menu .editprefs.c.id_prefix.l.m menu .editprefs.c.id_prefix.l.m .editprefs.c.id_prefix.l.m add command -label [mc "Help"] -command "taghelp editprefs_id_prefix" entry .editprefs.c.id_prefix.e -textvariable editprefs_id_prefix pack .editprefs.c.id_prefix.l .editprefs.c.id_prefix.e -side left -in .editprefs.c.id_prefix pack .editprefs.c.id_prefix set editprefs_start_procs $start_procs frame .editprefs.c.start_procs menubutton .editprefs.c.start_procs.l -text [mc "Start Procs"] -menu .editprefs.c.start_procs.l.m menu .editprefs.c.start_procs.l.m .editprefs.c.start_procs.l.m add command -label "--" -command "set editprefs_start_procs \"\"" .editprefs.c.start_procs.l.m add command -label "iconify_mainwin doShowProjects" -command "set editprefs_start_procs \"iconify_mainwin doShowProjects\"" .editprefs.c.start_procs.l.m add separator .editprefs.c.start_procs.l.m add command -label [mc "Help"] -command "taghelp editprefs_start_procs" entry .editprefs.c.start_procs.e -textvariable editprefs_start_procs pack .editprefs.c.start_procs.l .editprefs.c.start_procs.e -side left -in .editprefs.c.start_procs pack .editprefs.c.start_procs set editprefs_projects_url $projects_url frame .editprefs.c.projects_url menubutton .editprefs.c.projects_url.l -text [mc "Projects URL"] -menu .editprefs.c.projects_url.l.m menu .editprefs.c.projects_url.l.m .editprefs.c.projects_url.l.m add command -label [mc "Help"] -command "taghelp editprefs_projects_url" entry .editprefs.c.projects_url.e -textvariable editprefs_projects_url -width 40 pack .editprefs.c.projects_url.l .editprefs.c.projects_url.e -side left -in .editprefs.c.projects_url pack .editprefs.c.projects_url smtp init set editprefs_smtp_prefsfile $smtpv(prefsfile) frame .editprefs.c.smtp_prefsfile menubutton .editprefs.c.smtp_prefsfile.l -text [mc "SMTP Preferences filename"] -menu .editprefs.c.smtp_prefsfile.l.m menu .editprefs.c.smtp_prefsfile.l.m .editprefs.c.smtp_prefsfile.l.m add command -label "~/.smtp" -command "set editprefs_smtp_prefsfile \"~/.smtp\"" .editprefs.c.smtp_prefsfile.l.m add command -label "~/smtp.cfg" -command "set editprefs_smtp_prefsfile \"~/smtp.cfg\"" .editprefs.c.smtp_prefsfile.l.m add separator .editprefs.c.smtp_prefsfile.l.m add command -label [mc Help] -command "taghelp smtp_prefsfile" entry .editprefs.c.smtp_prefsfile.v -textvariable editprefs_smtp_prefsfile -width 15 pack .editprefs.c.smtp_prefsfile.l .editprefs.c.smtp_prefsfile.v -side left -in .editprefs.c.smtp_prefsfile pack .editprefs.c.smtp_prefsfile set editprefs_smtp_thishost $smtpv(thishost) frame .editprefs.c.smtp_thishost menubutton .editprefs.c.smtp_thishost.l -text "SMTP thishost" -menu .editprefs.c.smtp_thishost.l.m menu .editprefs.c.smtp_thishost.l.m .editprefs.c.smtp_thishost.l.m add command -label [mc Help] -command "taghelp smtp_thishost" entry .editprefs.c.smtp_thishost.v -textvariable editprefs_smtp_thishost pack .editprefs.c.smtp_thishost.l .editprefs.c.smtp_thishost.v -in .editprefs.c.smtp_thishost -side left pack .editprefs.c.smtp_thishost set editprefs_smtp_mailhost $smtpv(mailhost) frame .editprefs.c.smtp_mailhost menubutton .editprefs.c.smtp_mailhost.l -text "SMTP mailhost" -menu .editprefs.c.smtp_mailhost.l.m menu .editprefs.c.smtp_mailhost.l.m .editprefs.c.smtp_mailhost.l.m add command -label [mc Help] -command "taghelp smtp_mailhost" entry .editprefs.c.smtp_mailhost.v -textvariable editprefs_smtp_mailhost -width 15 pack .editprefs.c.smtp_mailhost.l .editprefs.c.smtp_mailhost.v -side left -in .editprefs.c.smtp_mailhost pack .editprefs.c.smtp_mailhost set editprefs_smtp_myemail $smtpv(myemail) frame .editprefs.c.smtp_myemail menubutton .editprefs.c.smtp_myemail.l -text "SMTP [mc {email address}]" -menu .editprefs.c.smtp_myemail.l.m menu .editprefs.c.smtp_myemail.l.m .editprefs.c.smtp_myemail.l.m add command -label [mc Help] -command "taghelp smtp_myemail" entry .editprefs.c.smtp_myemail.v -textvariable editprefs_smtp_myemail -width 20 pack .editprefs.c.smtp_myemail.l .editprefs.c.smtp_myemail.v -side left -in .editprefs.c.smtp_myemail pack .editprefs.c.smtp_myemail set editprefs_smtp_port $smtpv(port) frame .editprefs.c.smtp_port menubutton .editprefs.c.smtp_port.l -text "SMTP port" -menu .editprefs.c.smtp_port.l.m menu .editprefs.c.smtp_port.l.m .editprefs.c.smtp_port.l.m add command -label "25 ([mc traditional] SMTP)" -command "set editprefs_smtp_port 25" .editprefs.c.smtp_port.l.m add command -label "587 ([mc {local mail submission port}])" -command "set editprefs_smtp_port 587" .editprefs.c.smtp_port.l.m add separator .editprefs.c.smtp_port.l.m add command -label [mc Help] -command "taghelp smtp_port" entry .editprefs.c.smtp_port.v -textvariable editprefs_smtp_port -width 5 pack .editprefs.c.smtp_port.l .editprefs.c.smtp_port.v -side left -in .editprefs.c.smtp_port pack .editprefs.c.smtp_port frame .editprefs.c.bot button .editprefs.c.bot.ok -text Ok -command editprefsOK button .editprefs.c.bot.cancel -text [mc Cancel] -command { doCancel .editprefs } button .editprefs.c.bot.help -text [mc Help] -command "taghelp editprefs" pack .editprefs.c.bot.ok .editprefs.c.bot.cancel .editprefs.c.bot.help -side left -in .editprefs.c.bot pack .editprefs.c.bot -side bottom -before .editprefs.c.docdir # .editprefs.c configure -scrollregion [.editprefs.c bbox all] tkwait window .editprefs } proc savePrefs {} { global prefsfile tcl_platform global docdir global language global showtime_hours_per_day global dateformat_view dateformat_tcl global rootdir libsdir global num_today_actions history_win_depth current_win_depth global id_prefix global start_procs exit_procs global projects_url global showtime_spreadoverheads global timebook_startlastweek global activities global activitiesfilename global currentTimeFormat set header "# Preferences for taglog" set marker "# above this line is automatically saved - put your changes below here -" if { $prefsfile !="" } { set f [open $prefsfile] set prev_prefs [read $f] close $f # mangle previous preferences set autoend [string last $marker $prev_prefs] if { $autoend != -1 } { incr autoend [string length $marker] set prev_prefs [string trim [string range $prev_prefs $autoend end]] } set f [open $prefsfile w] puts $f "$header" puts $f "set language $language" puts $f "set showtime_hours_per_day $showtime_hours_per_day" puts $f "set docdir \"$docdir\"" puts $f "set libsdir \"$libsdir\"" puts $f "set rootdir \"$rootdir\"" puts $f "set showtime_spreadoverheads $showtime_spreadoverheads" puts $f "set timebook_startlastweek $timebook_startlastweek" puts $f "set dateformat_view $dateformat_view" puts $f "set dateformat_tcl $dateformat_tcl" puts $f "set currentTimeFormat $currentTimeFormat" puts $f "set num_today_actions $num_today_actions" puts $f "set history_win_depth $history_win_depth" puts $f "set current_win_depth $current_win_depth" puts $f "set id_prefix \"$id_prefix\"" puts $f "set start_procs \{ $start_procs \}" puts $f "set exit_procs $exit_procs" puts $f "set projects_url \"$projects_url\"" puts $f "set activitiesfilename \"$activitiesfilename\"" puts $f "$marker" puts $f "$prev_prefs" close $f } else { set prev_prefs "" # deal with new prefs file if {$tcl_platform(platform) == "unix"} { set prefsfile "~/.taglog" } elseif {$tcl_platform(platform) == "windows"} { set prefsfile "~/taglog.cfg" } else { puts "Unknown platform $tcl_platform(platform) - please report to john+taglog@paladyn.org" exit } set f [open $prefsfile w] puts $f "$header" puts $f "$marker" puts $f "$prev_prefs" close $f } } taglog-0.2.6/src/fr.msg0000644000175000017500000003047413534701742013376 0ustar johnjohn# namespace import -force msgcat::mcset mcset fr Help Aide #mcset fr Cancel Abbruch mcset fr Quit Stopp mcset fr Exit Sortie #mcset fr Next Weiter #mcset fr Action Aktion #mcset fr Actions Aktionen #mcset fr actions Aktionen #mcset fr Reports Berichte mcset fr Preferences Prfrences #mcset fr Open... ffnen #mcset fr Pause Anhalten #mcset fr Resume Fortfahren #mcset fr {Add/Edit Log} {Log Hinzufgen/ndern} #mcset fr Add... Hinzufgen... #mcset fr View Ansicht #mcset fr Complete Abschlieen #mcset fr Activate Aktivieren #mcset fr {Abort Active} {Abbruch Aktiv} #mcset fr {Abort Pending} {Abbruch Wartend} #mcset fr Abort Abbrechen #mcset fr Reactivate Reaktivieren #mcset fr Projects Projekte #mcset fr Add Hinzufgen #mcset fr Edit Bearbeiten #mcset fr About ber #mcset fr {Please select the date of log} {Bitte das Datum fr Logeintrge auswhlen,} #mcset fr {entries to be input or edited} {die bearbeitet oder neu eingegeben werden sollen} #mcset fr {Input and editing of log entries} {Eingabe und Bearbeitung von Logeintrgen} #mcset fr "Log edit" Log-Bearbeitung #mcset fr "Date selection" "Datumauswahl" #mcset fr "No date selected" "Kein Datum ausgewhlt" #mcset fr "Invalid date format" "Ungltiges Datumsformat" #mcset fr "Editing of log file" "Bearbeitung einer Log-Datei" mcset fr Day Jour mcset fr day jour mcset fr days jours #mcset fr week Woche #mcset fr "Import of log entries" "Import von Logeintrgen" #mcset fr File Datei #mcset fr {No entries found in file} {Keine Eintrge gefunden in Datei} #mcset fr "Import all" "Alles" #mcset fr Import Importieren #mcset fr Project Projekt #mcset fr "End " Ende #mcset fr End Ende #mcset fr Delete Lschen #mcset fr "Edit log entry" "Bearbeitung eines Log-Eintrages" #mcset fr "Add a new entry" "Neuer Log-Eintrag" #mcset fr {Start Time} Startzeit #mcset fr {End Time} Ende #mcset fr {ActionTitle} {Titel der Aktion} #mcset fr Activity Aktivitt #mcset fr Contact Kontakt #mcset fr Contacts Kontakte #mcset fr Save Speichern #mcset fr "Save As..." "Speichern unter..." #mcset fr Description Beschreibung #mcset fr "Adjust to previous EndTime" "Zeit an vorheriges Ende anpassen" #mcset fr "Adjust to following Startime" "An nchste Startzeit anpassen" #mcset fr "Invalid date range" "Zeitbereich ungltig" #mcset fr "The StartTime is greater\nthan the EndTime" "Startzeit grer als Endzeit" #mcset fr "Invalid date" "Ungltiges Datum" #mcset fr {Please enter a value for} {Bitte einen Wert eingeben fr:} #mcset fr {is not a valid\ntime value for} {ist keine gltige\nZeit fr Tag} #mcset fr "There are overlapping (marked with '>')\nand inconsistent (marked with '!') time ranges." "Es existieren berlappende ('>')\nund inkonsistente '(!)' Zeitbereiche." #mcset fr "There are overlapping time ranges (marked with '>')." "Es existieren berlappende Zeitbereiche." #mcset fr "There are inconsistent time ranges (marked with '!')." "Es existieren inkonsistente Zeitbereiche." #mcset fr {Do you want to save?} {Wollen Sie trotzdem abspeichern?} #mcset fr "Weekly time bookings by project" "Projekte: Wchentliche Zeitbuchungen" #mcset fr "Time by activity" "Gesamtzeit je Aktivitt" #mcset fr "Total time for a project" "Gesamtzeit fr ein Projekt" #mcset fr "Project Progress Report" "Projektfortschritt" #mcset fr Directory Verzeichnis #mcset fr "Current Directory" "Aktuelles Verzeichnis" #mcset fr "File name :" "Dateiname:" #mcset fr "Save Text" "Speichern als Text" #mcset fr "Save HTML" "Speichern als HTML" #mcset fr "Save HTML..." "Speichern als HTML ..." #mcset fr "Description contains" "Beschreibung enthlt" #mcset fr "Documentation Directory" "Dokumentationsverzeichnis" #mcset fr "Data directory root" "Wurzelverzeichnis fr Daten" #mcset fr Language Sprache #mcset fr "Hours Worked per Day (decimal)" "Arbeitsstunden pro Tag (dezimal)" #mcset fr "Date Format" Datumsformat #mcset fr "European (DD/MM/YYYY)" "Europisch (DD/MM/YYYY)" #mcset fr "American (MM/DD/YYYY)" "Amerikanisch (MM/DD/YYYY)" #mcset fr "History Window Depth" {Zeilen fr Historien-Fenster} #mcset fr "Current Window Depth" "Zeilen fr Log-Fenster" #mcset fr "Number of 'Today' actions" "Anzahl der 'Heute'-Aktionen" #mcset fr Prefix Prfix #mcset fr "SMTP Preferences filename" "Dateiname fr SMTP-Einstellungen" #mcset fr "email address" "EMail-Adresse" #mcset fr traditional traditionell #mcset fr "local mail submission port" "lokaler Mail-Port" #mcset fr "Input an action" "Eingabe einer Aktion" #mcset fr {Edit action} "Bearbeite Aktion" #mcset fr Title Titel #mcset fr Date Datum #mcset fr Priority Prioritt #mcset fr Expected-cost "Erwartete Kosten" #mcset fr Expected-time "Erwartete Zeit" #mcset fr Expected-Time "Erwartete Zeit" #mcset fr Revised-expected-time "Gend. Erwartete Zeit" #mcset fr Expected-start-date "Erwartete Startzeit" #mcset fr Completed-date "Fertigstellungsdatum" #mcset fr Active-date "Aktivierungsdatum" #mcset fr Aborted-date "Abbruchdatum" #mcset fr Expected-completed-date "Erw-Fertigstellungsdatum" #mcset fr Expected-Completed-Date "Erw-Fertigstellungsdatum" #mcset fr Revised-expected-completed-date "Gend. Erw-Fertigstellungsdatum" #mcset fr Revised-date Gend-Datum #mcset fr Precursor Vorgnger #mcset fr Active-after "Aktiv nach" #mcset fr Subtask-of "Unteraufgabe von" #mcset fr Next-action "Nchste Aktion" #mcset fr Abort-action Abbruch-Aktion #mcset fr Difficulty Schwierigkeit #mcset fr nobrainer simpel #mcset fr trivial trivial #mcset fr easy leicht #mcset fr tricky anspruchsvoll #mcset fr hard schwer #mcset fr "very hard" "sehr schwer" #mcset fr Email-status-to "Sende-Status an" #mcset fr Deliverable Auslieferbar #mcset fr Reason Grund #mcset fr Message Nachricht #mcset fr "Mail to" "Sende an" #mcset fr "Mail an action" "Sende eine Aktion" #mcset fr "Add a new project" "Neues Projekt" #mcset fr "Project name" Projektname #mcset fr "Book as breaks" "Als Pause buchen" #mcset fr "Book as overheads" "Als Overhead buchen" #mcset fr "Booking Code" "Buchungs-Code" #mcset fr "Start Date" "Startdatum" #mcset fr "End Date" "Beendigungsdatum" #mcset fr "Edit Projects" "Projekte bearbeiten" #mcset fr Breaks Pausen #mcset fr "Project Times" Projektzeiten #mcset fr Total Gesamt #mcset fr "Total (non breaks)" "Gesamt (ohne Pausen)" #mcset fr Today Heute #mcset fr "Select date range" "Zeitbereich" #mcset fr "Enter Project details" Projektdetails #mcset fr "Enter information for Project Progress Report" "Projektfortschritt" #mcset fr "Select Time Period" "Auswahl der Zeitbereichs" #mcset fr "Time Format" Zeitformat #mcset fr "Decimal hours" "Stunden dezimal" #mcset fr "Decimal days" "Tage dezimal" #mcset fr "Spread overhead projects" "Overhead Projekte aufteilen" #mcset fr "Book by Project" "Sortieren nach Projekt" #mcset fr Year Jahr #mcset fr weeks Wochen #mcset fr "starting at number" "Start bei" #mcset fr "Time by Activity" "Gesamtzeit je Aktivitt" #mcset fr "Project Progress Report for" "Projektfortschrittsbericht fr" #mcset fr "Total Times for" "Gesamtzeit fr" #mcset fr "Time Bookings" "Zeitbuchungen" mcset fr Sun "Dim" mcset fr Mon "Lun" mcset fr Tue "Mar" mcset fr Wed "Mer" mcset fr Thu "Jeu" mcset fr Fri "Ven" mcset fr Sat "Sam" #mcset fr "Breaks total" "Pausen gesamt" #mcset fr "Time Bookings for week" "Zeitbuchungen fr Kalenderwoche" #mcset fr of von #mcset fr "Warning - cant open" "Warnung - folgende Datei kann nicht geffnet werden:" #mcset fr "Total time" Gesamtzeit #mcset fr "Total time for" "Die Gesamtzeit fr" #mcset fr is ist #mcset fr "decimal days" "dezimale Tage" #mcset fr Examined "Untersucht wurden" #mcset fr "files and found entries for" "Dateien. Gefunden wurden Eintrge fr" #mcset fr "of them" "von ihnen" #mcset fr "First date was" "Erstes Datum:" #mcset fr "last date was" "Letztes Datum:" #mcset fr "Adjust start time" "Startzeit anpassen" #mcset fr "Adjust start time back towards previous start time of" "Startzeit anpassen in Richtung auf vorherige Startzeit von" #mcset fr "Adjust start time back towards the start of the day" "Startzeit an Tagesbeginn anpassen" #mcset fr "Adjust previous end time" "Vorherige End-Zeit anpassen" #mcset fr "New Start Time" "Neue Startzeit" #mcset fr "Minutes to Subtract from StartTime" "Zu subtrahierende Minuten" #mcset fr Set "Startzeit setzen" #mcset fr calendar Kalender #mcset fr Calendar Kalender #mcset fr Su So #mcset fr Tu Di #mcset fr We Mi #mcset fr Th Do #mcset fr January Januar #mcset fr February Februar #mcset fr March Mrz #mcset fr April April #mcset fr May Mai #mcset fr June Juni #mcset fr July Juli #mcset fr August August #mcset fr September September #mcset fr October Oktober #mcset fr November November #mcset fr December Dezember #mcset fr "Select Contacts to view" "Auswahl zum Anzeigen von Kontakten" #mcset fr Forename Vorname #mcset fr Phone Telefon #mcset fr Type Typ #mcset fr Surname Nachname #mcset fr "Contacts Display" "Anzeige der Kontakte" #mcset fr Close Schlieen #mcset fr Address Adresse #mcset fr Short-id Kurz-Id #mcset fr "Input a contact" "Kontakt eingeben" #mcset fr "Edit contact" "Bearbeite Kontakt" #mcset fr Mr Herr #mcset fr Ms Frulein #mcset fr Mrs Frau #mcset fr "Default-as" "Vorbesetzen mit" #mcset fr "Mobile Phone" Mobiltelefon #mcset fr Postcode Postleitzahl #mcset fr Country Land #mcset fr Note Bemerkung #mcset fr "Select Actions ..." "Aktionen auswhlen ..." #mcset fr Filename Dateiname #mcset fr All Alle #mcset fr Any Beliebig #mcset fr Unclaimed Unveranlagt #mcset fr Pending Wartend #mcset fr Active Aktiv #mcset fr Blocked Blockiert #mcset fr Completed Abgeschlossen #mcset fr Aborted Abgebrochen #mcset fr "Date Expected" "Erwartetes Datum" #mcset fr Tomorrow Morgen #mcset fr Later Spter #mcset fr Earlier Frher #mcset fr "Show Fields" "Felder anzeigen" #mcset fr "Due Date" "Flligkeitsdatum" #mcset fr Refresh Aktualisieren #mcset fr "Sort by" "Sortieren nach" #mcset fr "Actions view of" "Aktionen, Sicht von:" #mcset fr "Save Action History As ..." "Speichere Aktions-Historie unter..." #mcset fr "Action history" "Historie fr Aktion" #mcset fr Revise ndern #mcset fr History Historie #mcset fr Duration Dauer #mcset fr "Total duration" Gesamtdauer #mcset fr "Save Actions Display As ..." "Speichere Aktionsanzeige unter ..." #mcset fr "Save Log View Display As ..." "Speichere Log-Anzeige unter ..." #mcset fr "Select Log Files ..." "Auswahl von Log-Dateien" #mcset fr "Log view" "Log-Anzeige" #mcset fr "Edit Preferences" "Bearbeite Einstellungen" #mcset fr Displayed Angezeigt: #mcset fr "Total expected time" "Gesamte erwartete Zeit:" #mcset fr unknown unbekannt #mcset fr "Pick an action to move from" "Wechsel des Status einer Aktion von" #mcset fr to nach #mcset fr "Refresh Active" "Liste der aktiven Akt. neu aufbauen" #mcset fr "Active Time Blocked" "Aktiviere fllige Aktionen" #mcset fr "Archive Old Actions" "Archiviere alte Aktionen" #mcset fr colleague Kollege #mcset fr customer Kunde #mcset fr supplier Lieferant #mcset fr contact Kontakt #mcset fr friend Privat #mcset fr "Interruptions Report" "Unterbrechungen" #mcset fr "There were a total of" "Es gibt insgesamt" #mcset fr "interruptions in" "Unterbrechungen in" #mcset fr "days." "Tagen." #mcset fr "The average number of interruptions in a day was" "Die durchschnittliche Anzahl von Unterbrechungen pro Tag war" #mcset fr "The peak number of interruptions per day was" "Die Spitzen-Anzahl von Unterbrechungen pro Tag war" #mcset fr "vCard Files" "vCard Dateien" #mcset fr " vCard files to Import" " Zu importierende vCard Dateien" #mcset fr "Introduction" "Einfhrung" #mcset fr "Hints" "Hinweise" #mcset fr "Actions overrun" "berschreitung der geplanten Zeiten" #mcset fr "Actions not completed" "Aktivitten nicht beendet" #mcset fr "Interruptions" "Unterbrechungen" #mcset fr "Progress from" "Fortschritt von" #mcset fr " to " " bis " #mcset fr "Achievements" "Erreichtes" #mcset fr "Tasks completed since last report" "Seit letztem Bericht erledigte Aufgaben" #mcset fr "Expected" "Erwartet" #mcset fr "Actual" "Tatschlich" #mcset fr "Tasks started since last report" "Seit letztem Bericht gestartete Aufgaben" #mcset fr "Tasks slipped since last report" "Aufgaben, die die Zeit berschreiten werden" #mcset fr "Active tasks" "Aktive Aufgaben" #mcset fr "Scheduled" "Geplant" #mcset fr "Forecast" "Prognose" #mcset fr "Completion" "Erledigung" #mcset fr "Delegated-to" "Delegiert an" #mcset fr "Delegated" "Delegiert" #mcset fr "delegated" "delegiert" #mcset fr "Pick" "Auswahl" #mcset fr "Update" "Aktualisierung" #mcset fr "meeting-preparation" "Besprechungsvorbereitung" #mcset fr "meeting" "Besprechung" #mcset fr "email" "EMail" taglog-0.2.6/src/taglog_stack.tcl0000644000175000017500000000231113534701742015412 0ustar johnjohn # # taglog_stack.tcl - action and project stack for taglog # Copyright John Lines (john+taglog@paladyn.org) June 2002 # # This program is released under the terms of the GNU Public Licence # package provide taglog_stack 0.1 proc stack_push { type } { global stackdepth stack_project stack_action_title stack_action_id stack_log_id global currentProject currentActionTitle currentAction global stack_info incr stackdepth set stack_project($stackdepth) $currentProject set stack_action_title($stackdepth) $currentActionTitle set stack_action_id($stackdepth) $currentAction set stack_log_id($stackdepth) [donext ""] .actionbar.stack.pop configure -state normal set stack_info "$type $stack_log_id($stackdepth)" } proc stack_pop {} { global stackdepth stack_project stack_action_title stack_action_id stack_log_id global currentProject currentActionTitle currentAction global stack_info donext "" set currentProject $stack_project($stackdepth) set currentActionTitle $stack_action_title($stackdepth) set currentAction $stack_action_id($stackdepth) set stack_info "- $stack_log_id($stackdepth)" incr stackdepth -1 if { $stackdepth == 0 } { .actionbar.stack.pop configure -state disabled set stack_info "" } } taglog-0.2.6/src/taglog_action.tcl0000644000175000017500000021624613603645436015604 0ustar johnjohn# # taglog_action.tcl - routines dealing with actions for taglog # Copyright John Lines (john+taglog@paladyn.org) September 2000 # # This program is released under the terms of the GNU Public Licence # package provide taglog_action 0.1 proc setupActivateAfter { action } { # If required set up an event to activate an action after some time interval # Note that we dont worry if we are putting in an action which will happen a # very long time in the future set aa [tag_entryVal $action Active-after] # puts "setupActivateAfter Active-after = $aa" if {$aa == "" } return set st [tag_entryVal $action Status] if { ($st != "Blocked") && ($st != "Delegated") } return set timetowait [expr { [clock scan $aa] - [clock seconds] } ] set timetowait [expr { $timetowait * 1000 } ] set id [tag_entryVal $action Id] after $timetowait "activate_timeblocked_action $id" } proc actionInputOK { w winnum { idvar ""} } { global year month day hh mm id_prefix global actin_f_a global action_textarea_fields set thisaction "" # need to get the text variables from the window foreach field $action_textarea_fields { regsub -all {\.-} $field _ safe_label set safe_label [string tolower $safe_label] set actin_f_a($winnum,$field) [string trim [$w.m.c.f.$safe_label.tagvalue get 1.0 end]] } setupAutoId $winnum set thisaction [writeaction $thisaction $winnum] setactionsmenu set thisemail $actin_f_a($winnum,Email-status-to) if { $thisemail != "" } { if { ! [ smtp init ] } { # put up a dialog box saying that mail is not initialised } else { set msg "The attached action has just been created" smtp send -subject "Action creation notification" -attachtag $thisaction -header action $msg $actin_f_a($winnum,Email-status-to) } } if { $idvar != "" } { set $idvar $actin_f_a($winnum,Id) } destroy $w } proc actionEditOK { w winnum } { global year month day hh mm global allact allactstate global actin_f_a global actedit_fields global action_textarea_fields set thisaction "" # need to get the text variables from the window foreach field $action_textarea_fields { regsub -all {\.-} $field _ safe_label set safe_label [string tolower $safe_label] set actin_f_a($winnum,$field) [string trim [$w.m.c.f.$safe_label.tagvalue get 1.0 end]] } set action [ getact_input_fields $winnum -noend ] # add the fields from actedit_fields foreach field [array names actedit_fields] { set action [tagappend $action [index2fieldname $field] $actedit_fields($field)] } set endpair [list End ] lappend action $endpair set allactstate modified foreach item $action { if { [lindex $item 0] == "Id" } { set thisid [lindex $item 1] } } set test [ list Id "==" $thisid ] set idx 0 foreach entry $allact { if [ tag matchcond $entry $test ] { set allact [lreplace $allact $idx $idx $action] } incr idx } writeallact setactionsmenu setupActivateAfter $action destroy $w } proc actionInputWindow { mode {winnum 0} {idvar ""} {setValues ""} } { global actin_f_a global hh mm ss year month day global validStates global scrollside global allcontacts global currentProject set actin_filled_fields {} set actin_empty_fields {} # Change for 0.2.4 - the variable argument is no longer used - although still present at the moment # Instead the variable is always taken from the global array, and the winnum and label fields proc actin_setup_field { window winnum mode label variable label_width var_width var_type help_id var_default args } { # global $variable global scrollside global actin_f_a set variable actin_f_a($winnum,$label) upvar actin_filled_fields filled_fields upvar actin_emtpy_fields empty_fields upvar setValues setVals if { $setVals != "" } { # setVals is a list of variable names and values foreach zz $setVals { if {[lindex $zz 0] == $label } { set var_default [lindex $zz 1] # puts "setting the default for $label to $var_default" } } } regsub -all {\.-} $label _ safe_label set safe_label [string tolower $safe_label] if { $mode == "input" } { set $variable "$var_default" set filled 1 } else { set filled 0 } frame $window.m.c.f.$safe_label menubutton $window.m.c.f.$safe_label.tagname -text [mc $label] -width $label_width -menu $window.m.c.f.$safe_label.tagname.m menu $window.m.c.f.$safe_label.tagname.m if { $var_type == "selection" } { $window.m.c.f.$safe_label.tagname.m add command -label "--" -command "set $variable \"\"" set labels [lindex $args 0] set values [lindex $args 1] for { set i 0 } {$i < [llength $labels]} {incr i} { $window.m.c.f.$safe_label.tagname.m add command -label [lindex $labels $i] \ -command "set $variable \"[lindex $values $i]\"" } $window.m.c.f.$safe_label.tagname.m add separator } elseif { $var_type == "actid_new"} { $window.m.c.f.$safe_label.tagname.m add command -label "--" -command "set $variable \"\"" set newwinnum [incr winnum] $window.m.c.f.$safe_label.tagname.m add command -label [mc "Add..."] -command " actionInputWindow input $newwinnum $variable" } $window.m.c.f.$safe_label.tagname.m add command -label [mc "Help"] -command "taghelp $help_id" if { $var_type == "date" } { calUtil_win $window.m.c.f.$safe_label.tagvalue "" $variable $var_width } elseif { $var_type == "textarea" } { text $window.m.c.f.$safe_label.tagvalue -rel sunk -wrap word -yscrollcommand "$window.m.c.f.$safe_label.sb set" -width $var_width -height 5 scrollbar $window.m.c.f.$safe_label.sb -rel sunk -command "$window.m.c.f.$safe_label.tagvalue yview" } else { entry $window.m.c.f.$safe_label.tagvalue -width $var_width -textvariable $variable } if { $var_type == "textarea" } { pack $window.m.c.f.$safe_label.tagname -side left -in $window.m.c.f.$safe_label pack $window.m.c.f.$safe_label.tagvalue -side right -in $window.m.c.f.$safe_label pack $window.m.c.f.$safe_label.sb -side $scrollside -fill y -in $window.m.c.f.$safe_label if { $mode == "edit" } { upvar $variable varval $window.m.c.f.$safe_label.tagvalue insert end $varval } } else { pack $window.m.c.f.$safe_label.tagname $window.m.c.f.$safe_label.tagvalue -in $window.m.c.f.$safe_label -side left } if { $filled } { lappend filled_fields $window.m.c.f.$safe_label } else { lappend empty_fields $window.m.c.f.$safe_label } pack $window.m.c.f.$safe_label } set w .actinput$winnum # label width - width of the labels set lw 24 toplevel $w if { $mode == "input" } { wm title $w [mc "Input an action"] } else { wm title $w "[mc {Edit action}] $actin_f_a($winnum,Id)" } wm minsize $w 200 200 getallcontacts frame $w.m -bd 4 -relief sunken canvas $w.m.c -yscrollcommand "$w.m.scroll set" -scrollregion {0 0 0 650} -relief raised -confine false -yscrollincrement 25 scrollbar $w.m.scroll -command "$w.m.c yview" -relief raised pack $w.m.scroll -side right -fill y pack $w.m.c -side left -fill both -expand true pack $w.m -fill both -expand 1 set f [frame $w.m.c.f -bd 0] $w.m.c create window 0 0 -anchor nw -window $f actin_setup_field $w $winnum $mode Id actin_f_a($winnum,Id) $lw 40 string actinput_id "*Auto*" actin_setup_field $w $winnum $mode Title actin_f_a($winnum,Title) $lw 40 string actinput_title "" # set the first active project to be the current project if { $currentProject != "" } { lappend activeproj $currentProject set activeproj [concat $activeproj [taglog_getList proj]] } else { set activeproj [taglog_getList proj] } #for { set i 0 } {$i < [llength $projects]} {incr i} { # if { ! [projclosed [lindex [lindex $projects $i] 0]] } { # lappend activeproj [lindex [lindex $projects $i] 0] # } #} actin_setup_field $w $winnum $mode Project actin_f_a($winnum,Project) $lw 40 selection actinput_project "" $activeproj $activeproj actin_setup_field $w $winnum $mode Date actin_f_a($winnum,Date) $lw 40 string actinput_date "$year-$month-$day $hh:$mm" actin_setup_field $w $winnum $mode Priority actin_f_a($winnum,Priority) $lw 40 selection actinput_priority 50 {10 20 30 40 50 60 70 80 90} {10 20 30 40 50 60 70 80 90} foreach i $validStates { lappend vStates [mc $i] } actin_setup_field $w $winnum $mode Status actin_f_a($winnum,Status) $lw 40 selection actinput_status Pending $vStates $validStates actin_setup_field $w $winnum $mode Period actin_f_a($winnum,Period) $lw 40 string actinput_period "" actin_setup_field $w $winnum $mode Expected-cost actin_f_a($winnum,Expected-cost) $lw 40 string actinput_expected_cost "" actin_setup_field $w $winnum $mode Expected-time actin_f_a($winnum,Expected-time) $lw 40 selection actinput_expected_time "" [list "0:05" "0:10" "0:20" "0:30" "1:00" "2:00" "3:00" "4:00" "6:00" "8:00 (1 [mc day])" "12:00 (1.5 [mc days])" "16:00 (2 [mc days])" "24:00 (3 [mc days])" "40:00 (1 [mc week])"] [list "0:05" "0:10" "0:20" "0:30" "1:00" "2:00" "3:00" "4:00" "6:00" "8:00" "12:00" "16:00" "24:00" "40:00"] actin_setup_field $w $winnum $mode Expected-start-date actin_f_a($winnum,Expected-start-date) $lw 38 date actinput_expected_start_date "" actin_setup_field $w $winnum $mode Expected-completed-date actin_f_a($winnum,Expected-completed-date) $lw 38 date actinput_expected_completed_date "" actin_setup_field $w $winnum $mode Precursor actin_f_a($winnum,Precursor) $lw 40 string actinput_precursor "" actin_setup_field $w $winnum $mode Active-after actin_f_a($winnum,Active-after) $lw 38 date actinput_active_after "" actin_setup_field $w $winnum $mode Subtask-of actin_f_a($winnum,Subtask-of) $lw 40 string actinput_subtask_of "" actin_setup_field $w $winnum $mode Next-action actin_f_a($winnum,Next-action) $lw 40 actid_new actinput_next_action "" actin_setup_field $w $winnum $mode Abort-action actin_f_a($winnum,Abort-action) $lw 40 actid_new actinput_abort_action "" actin_setup_field $w $winnum $mode Difficulty actin_f_a($winnum,Difficulty) $lw 40 selection actinput_difficulty "" [list "0 - [mc nobrainer]" "1 - [mc trivial]" "2 - [mc easy]" "3 - [mc tricky]" "4 - [mc hard]" "5 - [mc {very hard}]" ] { 0 1 2 3 4 5 } foreach contact $allcontacts { set thisid "" set thisemail "" foreach item $contact { if { [lindex $item 0] == "Id" } { set thisid [lindex $item 1] } elseif { [lindex $item 0] == "Email" } { set thisemail [lindex $item 1] } } if { ($thisid != "") && ($thisemail !="") } { lappend conids $thisid lappend conemails $thisemail } } if { ! [info exists conids ] } { set conids "" } if { ! [info exists conemails ] } { set conemails "" } actin_setup_field $w $winnum $mode Email-status-to actin_f_a($winnum,Email-status-to) $lw 40 selection actinput_email_status_to "" $conids $conemails actin_setup_field $w $winnum $mode Delegated-to actin_f_a($winnum,Delegated-to) $lw 40 selection actinput_delegated_to "" $conids $conids actin_setup_field $w $winnum $mode Description actin_f_a($winnum,Description) $lw 40 textarea actinput_description "" actin_setup_field $w $winnum $mode Deliverable actin_f_a($winnum,Deliverable) $lw 40 textarea actinput_deliverable "" actin_setup_field $w $winnum $mode Reason actin_f_a($winnum,Reason) $lw 40 textarea actinput_reason "" actin_setup_field $w $winnum $mode Summary actin_f_a($winnum,Summary) $lw 40 textarea actinput_summary "" # Display the filled fields first # puts "filled fields are $actin_filled_fields" # puts "empty fields are $actin_empty_fields" set child [lindex [pack slaves $f] 0] tkwait visibility $child set incr [winfo height $child] set width [winfo width $f] set height [winfo height $f] $w.m.c config -scrollregion "0 0 $width $height" $w.m.c config -yscrollincrement $incr set actinput_maxrows 20 if {$height > $actinput_maxrows * $incr } { set height [expr $actinput_maxrows * $incr] } $w.m.c config -width $width -height $height frame $w.bot if { $mode == "input" } { button $w.bot.ok -text [mc Add] -command "actionInputOK $w $winnum $idvar" } elseif { $mode == "edit" } { button $w.bot.ok -text [mc "Edit"] -command "actionEditOK $w 0" } button $w.bot.subtask -text [mc "Add Subtask..."] -command "addSubtask $winnum" button $w.bot.mail -text "Mail..." -command "actionMail $w $winnum" if { $mode == "edit" } { button $w.bot.history -text [mc History] -command "displayHistory $actin_f_a($winnum,Id)" } button $w.bot.cancel -text [mc Cancel] -command "doCancel $w" button $w.bot.help -text [mc Help] -command "taghelp actinput" pack $w.bot.ok $w.bot.subtask $w.bot.mail -in $w.bot -side left if { $mode == "edit" } { pack $w.bot.history -in $w.bot -side left } pack $w.bot.cancel $w.bot.help -in $w.bot -side left pack $w.bot tkwait window $w } proc setupAutoId { winnum } { global actin_f_a global year month day hh mm if { $actin_f_a($winnum,Id) == "*Auto*" } { if { $actin_f_a($winnum,Project) != "" } { set projseq [incprojactindex $actin_f_a($winnum,Project)] regsub -all " " $actin_f_a($winnum,Project) _ actin_f_a($winnum,Id) set actin_f_a($winnum,Id) "$actin_f_a($winnum,Id).$projseq" } else { set actin_f_a($winnum,Id) "taglog.$year$month$day$hh$mm" } } } proc addSubtask { winnum } { global actin_f_a setupAutoId $winnum set parentProject $actin_f_a($winnum,Project) set parentActid $actin_f_a($winnum,Id) set newwinnum [incr winnum] set setV1 [list Project $parentProject] lappend setVals $setV1 set setV1 [list Subtask-of $parentActid] lappend setVals $setV1 actionInputWindow input $newwinnum "" $setVals } proc actionMailOK { actin_win winnum } { global actmail_to global year month day hh mm global actin_f_a set thisaction "" # need to get the text variables from the window set actin_f_a($winnum,Description) [string trim [$actin_win.m.c.f.description.tagvalue get 1.0 end]] set actin_f_a($winnum,Deliverable) [string trim [$actin_win.m.c.f.deliverable.tagvalue get 1.0 end]] set actin_f_a($winnum,Reason) [string trim [$actin_win.m.c.f.reason.tagvalue get 1.0 end]] set actin_f_a($winnum,Summary) [string trim [$actin_win.m.c.f.summary.tagvalue get 1.0 end]] set actmail_message [string trim [.actmail.message.body get 1.0 end]] setupAutoId $winnum set thisaction [getact_input_fields $winnum] if { $actmail_to != "" } { if { ! [ smtp init ] } { # put up a dialog box saying that mail is not initialised } else { smtp send -subject "Action creation notification" -attachtag $thisaction -header action $actmail_message $actmail_to } } destroy $actin_win destroy .actmail } proc actionMail { actin_win winnum } { global allcontacts toplevel .actmail wm title .actmail [mc "Mail an action"] getallcontacts frame .actmail.main menubutton .actmail.main.l -text [mc "Mail to"] -menu .actmail.main.l.m menu .actmail.main.l.m .actmail.main.l.m add command -label "--" -command "set actmail_to \"\"" foreach contact $allcontacts { set thisid "" set thisemail "" foreach item $contact { if { [lindex $item 0] == "Id" } { set thisid [lindex $item 1] } elseif { [lindex $item 0] == "Email" } { set thisemail [lindex $item 1] } } .actmail.main.l.m add command -label "$thisid" -command "set actmail_to \"$thisemail\"" } .actmail.main.l.m add separator .actmail.main.l.m add command -label [mc "Help"] -command "taghelp actmail_to" entry .actmail.main.v -textvariable actmail_to -width 20 pack .actmail.main.l .actmail.main.v -side left -in .actmail.main pack .actmail.main frame .actmail.message menubutton .actmail.message.l -text [mc Message] -menu .actmail.message.l.m menu .actmail.message.l.m .actmail.message.l.m add command -label [mc Help] -command "taghelp actmail_message" text .actmail.message.body -rel sunk -wrap word -yscrollcommand ".actmail.message.sb set" scrollbar .actmail.message.sb -rel sunk -command ".actmail.message.body yview" pack .actmail.message.l -side left -in .actmail.message pack .actmail.message.body -side right -in .actmail.message pack .actmail.message.sb -fill y -side right -in .actmail.message pack .actmail.message frame .actmail.bot button .actmail.bot.ok -text Mail -command "actionMailOK $actin_win $winnum" button .actmail.bot.cancel -text [mc Cancel] -command { doCancel .actmail } button .actmail.bot.help -text [mc Help] -command "taghelp actmail" pack .actmail.bot.ok .actmail.bot.cancel .actmail.bot.help -side left -in .actmail.bot pack .actmail.bot tkwait window .actmail } proc getact_input_fields { winnum args } { # get the fields from the global variables set by actinput and return them # as an action global actin_f_a if { [llength $args] > 0 } { set endflag 0 } else { set endflag 1 } set action "" set action [tagappend $action Id $actin_f_a($winnum,Id)] set action [tagappend $action Title $actin_f_a($winnum,Title)] set action [tagappend $action Project $actin_f_a($winnum,Project)] set action [tagappend $action Date $actin_f_a($winnum,Date)] set action [tagappend $action Priority $actin_f_a($winnum,Priority)] set action [tagappend $action Status $actin_f_a($winnum,Status)] set action [tagappend $action Period $actin_f_a($winnum,Period)] set action [tagappend $action Expected-cost $actin_f_a($winnum,Expected-cost)] set action [tagappend $action Expected-time $actin_f_a($winnum,Expected-time)] set action [tagappend $action Expected-start-date $actin_f_a($winnum,Expected-start-date)] set action [tagappend $action Expected-completed-date $actin_f_a($winnum,Expected-completed-date)] set action [tagappend $action Precursor $actin_f_a($winnum,Precursor)] set action [tagappend $action Active-after $actin_f_a($winnum,Active-after)] set action [tagappend $action Subtask-of $actin_f_a($winnum,Subtask-of)] set action [tagappend $action Next-action $actin_f_a($winnum,Next-action)] set action [tagappend $action Abort-action $actin_f_a($winnum,Abort-action)] set action [tagappend $action Email-status-to $actin_f_a($winnum,Email-status-to)] set action [tagappend $action Delegated-to $actin_f_a($winnum,Delegated-to)] set action [tagappend $action Difficulty $actin_f_a($winnum,Difficulty)] set action [tagappend $action Description $actin_f_a($winnum,Description) END_D] set action [tagappend $action Deliverable $actin_f_a($winnum,Deliverable) END_D] set action [tagappend $action Reason $actin_f_a($winnum,Reason) END_D] set action [tagappend $action Summary $actin_f_a($winnum,Summary) END_D] if { $endflag } { set endpair [list End ] lappend action $endpair } return $action } proc writeaction { action winnum } { # We dont actually use the action which is our parameter at present, # just use the global variables set by actionInputWindow global actin_f_a global allact allactstate getallact # set the status of actions which are active after some date to blocked unless they are # Delegated, in which case they stay Delegated. if { $actin_f_a($winnum,Active-after) != "" } { if { $actin_f_a($winnum,Status) != "Delegated" } { set actin_f_a($winnum,Status) Blocked } } set action [ getact_input_fields $winnum ] lappend allact $action set allactstate modified writeallact setupActivateAfter $action return $action } proc doactviewOK {} { destroy .actview } proc doactviewSaveAs {} { set fn [tk_getSaveFile -defaultextension ".txt" ] if { $fn != "" } { set f [open $fn w] puts $f [ .actview.main.body get 1.0 end ] close $f } } proc set_actsel_tests {} { global actsel_project actsel_st_any actsel_st_unclaimed actsel_st_pending actsel_st_active actsel_st_blocked actsel_st_delegated actsel_st_completed actsel_st_aborted actsel_st_periodic actsel_showfields actsel_maxpriority actsel_expected_start actsel_expected_completed actsel_expected_start_test actsel_expected_completed_test actsel_filename actsel_id actsel_title if {$actsel_project !=""} { set test [list Project == $actsel_project] lappend tests $test } if {! $actsel_st_any } { if { $actsel_st_unclaimed } { lappend status_list Unclaimed } if { $actsel_st_pending } { lappend status_list Pending } if { $actsel_st_active } { lappend status_list Active } if { $actsel_st_delegated } { lappend status_list Delegated } if { $actsel_st_blocked } { lappend status_list Blocked } if { $actsel_st_completed } { lappend status_list Completed } if { $actsel_st_aborted } { lappend status_list Aborted } if { $actsel_st_periodic } { lappend status_list Periodic } set test [list Status "-in" $status_list] lappend tests $test } if { $actsel_maxpriority != "" } { set test [list Priority <= $actsel_maxpriority] lappend tests $test } if { $actsel_expected_start != "" } { set test [list Expected-start-date $actsel_expected_start_test $actsel_expected_start ] lappend tests $test } if { $actsel_expected_completed != "" } { set test [list Expected-completed-date $actsel_expected_completed_test $actsel_expected_completed ] lappend tests $test } if { $actsel_id !=""} { set test [list Id == $actsel_id] lappend tests $test } if { $actsel_title !=""} { set test [list Title == $actsel_title] lappend tests $test } if { [info exists tests] } { return $tests } else { return {} } } proc editaction { actid {winnum 0} } { global actin_f_a global hh mm ss year month day global validStates global scrollside global allcontacts global allact allactstate global actedit_fields getallact # convert actid to a 'safe' value #regsub -all {\.} $actid _ actid_safe #set w ".$actid_safe" #toplevel $w #wm title $w "Edit action $actid" set actin_f_a($winnum,Description) "" set actin_f_a($winnum,Reason) "" set actin_f_a($winnum,Deliverable) "" set actin_f_a($winnum,Summary) "" if { [info exist actedit_fields] } { unset actedit_fields } # find the appropriate action. set actin_f_a($winnum,Id) $actid set test [list Id "==" $actid] lappend tests $test set thisaction [tag extract $allact $tests] foreach action $thisaction { foreach item $action { if { [lindex $item 0] == "Title" } { set actin_f_a($winnum,Title) [lindex $item 1] } elseif { [lindex $item 0] == "Project"} { set actin_f_a($winnum,Project) [lindex $item 1] } elseif { [lindex $item 0] == "Date"} { set actin_f_a($winnum,Date) [lindex $item 1] } elseif { [lindex $item 0] == "Priority"} { set actin_f_a($winnum,Priority) [lindex $item 1] } elseif { [lindex $item 0] == "Status"} { set actin_f_a($winnum,Status) [lindex $item 1] } elseif { [lindex $item 0] == "Period"} { set actin_f_a($winnum,Period) [lindex $item 1] } elseif { [lindex $item 0] == "Expected-cost"} { set actin_f_a($winnum,Expected-cost) [lindex $item 1] } elseif { [lindex $item 0] == "Expected-time"} { set actin_f_a($winnum,Expected-time) [lindex $item 1] } elseif { [lindex $item 0] == "Expected-start-date"} { set actin_f_a($winnum,Expected-start-date) [lindex $item 1] } elseif { [lindex $item 0] == "Expected-completed-date"} { set actin_f_a($winnum,Expected-completed-date) [lindex $item 1] } elseif { [lindex $item 0] == "Precursor"} { set actin_f_a($winnum,Precursor) [lindex $item 1] } elseif { [lindex $item 0] == "Difficulty"} { set actin_f_a($winnum,Difficulty) [lindex $item 1] } elseif { [lindex $item 0] == "Active-after"} { set actin_f_a($winnum,Active-after) [lindex $item 1] } elseif { [lindex $item 0] == "Subtask-of"} { set actin_f_a($winnum,Subtask-of) [lindex $item 1] } elseif { [lindex $item 0] == "Next-action"} { set actin_f_a($winnum,Next-action) [lindex $item 1] } elseif { [lindex $item 0] == "Abort-action"} { set actin_f_a($winnum,Abort-action) [lindex $item 1] } elseif { [lindex $item 0] == "Description"} { set actin_f_a($winnum,Description) [lindex $item 1] } elseif { [lindex $item 0] == "Deliverable"} { set actin_f_a($winnum,Deliverable) [lindex $item 1] } elseif { [lindex $item 0] == "Reason" } { set actin_f_a($winnum,Reason) [lindex $item 1] } elseif { [lindex $item 0] == "Summary" } { set actin_f_a($winnum,Summary) [lindex $item 1] } elseif { [lindex $item 0] == "Email-status-to"} { set actin_f_a($winnum,Email-status-to) [lindex $item 1] } elseif { [lindex $item 0] == "Delegated-to"} { set actin_f_a($winnum,Delegated-to) [lindex $item 1] } elseif { [lindex $item 0] == "End" } { # special case - dont do anything } elseif { [lindex $item 0] == "Id" } { # we have already picked this up } else { set fieldname [fieldname2index [lindex $item 0]] set actedit_fields($fieldname) [lindex $item 1] } } } set action [actionInputWindow edit] } proc showactfield { selector tagname tagvalue } { if { $tagname == $selector } { .actview.main.body insert end "$tagname: " .actview.main.body insert end "$tagvalue" .actview.main.body insert end "\n" } } proc fillactwindow {} { global actsel_project actsel_st_any actsel_st_unclaimed actsel_st_pending actsel_st_active actsel_st_blocked actsel_st_delegated actsel_st_completed actsel_st_aborted actsel_st_periodic actsel_showfields actsel_maxpriority actsel_expected_start actsel_expected_completed actsel_expected_start_test actsel_expected_completed_test actsel_filename actsel_sortby global actionsfilename allact .actview.main.body delete 1.0 end .actview.main.body mark set prvmark 1.0 .actview.main.body mark gravity prvmark left set numactions 0 set total_expected_time "00:00" if { $actsel_filename != $actionsfilename } { set actions [ tag readfile $actsel_filename] # get rid of the header set actions [lrange $actions 1 end ] } else { set actions [lrange $allact 1 end ] } # possibly get rid of actions which do not match our selection criteria # set tests {} set tests [ set_actsel_tests ] if {[info exists tests]} { set actions [ tag extract $actions $tests ] } if { $actsel_sortby != "" } { if { $actsel_sortby == "Priority" } { set actions [tag sort $actions Priority -integer] } } foreach entry $actions { foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } { .actview.main.body insert end "___________________________________\n" incr numactions .actview.main.body tag add tag_$actid prvmark insert .actview.main.body tag bind tag_$actid "editaction $actid" .actview.main.body mark set prvmark insert } else { # special fields handling for stats if { $tagname == "Expected-time"} { set exptime [timediff "00:00:00" $tagvalue] inctime total_expected_time $exptime } if { $tagname == "Id" } { set actid $tagvalue } if { $actsel_showfields(all) } { .actview.main.body insert end "[mc $tagname]: " .actview.main.body insert end "$tagvalue" .actview.main.body insert end "\n" } else { if { $actsel_showfields(id) } { showactfield Id $tagname $tagvalue } if { $actsel_showfields(date) } { showactfield Date $tagname $tagvalue } if { $actsel_showfields(title)} { showactfield Title $tagname $tagvalue } if { $actsel_showfields(priority)} { showactfield Priority $tagname $tagvalue } if { $actsel_showfields(project)} { showactfield Project $tagname $tagvalue } if { $actsel_showfields(status)} { showactfield Status $tagname $tagvalue } if { $actsel_showfields(expected_completed)} { showactfield Expected-completed-date $tagname $tagvalue } if { $actsel_showfields(summary)} { showactfield Summary $tagname $tagvalue } } } } } .actview.stats.body insert end "[mc Displayed] $numactions [mc actions]\n" .actview.stats.body insert end "[mc {Total expected time}] $total_expected_time\n" } proc displayActions {} { global actionsfilename actsel_filename set actions {} toplevel .actview wm title .actview "[mc {Actions view of}] $actsel_filename" frame .actview.main text .actview.main.body -rel sunk -wrap word -yscrollcommand ".actview.main.sb set" scrollbar .actview.main.sb -rel sunk -command ".actview.main.body yview" pack .actview.main.body -side right -in .actview.main pack .actview.main.sb -side right -fill y -in .actview.main pack .actview.main frame .actview.stats text .actview.stats.body -rel sunk -wrap word -height 6 pack .actview.stats.body -in .actview.stats pack .actview.stats frame .actview.bot button .actview.bot.ok -text OK -command doactviewOK button .actview.bot.select -text Select -command fillactwindow button .actview.bot.saveas -text [mc "Save As..."] -command doactviewSaveAs pack .actview.bot.ok .actview.bot.saveas -side left pack .actview.bot # Now fill the window fillactwindow tkwait window .actview } proc doHistorySaveAsOK { filename window hvsawin } { set f [open $filename w] puts $f [ $window.act.body get 1.0 end] puts $f [ $window.text.body get 1.0 end] close $f destroy $hvsawin } proc doHistorySaveAs { window } { global histfile histwindow thiswindow set histwindow ".$window" set thiswindow ".hvsa$window" toplevel .hvsa$window wm title .hvsa$window [mc "Save Action History As ..."] frame .hvsa$window.filename label .hvsa$window.filename.label -text [mc "File name :"] entry .hvsa$window.filename.name -relief sunken -textvariable histfile pack .hvsa$window.filename.label .hvsa$window.filename.name -side left -in .hvsa$window.filename pack .hvsa$window.filename frame .hvsa$window.bot button .hvsa$window.bot.ok -text OK -command { doHistorySaveAsOK $histfile $histwindow $thiswindow } button .hvsa$window.bot.cancel -text [mc Cancel] -command { doCancel $thiswindow } pack .hvsa$window.bot.ok .hvsa$window.bot.cancel -in .hvsa$window.bot -side left pack .hvsa$window.bot tkwait window .hvsa$window } proc doReviseAction { action redate retime summary } { global allact allactstate set revised 0 if {$redate != ""} { if { [tag_entryVal $action Original-expected-completed-date] == "" } { tag setorreplace action Original-expected-completed-date [tag_entryVal $action Expected-completed-date] } #tag setorreplace action Revised-expected-completed-date $redate tag setorreplace action Expected-completed-date $redate set revised 1 } if {$retime != ""} { if { [tag_entryVal $action Original-expected-time] == "" } { tag setorreplace action Original-expected-time [tag_entryVal $action Expected-time] } tag setorreplace action Expected-time $retime set revised 1 } if {$summary !=""} { tag setorreplace action Summary $summary set revised 1 } if {$revised} { tag setorreplace action Revised-date [clock format [clock seconds] -format "%Y-%m-%d"] set allactstate modified # tag update $actionsfilename $action Id foreach item $action { if { [lindex $item 0] == "Id" } { set thisid [lindex $item 1] } } set test [ list Id "==" $thisid ] set idx 0 foreach entry $allact { if [ tag matchcond $entry $test ] { set allact [lreplace $allact $idx $idx $action] } incr idx } writeallact } } proc doRevise { action i } { global revisedExpectedDate revisedExpectedTime global allact allactstate set redate $revisedExpectedDate($i) set retime $revisedExpectedTime($i) set summary [string trim [.acthist$i.summary.body get 1.0 end]] set revised 0 if {$redate != ""} { if {[tag_entryVal $action Original-expected-completed-date] == ""} { tag setorreplace action Original-expected-completed-date [tag_entryVal $action Expected-completed-date] } #tag setorreplace action Revised-expected-completed-date $redate tag setorreplace action Expected-completed-date $redate set revised 1 } if {$retime != ""} { if {[tag_entryVal $action Original-expected-time] == ""} { tag setorreplace action Original-expected-time [tag_entryVal $action Expected-time] } tag setorreplace action Expected-time $retime set revised 1 } if {$summary !=""} { tag setorreplace action Summary $summary set revised 1 } if {$revised} { tag setorreplace action Revised-date [clock format [clock seconds] -format "%Y-%m-%d"] set allactstate modified # tag update $actionsfilename $action Id foreach item $action { if { [lindex $item 0] == "Id" } { set thisid [lindex $item 1] } } set test [ list Id "==" $thisid ] set idx 0 foreach entry $allact { if [ tag matchcond $entry $test ] { set allact [lreplace $allact $idx $idx $action] } incr idx } writeallact } } proc displayHistory { {actid {}} } { global revisedExpectedDate revisedExpectedTime global actsel_filename proc displayAnActionHistory { i action } { toplevel .acthist$i wm title .acthist$i "[mc {Action history}] $i" frame .acthist$i.act text .acthist$i.act.body -rel sunk -wrap word -yscrollcommand ".acthist$i.act.sb set" -height 5 scrollbar .acthist$i.act.sb -rel sunk -command ".acthist$i.act.body yview" pack .acthist$i.act.body -in .acthist$i.act -side right pack .acthist$i.act.sb -in .acthist$i.act -side right -fill y pack .acthist$i.act frame .acthist$i.text text .acthist$i.text.body -rel sunk -wrap word -yscrollcommand ".acthist$i.text.sb set" scrollbar .acthist$i.text.sb -rel sunk -command ".acthist$i.text.body yview" pack .acthist$i.text.body -in .acthist$i.text -side right pack .acthist$i.text.sb -in .acthist$i.text -side right -fill y pack .acthist$i.text frame .acthist$i.summary text .acthist$i.summary.body -rel sunk -wrap word -yscrollcommand ".acthist$i.summary.sb set" -height 5 scrollbar .acthist$i.summary.sb -rel sunk -command ".acthist$i.summary.body yview" pack .acthist$i.summary.body -in .acthist$i.summary -side right pack .acthist$i.summary.sb -in .acthist$i.summary -side right -fill y pack .acthist$i.summary frame .acthist$i.bot button .acthist$i.bot.revise -text [mc "Revise"] -command "doRevise \"$action\" $i" menubutton .acthist$i.bot.expdate -text [mc Expected-Completed-Date] -menu .acthist$i.bot.expdate.m menu .acthist$i.bot.expdate.m entry .acthist$i.bot.expdateentry -textvariable revisedExpectedDate($i) -width 12 menubutton .acthist$i.bot.exptime -text [mc Expected-Time] -menu .acthist$i.bot.exptime.m menu .acthist$i.bot.exptime.m entry .acthist$i.bot.exptimeentry -textvariable revisedExpectedTime($i) -width 5 button .acthist$i.bot.saveas -text [mc "Save As..."] -command "doHistorySaveAs acthist$i" button .acthist$i.bot.cancel -text [mc Cancel] -command " doCancel .acthist$i " pack .acthist$i.bot.revise .acthist$i.bot.expdate .acthist$i.bot.expdateentry .acthist$i.bot.exptime .acthist$i.bot.exptimeentry .acthist$i.bot.saveas .acthist$i.bot.cancel -in .acthist$i.bot -side left pack .acthist$i.bot foreach item $action { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Date" } { set actiondate $tagvalue } elseif { $tagname == "Title" } { set actiontitle $tagvalue } elseif { $tagname == "Status" } { set actionstatus $tagvalue } elseif { $tagname =="Id" } { set actionid $tagvalue } elseif { $tagname == "Project" } { set actionproject $tagvalue } elseif { $tagname == "Expected-completed-date" } { set actionexpectedcompleteddate $tagvalue } elseif { $tagname == "Expected-time" } { set actionexpectedtime $tagvalue } elseif { $tagname == "Revised-expected-completed-date"} { set actionrevisedexpectedcompleteddate $tagvalue } elseif { $tagname == "Revised-expected-time" } { set actionrevisedexpectedtime $tagvalue } elseif { $tagname == "Original-expected-time" } { set actionoriginalexpectedtime $tagvalue } elseif { $tagname == "Original-expected-completed-date" } { set actionoriginalexpectedcompleteddate $tagvalue } elseif { $tagname == "Revised-date" } { set actionreviseddate $tagvalue } elseif { $tagname == "Summary" } { set actionsummary $tagvalue } } .acthist$i.act.body delete 1.0 end #%%%%%%%%%%%%%% actionid was not set %%%%%%%%%%%%%%%%%%%%%%%% if {! [info exist actionid ] || ! [info exist actiondate ] || ! [info exist actiontitle ]} return #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% .acthist$i.act.body insert end "$actionid\t" .acthist$i.act.body insert end "$actiontitle\n\n" if [info exist actionproject ] { .acthist$i.act.body insert end "[mc Project]: $actionproject\n" } if [info exist actionoriginalexpectedcompleteddate ] { .acthist$i.act.body insert end "[mc Original-expected-completed-date]: $actionoriginalexpectedcompleteddate\n" } if [info exist actionoriginalexpectedtime ] { .acthist$i.act.body insert end "[mc Original-expected-time]: $actionoriginalexpectedtime\n" } if [info exist actionexpectedcompleteddate ] { .acthist$i.act.body insert end "[mc Expected-completed-date]: $actionexpectedcompleteddate\n" } if [info exist actionexpectedtime ] { .acthist$i.act.body insert end "[mc Expected-time]: $actionexpectedtime\n" } if [info exist actionrevisedexpectedcompleteddate] { .acthist$i.act.body insert end "[mc Revised-expected-completed-date]: $actionrevisedexpectedcompleteddate\n" } if [info exist actionrevisedexpectedtime] { .acthist$i.act.body insert end "[mc Revised-expected-time]: $actionrevisedexpectedtime\n" } if [info exist actionreviseddate] { .acthist$i.act.body insert end "[mc Revised-date]: $actionreviseddate\n" } .acthist$i.text.body delete 1.0 end set test [ list Action "==" $actionid ] lappend tests $test set fileslist [dateRangeToLogfileList $actiondate ""] foreach filename $fileslist { set logs [tag readselected $filename $tests] set dateseparator 0 foreach entry $logs { # for now just write them out if { ! $dateseparator } { set dateseparator 1 set headerdate [logfilename2date $filename] .acthist$i.text.body insert end "\n\n $headerdate\n\n" } foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "End" } { .acthist$i.text.body insert end "_______________________________\n" } elseif { $tagname == "Id" } { # dont do anything } elseif { $tagname == "Action" } { # } elseif { $tagname == "ActionTitle" } { # } elseif { $tagname == "Project" } { # } elseif { $tagname == "StartTime" } { set starttime $tagvalue } elseif { $tagname == "EndTime" } { # We should always have a start time and an end time - put them out # as a single line set endtime $tagvalue set duration [timediff $starttime $endtime] inctime actiontotal $duration set dispduration "00:00" inctime dispduration $duration .acthist$i.text.body insert end "Start $starttime [mc {End }] $endtime [mc Duration] $dispduration\n" } else { .acthist$i.text.body insert end "[mc $tagname]: " .acthist$i.text.body insert end "$tagvalue " .acthist$i.text.body insert end "\n" } } } } # we have read all the logs - show the total duration if [info exist actiontotal] { .acthist$i.act.body insert end "[mc {Total duration}]: $actiontotal\n" } .acthist$i.summary.body delete 1.0 end if [info exist actionsummary ] { .acthist$i.summary.body insert end "$actionsummary" } } if { $actid != "" } { set test [list Id "==" $actid] lappend tests $test } else { set tests [ set_actsel_tests ] } set actions [tag readselected $actsel_filename $tests ] # Display the history of each selected action in its own window. set i 1 foreach action $actions { displayAnActionHistory $i $action incr i } } proc setup_actsel_menus {} { global actsel_filename actionsfilename allact .actsel.oneact.id.m delete 1 end .actsel.oneact.title.m delete 1 end set tests [ set_actsel_tests ] if { $actionsfilename != $actsel_filename } { set actions [tag readselected $actsel_filename $tests ] } else { getallact set actions [tag extract $allact $tests ] } foreach action $actions { foreach item $action { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Id" } { .actsel.oneact.id.m add command -label $tagvalue -command "set actsel_id $tagvalue" } elseif { $tagname == "Title"} { .actsel.oneact.title.m add command -label $tagvalue -command "set actsel_title \"$tagvalue\"" } } } .actsel.oneact.id.m add separator .actsel.oneact.id.m add command -label [mc Help] -command "taghelp actsel_id" .actsel.oneact.title.m add separator .actsel.oneact.title.m add command -label [mc Help] -command "taghelp actsel_title" } proc actSelect { okcommand } { global actsel_project actsel_st_any actsel_st_unclaimed actsel_st_pending actsel_st_active actsel_st_blocked actsel_st_delegated actsel_st_completed actsel_st_aborted actsel_st_periodic actsel_maxpriority actsel_showfields actsel_filename actsel_filenames actsel_expected_start actsel_expected_completed actsel_expected_start_test actsel_expected_completed_test actsel_id actsel_title actsel_projstat actsel_sortby proc setupActselProjMenu { varname index op } { global actsel_projstat setupProjMenu .actsel.tagselect.p.project.m actsel_project $actsel_projstat actsel_project } trace variable actsel_projstat w setupActselProjMenu toplevel .actsel wm title .actsel [mc "Select Actions ..."] frame .actsel.fileselect menubutton .actsel.fileselect.filename -text [mc Filename] -menu .actsel.fileselect.filename.m menu .actsel.fileselect.filename.m for { set i 0 } {$i < [llength $actsel_filenames]} {incr i} { if { [ file exists [lindex $actsel_filenames $i ]] } { .actsel.fileselect.filename.m add command -label [lindex $actsel_filenames $i ] \ -command "set actsel_filename \"[lindex $actsel_filenames $i]\"" } } .actsel.fileselect.filename.m add separator .actsel.fileselect.filename.m add command -label [mc Help] -command "taghelp actsel_filename" entry .actsel.fileselect.fileentry -textvariable actsel_filename -width 30 pack .actsel.fileselect.filename .actsel.fileselect.fileentry -in .actsel.fileselect -side left pack .actsel.fileselect frame .actsel.tagselect frame .actsel.tagselect.p menubutton .actsel.tagselect.p.project -text [mc Project] -menu .actsel.tagselect.p.project.m menu .actsel.tagselect.p.project.m setupActselProjMenu 1 2 3 entry .actsel.tagselect.p.projectentry -textvariable actsel_project -width 10 radiobutton .actsel.tagselect.p.all -text [mc "All"] -variable actsel_projstat -value "all" radiobutton .actsel.tagselect.p.active -text "Active" -variable actsel_projstat -value "active" pack .actsel.tagselect.p.project .actsel.tagselect.p.projectentry .actsel.tagselect.p.all .actsel.tagselect.p.active -in .actsel.tagselect.p -side left pack .actsel.tagselect.p frame .actsel.tagselect.status menubutton .actsel.tagselect.status.l -text Status -menu .actsel.tagselect.status.l.m menu .actsel.tagselect.status.l.m .actsel.tagselect.status.l.m add command -label [mc Help] -command "taghelp actsel_st" checkbutton .actsel.tagselect.status.any -text [mc Any] -variable actsel_st_any checkbutton .actsel.tagselect.status.unclaimed -text [mc Unclaimed] -variable actsel_st_unclaimed checkbutton .actsel.tagselect.status.pending -text [mc Pending] -variable actsel_st_pending checkbutton .actsel.tagselect.status.active -text [mc Active] -variable actsel_st_active checkbutton .actsel.tagselect.status.blocked -text [mc Blocked] -variable actsel_st_blocked checkbutton .actsel.tagselect.status.delegated -text [mc Delegated] -variable actsel_st_delegated checkbutton .actsel.tagselect.status.completed -text [mc Completed] -variable actsel_st_completed checkbutton .actsel.tagselect.status.aborted -text [mc Aborted] -variable actsel_st_aborted checkbutton .actsel.tagselect.status.periodic -text [mc Periodic] -variable actsel_st_periodic pack .actsel.tagselect.status.l .actsel.tagselect.status.any .actsel.tagselect.status.unclaimed .actsel.tagselect.status.pending .actsel.tagselect.status.active .actsel.tagselect.status.blocked .actsel.tagselect.status.delegated .actsel.tagselect.status.completed .actsel.tagselect.status.aborted .actsel.tagselect.status.periodic -side left -in .actsel.tagselect.status pack .actsel.tagselect.status frame .actsel.tagselect.priority menubutton .actsel.tagselect.priority.l -text "[mc Priority] <=" -menu .actsel.tagselect.priority.l.m menu .actsel.tagselect.priority.l.m .actsel.tagselect.priority.l.m add command -label [mc Help] -command "taghelp actsel_maxpriority" entry .actsel.tagselect.priority.e -textvariable actsel_maxpriority pack .actsel.tagselect.priority.l .actsel.tagselect.priority.e -in .actsel.tagselect.priority -side left pack .actsel.tagselect.priority set actsel_expected_start "" set actsel_expected_completed "" set actsel_expected_start_test "-later" set actsel_expected_start_testlabel "<" set actsel_expected_completed_test "-later" set actsel_expected_completed_testlabel ">" frame .actsel.tagselect.date label .actsel.tagselect.date.l -text [mc "Date Expected"] menubutton .actsel.tagselect.date.ls -text Start -menu .actsel.tagselect.date.ls.m menu .actsel.tagselect.date.ls.m set todayval [clock format [clock seconds] -format "%Y-%m-%d"] .actsel.tagselect.date.ls.m add command -label "--" -command "set actsel_expected_start \"\"" .actsel.tagselect.date.ls.m add command -label "[mc Today] ($todayval)" -command "set actsel_expected_start $todayval" set tomorrowval [clock format [clock scan tomorrow] -format "%Y-%m-%d"] .actsel.tagselect.date.ls.m add command -label "[mc Tomorrow] ($tomorrowval)" -command "set actsel_expected_start $tomorrowval" calUtil_menu .actsel.tagselect.date.ls.m .actsel.tagselect.date.es .actsel.tagselect.date.ls.m add separator .actsel.tagselect.date.ls.m add command -label [mc Help] -command "taghelp actsel_expected_start" menubutton .actsel.tagselect.date.st -text $actsel_expected_start_testlabel -menu .actsel.tagselect.date.st.m menu .actsel.tagselect.date.st.m .actsel.tagselect.date.st.m add command -label "[mc Later] (>)" -command "set actsel_expected_start_test -later ; set actsel_expected_start_testlabel \">\" ; .actsel.tagselect.date.st configure -text \">\"" .actsel.tagselect.date.st.m add command -label "[mc Earlier] (<)" -command "set actsel_expected_start_test -earlier ; set actsel_expected_start_testlabel \">\" ; .actsel.tagselect.date.st configure -text \"<\"" entry .actsel.tagselect.date.es -textvariable actsel_expected_start -width 16 menubutton .actsel.tagselect.date.lc -text [mc Completed] -menu .actsel.tagselect.date.lc.m menu .actsel.tagselect.date.lc.m .actsel.tagselect.date.lc.m add command -label "--" -command "set actsel_expected_completed \"\"" .actsel.tagselect.date.lc.m add command -label "[mc Today] ($todayval)" -command "set actsel_expected_completed $todayval" .actsel.tagselect.date.lc.m add command -label "[mc Tomorrow] ($tomorrowval)" -command "set actsel_expected_completed $tomorrowval" calUtil_menu .actsel.tagselect.date.lc.m .actsel.tagselect.date.ec .actsel.tagselect.date.lc.m add separator .actsel.tagselect.date.lc.m add command -label [mc Help] -command "taghelp actsel_expected_completed" menubutton .actsel.tagselect.date.ct -text $actsel_expected_completed_testlabel -menu .actsel.tagselect.date.ct.m menu .actsel.tagselect.date.ct.m .actsel.tagselect.date.ct.m add command -label "[mc Later] (>)" -command "set actsel_expected_completed_test -later ; set actsel_expected_completed_testlabel \">\" ; .actsel.tagselect.date.ct configure -text \">\"" .actsel.tagselect.date.ct.m add command -label "[mc Earlier] (<)" -command "set actsel_expected_completed_test -earlier ; set actsel_expected_completed_testlabel \"<\" ; .actsel.tagselect.date.ct configure -text \"<\"" entry .actsel.tagselect.date.ec -textvariable actsel_expected_completed -width 16 pack .actsel.tagselect.date.l .actsel.tagselect.date.ls .actsel.tagselect.date.st .actsel.tagselect.date.es .actsel.tagselect.date.lc .actsel.tagselect.date.ct .actsel.tagselect.date.ec -in .actsel.tagselect.date -side left pack .actsel.tagselect.date pack .actsel.tagselect frame .actsel.fields menubutton .actsel.fields.l -text [mc "Show Fields"] -menu .actsel.fields.l.m menu .actsel.fields.l.m .actsel.fields.l.m add command -label [mc Help] -command "taghelp actsel_showfields" checkbutton .actsel.fields.all -text [mc All] -variable actsel_showfields(all) checkbutton .actsel.fields.id -text Id -variable actsel_showfields(id) checkbutton .actsel.fields.date -text [mc Date] -variable actsel_showfields(date) checkbutton .actsel.fields.title -text [mc Title] -variable actsel_showfields(title) checkbutton .actsel.fields.priority -text [mc Priority] -variable actsel_showfields(priority) checkbutton .actsel.fields.project -text [mc Project] -variable actsel_showfields(project) checkbutton .actsel.fields.status -text Status -variable actsel_showfields(status) checkbutton .actsel.fields.completeddate -text [mc "Due Date"] -variable actsel_showfields(expected_completed) checkbutton .actsel.fields.summary -text [mc Summary] -variable actsel_showfields(summary) pack .actsel.fields.l .actsel.fields.all .actsel.fields.id .actsel.fields.date .actsel.fields.title .actsel.fields.priority .actsel.fields.project .actsel.fields.status .actsel.fields.completeddate .actsel.fields.summary -in .actsel.fields -side left pack .actsel.fields frame .actsel.oneact button .actsel.oneact.refresh -text [mc "Refresh"] -command setup_actsel_menus menubutton .actsel.oneact.id -text Id -menu .actsel.oneact.id.m menu .actsel.oneact.id.m entry .actsel.oneact.identry -textvariable actsel_id -width 10 menubutton .actsel.oneact.title -text [mc Title] -menu .actsel.oneact.title.m menu .actsel.oneact.title.m entry .actsel.oneact.titleentry -textvariable actsel_title -width 20 pack .actsel.oneact.refresh .actsel.oneact.id .actsel.oneact.identry .actsel.oneact.title .actsel.oneact.titleentry -in .actsel.oneact -side left pack .actsel.oneact frame .actsel.sortby menubutton .actsel.sortby.l -text [mc "Sort by"] -menu .actsel.sortby.l.m menu .actsel.sortby.l.m .actsel.sortby.l.m add command -label "--" -command "set actsel_sortby \"\"" .actsel.sortby.l.m add command -label [mc "Priority"] -command "set actsel_sortby Priority" .actsel.sortby.l.m add separator .actsel.sortby.l.m add command -label [mc "Help"] -command "taghelp actsel_sortby" entry .actsel.sortby.e -textvariable actsel_sortby -width 10 pack .actsel.sortby.l .actsel.sortby.e -side left -in .actsel.sortby pack .actsel.sortby frame .actsel.bot button .actsel.bot.ok -text OK -command $okcommand button .actsel.bot.cancel -text [mc Cancel] -command { doCancel .actsel } button .actsel.bot.help -text [mc Help] -command "taghelp actsel" pack .actsel.bot.ok .actsel.bot.cancel .actsel.bot.help -in .actsel.bot -side left pack .actsel.bot tkwait window .actsel trace vdelete actsel_projstat w setupActselProjMenu } proc getactiveactions {} { global activeactions global allact allactstate set activeactions "" # Seems to work - I thought I might have to use unset set test [list Status "-in" { Active } ] lappend tests $test getallact #set actions [ tag extract $allact $tests ] set idx 0 while { $idx != -1 } { set idx [tag find $allact $tests $idx] if { $idx != -1 } { # Now to extract the bits of info we need - set entry [lindex $allact $idx] set thisproject "" set thispriority 50 foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Id" } { set thisid $tagvalue } elseif { $tagname == "Title"} { set thistitle $tagvalue } elseif { $tagname == "Project"} { set thisproject $tagvalue } elseif { $tagname == "Priority"} { set thispriority $tagvalue } } set thisentry [ list $thisid $thistitle $thisproject $thispriority $idx] incr idx lappend activeactions $thisentry } } if { [info tclversion] >=8.0 } { set activeactions [lsort -integer -index 3 $activeactions] } } proc setactionsmenu {} { global activeactions num_today_actions allact getactiveactions .actionbar.action.m delete 1 end .actionbar.action.m add command -label "--" \ -command "setcurrentAction -1" for { set i 0 } {$i < [llength $activeactions]} {incr i} { # hide subtasks from top level if { [tag_entryVal [lindex $allact [lindex [lindex $activeactions $i] 4]] Subtask-of] != "" } { continue } .actionbar.action.m add command -label [lindex [ lindex $activeactions $i ] 1] \ -command "setcurrentAction \"[lindex [lindex $activeactions $i ] 0]\"" # if it had subtasks the add them. (note that this bit should really be # recursive if { [tag_entryVal [lindex $allact [lindex [lindex $activeactions $i] 4]] Subtasks] != "" } { set submenu .actionbar.action.m.s$i .actionbar.action.m add cascade -label "[lindex [ lindex $activeactions $i ] 1]..." -menu $submenu if {[winfo exists $submenu]} { $submenu delete 1 end } else { menu $submenu } set subacts [split [tag_entryVal [lindex $allact [lindex [lindex $activeactions $i] 4]] Subtasks] ","] foreach subact $subacts { # We are only interested in active subactions, which must be in activeactions for { set j 0 } {$j < [llength $activeactions]} {incr j} { if {[lindex [lindex $activeactions $j ] 0]==$subact } { $submenu add command -label "[lindex [lindex $activeactions $j ] 1]" \ -command "setcurrentAction \"[lindex [lindex $activeactions $j ] 0]\"" } } } } } for { set i 1 } { $i <= $num_today_actions } { incr i } { menu_create .actions.a$i.id [mc Action]$i actreminder 0 actAct menu_setText .actions.a$i.title } } proc setcurrentAction { id } { global currentAction currentProject activeactions currentActionTitle if { $id < 0 } { set currentAction "" set currentActionTitle "" return } set currentAction $id set currentProject "" foreach entry $activeactions { set thisid [lindex $entry 0] if { $thisid == $id } { set currentProject [lindex $entry 2] set currentActionTitle [lindex $entry 1] } } } proc setcurrentPeriodicAction { id } { global currentAction currentProject currentActionTitle allact # Note that the format of periodicActions as generated here is a full # subset of allact - rather than just a a list of id project and title # so need to deal with this when setting up donext "" if { $id < 0 } { set currentAction "" set currentActionTitle "" return } set currentAction $id set currentProject "" foreach action $allact { foreach item $action { # puts "item is $item" if {( [lindex $item 0] == "Status" ) && ([lindex $item 1] == "Periodic" )} { # need to check if it has already been done - i.e. Completed during this period # but for now .. lappend periodicActions $action # } } } # puts "periodicActions is $periodicActions" foreach entry $periodicActions { set thisid [lindex $entry 0] # puts "thisid is $thisid" if { [lindex $thisid 1] == $id } { foreach item $entry { if {[lindex $item 0] == "Project" } { set currentProject [lindex $item 1] } if {[lindex $item 0] == "Title" } { set currentActionTitle [lindex $item 1] } } } } } proc actNewState { actid newstate oldstate actnote winname } { global allact allactstate # puts "actNewState $actid $newstate $oldstate $actnote" # work out which action we are talking about set i 0 foreach entry $allact { foreach item $entry { if { [lindex $item 0] == "Id" } { if { [lindex $item 1 ] == $actid } { set idx $i } } } incr i } set entry [lindex $allact $idx] # puts "entry is $entry" tag replace entry Status $newstate set newstate_date [list $newstate-date [clock format [clock seconds] -format "%Y-%m-%d %H:%M"]] set len [llength $entry] incr len -1 set entry [linsert $entry $len $newstate_date] if { $actnote != "" } { set newstate_note [ list $newstate-note $actnote "END_D" ] set len [llength $entry] incr len -1 set entry [linsert $entry $len $newstate_note] } #puts "$entry" set email_status_to "" # Does this entry contain an Email-status-to field ? foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Email-status-to"} { set email_status_to $tagvalue } } if {$email_status_to != ""} { if { ! [ smtp init ] } { # put up a dialog box saying that mail is not initialised } else { set msg "The attached action has just changed state from $oldstate to $newstate" smtp send -subject "Action status change notification" -attachtag $entry -header action $msg $email_status_to } } if { $newstate == "Completed" } { set next_action_id "" foreach item $entry { if { [lindex $item 0] == "Next-action"} { set next_action_id [lindex $item 1] } } if { $next_action_id != "" } { actNewState $next_action_id Active Pending "" "" setcurrentAction $next_action_id } } if { $newstate == "Aborted"} { set abort_action_id "" foreach item $entry { if { [lindex $item 0] == "Next-action"} { set abort_action_id [lindex $item 1] } } if { $abort_action_id != "" } { } } set allact [lreplace $allact $idx $idx $entry] set allactstate modified setactionsmenu if { $winname != "" } { destroy $winname } } proc doNewState { oldstate newstate } { proc doNewStateOK { newstate oldstate } { global allact allactstate # # Have to choose between passing the entire array and re-reading the entire # file # I think we can pick up the key variables from the outer procedure #upvar 2 newstate mynewstate #upvar 2 actions myactions # - no we cant - despite being nested inside doNewState # set actselection [.docomplete.pick.actions curselection] # puts "current selection is $actselection" set actnote [string trim [.docomplete.note.text get 1.0 end]] # I should deal with a list - just do one for the moment foreach actsel $actselection { set acttitle [.docomplete.pick.actions get $actsel] # puts "acttitle is $acttitle" set idx [string range $acttitle 0 [ string first " " $acttitle]] # puts "idx is $idx" # find out what the action id is set entry [lindex $allact $idx] set actid "" foreach item $entry { if {[lindex $item 0] == "Id" } { set actid [lindex $item 1] } } if { $actid == "" } { return } actNewState $actid $newstate $oldstate $actnote "" } set allactstate modified writeallact destroy .docomplete } global allact allactstate # I might be able to make this a menu, but I dont want to set it up until it # is needed, so it will have to be a window for now toplevel .docomplete wm title .docomplete "[mc "Pick an action to move from"] [mc $oldstate] [mc to] [mc $newstate]" frame .docomplete.pick listbox .docomplete.pick.actions -relief raised -borderwidth 2 -yscrollcommand ".docomplete.pick.scroll set" -width 60 -height 15 scrollbar .docomplete.pick.scroll -command ".docomplete.pick.actions yview" pack .docomplete.pick.actions -in .docomplete.pick -side left pack .docomplete.pick.scroll -in .docomplete.pick -side right -fill y set i 0 foreach entry $allact { foreach item $entry { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Id" } { set thisid $tagvalue } elseif { $tagname == "Title"} { set thistitle $tagvalue } elseif { $tagname == "Project"} { set thisproject $tagvalue } elseif { $tagname =="Status"} { if {$tagvalue == $oldstate} { set idxtitle "$i $thistitle" .docomplete.pick.actions insert end $idxtitle frame .docomplete.a$i button .docomplete.a$i.b -text $thistitle -command "doNewStateOK $i $newstate $oldstate" pack .docomplete.a$i.b -in .docomplete.a$i # pack .docomplete.a$i } } } incr i } pack .docomplete.pick frame .docomplete.note text .docomplete.note.text -rel sunk -wrap word -yscrollcommand ".docomplete.note.sb set" -width 50 -height 5 scrollbar .docomplete.note.sb -rel sunk -command ".docomplete.note.text yview" pack .docomplete.note.text .docomplete.note.sb -side left -fill y -in .docomplete.note pack .docomplete.note frame .docomplete.bot button .docomplete.bot.ok -text OK -command " doNewStateOK $newstate $oldstate" button .docomplete.bot.cancel -text [mc Cancel] -command { doCancel .docomplete } pack .docomplete.bot.ok .docomplete.bot.cancel .docomplete.bot -side left pack .docomplete.bot tkwait window .docomplete } proc activate_timeblocked_action { actid } { global allact allactstate # Activate an action which was blocked until a particular time. # This includes changing the state, and popping up a notification window. getallact # get the title and description of the action set title "" set description "" set test [list Id "==" $actid] lappend tests $test set actions [tag extract $allact $tests] foreach action $actions { # (Highlander - there shall be only one) foreach item $action { if { [lindex $item 0] == "Title" } { set title [lindex $item 1] } if { [lindex $item 0] == "Description" } { set description [lindex $item 1] } } } regsub -all {\.} "timeblocked_$actid" _ winname set winname ".$winname" toplevel $winname wm title $winname "Activate Time Blocked action $actid" frame $winname.mesg message $winname.mesg.m -width 4i -text \ "Time blocked action $actid activated\n $title\n$description" pack $winname.mesg.m $winname.mesg frame $winname.bot button $winname.bot.ok -text OK -command "actNewState $actid Active Blocked \"\" $winname" button $winname.bot.cancel -text [mc Cancel] -command "doCancel $winname " pack $winname.bot.ok $winname.bot.cancel -side left -in $winname.bot pack $winname.bot tkwait window $winname } proc activate_timeblocked {} { global allact allactstate # Activate, or prepare 'after' commands to activate, all the timeblocked actions# which will become due this day. # # This can be called when taglog starts and it will activate any timeblocked # actios which are due now. # getallact # find all the possible candidates - only interested in actions which have # the Active-after field and which are blocked. set test [list Status "-in" { Blocked Delegated }] lappend tests $test set tomorrow [clock format [clock scan tomorrow] -format "%Y-%m-%d"] set test [list Active-after -earlier $tomorrow] lappend tests $test set actions [ tag extract $allact $tests ] # puts "Time blocked actions $actions" # Find out which of those actions have already passed. set test [ list Active-after -earlier [clock format [clock seconds] -format "%Y-%m-%d %T"]] lappend nowtest $test set pastactions [ tag extract $actions $nowtest] # We can just activate all the past actions. foreach action $pastactions { foreach item $action { if { [lindex $item 0] == "Id" } { activate_timeblocked_action [lindex $item 1] } } } set test [ list Active-after -later [clock format [clock seconds] -format "%Y-%m-%d %T"]] lappend futuretest $test set futureactions [tag extract $actions $futuretest] #puts "future actions are $futureactions" foreach action $futureactions { set thisid "" foreach item $action { set tagname [lindex $item 0] set tagvalue [lindex $item 1] if { $tagname == "Id" } { set thisid $tagvalue } if { $tagname == "Active-after" } { set timetowait [expr { [clock scan $tagvalue] - [clock seconds] } ] set timetowait [expr { $timetowait * 1000 } ] after $timetowait "activate_timeblocked_action $thisid" } } } } proc getallact {} { global actionsfilename allact allactstate if { $allactstate == "closed" } { set allact [tag readfile $actionsfilename] set allactstate open # If allact is emtpy then we are just getting started - we want to put a # header on the start of the file. if { [llength $allact] == 0 } { set hdr "" set header [list Tag-action-version 1.0] lappend hdr $header set endpair [list End ] lappend hdr $endpair lappend allact $hdr } } # puts "allact is $allact" } proc writeallact {} { global actionsfilename allact allactstate if { $allactstate == "modified" } { tag writefile $actionsfilename $allact set allactstate open } } proc actCompleteCurrent {} { global currentAction activeactions if { $currentAction == "" } { return } set a $currentAction # if the current state of the action is Periodic then do not set its # state to Completed, just set the Completed-date and refresh # Period Actions view set thisact [actionFromActid $a] foreach item $thisact { # puts "item is $item" if { [lindex $item 0] == "Status" && [ lindex $item 1] == "Periodic" } { # puts "This action is Periodic" completePeriodicAction $a return } } # puts "This action is not periodic" donext "" actNewState $a Completed Active "" "" getactiveactions } proc actAbortCurrent {} { global currentAction activeactions if { $currentAction == "" } { return } set a $currentAction donext "" actNewState $a Aborted Active "" "" getactiveactions } proc archiveOldActions {} { # # Move all actions completed or aborted more than a month ago to an archive # file global allact allactstate proc oldActionsArchiveName { archdate } { global rootdir # return the name of the old actions file - takes in a date which is # the nomimal archive date.. set yearmon [clock format [clock scan $archdate] -format "%Y%m"] return "$rootdir/actions-$yearmon.tag" } set monthdate [clock format [clock scan "last month"] -format "%Y-%m-01"] getallact # extract the actions which are completed or aborted before the date set headerwritten 0 set test [list Completed-date "-earlier" $monthdate] lappend tdates $test set test [list Aborted-date "-earlier" $monthdate] lappend tdates $test foreach entry $allact { if { [tag matchany $entry $tdates] } { if { ! $headerwritten } { set filename [oldActionsArchiveName $monthdate] if { ! [ file exists $filename] } { set f [open $filename w] puts $f "Tag-action-version: 1.0" puts $f "End:" } else { set f [open $filename a] } set headerwritten 1 } tag writeentry $f $entry } else { lappend newacts $entry } } if { $headerwritten } { close $f } # Now - we update allact to be newacts # puts "newacts is $newacts" set allact $newacts set allactstate modified writeallact } proc Update_subtasks { actionid {subtaskid ""} } { global allact allactstate # Update the subtask field for actionid # - If a subtask Id is specified then only that subtask is added to the # subtasks for that action - otherwise all actions are checked to see if they # are subtasks of the action. if { $actionid == "" } { error "Update_subtasks called with null actionid" return } if { $subtaskid == "" } { set si 0 while { $si != -1} { set si [tag findval $allact Subtask-of $actionid $si ] if { $si != -1 } { Update_subtasks $actionid [tag_entryVal [lindex $allact $si] Id] incr si } } } else { # check if the subtaskid already appears in the subtasks field for the action set idx [tag findval $allact Id $actionid] if { $idx == -1 } { error "Update_subtasks called for non-existant action $actionid" return } set entry [lindex $allact $idx] set subtasks [tag_entryVal $entry Subtasks ] if { [string first $subtaskid $subtasks] != -1 } { return } if {$subtasks == "" } { set subtasks $subtaskid } else { set subtasks "$subtasks,$subtaskid" } if { $subtasks != "" } { tag setorreplace entry Subtasks $subtasks set allact [lreplace $allact $idx $idx $entry] set allactstate modified } writeallact } } proc Update_all_subtasks {} { # Find all actions which have subtasks and call Update_subtasks on them. # I think I need to work through all actions. global allact foreach action $allact { set id [tag_entryVal $action Id] if { $id != "" } { Update_subtasks [tag_entryVal $action Id] } } } proc completePeriodicAction { actid } { global allact allactstate set now [clock format [clock seconds] -format "%Y-%m-%d %H:%M"] set idx [tag findval $allact Id $actid] if { $idx == -1 } { error "Update_subtasks called for non-existant action $actid" return } set entry [lindex $allact $idx] tag setorreplace entry Completed-date $now set allact [lreplace $allact $idx $idx $entry] set allactstate modified writeallact donext "" displayPeriodicActions } proc displayPeriodicActions {} { # Display all the active periodic actions in their own window global allact debug # Find out if we have any to display foreach action $allact { foreach item $action { if {( [lindex $item 0] == "Status" ) && ([lindex $item 1] == "Periodic" )} { # need to check if it has already been done - i.e. Completed during this period # Note that there will be a Period field, and that Period could be Period: Daily # or even Period: Daily 15 # which will work in a similar way to Active-After set iscompleted 0 set period "Daily" set periodval 0 # Check for a Period foreach i $action { if { [lindex $i 0] == "Period" } { set periodstr [lindex $i 1] set periodlist [split $periodstr] set period [lindex $periodlist 0] if {[ llength $periodlist] > 1 } { set periodval [lindex $periodlist 1] } } } # Check for a Completed-date - if there is not one, then it cant be completed foreach i $action { if { [lindex $i 0] == "Completed-date" } { set cdate [lindex $i 1] if { $period == "Daily" } { set PeriodStart "[clock format [clock scan $periodval -format %H] -format %Y-%m-%d] 00:00" } elseif { $period == "Weekly" } { if {$periodval == 0 } { set periodval 1 } # set PeriodStart "[clock format [clock scan $periodval -format %u ] -format %Y-%m-%d] 00:00" # set PeriodStart "[clock format [clock scan { -1 week + 6 days } ] -format %Y-%m-%d] 00:00" # if we are after the day in the week indicated in periodval then check from this week, otherwise check from last week if { [clock format [ clock seconds ] -format %u ] >= $periodval } { # puts "Checking from this week" set PeriodStart "[clock format [clock scan $periodval -format %u ] -format %Y-%m-%d] 00:00" } else { # puts "Checking from last week" set PeriodStart "[clock format [clock scan $periodval -format %u -base [clock scan "last week"] ] -format %Y-%m-%d] 00:00" } } elseif { $period == "Monthly" } { if {$periodval == 0 } { set periodval 1 } if { [clock format [ clock seconds ] -format %d ] >= $periodval } { set PeriodStart "[clock format [clock scan $periodval -format %d ] -format %Y-%m-%d] 00:00" } else { set PeriodStart "[clock format [clock scan $periodval -format %d -base [clock scan "last month"] ] -format %Y-%m-%d] 00:00" } } elseif { $period == "Yearly" } { if {$periodval == 0 } { set periodval 1 } if { [clock format [ clock seconds ] -format %j ] >= $periodval } { set PeriodStart "[clock format [clock scan $periodval -format %j ] -format %Y-%m-%d] 00:00" } else { set PeriodStart "[clock format [clock scan $periodval -format %j -base [clock scan "last year"] ] -format %Y-%m-%d] 00:00" } } else { puts "Invalid period type - set to Daily" set period = "Daily" set PeriodStart "[clock format [clock seconds] -format %Y-%m-%d] 00:00" } if { $debug > 1 } { puts "Completed $cdate - PeriodStart $PeriodStart" } if { [clock scan $cdate -format "%Y-%m-%d %H:%M"] > [clock scan $PeriodStart -format "%Y-%m-%d %H:%M"] } { if { $debug > 1 } { puts "Is already completed for this period" } set iscompleted 1 } } } # but for now .. if { ! $iscompleted } { lappend periodicActions $action } # } } } if {[info exists periodicActions]} { # We may be being called when the window already exists if { ! [winfo exists .periodicActions ] } { toplevel .periodicActions wm title .periodicActions "Periodic Actions" } else { # If the window exists, get rid of the body - it will be recreated destroy .periodicActions.body } frame .periodicActions.body set i 1 foreach action $periodicActions { foreach item $action { if {( [lindex $item 0] == "Title" ) } { set actionTitle [lindex $item 1] } if {( [lindex $item 0] == "Id" ) } { set actionId [lindex $item 1] } } frame .periodicActions.body.i$i button .periodicActions.body.i$i.title -text $actionTitle -command "setcurrentPeriodicAction $actionId" button .periodicActions.body.i$i.done -text "Done" -command "completePeriodicAction $actionId" pack .periodicActions.body.i$i.title .periodicActions.body.i$i.done -in .periodicActions.body.i$i -side left pack .periodicActions.body.i$i -in .periodicActions.body incr i } pack .periodicActions.body -side top if { ! [winfo exists .periodicActions.bot] } { frame .periodicActions.bot button .periodicActions.bot.ok -text OK -command {doCancel .periodicActions} pack .periodicActions.bot.ok -in .periodicActions.bot pack .periodicActions.bot -side bottom } tkwait window .periodicActions } else { # puts "There are no actions to display - check to see if the window should be destroyed" if { [ winfo exists .periodicActions] } { destroy .periodicActions } } } # Action utility functions proc actionFromActid { actid } { global allact set idx [tag findval $allact Id $actid] if { $idx == -1 } { error "actionFromActid called for non-existant action $actid" return } return [lindex $allact $idx] } taglog-0.2.6/src/taglog_help_en.tag0000644000175000017500000012364313603645471015727 0ustar johnjohnTag-help-version: 1.0 Translated-by: John Lines Sorted-date: 2020-01-03 14:10:11 Sort-key: Id End: Id: About Description:: END_D This is version $1 Copyright 2000 John Lines Taglog is Free Software, released under the terms of the GNU Public License. See https://github.com/JohnLines/taglog/wiki for the taglog home page END_D End: Id: actinput Description:: END_D An action should be a clearly definable piece of work which you (or someone else) intend to do. You can use the fields in the action input menu to set key attributes of the action. Each of those fields has its own help. Before entering an action you should consider if it should be done at all. Remember Stephen R Coveys Circle of Concern and Circle of Influence from the 7 Habits of Highly Effective People. If an action does not fall within your Circle of Influence then you are best to abandon it and move on to something where you can have an effect. END_D End: Id: actinput_abort_action Description:: END_D This field contains the Id of an action which will be started if the action being entered is aborted. END_D End: Id: actinput_active_after Description:: END_D If you set a date, and optionally a time, then the action will be entered as being Blocked, and will automatically become Active at the given time, or the next time that taglog is started if the Active-after time occurred while taglog was not running. A window will pop up when the action is activated, telling you its Title and Description. This allows you to use the system for timed reminders. END_D End: Id: actinput_date Description:: END_D The Date field contains the date the action was added. It is filled in automatically by the program. END_D End: Id: actinput_delegated_to Description:: END_D This contains the Contact Id (or just the name if you are not using the Contacts) of the person that the action has been deleted to. At present taglog does not notify the person that the action has been delegated, so you will have to do that yourself. END_D End: Id: actinput_deliverable Description:: END_D The Deliverable field exists so you can define exactly how you will know when the action has been completed. If you find that actions are accumulating which are not Completed it may be that you need more precision in setting the deliverables. If the goalposts move and the action can no longer be Completed it should probably be Aborted, and a new action started with the new deliverable. END_D End: Id: actinput_description Description:: END_D Here you can enter a long description of what you are supposed to do. If you were asked to do something via an email you could cut and paste the key bits of that mail message into the description. END_D End: Id: actinput_difficulty Description:: END_D If you set a difficulty for an action you can use it later to select only actions which are easier than some level. For example you may wish to pick off a few easy actions towards the end of the day, but not want to start on something which you know will be tricky. END_D End: Id: actinput_email_status_to Description:: END_D If you set this field, and your email preferences have been set up, then a mail message will be sent to the given address every time the status of the action changes. This includes it first being created. The mail message contains all the fields in the action. Using this will let you keep someone updated on the progress of the action without you having to do any extra work. END_D End: Id: actinput_expected_completed_date Description:: END_D Enter the date by which you expect the action to be completed. The date should be entered in ISO format i.e. yyy-mm-dd You can also enter the date by clicking on the calendar widget to the right of the input field and using the displayed calendar to select the date. By recording the date when you expect to complete the action you will be able to check which actions should have completed by some date. END_D End: Id: actinput_expected_cost Description:: END_D Enter the amount (in whatever currency units are convenient to you) which you expect the action to cost (apart from the cost of the time). The cost should be spedified as a real number END_D End: Id: actinput_expected_start_date Description:: END_D Enter the date on which you expect to be able to start this action, i.e. the date you expect it to move from Pending to Active. The date should be entered in ISO format, i.e. yyyy-mm-dd You can also enter the date by clicking on the calendar widget to the right of the input field and using the displayed calendar to select the date. END_D End: Id: actinput_expected_time Description:: END_D Enter the amount of time you expect this job to take, in hours and minutes of actual work, not the elapsed time. You can select one of the values from the menu, or enter your own value in the text field, for example 3:15 for 3 hours and 15 minutes END_D End: Id: actinput_id Description:: END_D Every action is given a unique identifier. If you leave the Id field as *Auto* then an Id will be generated automatically. If you have specified an id prefix in your preferences then this forms the first part of the Id. If the action is associated with a project then the Id is generated from the name of the project, followed by a serial number which increments with each action for that project - for example jlines.test_project.57 If the action is not associated with a project then the identifier which is generated is of the for taglog.yyyymmddhhmm - taken from the current date and time - for example jlines.taglog.200011190945 Note that the prefix part goes with the originator of the action, not nescessarily with who is going to do it - it is there to make sure that the actions are unique - so that there is no confusion if someone ask - 'Have you finished jlines.test_project.57 ?' END_D End: Id: actinput_next_action Description:: END_D This field contains the Id of an action which will be started as soon as the action being entered is completed. END_D End: Id: actinput_period Description:: END_D For an action with a status of Period, the frequency or Period this action becomes active again. It is in the format Period: Daily|Weekly|Monthly|Yearly [when] where when is an optional number for the hour of day, or day of week or month when the action becomes due again. For a Daily action this defaults to 0, for Weekly, Monthly or Yearly it defaults to 1. If the field is absent or empty it defaults to Daily END_D End: Id: actinput_precursor Description:: END_D The precursor field allows an action to be blocked until another action has completed. The precursor attribute is not used yet. END_D End: Id: actinput_priority Description:: END_D Taglog uses priorities in a range from 0 to 100, where priority 0 is the most urgent, and priority 100 is behind everything else. The default priority is 50. END_D End: Id: actinput_project Description:: END_D Taglog uses the term project to refer to a way of dividing up your time for accounting purposes. If you associate an action with a project then whenever you tell taglog that you are working on that action your time will be booked to its associated project. If you do not have any projects defined yet then you can add them using the Projects/Add option of the main menu bar. END_D End: Id: actinput_reason Description:: END_D Sometimes it is difficult to remember why you are doing this in the first place. You may find that having access to the reason why you are working on this action will help motivate you. If it wont - for example if the reason is 'My boss told me to' then dont bother with this field END_D End: Id: actinput_status Description:: END_D Actions normally start with a status of Pending - which means that they are waiting to be worked on. Active actions are the ones you are currently working on, until they are Completed. Actions may be Aborted if you decide not to finish them. Actions which would be Active but for some reason which is preventing you from working on them are Blocked. Actions may also be Delegated to someone else. If you have no further responsibility for the action they you could just Complete it instead. The Unclaimed status is intended for use by a pool of people looking at a common set of actions - an action can be labeled as Unclaimed and then people can change the status to Pending, or Active and label the action as being assigned to themselves. Periodic Actions have an associated Period, which defaults to Daily. At that start of that Period the action is active, but when it is Completed it stays as a Periodic Action and is displayed again in the next Period END_D End: Id: actinput_subtask_of Description:: END_D The Subtask-of indicates that a task is a subtask of another task. It is not yet implemented. END_D End: Id: actinput_title Description:: END_D Choose a short title for this action. There are several places where you will want to identify the action from its title, without seeing the rest of the information about the task, such as the description, or the project - so try to make the title stand on its own. END_D End: Id: actions Description:: END_D The actions facility helps you to organise your 'todo' list. Once you have entered some actions you can indicate that you are working on an action by clicking on the Action button in the middle menu bar and selecting from the actions which are currently active. Add... creates a new action. View allows you to select actions to display and to edit them by right clicking on a displayed action. History finds all the log entries associated with a particular action and displays them. It also sums up all the time spent on the action and allows you to revise your estimate of the time it will take, and when it will be complete. Complete selects and active action and marks it complete. The date the action was completed is recorded and you can add a note about the completion. Activate selects a pending action and marks it as active. Abort Active marks an active action as aborted Abort Pending marks a pending action as aborted Reactivate marks an action which you thought was completed as active again. Extra... has internal facilities for manipulating the actions data which should not be required in normal use. END_D End: Id: actmail_message Description:: END_D Enter the body of the message you wish to send as a covering note to go with this action END_D End: Id: actmail_to Description:: END_D Enter the email address of the person the mail message should be sent to, or select their contact Id from the list, and their email address will be inserted automatically END_D End: Id: actreminder Description:: END_D Use this field to give you a reminder of the actions you plan to do today. At the moment this is just an ordinary text field and is not tied in to the main actions data. When you exit the program the contents of the action fields are saved so you can look back and remind yourself what you were working on yesterday. (only by looking at the raw file at present) END_D End: Id: actsel Description:: END_D There are several ways to select a set of actions. This window allows you to set the attributes of the actions you wish to select. The attributes are cumulative, so actions must match all the criteria to be selected. The Refresh button refreshes the set of actions in the drop down menus for Id and Title according to all the other criteria. END_D End: Id: actsel_expected_completed Description:: END_D You can select actions by the date you expected them to be completed. END_D End: Id: actsel_expected_start Description:: END_D You can select actions by the date you expected them to start. END_D End: Id: actsel_filename Description:: END_D Select the filename from which you are selecting actions. The default is the current active actions file END_D End: Id: actsel_id Description:: END_D If you press the Refresh button to the left of the Id field then the Id menu will be filled with the action Ids of all the actions which match the other fields. You can then use the Id field to select one particular action. END_D End: Id: actsel_maxpriority Description:: END_D Here you can choose the maximum priority for the actions which are selected. Priorities are normally on a scale from 100, as the least important to 1 as the most important. The default priority is 50. This allows you to pick actions which are more important than some level. END_D End: Id: actsel_project Description:: END_D Choose the project for which you are selecting actions. Only actions associated with that project will then be selected. END_D End: Id: actsel_showfields Description:: END_D You can select the fields which are shown when you list actions. If the All checkbox is selected then all fields are shown, otherwise only the fields selected from the other checkboxes are shown END_D End: Id: actsel_sortby Description:: END_D The actions list returned by the display can be sorted by certain fields. Select a value here to sort the selected actions by the given field value before they are displayed. END_D End: Id: actsel_st Description:: END_D If the Any checkbutton is selected then all actions are selected, regardless of status. If the Any checkbutton is not selected then only actions with a status which matches the other checkbuttons will be selected. END_D End: Id: actsel_title Description:: END_D If you press the Refresh button to the left of the Id field then the Title menu will be filled with the action titles of all the actions which match the other fields. You can then use the Title field to select one particular action. END_D End: Id: add_old_log Description:: END_D Using this panel you can add an old log entry. The entry is always appended to the log file, even if it already exists and you are adding a time range which is earlier than any of the times in that file, or which overlaps. This will confuse the reporting tools if you use them on such a file. The main use for this facility is so you can fill in an entry if ypu spent a whole day away from your computer - on leave, or on a course. END_D End: Id: addcontact Description:: END_D Fill in the fields to add a new contact. You can then use these contacts to simplify mailing of reports, and to keep track of phone calls you are due to make, or a history of contact with a particular person. END_D End: Id: addcontact_address Description:: END_D Enter the parts of the address for this contact which can not be supplied in any other field. END_D End: Id: addcontact_country Description:: END_D Enter the country where this contact resides. I suggest using the ISO country code, so as to be consistent, but the program does not enforce this. END_D End: Id: addcontact_default_as Description:: END_D This is an experimental facility in which - in a future release, you will be able to add the Id of another contact here, and all the fields for this contact, except those specified more fully in this contact, will be filled in from the values in the contact pointed to by Default-as. In this release this is just a place holder for this field - which does not do anything. END_D End: Id: addcontact_email Description:: END_D Enter the electronic mail address of the contact. END_D End: Id: addcontact_fax Description:: END_D Enter the fax number for this contact. END_D End: Id: addcontact_forename Description:: END_D Enter the forename of this contact. END_D End: Id: addcontact_id Description:: END_D Enter an identifier to use for this contact. This should be something short but memorable as it you may be selecting it from a menu of contacts. Depending on how many contacts you expect to have you could use peoples initials, or there full name. END_D End: Id: addcontact_ldap Description:: END_D Enter an LDAP URL for this contact, as described in RFC 2255 e.g. ldap://ldap.example.com/cn=smith,dc=example,dc=com Potentially this could be used to get or verify this contact's details against the LDAP server. END_D End: Id: addcontact_mobilephone Description:: END_D Enter the mobile phone number for this contact. END_D End: Id: addcontact_organisation Description:: END_D Enter the organisation associated with this contact, for example the company they work for. END_D End: Id: addcontact_phone Description:: END_D Enter the land line phone number for this contact END_D End: Id: addcontact_postcode Description:: END_D Enter the postcode, or zip code, for this contact END_D End: Id: addcontact_short_id Description:: END_D Give a short (2 or 3 character) identifier for this contact. This is used for action reports where an action is assigned to one or more people, in order to take up a small amount of space in the report. This field is only meaningful (at present) for co-workers. If it is not supplied then the normal Id is displayed instead. END_D End: Id: addcontact_surname Description:: END_D Enter the surname of this contact. END_D End: Id: addcontact_title Description:: END_D Enter the title of this contact, or select from the drop down list. Note that there are so many possible titles that the list does not even attempt to cover Professor, Lady etc. END_D End: Id: addcontact_type Description:: END_D Select the type of contact from the drop down list. You can override the contact types from your preferences file. END_D End: Id: addcontact_web Description:: END_D Enter an HTTP URL for the home page of this contact. END_D End: Id: addproject Description:: END_D Taglog uses Project in the sense of something to which you book time. The project name should be a memorable name for the project. The booking code is the way the project is identified in your billing system, which may not use memorable names for billing items. You can have a project (or more than one project) which are flagged as breaks, i.e. they are not billable time. You can also have one or more proejcts which are costed as overheads. When you generate time bookings reports you can have the time spent on your overheads proejcts spread across your real billable projects. The main projects which you are currently working on should be marked as Active. They will always appear in the Projects/View display, even if you have not booked any time on them yet today. The system automatically fills in the date that you created the project, and you can fill in the date you expect it to end, or you can fill it in later using the Projects/Edit menu entry. The system uses the dates to make the scan for total time spent on a project more effective because it only has to look at logs after the project was created. After the end date has passed you will no longer be offered the project as an option to book new time to. The Expected-time is the time - in hours and minutes you expect to book to the project over its lifetime. END_D End: Id: adjstart Description:: END_D The ability to adjust the start time of a log entry may be useful if, for example, you were away from your desk, logging time to one project, and someone diverts you to have a brief word, which turns into an extended discussion, about some other project. You can adjust the start time of the current action (the one whose description you type into the lower large window) by clicking on the Start button. You can either type the revised start time in to the box next to the label 'New Start Time' or adjust the time with the slider to subtract some number of minutes. If you are not adjusting the start time of the first entry of the day then you are offered the chance to change the end time of the previous entry to match the new start time. This is the default. If you do not adjust the end time of the previous action then you will double account for the time by which you adjusted the start. END_D End: Id: alwin_project Description:: END_D Enter or select from the drop down list the name of the project which is associated with the old log entry. All project names, even those which are now past their end date, are available for selection. END_D End: Id: archiveproject Description:: END_D From here you can move projects which have been closed to a seperate file. This will reduce the number of old projects which you are offered in the some of the drop down menus, and will save memory as all projects in the main projects file are kept in memory, even if they are closed. END_D End: Id: contacts Description:: END_D Managing contacts is not a primary function for taglog, but it has a contacts facility so you can associate a log entry with a person and search for records which relate to that person. You can also store email addresses and use them in conjunction with taglogs email facility. END_D End: Id: contactview Description:: END_D Use the fields to select the contact(s) you wish to view and click on View. If a field is blank then it matches every contact, so leaving all fields blank will return all your contacts. END_D End: Id: cview_forename Description:: END_D Enter the forename, or part of the forename, of the contact you are searching for. END_D End: Id: cview_organisation Description:: END_D Enter the name of the organisation, or part of the organisation name you wish to search for. END_D End: Id: cview_phone Description:: END_D Enter the phone number, or part of the phone number you wish to search for. END_D End: Id: cview_surname Description:: END_D Enter the surname, or part of the surname, of the contact you are searching for. END_D End: Id: cview_type Description:: END_D Select a type of contact to limit matches to that type. END_D End: Id: editprefs Description:: END_D Taglog stores its user preferences in the file named in the title of the Edit Preferences window. Here you can change several things which affect the way to the program works. Each has its own description as a Help entry in the label button. Select OK to save the preferences to this file. END_D End: Id: editprefs_current_win_depth Description:: END_D You can set the depth of the current log entry frame here, though this window will resize if you resize the whole window. END_D End: Id: editprefs_history_win_depth Description:: END_D You can reduce the depth of the History window (the one which shows log entries from earlier in the day) by reducing this value. This allows taglog to take up less screen space on a small display. END_D End: Id: editprefs_id_prefix Description:: END_D The ID prefix is used to make actions which you create unique (within a workgroup). If this is set then the Id of any actions you create will be prefixed with this prefix END_D End: Id: editprefs_num_today_actions Description:: END_D You can keep a reminder of your top 'n' actions for the day above the previous entries frame. Setting this to 0 will remove the top actions frame completely. END_D End: Id: editprefs_projects_url Description:: END_D Specify the URL to a web page which will supply the list of projects to which you can book. For example http://projects.example.com/projects-list.php?jl END_D End: Id: editprefs_start_procs Description:: END_D Any procedures listed here will be executed when taglog starts. If you want to start with the main window iconified and just a window showing the currently active project names and the amount of time booked to them today then select 'iconify_mainwin doShowProjects' END_D End: Id: editproject Description:: END_D Taglog uses Project in the sense of something to which you book time. Each project has a name, some flags related to how time for that project is booked, a booking code and a start and end date. The flags are: Breaks - this project is not normal work time. Time recorded here is treated differently when reporting and Overheads projects time is not spread into it. Overheads - time spent on this project can be spread across the real billable projects for reporting purposes. Active - This project is being actively worked on (as opposed to just being open). This causes it to always appear in the Projects/View menu even if you have not spent any time on it today yet. Immutable - Overheads are not to be spread into this project. You can prevent a project from showing up in the main selection panel by giving it an end date earlier than today. END_D End: Id: endbutton Description:: END_D The menus which come from the End button control miscellaneous features of the log entry. You can Complete the current action. You can Abort the current action. You can associate a contact with the current log entry - this is reset on moving to the next log entry. You can associate a rate with the current log entry. This is 'sticky', so if you indicate that you are now on Overtime rate you will stay on it until you exit the program or clear the rate. END_D End: Id: ep_enddate Description:: END_D Enter the date on which this project ended. END_D End: Id: file Description:: END_D Open... allows you to look at entries from previous days. You can find entries which match particular criteria, such as project or type of activity. Exit should be used to terminate the program at the end of the day. Quit terminates the program without saving the last entry. Add/Edit Log allows entries from previous days to be created or edited. To edit previous entries in todays log you should right click the entry in the upper window. Pause and Resume allow the bookings clock to be stopped and started. You may wish to create a Breaks project and switch to that instead. (see Projects/Add) Preferences allows you to customise several features of the program END_D End: Id: hint_activity_pre_meeting Description:: END_D Meetings can be a great waste of time, or they can be extremely productive. The key is preparation. Think about the following before the meeting. Why are you going to be there ? Are you running the meeting ? If so do you have an agenda with your personal guidelines for how long the items should take ? Are you to provide technical input ? If so have you done your background research ? What questions might you be asked ? Are you there to find information ? What are your objectives ? If you know what you want out of the meeting, and nobody else is prepared then you will probably get your objectives. END_D End: Id: hint_help Description:: END_D This section contains background information time management. Some of it gives suggestions for solving time management problems with taglog, but it also contains more general time management help. Additions to the hints are welcomed. If you have a great time management tip please send it to the taglog author. END_D End: Id: hint_problem_actions_overrun Description:: END_D If you find that actions are taking longer than you originally expected then you are probably being too optomistic at the outset. If you are not already doing so, try to start entering initial estimates of expected elapsed time when you enter actions. Review your active actions regularly, by using the Actions/History menu item - and update the Expected Time and Completed Date entries. The Actions/History summary will show you how your latest estimates compare with the original estimates. Use this information to help you give better original estimates in future. END_D End: Id: hint_problem_interruptions Description:: END_D If you find that interruptions are a problem you should try to set aside some time when people know you should not be interrupted. Put a notice on your door, or at your desk in an open plan office. Set up an answering machine or voicemail message telling people when you prefer to receive calls. END_D End: Id: introduction Description:: END_D Taglog provides a way to measure how you spend your time, and to assist with planning actions (tasks). You can book time to projects, which is the term taglog uses for the way you divide your time for booking purposes. If you want to book time to projects then you should create some projects entries as your next step. The main function of taglog is to make notes about how you spend your time. You enter these notes into the large lower window below. When you switch to a different activity click on the Next button and the time you started and finished that activity will be recorded. Many of the text labels have on line help, and also allow you to select values for the associated field from a list. Click on the label to see the values and help. To exit the program use the File/Exit menu item. END_D End: Id: led_calendar Description:: END_D Press one of the buttons in the calendar to select the day for which you want to input or edit the log entries. The buttons ">>" and "<<" allow to change to the next of previous month. If there is a log file available for a day, the background colour of the corresponding button is yellow. END_D End: Id: led_ediEnt Description:: END_D This window allows to edit the parameters of a log entry. END_D End: Id: led_entList This window displays the List of all log entries of a selected day. Entries with start times greater than the end time of the previous entry are marked with ">". If the start time of an entry is greater than its end time this entry is marked with "!". Marked entries are highlighted if it is supported by your TCL/TK version. The following editing options are available: Edit... This option is only active if entries are selected from the list. For each selected entry an editing window will be opened which displays all the parameters of an log entry. Add... An input window is opened to add a new log entry. Delete The selected items will be deleted. Import... This option allows to load log entries from a file. In addition you can adjust the start an end time of a log entry to the end or start time of the previous or next log entry. These operations are available iy you select an entry in the list with the right mouse button. A menu will where you can select the adjustment option. Description:: END_D END_D End: Id: led_impList This list contains the log entries of the selected file. Entries with start times greater than the end time of the previous entry are marked with ">". If the start time of an entry is greater than its end time this entry is marked with "!". Marked entries are highlighted if it is supported by your TCL/TK version. With "Import" one can transfer selected entries to the target list. "Import all" allows to import the entire list. Description:: END_D END_D End: Id: led_newEnt Description:: END_D Here you can enter the parameters for a new log entry. END_D End: Id: logedit Description:: END_D According to The Rubaiyat of Omar Khayyam (translated by Edward Fitzgerald) The Moving Finger writes; and, having writ, Moves on; nor all thy Piety nor Wit Shall lure it back to cancel half a Line, Nor all thy Tears wash out a Word of it. The taglog program, however, gives you the chance to right click on an item in the previous entries window and edit that entry. END_D End: Id: logedit_action Description:: END_D You can change the action associated with this entry. At presnet you can not select this from a list of actions, and the action Id is not verified, so take care. You should also adjust the ActionTitle field if you change this. END_D End: Id: logedit_actiontitle Description:: END_D You can change the action title associated with this entry. At presnet you can not select this from a list - also note that you should keep this in step with the Action field - which you will have to do manually at present END_D End: Id: logedit_activity Description:: END_D You can change the activity associated with this entry. END_D End: Id: logedit_contact Description:: END_D You can change the contact associated with this entry. END_D End: Id: logedit_description Description:: END_D You can change the description associated with this entry. END_D End: Id: logedit_end Description:: END_D You can change the end time of this entry - though note that at present there is no attempt to adjust the start time of the following entry. You will have to do this yourself if you want to keep your logs consistent END_D End: Id: logedit_id Description:: END_D This field shows the identifier associated with this log entry. It is not sensible to change it. END_D End: Id: logedit_project Description:: END_D Change the project associated with this entry. END_D End: Id: logedit_rate Description:: END_D You can change the rate associated with this entry. For example you could indicate that this entry is to be charged at Overtime rate. END_D End: Id: logedit_start Description:: END_D You can change the start time of this entry - though note that at present there is no attempt to adjust the end time of the preceding entry. You will have to do this yourself if you want to keep your logs consistent END_D End: Id: logsel Description:: END_D Use the date fields in the top section to select which files should be opened. You can use the fields below to restrict which entries in those files are displayed. END_D End: Id: logsel_activity Description:: END_D If you select a type of activity here then only entries which match that type of activity will be shown in the resulting display END_D End: Id: logsel_contact Description:: END_D If you select a contact here then only entries which are associated with that contact name are displayed. You could use this to review all the things you have discussed with a particular person over the last month, for example END_D End: Id: lvsa_dirname Description:: END_D Enter or select the name of the directory where the file to be saved will be stored END_D End: Id: prefs_activitiesfile Description:: END_D The activities file holds the names of the types of activity which you wish to record. The file contains one activity type per line. You need to restart taglog after making a change to this file before you can use the new activities END_D End: Id: prefs_dateformat Description:: END_D Enter your preferred format for entry and display of dates (selecting one from the options given). The taglog program always works internally in ISO 8601 format but some parts will take input dates, and output them, in your preferred format. Note that support for other date formats is currently incomplete. END_D End: Id: prefs_docdir Description:: END_D Taglog keeps its on line documentation in this directory. If you are reading this message then the docdir value is presumably already correct. If the value is not correct then you will not see this message. Thus if you can read this, do not change the value unless you really know what you are doing. END_D End: Id: prefs_language Description:: END_D This field indicates your preferred language, as an ISO 639 language code. At present only the help information is available is available in more than one language. Help with better translations and more languages is always appreciated END_D End: Id: prefs_libsdir Description:: END_D This is the directory where the main taglog program finds its libraries. Unless you really know what you are doing you should not change this. END_D End: Id: prefs_rootdir Description:: END_D The data files for taglog are all stored in this directory, or its subdirectories. Note that if you change it you may already have log files under the old directory, which you will have to move. END_D End: Id: prefs_showtime_hours_per_day Description:: END_D Enter the nominal length of your working day, in decimal hours. This is used by the Weekly Time Bookings report if you ask for times to be reported as decimal days. END_D End: Id: prefs_showtime_spreadoverheads Description:: END_D Select this if you want the time booked against overheads projects to be spread across all the bookable projects by default. END_D End: Id: prefs_timebook_startlastweek Description:: END_D If you usually run the time bookings report for the previous week then set this to last week. If you usually run the time bookings report for the current week then set this variable to this week. END_D End: Id: prefs_timeformat Description:: END_D Enter your preferred format for display of times. The taglog program will format three numbers, representing HH, MM and SS, using your preferred format. The format string is the same as used by TCL's format function or printf. For example, to alway have leading zeros in hours but no leading zeros in minutes, try "%02d:%d". END_D End: Id: project_expectedtime Description:: END_D Enter the total time (in hours) you expect to spend on this project. END_D End: Id: projects Description:: END_D Within taglog a project is a way you divide your time for booking purposes. For the ability to schedule and control activites you should look at Actions. Add creates a new project Edit allows the projects to be edited or deleted. Update allows you to fetch projects information from the URL specified in preferences. View shows the way time has been spread across projects in the current day, and allows you to switch between projects with a minimised main window. END_D End: Id: reports Description:: END_D Taglog can produce a number of reports on the information it has collected. 'Weekly Time Bookings by project' provides the information you need to feed into your company time booking system, with the time spent on each project, per day, and totaled for the week. 'Time by Activity' tells you where your time has been going in terms of meetings, phone calls etc. 'Total time for a project' goes through all the log entries for a project since it started and adds up the total time spend. 'Project Progress Report' shows the actions for a project have been completed in some time frame, and the ones which should have started or completed, but have not. 'Interruptions Report' summarizes the information gathered from using the action stack to change activity on an interruption by telling you how often this happens over some time period. 'Active and Pending actions' is a shortcut to doing Actions/View and selecting Active and Pending. 'Active Actions Review' is a more comprehensive review of all active actions, finding how much time has been spent on each one so far and offering a chance to review the amount of time you expect to spend working on them, and the time they are expected to be completed. END_D End: Id: smtp_mailhost Description:: END_D Enter the name of a computer which can be used as your mailhost, that is, a computer which will accept mail from you for delivery to other people. For Unix users the default is localhost END_D End: Id: smtp_myemail Description:: END_D Enter your email address here - the address which you wish the mail to be labeled as coming from. END_D End: Id: smtp_port Description:: END_D SMTP to another host normally uses port 25, but some systems use port 587 for local mail submission. END_D End: Id: smtp_prefsfile Description:: END_D The preferences for the mail configuration are stored in their own file. For Unix the file is ~/.smtp For Windows the file is ~/smtp.cfg If neither file is found then the smtp parameters are initialised to a set of internal defaults. END_D End: Id: smtp_thishost Description:: END_D Enter the name of this computer, which will be used in the HELO part of the SMTP dialog. END_D End: Id: summarybox Description:: END_D Enter a summary of the days events here. Note that if you hit Cancel here the program will still Exit - but without writing a summary. END_D End: Id: timebook_numweeks Description:: END_D Enter the number of weeks for which you want a report. This allows you to catch up on time bookings reporting by doing several weeks at a time. END_D End: Id: timebook_weekno Description:: END_D Enter the week number - it defaults to the current week and can be adjusted with the - and + buttons. END_D End: Id: timebook_year Description:: END_D Select which year the week of the time bookings starts in. Note that time booking reports which straddle years will probably not work END_D End: Id: timebooksel Description:: END_D Here you can control the generation of the time bookings report. You can display the times in the report as hours and minutes, or as decimal fractions of hours, or as decimal fractions of days. The preferences setting Hours per Day controls the conversion for decimal fractions of days. If you select to Spread overhead projects then the time booked to projects which are flagged as overheads is distributed across all the other projects (apart from those flagged as breaks. The overheads time for each day is spread according to the distribution of time across all bookable projects for that week. The facility to spread overhead projects by day is not yet enabled. You can choose how the projects are displayed, by booking code, or by name or both together. If you have more than one project with the same booking code and you select the 'Book by Code' option then the totals for those projects will be amalgamated. You should type in the year if you are not looking at the current year. You can change the week of the year you generate the report for, by entering the week number, or moving forwards and back with the + and - buttons. END_D End: Id: timebooksel_spreadoverheads Description:: END_D The time booked to projects which are flagged as Overheads can be redistributed across other projects. If this is set to Off then no redistribution occurs and Overheads projects are shown in the output. If this is set to Week then the total times for every normal project for the week are summed, and this is redistributed proportionally amongst the non overheads projects. If this is set to Day then the redistribution only takes place within a day. Redistribution by Day is experimental at present. Projects which are labeled as Immutable or Breaks do not participate in the redistribution process. END_D End: Id: timebooksel_timeformat Description:: END_D Time can be reported as hours and minutes, decimal hours or decimal days. The preferences setting Hours per Day controls the conversion for decimal fractions of days. END_D End: Id: UNKNOWN Description:: END_D There is no help for this item in English. I would be very grateful if you could supply a translation to john+taglog@paladyn.org END_D End: Id: viewc Description:: END_D Right clicking on a contact will bring up a menu which will allow you to edit its details END_D End: Id: viewproject Description:: END_D The 'View Project Times' display shows the cumulative time for each project you have booked to in the current day. It also shows the total time for all projects and the total time for all projects which are not labeled as 'breaks' Projects which have not been booked on the current day at the time the window is opened will not be displayed, but will show up if you click OK and then select Projects/View again You can switch to a different project by clicking on one of the project labels. END_D End: taglog-0.2.6/src/tagtest.tcl0000755000175000017500000000216313534701742014433 0ustar johnjohn#!/usr/bin/tclsh source tag.tcl proc urltest { tagname tagvalue } { if { $tagname == "URL"} { return 1 } else { return 0 } } set test [tag readfile test.tag] puts "test is $test" set newtest [ tag extract $test { { Id == nextthing } } ] puts "newtest is $newtest" set newtest [ tag extract $test { { Description -contains "second line"} } ] puts "newtest is $newtest" set newtest [ tag extract $test { { Description -exists } } ] puts "newtest is $newtest" set testentry [ lindex $test 1] puts "testentry is $testentry" tag replace testentry Tag "New value" puts "testentry is now $testentry" tag writefile "test-out.tag" $test set f [open tagtest.html w] tag writehtml dlist $f $test -isurlcall urltest close $f set sortlist [tag sort $test Priority -integer] puts "sortlist is $sortlist" set header [tag readheader test.tag] puts "header is $header" # performance test for { set i 1 } { $i<=100 } { incr i } { tag writefile "largetest.tag" $test a } set time1 [time {set t1 [tag readfile largetest.tag] } ] set time2 [time {set t2 [tag readfile0 largetest.tag] } ] puts "time1 is $time1 time2 is $time2" taglog-0.2.6/src/taglog_help_es.tag0000644000175000017500000000037213534701742015722 0ustar johnjohnTag-help-version: 1.0 Translated-by: John Lines End: Id: UNKNOWN Description:: END_D No hay ayuda para este item en Espaol. Sera muy agradecido si usted podra proveer una traduccin a john+taglog@paladyn.org END_D End: taglog-0.2.6/src/taglog_widgets.tcl0000644000175000017500000005630513534701742015767 0ustar johnjohnpackage provide taglog_widgets 0.1 # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # This file contains composed widgets and some utilities for the manipulation # of these widgets # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # +++++++++++++++++++++++++++ the menu widget +++++++++++++++++++++++++++ # ---------------------- menu_create ------------------------------------ # creates or re-builds a menu button with a pull down menu, the menu # contains command buttons which call a user defined function and/or # a help button and/or a menu entry "--" usually used to clear data # mButton name of the menu button # mLabel label for the menu button # help the help-id or "" if no help button is required # blankSw switch to allow the menu entry "--" # 0 no menu entry "--" # 1 menu entry "--" # "--" has to be handled by "cmd" # lType type of the list for button labels # see lType in "taglog_getList" # cmd name of the procedure that is called when a button in the menu # is pressed, if cmd == "menu_setText" the autocompletion # function for the entry widget "cmdData" is registered # the procedure has two parameters: # lab the label text of the button # cmdData user defined data (see next parameter) # cmdData user defined data expected for procedure "cmd" proc menu_create {mButton mLabel help {blankSw 0} {lType ""} \ {cmd ""} {cmdData ""}} { if {![winfo exists $mButton]} { # create the menu button menubutton $mButton -text $mLabel -menu $mButton.menu } if {[winfo exists $mButton.menu]} { # menu already exists, delete the menu entries $mButton.menu delete 0 end } else { menu $mButton.menu } set labCount 0 if {$blankSw == 1} { # create a menu entry "--" if {$cmd != ""} { $mButton.menu add command -label "--" -command [list $cmd "--" $cmdData] } else { $mButton.menu add command -label "--" } } foreach memb [taglog_getList $lType] { # create the command buttons within the menu if {$memb != ""} { incr labCount if {$cmd != ""} { $mButton.menu add command -label $memb \ -command [list $cmd $memb $cmdData] } else { $mButton.menu add command -label $memb } } } if {$help != ""} { # help button requested if {$labCount > 0} { # create separator widget if additional command buttons are available $mButton.menu add separator } $mButton.menu add command -label [mc Help] -command "taghelp $help" } if {$cmd == "menu_setText" && $cmdData != ""} { # because the entry widget is not jet registered we wait a few millisecs after 200 "autoCom_register $cmdData taglog_getList $lType" } return $mButton.menu } # ---------------------- menu_setText ----------------------------------- # sets the text in an entry widget with the label text of a menu command # button # # label text to be set # win entry widget proc menu_setText {label win} { if {$win != ""} { if {[winfo exists $win]} { $win delete 0 end if {$label != "--"} { $win insert 0 $label } } } } # +++++++++++++++++++++++++++ the calendar widget +++++++++++++++++++++++ # The global variable "LGL_calInfo" is only used in this file and only for # the functions of the calendar widget # ---------------------- tkCal_create ----------------------------------- # creates an calendar within a toplevel widget # # win name of the toplevel widget # "auto" means that the function creates an unique widget name # selCmd command which will be executed when a day was selected # the command has the following parameters: # win name of the toplevel calendar widget # date list containing the selected date {year month day} # selData additional information required by "selCmd" # selData additional information required by "selCmd" # day the default day in the calendar, "this" means the current day # month the default month in the calendar,"this" means the current month # year the default year in the calendar, "this" means the current year # colCmd command which will be executed when creating a calendar button # if "colCmd" returns a color name the background is set to # this color # the command has the following parameters: # year the year (four digits) # month the month number 01, 02, ..., 11, 12 # day the day number 01, 02, ..., 30, 31 # colData additional information required by "colCmd" # return: name of a color or "" # colData additional information required by "colCmd" # helpId if set, a HELP-button is created which calls "taghelp helpId" # # return: the name of the toplevel widget proc tkCal_create {{win "auto"} \ {selCmd ""} {selData ""} \ {day "this"} {month "this"} {year "this"} \ {colCmd ""} {colData ""} \ {helpId ""} } { global LGL_calInfo if {$win == "auto"} { # automatic naming of widget (e.g. .cal4) set count 0 set win ".cal[incr count]" while {[winfo exists $win]} { set win ".cal[incr count]" } } toplevel $win -class "calendar" wm title $win [mc "calendar"] wm group $win . # calculate/set current date set secs [clock seconds] if {$year == "this"} {set year [clock format $secs -format %Y]} if {$month == "this"} {set month [clock format $secs -format %m]} if {$day == "this"} {set day [clock format $secs -format %d]} set secs [clock scan "$month/$day/$year"] set LGL_calInfo($win-defY) $year set LGL_calInfo($win-defM) [string trimleft $month 0] set LGL_calInfo($win-defD) [string trimleft $day 0] set LGL_calInfo($win-actY) $year set LGL_calInfo($win-actM) [string trimleft $month 0] set LGL_calInfo($win-selCmd) [string trim $selCmd] set LGL_calInfo($win-selData) $selData set LGL_calInfo($win-colCmd) [string trim $colCmd] set LGL_calInfo($win-colData) $colData # header line with year, month and buttons to change th month set ymName "[mc [clock format $secs -format %B]] $year" frame $win.month -borderwidth 2 -relief raised pack $win.month -side top -fill both -expand 1 button $win.month.left -text "<<" -pady 0 -command "tkCal_shift $win -1" label $win.month.month -text $ymName button $win.month.right -text ">>" -pady 0 -command "tkCal_shift $win 1" pack $win.month.left -side left pack $win.month.month -side left -expand 1 -fill both pack $win.month.right -side right # create the body tkCal_redraw $win # (HELP and) cancel button frame $win.buttons -borderwidth 2 -relief raised button $win.buttons.cancel -text [mc "Cancel"] \ -command "destroy $win" -width 6 pack $win.buttons.cancel -side left -expand 1 if {$helpId != ""} { button $win.buttons.help -text [mc "Help"] -command "taghelp $helpId" -width 6 pack $win.buttons.help -side left -expand 1 } pack $win.buttons -side top -fill both -expand 1 return $win } # ---------------------- tkCal_redraw ----------------------------------- # INTERNAL USE ONLY # (re-)builds the body of the calendar, tht buttond with the days of a month # # win name of the toplevel widget proc tkCal_redraw {win} { global LGL_calInfo if {[winfo exists $win.cal]} { # delete existing buttons for {set i 6} {$i > 0} {incr i -1} { foreach j [grid slaves $win.cal -row $i] { destroy $j } } } else { # top row with abbreviations of the das names frame $win.cal -borderwidth 2 -relief sunken pack $win.cal -side top -fill both -expand 1 label $win.cal.so -text [mc Su] label $win.cal.mo -text [mc Mo] label $win.cal.di -text [mc Tu] label $win.cal.mi -text [mc We] label $win.cal.do -text [mc Th] label $win.cal.fr -text [mc Fr] label $win.cal.sa -text [mc Sa] grid $win.cal.so $win.cal.mo $win.cal.di $win.cal.mi \ $win.cal.do $win.cal.fr $win.cal.sa -row 0 -sticky nsew } set actM $LGL_calInfo($win-actM) set actY $LGL_calInfo($win-actY) # get the highest day of the month foreach maxDays {31 30 29 28} { if {[catch { clock scan "$actM/$maxDays/$actY" }] == 0} break } # get the starting position of the first day set secs [clock scan "$actM/1/$actY"] set icol [clock format $secs -format %w] # loop through days and build the buttons set irow 1 for {set i 1} {$i <= $maxDays} {incr i} { button $win.cal.b$i -text $i -command "puts $i" \ -borderwidth 1 -highlightthickness 1 -highlightcolor red grid configure $win.cal.b$i -column $icol -row $irow -sticky nsew if {$LGL_calInfo($win-selCmd) != ""} { # set the selection command $win.cal.b$i configure -command [list $LGL_calInfo($win-selCmd) $win \ [list $actY $actM $i] \ $LGL_calInfo($win-selData)] } if {$LGL_calInfo($win-colCmd) != ""} { # set the background color of the button set color [$LGL_calInfo($win-colCmd) $actY $actM $i $LGL_calInfo($win-colData)] if {$color != ""} { $win.cal.b$i configure -background $color -activebackground $color } } if {$icol == 6} { set icol 0 incr irow } else { incr icol } } if {$LGL_calInfo($win-actY) == $LGL_calInfo($win-defY) && \ $LGL_calInfo($win-actM) == $LGL_calInfo($win-defM)} { # set the focus to the default day focus $win.cal.b$LGL_calInfo($win-defD) } return } # ---------------------- tkCal_shift ------------------------------------ proc tkCal_shift {win mShift} { # INTERNAL USE ONLY # callback function to increase or de-crease the month # # win name of the toplevel widget # mShift number of month to be shifted, a negative number means # to de-crease global LGL_calInfo if {$mShift == 0} return set yy $LGL_calInfo($win-actY) set mm [expr $LGL_calInfo($win-actM) + $mShift] if {$mm > 12} { set mm 1 incr yy } elseif {$mm < 1} { set mm 12 incr yy -1 } set LGL_calInfo($win-actY) $yy set LGL_calInfo($win-actM) $mm # update the month (and year) in the header set secs [clock scan "$LGL_calInfo($win-actM)/1/$LGL_calInfo($win-actY)"] set ymName "[mc [clock format $secs -format %B]] $LGL_calInfo($win-actY)" $win.month.month configure -text $ymName tkCal_redraw $win } # ---------------------- calUtil_menu -------------------------------------- # creates a menu entry for date selection using a calendar # # menuW name of the pull down menu # dateFormat format of the date string in the entry widget # three formats are available: # DD/MM/YYYY (e.g. 24/01/2001 or 24/1/01) # MM/DD/YYYY (e.g. 01/24/2001 or 1/24/01) # YYYY-MM-DD (e.g. 2001-01-24 or 01-1-24) DEFAULT # colCmd command which will be executed when creating a calendar button # if "colCmd" returns a color name the background is set to # this color # the command has the following parameters: # year the year (four digits) # month the month number 01, 02, ..., 11, 12 # day the day number 01, 02, ..., 30, 31 # colData additional information required by "colCmd" # return: name of a color or "" # colData additional information required by "colCmd" # helpId if set, a HELP-button is created which calls "taghelp helpId" proc calUtil_menu {menuW entryW {dateFormat "YYYY-MM-DD"} \ {colCmd ""} {colData ""} \ {helpId ""} } { $menuW add command -label [mc "Calendar"] -command \ "calUtil_open $entryW $dateFormat $colCmd [list $colData] $helpId" } # ---------------------- calUtil_win --------------------------------------- # creates a combined widget for date selection consisting of an entry widget # (containing the date string), a button which allows to open a calendar and # a container for the two widgets # # win name of the container widget # dateFormat format of the date string in the entry widget # three formats are available: # DD/MM/YYYY (e.g. 24/01/2001 or 24/1/01) # MM/DD/YYYY (e.g. 01/24/2001 or 1/24/01) # YYYY-MM-DD (e.g. 2001-01-24 or 01-1-24) DEFAULT # tVar name of a global text variable for the entry widget, # MDOIFIED # width the width of the entry widget in no. of characters # colCmd command which will be executed when creating a calendar button # if "colCmd" returns a color name the background is set to # this color # the command has the following parameters: # year the year (four digits) # month the month number 01, 02, ..., 11, 12 # day the day number 01, 02, ..., 30, 31 # colData additional information required by "colCmd" # return: name of a color or "" # colData additional information required by "colCmd" # helpId if set, a HELP-button is created which calls "taghelp helpId" # # return: name of the entry widget proc calUtil_win {win {dateFormat "YYYY-MM-DD"} {tVar ""} {width 10} \ {colCmd ""} {colData ""} \ {helpId ""} } { global CALIMAGE frame $win pack $win entry $win.date -textvariable $tVar -width $width button $win.doit -bitmap @$CALIMAGE \ -command "calUtil_open $win.date $colCmd [list colData] $helpId" pack $win.date $win.doit -side left -fill both -expand 1 return $win.date } # ---------------------- calUtil_open -------------------------------------- # opens a calendar widget # # entryWin entry widget which is going to be update by the calendar # dateFormat format of the date string in the entry widget # three formats are available: # DD/MM/YYYY (e.g. 24/01/2001 or 24/1/01) # MM/DD/YYYY (e.g. 01/24/2001 or 1/24/01) # YYYY-MM-DD (e.g. 2001-01-24 or 01-1-24) DEFAULT # colCmd command which will be executed when creating a calendar button # if "colCmd" returns a color name the background is set to # this color # the command has the following parameters: # year the year (four digits) # month the month number 01, 02, ..., 11, 12 # day the day number 01, 02, ..., 30, 31 # colData additional information required by "colCmd" # return: name of a color or "" # colData additional information required by "colCmd" # helpId if set, a HELP-button is created which calls "taghelp helpId" proc calUtil_open {entryWin {dateFormat "YYYY-MM-DD"} \ {colCmd ""} {colData ""} \ {helpId ""} } { set dateStr [calUtil_parse $dateFormat [$entryWin get]] if {$dateStr == ""} { set yy "this" set mm "this" set dd "this" } else { set yy [lindex $dateStr 0] set mm [lindex $dateStr 1] set dd [lindex $dateStr 2] } tkCal_create "auto" "calUtil_set" \ [list $entryWin $dateFormat] $dd $mm $yy $colCmd $colData $helpId } # ---------------------- calUtil_parse ------------------------------------- # parses a date string # # dateFormat expected format of the date string, three formats are available: # DD/MM/YYYY (e.g. 24/01/2001 or 24/1/01) # MM/DD/YYYY (e.g. 01/24/2001 or 1/24/01) # YYYY-MM-DD (e.g. 2001-01-24 or 01-1-24) # date the date string to be parsed # # return: a list of three numbers: {YYYY MM DD} (e.g. {2001 01 24}) # or empty string if failed proc calUtil_parse {dateFormat date} { set date [string trim $date] if {[string length $date] < 6 || [string length $date] > 10 || \ [catch { if {$dateFormat == "DD/MM/YYYY"} { regsub -all -- "/" $date " " dateStr set yy [lindex $dateStr 2] set mm [lindex $dateStr 1] set dd [lindex $dateStr 0] } elseif {$dateFormat == "MM/DD/YYYY"} { regsub -all -- "/" $date " " dateStr set yy [lindex $dateStr 2] set mm [lindex $dateStr 0] set dd [lindex $dateStr 1] } else { regsub -all -- "-" $date " " dateStr set yy [lindex $dateStr 0] set mm [lindex $dateStr 1] set dd [lindex $dateStr 2] } # re-calculate the date string to check for a correct date set date [clock format [clock scan "$mm/$dd/$yy"] -format "%Y-%m-%d"] scan $date "%4d-%2d-%2d" yy mm dd }]} { # parsing failed return "" } return [format "%4d %02d %02d" $yy $mm $dd] } # ---------------------- calUtil_set --------------------------------------- # callback function for the calendar window, fills an entry widget with a # date string and closes the calender # INTERNAL USE ONLY # # calWin the toplevel widget of the calendar # date list containing the date {year month day} # cmdInfo additional information used for this function, # list with 2 elements: target window (entry widget) and # date format proc calUtil_set {calWin date cmdInfo} { set tgWin [lindex $cmdInfo 0] set dateFormat [lindex $cmdInfo 1] if {[winfo exists $tgWin]} { # erase the old string $tgWin delete 0 end set year [lindex $date 0] set month [lindex $date 1] set day [lindex $date 2] # insert the new string if {$dateFormat == "DD/MM/YYYY"} { $tgWin insert 0 [format "%02d/%02d/%4d" $day $month $year] } elseif {$dateFormat == "MM/DD/YYYY"} { $tgWin insert 0 [format "%02d/%02d/%4d" $month $day $year] } else { $tgWin insert 0 [format "%4d-%02d-%02d" $year $month $day] } } # colse the calendar destroy $calWin } # +++++++++++++++++++++++++++ automatic completion of text ++++++++++++++ # The global variable "LGL_autoC" is only used in this file and only for # the automatic completion of text # ---------------------- autoCom_register ------------------------------- # registers an key-event driven procedure to complete text in an entry widget # the list of text strings used for the completion are provided by an # application defined function # # entW name of the entry widget # cmd application defined function which provides a list of # strings. "cmd" has one parameter "cmdArgs". If "cmd" # is "" then the parameter "cmdArgs" is used as the list. # cmdArgs list of arguments for function "cmd" or in case of an # empty "cmd" it is the list used for the completion # # required global variables: # GL_autoComCase switch to ignore the case: 0=no, 1=yes # GL_autoComMsec "GL_autoComMsec" milliseconds after a keyboard input # the completion is performed # 0 means: compleation after key only proc autoCom_register {entW cmd cmdArgs} { global LGL_autoC global GL_autoComCase global GL_autoComMsec set idx 0 # get a free identification number for "LGL_autoC" while {[info exists LGL_autoC($idx-entW)]} {incr idx} set LGL_autoC($idx-entW) $entW set LGL_autoC($idx-cmd) $cmd set LGL_autoC($idx-cmdArgs) $cmdArgs set LGL_autoC($idx-mSecs) $GL_autoComMsec set LGL_autoC($idx-caseSw) $GL_autoComCase set LGL_autoC($idx-string) [$entW get] if {$GL_autoComMsec > 0} { # for all KeyRelease events set kEvent } else { # for -KeyPress event set kEvent } bind $entW $kEvent "autoCom_keyEvent $idx %K" # free entries in global variable when the widget gets destroyed bind $entW Destroy "autoCom_unset $idx" return idx } # ---------------------- autoCom_keyEvent ------------------------------- # INTERNAL USE ONLY # function called by the key binding defined in autoCom_register # # idx unique identification used for "LGL_autoC" # key keysymbol proc autoCom_keyEvent {idx key} { global LGL_autoC # global information available? if {![info exists LGL_autoC($idx-entW)]} return if {![winfo exists $LGL_autoC($idx-entW)]} return set LGL_autoC($idx-string) [$LGL_autoC($idx-entW) get] if {[info exists LGL_autoC($idx-afterId)]} { # cancel older completion requests after cancel $LGL_autoC($idx-afterId) } # the following keys have no automatic completion if {$key == "BackSpace" || \ $key == "Left" || \ $key == "Right" || \ $key == "Delete"} return if {$LGL_autoC($idx-mSecs) > 0 && $key != "Escape"} { # start completion after "LGL_autoC($idx-mSecs)" milliseconds set LGL_autoC($idx-afterId) \ [after $LGL_autoC($idx-mSecs) "autoCom_doIt $idx"] } else { # start completion now autoCom_doIt $idx } } # ---------------------- autoCom_doIt ----------------------------------- # INTERNAL USE ONLY # completion function # # idx unique identification used for "LGL_autoC" proc autoCom_doIt idx { global LGL_autoC if {[info exists LGL_autoC($idx-afterId)]} { # unset the timer-Id unset LGL_autoC($idx-afterId) } # global information available? if {![info exists LGL_autoC($idx-entW)]} return if {![winfo exists $LGL_autoC($idx-entW)]} return set str [$LGL_autoC($idx-entW) get] # a completion is done only if the input string hasn't changed during the # waiting period if {$LGL_autoC($idx-string) != $str} return set LGL_autoC($idx-string) $str if {$str == ""} return if {$LGL_autoC($idx-cmd) == ""} { # cmdArgs contains the list for completion set xList $LGL_autoC($idx-cmdArgs) } else { # cmd provides the list for completion set xList [$LGL_autoC($idx-cmd) $LGL_autoC($idx-cmdArgs)] } # build a list of all members in the list which start with the string # input in the entry widget if {$LGL_autoC($idx-caseSw)} { set strC [string tolower $str] foreach i $xList { if {[string match ${strC}* [string tolower $i]]} {lappend iList $i} } } else { foreach i $xList { if {[string match ${str}* $i]} {lappend iList $i} } } if {[info exists iList]} { set nStr [autoCom_check [string length $str] $iList $LGL_autoC($idx-caseSw)] $LGL_autoC($idx-entW) delete 0 end $LGL_autoC($idx-entW) insert 0 [lindex $nStr 1] if {![lindex $nStr 0]} bell } } # ---------------------- autoCom_check ---------------------------------- # INTERNAL USE ONLY # provides the maximum text string all members of a list start with # # iLen the number of characters which are identical in all members # of the list # iList list with text strings, at least the first "iLen" characters # of each string are identical # caseSw switch to ignore the case of the letters # 0 do NOT ignore the case # 1 ignore the case # # return: list of two parameters {iSw maxStr} # iSw: switch # 0 input string extended, more than one list member # starts with this string # 1 input string not extended or the extension matches # exactly one member # maxStr: text string all members of the list "iList" start with proc autoCom_check {iLen iList caseSw} { if {$iLen < 1 || [llength $iList] < 1} {return {"1" ""}} set m1 [lindex $iList 0] # only one member in the list? if {[llength $iList] == 1} {return "1 [list $m1]"} set l1 [string length $m1] set retVal [string range $m1 0 [expr $iLen -1]] set iSw 1 for {set i $iLen} {$i < $l1} {incr i} { set cTst [string index $m1 $i] if {$caseSw} {set cTst [string tolower $cTst]} foreach m [lrange $iList 1 end] { if {[string length $m] <= $i} {return "$iSw [list $retVal]"} if {$caseSw} { if {[string tolower [string index $m $i]] != $cTst} { return "$iSw [list $retVal]" } } else { if {[string index $m $i] != $cTst} {return "$iSw [list $retVal]"} } } set retVal [string range $m1 0 $i] set iSw 0 } foreach m [lrange $iList 1 end] { if {[string length $m] > $i} {return "0 [list $m1]"} } return "1 [list $m1]" } # ---------------------- autoCom_unset ---------------------------------- # INTERNAL USE ONLY # unsets all entries of the global array LGL_autoC associated with "idx" # # idx unique identification used for "LGL_autoC" proc autoCom_unset idx { global LGL_autoC foreach i [array names "$idx-*"] { unset LGL_autoC($i) } # only for higher tcl version #array unset LGL_autoC "$idx-*" } taglog-0.2.6/src/taglog_help_nl.tag0000644000175000017500000000110313603645471015720 0ustar johnjohnTag-help-version: 1.0 Translated-by: John Lines Sorted-date: 2020-01-03 14:10:11 Sort-key: Id End: Id: About Description:: END_D Dit is versie $1 Auteursrecht 2000 John Lines Taglog Vrije Software zijn, die in het kader van de termijnen van de Openbare Vergunning van GNU wordt vrijgegeven. Zie https://github.com/JohnLines/taglog/wiki voor de taglog homepage END_D End: Id: UNKNOWN Description:: END_D Er is geen hulp voor dit punt in het Nederlands. Ik zou zeer dankbaar zijn als u een vertaling aan john+taglog@paladyn.org kon leveren. END_D End: taglog-0.2.6/src/smtptest.tcl0000755000175000017500000000041013534701742014634 0ustar johnjohn#!/usr/bin/tclsh source smtp.tcl source tag.tcl set testtag { { Id test.1 } { tag1 value1 } { test2 value2 } { End } } smtp send -subject "Test subject" -attachtag $testtag -attachname "testname.tag" "Test message\nthis is a two line message" john@localhost taglog-0.2.6/src/cal2.xbm0000644000175000017500000000057713534701742013611 0ustar johnjohn#define cal2_width 21 #define cal2_height 16 static unsigned char cal2_bits[] = { 0x00, 0x00, 0x00, 0x80, 0x24, 0x09, 0x80, 0x24, 0x09, 0x00, 0x00, 0x00, 0x92, 0x24, 0x09, 0x92, 0x24, 0x09, 0x00, 0x00, 0x00, 0x92, 0x24, 0x09, 0x92, 0x24, 0x09, 0x00, 0x00, 0x00, 0x92, 0x24, 0x09, 0x92, 0x24, 0x09, 0x00, 0x00, 0x00, 0x92, 0x24, 0x00, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00}; taglog-0.2.6/src/pkgIndex.tcl0000644000175000017500000000211513534701742014523 0ustar johnjohn# hand make package index package ifneeded tag 0.1 [list source [file join $dir tag.tcl]] package ifneeded smtpclient 0.1 [list source [file join $dir smtp.tcl]] # The following are internal taglog routines package ifneeded taglog_help 0.1 [list source [file join $dir taglog_help.tcl]] package ifneeded taglog_report 0.1 [list source [file join $dir taglog_report.tcl]] package ifneeded taglog_init 0.1 [list source [file join $dir taglog_init.tcl]] package ifneeded taglog_util 0.1 [list source [file join $dir taglog_util.tcl]] package ifneeded taglog_project 0.1 [list source [file join $dir taglog_project.tcl]] package ifneeded taglog_action 0.1 [list source [file join $dir taglog_action.tcl]] package ifneeded taglog_contact 0.1 [list source [file join $dir taglog_contact.tcl]] package ifneeded taglog_widgets 0.1 [list source [file join $dir taglog_widgets.tcl]] package ifneeded logEdit 0.1 [list source [file join $dir logEdit.tcl]] package ifneeded mainwin 0.1 [list source [file join $dir mainwin.tcl]] package ifneeded taglog_stack 0.1 [list source [file join $dir taglog_stack.tcl]] taglog-0.2.6/test.tag0000644000175000017500000000071513534701742013137 0ustar johnjohnTag-test-version: 1.0 Description: Test tag file - note that this is in the header End: Id: something Tag: some value NextTag: next value End: Id: nextthing Description:: END_D This is a multiline description Here is the second line END_D Priority: 50 End: Id: anotherthing Description: just a description URL: http://www.example.com/ Purpose: testing URL display Priority: 20 End: Id: yetanotherthing Priority: 60 End: Id: importantthing Priority: 5 End: taglog-0.2.6/cleanup_projlogs0000755000175000017500000000107213534701742014754 0ustar johnjohn#!/usr/bin/tclsh # Script to take a tag log file and convert every line which says # Project: something (other) # to # Project: something # set filename $argv set f [ open $filename r ] set outfile "$filename.new" set f2 [ open $outfile w ] while { ![eof $f]} { set line [ gets $f] # does it start with Project: if { [string match Project:* $line ]} { set idx [ string first ( $line ] # do something with it if { $idx !=-1 } { incr idx -1 set line [ string range $line 0 $idx] set line [string trimright $line] } } puts $f2 $line } taglog-0.2.6/INSTALL0000644000175000017500000000571513534701742012521 0ustar johnjohn Taglog Installation Instructions Requirements ------------ Taglog requires TCL and TK - almost any version should do. It has been tested under Linux, Solaris and Windows NT and 95. It uses the clock tcl function present in tcl 8.2 - though I am not sure when it appeared - if the version of tcl is older than this then it uses the GNU date command (at present - although support for other forms of the command are intended for future releases) Some facilities use TCL8.3 features and this is the TCL version which has had the most thorough testing with taglog. If you do not have TCL on your computer you can download a version, for Unix or Windows from www.scriptics.com. This is a Free download. The taglog program is distributed as a gzipped tar archive. If you are on a Windows system you will need a program which can unpack the distribution. I have successfully used PowerArchiver - from www.powerarchiver.com or pkzip - from www.pkware.com. Powerarchiver used to be free, and is now shareware. If you have plenty of disk space - about 200Mb (and time for the download) you can install Cygwin for free. This is a full suite of free programs giving you many powerful Unix tools on your Windows PC. You can download Cygwin from http://sources.redhat.com/cygwin/ Installation for Unix (as a user) --------------------------------- Make sure you have TCL installed on your system. Unpack the downloaded tar.gz file into a temporary directory. Change directory into the directory which contains the unpacked taglog distribution. Enter the command 'wish src/install.tcl' The graphical installer will show you the directories where the files will be installed. Installation for Unix (as root) ------------------------------- Make sure you have TCL installed on your system. Unpack the downloaded tar.gz file into a temporary directory. Change directory into the directory which contains the unpacked taglog distribution. Enter the command 'tclsh src/install.tcl -system' The taglog file will be installed into /usr/lcoal/bin, the libraries into /usr/local/lib/taglog and the documentation into /usr/local/doc/taglog Installation for Windows ------------------------ Make sure yoy have tcl and an archive program which can unpack at tar.gz file. Unpack the distribution into a temporary directory, and execute the install.tcl script by clicking on its icon. You may want to make a shortcut to the taglog.tcl program and place it on your Windows desktop. Post install configuration for all platforms -------------------------------------------- By default the log files which taglog creates are stored in a directory called ~/diary. You can change the location of these files by using the File/Preferences option. If you want to use the built in mail facilities of the program you will have to set up the mail related fields in File/Preferences. Please report any problems with installation to john+taglog@paladyn.org, or create in issue in Github at https://github.com/JohnLines/taglog/issues