Mercurial > pyarq-presupuestos
changeset 1:2ac1551ad2ab version 0.0.0
add code
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + 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 <http://www.gnu.org/licenses/>. + +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: + + <program> Copyright (C) <year> <name of author> + 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 +<http://www.gnu.org/licenses/>. + + 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 +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Generic/__init__.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +## +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. +# +# define __all__ so 'from Generic import *' works +# +__all__ = [ + 'base', + 'config', + 'durusdatabase', + 'fiebdc', + 'globals', + 'openwith', + 'utils', + ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Generic/base.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,3453 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File base.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. + +"""base module + +In this module are defined the data structures in the +classes: + * Record: data of each record + * ParamentricRecord: data of each parametric record + * Decomposition: data of the decomposition of each record + * Measure: data of the measure of each record + * MeasureLine: each measure line data + * Decimals: data of the decimal places of all the numbers in a budget + * Sheet: data of the sheet of conditions of a budget + * Budget: all data of a budget + * Company: company data + * Office: company office data + * File: file data + * RecordType: Record type data + +schema: + * Budget: + +-- __records: dictionary records { code : Record } + * Record: + +-- code: record code + +-- synonyms: list of synonym codes + +-- hierarchy: A integer number: + 0 -> root + 1 -> Chapter/Subchapter + 2 -> Other + +-- unit: unit of measure of the record + +-- summary: Short description of the record + +-- prices: List of Prices/Dates + +-- type + +-- subtype + "type" and "subtype": + 0 Without classifying + EA Auxiliary element + EU Unitary element + EC Complex element + EF Functional element + OB Construction site + PA Cost overrun + PU Unitary budget + 1 Labourforce + H Labourforce + 2 Machinery and auxiliary equipment + Q Machinery + % Auxiliary equipment + 3 Building materials + MC Cement + MCr Ceramic + MM Wood + MS Iron and steel + ME Energy + MCu Copper + MAl Aluminium + ML Bonding agents + M Others materials + Hierarchy type subtype + 0->root -> 0 -> None,OB + 1->[sub]chapter -> 0 -> None,PU + 2->Other -> 0 -> None,EA,EU,EC,EF,PA + 1 -> None,H + 2 -> None,Q,% + 3 -> None,MC,MCr,MM,MS,ME,MCu,Mal,ML,M + +-- parents: List of parent codes + +-- children: list of Decomposition + * Decomposition: + +-- position: Position of the child in the parent descomposition + TODO: change this: the position of the record in the budget + +-- code: child record code + +-- budget: list of budget and amended budget measures + * Measure: + +-- measure: Total result of measure + +-- lines: List of measure lines + * MeasureLine: + +-- type: Line type: + empty string -> Normal + 1 -> Parcial Subtotal + 2 -> Accumulated Subtotal + 3 -> Formula, the comment is a formula. + +-- comment: Can be a descriptive text or a formula + Valid Operator: '(', ')', '+', '-', '*', '/' and + '^' + Valid variable: 'a', 'b', 'c','d' y 'p' + (Pi=3.1415926) + +-- units: Number of Units (a) + +-- length: length (b) + +-- width: width (c) + +-- height: height (d) + +-- label: Record Identifiers that are used by some measure + programs + +-- factor: Factor + +-- yield_: Yield + +-- certification: list of certifications for months measures + * Measure + +-- real_cost: list of real cost of construction for months + measures + * Measure + +-- cost_goals: list of cost goals of construction for months + measures + * Measure + +-- cost_planned: list of costs planned and amended cost planned + measures + * Measure + +-- text: Long Description of the record + +-- sheet: Sheet of conditions object + * Sheet: + +-- sheet_dict: + { <Field key> : { <Section key> : <Paragraph key>}} + +-- files: List of file object + +-- file + * Name + * Type + * Description + +-- __synonyms: synonyms dictionary. TODO + +-- __root: root record code + +-- __decimals: decimals dictionay = { int : Decimals } + * Decimals: + +-- DN: Number of decimal places of the field "equal-size parts" in the + measure lines. + Default: 2 decimal places. + +-- DD: Number of decimal places of the three dimensions in the + measure lines. + Default: 2 decimal places. + +-- DS: Number of decimal places of the total sum of a measure. + Default: 2 decimal places. + +-- DFP: Number of decimal places of the yield factor in a + decomposition of a budget record. + Default: 3 decimal places. + +-- DFC: Number of decimal places of the yield factor in a + decomposition of a chapter or subchapter, and in its measure lines. + Dafault: 3 decimal places. + +-- DFUO: Number of decimal places of the yield factor in a + decomposition of a unit of work. + Default: 3 decimal places. + +-- DFA: Number of decimal places of the yield factor in a + decomposition of a Auxiliary element. + Default: 3 decimal places. + +-- DRP: Number of decimal places of the yield in a decomposition + of a budget record. + Number of decumal places of the result of the multiplication of + the factor and the yield in a decompositon of a budget. + Default: 3 decimal places. + +-- DRC: Number of decimal places of the yield (or measure) in a + decomposition of a chapter or subchapter. + Number of decimal places of the result of the multiplictaion of + the yield (or measure) and the factor in a decomposition of a + chapter or subcharter. + Default: 3 decimal places. + +-- DRUO: Number of decimal places of the yield in a decomposition of a + unit of work. + Decimal places of the result of the multiplication of the yield + and the factor in a descomposition of a unit of work. + Default: 3 decimal places. + +-- DRA: Number of decimal places of the yield in a decompositon of a + auxiliar element. + Number of decimal places of the result of the multiplication of + the yield and the factor in a descomposition of a auxilar element. + Default: 3 decimal places. + +-- DP: Number of decimal places of the price of a budget. + Default: 2 decimal places. + +-- DC: Number of decimal places of the price of a chapter or + subchapter. + Default: 2 decimal places. + +-- DUO: Number of decimal places of the price of a unit of work. + Default: 2 decimal places. + +-- DEA: Number of decimal places of the price of a auxiliar element. + Default: 2 decimal places. + +-- DES: Number of decimal places of the price of the simple elements. + Default: 2 decimal places. + +-- DIR: Number of decimal places of the resulting amount to multiply + the total yield and the price of the elements of a unit of work. + (When there are not measures) + +-- DIM: Number of decimal places of the resulting amount to multiply + the total yield and the price of the elements of a unit of work. + (When there are measures) + +-- DIRC: Number of decimal places of the resulting amount to multiply + the total yield and the price of the elements of a budget, chapter + or a subchapter.(When there are not measures) + +-- DIMC: Number of decimal places of the resulting amount to multiply + the total yield and the price of the elements of a budget, chapter + or a subchapter. (When there are measures) + +-- DCD: Number of decimal places ot the resulting amount to sum the + direct costs of a unit of work (and auxiliar element). + Number of decimal places of the indirect costs. + Default: 2 decimal places. + +-- DIVISA: monetary unit. + +-- __percentages: percentages dictionary: + { "CI" : "", + "GG" : "", + "BI" : "", + "BAJA": "", + "IVA" : ""} + +-- __file_owner + +-- __title_list: titles list: [ "Header", ["Title1", "Title2", ... ] ] + +-- __title_index: A integer. The active group of Prices and Decimals. + +-- __sheet_sections: sheet sections dictionary { sheet_code : sheet_title } + +-- __sheet_fields: sheet fields dictionary { field_code : field_title } + +-- __sheet_paragraphs: sheet paragraphs dictionary + { paragraph_code : paragraph_text} + +-- __companys: Dictionary whith companys object + { company_code: company_object } + * Comapany: + +-- code: company code + +-- summary: short name + +-- name: long name + +-- offices: List of offices: + * Office: + +-- type: office type + "C" Central office. + "D" Local Office. + "R" Performer. + +-- subname: Office name + +-- address: Ofiice address + +-- postal_code: postal code + +-- town: town + +-- province: province/state + +-- country: country + +-- phone: list of phone numbers + +-- fax: list of fax numbers + +-- contact_person: Contact person in the office + +-- cif: CIF + +-- web: web page + +-- email: email +""" + +# Modules +import re +import datetime +import os + +# pyArq-Presupuestos modules +from Generic import fiebdc +from Generic import utils + +class Record(object): + """base.Record: + + Description: + Record object + Constructor: + base.Record(code, synonyms, hierarchy, unit, summary, prices, type, + subtype, text="") + Ancestry: + +-- object + +-- Record + Atributes: + "code": Code string + "recordType": RecordType object + "synonyms": List of synonym codes. + "parents":List of parent codes + "children": Decomposition list, + list of "Decomposition" instances + "unit": measure unit of the record + "summary": Short description of the record + "prices": List of prices/dates + "text": Long Description of the record + "sheet": Sheet of conditions object + "files": List of file object + "labels": List of record labels + Methods: + __getstate__(self) + __setstate__(self, tuple) + __init__(self, filename=None, budget=None) + {get/set}Code + {get/set}Synonyms + {get/set}RecordType + {get/set}Unit + {get/set}Summary + {get/set}Prices + addPrice + _validate_price_date + getPrice + getAmount + getDate + {get/set}Parents + appendParent + {get/set}children + appendChild + {get/set}Text + {get/set}Sheet + {get/set}Files + addFile + {get/set}Labels + addLabel + """ + __slots__ = ["_Record__code", "_Record__synonyms", + "_Record__recordType", "_Record__unit", + "_Record__summary", "_Record__prices", + "_Record__parents", "_Record__children", + "_Record__text", "_Record__sheet", + "_Record__files", "_Record__labels"] + + def __getstate__(self): + return (self.__code, self.__synonyms, self.__recordType, + self.__unit, self.__summary, self.__prices, + self.__parents, self.__children, self.__text, + self.__sheet, self.__files, self.__labels) + + def __setstate__(self, tuple): + self.__code = tuple[0] + self.__synonyms = tuple[1] + self.__recordType = tuple[2] + self.__unit = tuple[3] + self.__summary = tuple[4] + self.__prices = tuple[5] + self.__parents = tuple[6] + self.__children = tuple[7] + self.__text = tuple[8] + self.__sheet = tuple[9] + self.__files = tuple[10] + self.__labels = tuple[11] + + def __init__(self, decimals, code, synonyms, hierarchy, unit, summary, + prices, type, subtype, parents=[], text=""): + self.code = code + self.synonyms = synonyms + self.recordType = (hierarchy, type, subtype) + self.unit = unit + self.summary = summary + self.setPrices(prices, decimals) + self.parents = parents + self.children = [] + self.text = text + self.sheet = Sheet() + self.files = [] + self.labels = [] + + def getCode(self): + return self.__code + + def setCode(self, code): + """setCode(self,code) + + Sets the code, must be a valid code + """ + if not utils.is_valid_code(code)[0]: + raise ValueError, utils.mapping(_("Invalid code: $1"),(str(code),)) + self.__code = code + + def getSynonyms(self): + return self.__synonyms + + def setSynonyms(self,synonyms): + """setSynonyms(self,synonyms) + + Sets the synonyms codes of the record. + synonyms must fulfill: + - must be a list + - the items must be valid codes + """ + if not isinstance(synonyms, list): + raise TypeError, utils.mapping(_("Synonyms ($1) must be a list, " \ + "code: $2"), (str(synonyms), self.__code)) + for code in synonyms: + if not utils.is_valid_code(code)[0]: + raise ValueError, utils.mapping(_("Invalid Code in synomyms "\ + "list ($1) code: $2"), (str(code), self.__code)) + self.__synonyms = synonyms + + def getRecordType(self): + return self.__recordType + + def setRecordType(self, recordType): + """setRecordType(self, recordType) + + Set the record type. + recordType (hierarchy, type,subtype) + + hierarchy must be -1, 0, 1 or 2 + type must be 0, 1, 2, 3 or a empty string + subtype must be EA, EU, EC, EF, OB, PA, PU, H, Q, %, MC, MCr, + MM, MS, ME, MCu, MAl, ML, M, or a empty string + """ + _recordType = RecordType(recordType[0],recordType[1],recordType[2]) + self.__recordType = _recordType + + def getUnit(self): + return self.__unit + + def setUnit(self,unit): + """setUnit(self,unit) + + Set the unit of measure + The unit must be a string. + """ + if not isinstance(unit, str): + raise TypeError, utils.mapping(_("Unit ($1) must be a string: $2"), + (str(unit), self.__code)) + self.__unit = unit + + def getSummary(self): + return self.__summary + + def setSummary(self,summary): + """setSummary(self,summary) + + Set the summary of a record + The summary must be a string. + """ + if not isinstance(summary, str): + raise TypeError, utils.mapping(_("Summary ($1) must be a string: "\ + "$1"), (str(summary), self.__code)) + self.__summary = summary + + def getPrices(self): + return self.__prices + + def setPrices(self, prices, decimals): + """setPrice(self, prices, decimals) + + Set the price list of the record. + prices must fulfill: + - it must be a list + - the items must be a list with two items + - the first item: price must be a float + """ + if not isinstance(prices, list): + raise TypeError, utils.mapping(_("Prices ($1) must be a list: $2"), + (str(prices), self.__code)) + for index in range(len(prices)): + _price_date = prices[index] + _price_date = self._validate_price_date(_price_date, decimals) + prices[index] = _price_date + self.__prices = prices + + def addPrice(self, price_date, decimals): + """addPrice(self, price_date, decimals) + + Add a price to the price list of the record. + price must fulfill: + - must be a list with two items + - the first item: price must be a float + """ + price_date = self._validate_price_date(price_date, decimals) + self.__prices.append(price_date) + + def _validate_price_date(self, price_date, decimals): + if not isinstance(price_date, list) and len(price_date) == 2: + raise ValueError, utils.mapping(_("Price ($1) must be a list"\ + " with two items: $2"), (str(price_date), self.__code)) + _price = price_date[0] + _date = price_date[1] + if not isinstance(_price, float): + raise TypeError, utils.mapping(_("Price must be a float "\ + "number: $1"), (str(_price),)) + _D = decimals.getD(self.recordType) + _price = round(_price, _D) + price_date[0] = _price + # TODO: validate date + return price_date + + def getPrice(self, index_price): + if len(self.__prices) <= index_price: + raise IndexError, _("The record do not have this Price. Code: %s" + % self.__code) + return self.__prices[index_price][0] + + def getDate(self, index_price): + if len(self.__prices) <= index_price: + raise IndexError, _("The record do not have this Price") + return self.__prices[index_price][1] + + def getParents(self): + return self.__parents + + def setParents(self,parents): + """setParents(self,parents) + + Sets the list of parents codes of the record. + parents must fulfill + - it must be a list + - the items must be valid codes + """ + if not isinstance(parents, list): + raise TypeError, utils.mapping(_("Parents ($1) must be a list: $2"), + (str(parents), self.__code)) + for parent in parents: + if not utils.is_valid_code(parent)[0]: + raise ValueError, utils.mapping(_("Invalid parent code ($1) " \ + "in the record: $2"), (str(padre), self.__code)) + self.__parents = parents + + def appendParent(self, parent): + """appendParent(self, parent) + + parent must be a valid code + Append a parent to the list of parents codes of the record. + + """ + if not utils.is_valid_code(parent)[0]: + raise ValueError, utils.mapping(_("Invalid parent code ($1) " \ + "in the record: $2"), (str(parent), self.__code)) + self.__parents.append(parent) + + def getchildren(self): + return self.__children + + def setchildren(self,children): + """setchildren(self,children) + + Sets the list of children of a record + children must fulfill + - it must be a list + - the items must be instances of Decomposition class + """ + if not isinstance(children, list): + raise TypeError, utils.mapping(_("children ($1) must be a list, "\ + "record: $2"), (str(children), self.__code)) + for _child in children: + if not isinstance(_child, Decomposition): + raise ValueError, utils.mapping(_("child ($1) must be a "\ + "Decomposition object, record: $2"), + (str(_child), self.__code)) + _record_code = self.code + for _measure_list in [_child.budgetMeasures, _child.certification, + _child.real_cost, _child.cost_goals, + _child.cost_planned]: + if isinstance(_measure_list, list): + for _measure in _measure_list: + _measurerecordCode = _record_code + self.__children = children + + def appendChild(self, child_code, decimals, factor=0.0, yield_=0.0, + measure=0.0, measure_list=[], type ="", label=""): + """appendChildren(self, child_code, factor=0.0, yield_=0.0, + measure=0.0, measure_list=[], type ="", label="")) + + position: + child_code: + factor: + yield_: + measure: + measure_list: + type: + label: + + Append a child to the list of children + """ + _measure = Measure(decimals, self.recordType, + measure, [], label, factor, yield_) + if len(measure_list) > 0: + measure.buildMeasure(_measure, measure_list, type, decimals, + self.recordType) + _position = len(self.__children) + _child = Decomposition(_position, child_code, [_measure]) + self.__children.append(_child) + return _child + + def getText(self): + return self.__text + + def setText(self,text): + """setText(self,text) + + Sets the text of the record + It must be a string + """ + if not isinstance(text, str): + raise TypeError, utils.mapping(_("Text ($1) must be a string, "\ + "record: $2"), (str(text), self.__code)) + self.__text = text + + def getSheet(self): + return self.__sheet + + def setSheet(self, sheet): + """setSheet(self, sheet) + + Sets the sheet of condition object + """ + if not isinstance(sheet, Sheet): + raise ValueError, _("sheet must be a Sheet instance") + self.__sheet = sheet + + def getFiles(self): + return self.__files + + def setFiles(self, files): + """setFiles(self, files) + + Sets the files list + """ + # TODO: only sets files and File object format (durusdatabase) + if not isinstance(files, list): + raise ValueError, utils.mapping(_("files must be a list: $1"), + str(files)) + _files = [] + for file in files: + if isinstance(file, File): + _files.append(file) + elif isinstance(file, list): + _file_path = file[0] + _type = file[1] + _description = file[2] + if not os.path.exists(file[0]): + raise ValueError, _("Incorrect path") + _file = File(file_path, type, description) + _files.append(_file) + else: + raise ValueError, utils.mapping(_( + "file must be a list or a File object: $1"),str(file)) + self.__files = _files + + + def addFile(self, file_path, type, description): + """addFile(self, file_path, type, description) + + Add a file to a record instance + """ + if not os.path.exists(file_path): + raise ValueError, _("Incorrect path") + _name = os.path.basename(file_path) + _isin = False + for _ofile in self.__files: + if _ofile.name == _name: + _isin = True + if not _isin: + _file = File(_name, type, description) + self.__files.append(_file) + + def getLabels(self): + return self.__labels + + def setLabels(self, labels): + """setLabels(self, labels) + + Sets the labels list of a record + """ + if not isinstance(labels, list): + raise ValueError, _("labels must be a list") + _labels = [] + for _label in labels: + if isinstance(_label, str): + _labels.append(_label) + else: + raise ValueError, _("label must be a string") + self.__labels = _labels + + def addLabel(self, label): + """addLabel(self, label) + + Add a label to a record instance + """ + if not isinstance(label, str): + raise ValueError, _("Label must be a string") + if not label in self.__labels: + self.__labels.append(label) + + recordType = property(getRecordType, setRecordType, None, + """Record Type object + """) + code = property(getCode, setCode, None, + """Record code + """) + synonyms = property(getSynonyms, setSynonyms, None, + """List of codes synonyms of the code + """) + unit = property(getUnit,setUnit, None, + """Measure Unit of the record + """) + summary = property(getSummary, setSummary, None, + """Short description of the record + """) + prices = property(getPrices, None, None, + """List of Price/Date + """) + parents = property(getParents, setParents, None, + """List of codes of the records which the record is in + its decomposition + """) + children = property(getchildren, setchildren, None, + """List of Decompositon intances""") + text = property(getText, setText, None, + """Long description of the record""") + sheet = property(getSheet, setSheet, None, + """Sheet of conditions object""") + files = property(getFiles, setFiles, None, + """File list""") + labels = property(getLabels, setLabels, None, + """Label list""") + +class ParametricRecord(Record): + """base.ParametricRecord: + + Description: + Parametric Record object + Constructor: + base.ParametricRecord(code, synonyms, hierarchy, unit, summary, prices, + type, subtype, text="") + Ancestry: + +-- object + +-- Record + +-- ParametricRecord + Atributes: + + Methods: + + """ + + __slots__ = ["_ParametricRecord__budget", + "_ParametricRecord__code", "_ParametricRecord__synonyms", + "_ParametricRecord__hierarchy", "_ParametricRecord__unit", + "_ParametricRecord__summary", "_ParametricRecord__prices", + "_ParametricRecord__type", "_ParametricRecord__subtype", + "_ParametricRecord__parents", "_ParametricRecord__children", + "_ParametricRecord__text", "_ParametricRecord__sheet", + "_ParametricRecord__files", "_ParametricRecord__labels", + "_ParametricRecord__parameters", + "_ParametricRecord__select_comment", + "_ParametricRecord__vars", + "_ParametricRecord__parametric_summary", + "_ParametricRecord__parametric_text",] + + def __getstate__(self): + return (self.__budget, self.__code, self.__synonyms, self.__hierarchy, + self.__unit, self.__summary, self.__prices, self.__type, + self.__subtype, self.__parents, self.__children, self.__text, + self.__sheet, self.__files, self.__labels, self.__parameters, + self.__select_comment, self.__vars, + self.__parametric_summary, self.__parametric_text) + + def __setstate__(self, tuple): + self.__budget = tuple[0] + self.__code = tuple[1] + self.__synonyms = tuple[2] + self.__hierarchy = tuple[3] + self.__unit = tuple[4] + self.__summary = tuple[5] + self.__prices = tuple[6] + self.__type = tuple[7] + self.__subtype = tuple[8] + self.__parents = tuple[9] + self.__children = tuple[10] + self.__text = tuple[11] + self.__sheet = tuple[12] + self.__files = tuple[13] + self.__labels = tuple[14] + self.__parameters = tuple[15] + self.__select_comment = tuple[16] + self.__vars = tuple[17] + self.__parametric_summary = tuple[18] + self.__parametric_text = tuple[19] + + def __init__(self, budget, code, synonyms, hierarchy, unit, summary, + prices, type, subtype, parents=[], text=""): + Record.__init__(self, budget, code, synonyms, hierarchy, unit, summary, + prices, type, subtype, parents=[], text="") + self.__parameters = {} + self.__select_comment = "" + self.__vars = {} + self.parametric_summary = "" + self.parametric_text = "" + + def getParameter(self, parameter): + if parameter in self.__parameters: + return self.__parameters[parameter] + else: + return None + + def setParameter(self, parameter, parameter_list): + self.__parameters[parameter] = parameter_list + + def getSelectComment(self): + return self.__select_comment + + def setSelectComment(self, select_comment): + self.__select_comment = select_comment + def getVar(self, var): + if var in self.__vars: + return self.__vars[var] + else: + return None + + def setVar(self, var, var_list): + self.__vars[var] = var_list + + def getParametricSummary(self): + return self.__parametric_summary + + def setParametricSummary(self, parametric_summary): + self.__parametric_summary = parametric_summary + + def getParametricText(self): + return self.__parametric_text + + def setParametricText(self, parametric_text): + self.__parametric_text = parametric_text + + parameter = property(getParameter, setParameter, None, + """Record parameter + """) + select_comment = property(getSelectComment, setSelectComment, None, + """Seclect comment + """) + var = property(getVar, setVar, None, + """Record var + """) + parametric_summary = property(getParametricSummary, setParametricSummary, + None, + """Parametric summary + """) + parametric_text = property(getParametricText, setParametricText, None, + """Seclect comment + """) + +class Decomposition(object): + """base.Decomposition: + + Description: + Decomposition object + Constructor: + base.Decomposition(position, code, budgetMeasures, certification=None, + real_cost=None, cost_goals=None, cost_planned=None) + Ancestry: + +-- object + +-- Decomposition + Atributes: + "position": the position of the child record in the parent record + "code": Record code. + Measures: + "budgetMeasures": list of budget and Amended budget measures + "certification": list of certifications for months measures + "real_cost": list of real cost of construction for months measures + "cost_goals": list of cost goals of construction for months measures + "cost_planned": list of costs planned and amended cost planned measures + Methods: + __getstate__(self) + __setstate__(self, tuple) + __init__( position, code, budgetMeasures, certification=None, + real_cost=None, cost_goals=None, cost_planned=None) + {get/set}position + {get/set}Code + {get/set}BudgetMeasures + {get/set}Certification + {get/set}RealCost + {get/set}CostGoals + {get/set}CostPlanned + """ + __slots__ = ["_Decomposition__position", + "_Decomposition__code", + "_Decomposition__budgetMeasures", + "_Decomposition__certification", + "_Decomposition__real_cost", + "_Decomposition__cost_goals", + "_Decomposition__cost_planned", + ] + def __getstate__ (self): + return (self.__position, self.__code, self.__budgetMeasures, + self.__certification, self.__real_cost, self.__cost_goals, + self.__cost_planned) + def __setstate__(self,tuple): + self.__position = tuple[0] + self.__code = tuple[1] + self.__budgetMeasures = tuple[2] + self.__certification = tuple[3] + self.__real_cost = tuple[4] + self.__cost_goals = tuple[5] + self.__cost_planned = tuple[6] + + def __init__(self, position, code, budgetMeasures, certification=None, + real_cost=None, cost_goals=None, cost_planned=None): + self.position = position + self.code = code + self.budgetMeasures = budgetMeasures + self.certification = certification + self.real_cost = real_cost + self.cost_goals = cost_goals + self.cost_planned = cost_planned + def getPosition(self): + return self.__position + def setPosition(self, position): + if not isinstance(position, int): + raise ValueError, _("Position must be a integer") + self.__position = position + def getCode(self): + return self.__code + def setCode(self, code): + self.__code = code + def getBudgetMeasures(self): + return self.__budgetMeasures + def setBudgetMeasures(self, budgetMeasures): + if not isinstance(budgetMeasures, list): + raise ValueError, _("BudgetMeasures atribute must be a list") + for _measure in budgetMeasures: + if not isinstance(_measure, Measure): + raise ValueError, _("BudgetMeasures item must be a Measure "/ + "object") + self.__budgetMeasures = budgetMeasures + def getCertification(self): + return self.__certification + def setCertification(self, certification): + if not (certification is None or isinstance(certification, list)): + raise ValueError, _("Certification atribute must be a list or None") + self.__certification = certification + def getRealCost(self): + return self.__real_cost + def setRealCost(self, real_cost): + if not (real_cost is None or isinstance(real_cost, list)): + raise ValueError, _("Real cost atribute must be a list or None") + self.__real_cost = real_cost + def getCostGoals(self): + return self.__cost_goals + def setCostGoals(self, cost_goals): + if not (cost_goals is None or isinstance(cost_goals, list)): + raise ValueError, _("Cost goals atribute must be a list or None") + self.__cost_goals = cost_goals + def getCostPlanned(self): + return self.__cost_planned + def setCostPlanned(self, cost_planned): + if not (cost_planned is None or isinstance(cost_planned, list)): + raise ValueError, _("Cost Planned atribute must be a list or None") + self.__cost_planned = cost_planned + position = property(getPosition, setPosition, None, + """Postion of the record in the budget + """) + code = property(getCode, setCode, None, + """Record code + """) + budgetMeasures = property(getBudgetMeasures, setBudgetMeasures, None, + """list of budget and Amended budget measures + """) + certification = property(getCertification, setCertification,None, + """ list of certifications by months measures + """) + real_cost = property(getRealCost, setRealCost, None, + """ list of real cost of construction for months measures + """) + cost_goals = property(getCostGoals, setCostGoals, None, + """ list of cost goals of construction for months measures + """) + cost_planned = property(getCostPlanned, setCostPlanned, None, + """ list of costs planned and amended cost planned measures + """) + + +class Measure(object): + """base.Measure: + + Description: + Measure object + Constructor: + base.Measure(decimals, recordType, measure, lines, + label, factor, yield_) + Ancestry: + +-- object + +-- Measure + Atributes: + "measure": Total result of measure. + "lines": List of measure lines, List of LineM instances. + "label": Record Identifiers that are used by some measure programs. + "factor": + "yield": + "fixed": If fixed is True the yield is not calculated from measure + Methods: + __getstate__() + __setstate__(tuple) + __init__(decimals, recordType, measure, lines, + label, factor, yield_) + getMeasure() + setMeasure(measure, decimals) + {get/set}Lines + {get/set}Label + getFactor() + setFactor(factor, decimals, recordType) + getYield() + setYield(yield_, decimals, recordType) + getFixed() + setFixed(decimals) + buildMeasure(list_lines, type, decimals) + calculateMeasure(decimals) + updateYield(decimals) + """ + __slots__ = ["_Measure__measure", + "_Measure__lines", + "_Measure__label", + "_Measure__factor", + "_Measure__yield_", + "_Measure__fixed"] + def __getstate__ (self): + return (self.__measure, self.__lines, self.__label, + self.__factor, self.__yield_, self.__fixed) + def __setstate__(self,tuple): + self.__measure = tuple[0] + self.__lines = tuple[1] + self.__label = tuple[2] + self.__factor = tuple[3] + self.__yield_ = tuple[4] + self.__fixed = tuple[5] + def __init__(self, decimals, recordType, measure, lines, + label, factor, yield_): + self.setMeasure(measure, decimals) + self.lines = lines + self.label = label + self.setFactor(factor, decimals, recordType) + self.setYield(yield_, decimals, recordType) + self.__fixed = False + + def getMeasure(self): + return self.__measure + def setMeasure(self, measure, decimals): + if not isinstance(measure, float): + raise ValueError, utils.mapping(_("Measure must be a float "\ + "number. Type: $1"), (type(measure),)) + # TODO: test after + _DS = decimals.DS + measure = round(measure, _DS) + self.__measure = measure + + def getLines(self): + return self.__lines + def setLines(self, lines): + if not isinstance(lines, list): + raise ValueError, _("Lines must be a list") + for _line in lines: + if not isinstance(_line, MeasureLine): + raise ValueError, _("Line must be a MeasureLine objetc") + self.__lines = lines + def getLabel(self): + return self.__label + def setLabel(self, label): + self.__label = label + def setFactor(self, factor, decimals, recordType): + if not isinstance(factor, float): + raise ValueError, utils.mapping(_("Factor must be a float number "\ + "|$1|"), (factor,)) + # TODO: test after + _DF = decimals.getDF(recordType) + factor = round(factor, _DF) + self.__factor = factor + + def getFactor(self): + return self.__factor + + def setYield(self, yield_, decimals, recordType): + if not isinstance(yield_, float): + raise ValueError, _("Yield must be a float number") + # TODO: test after + _DR = decimals.getDR(recordType) + yield_ = round(yield_, _DR) + self.__yield_ = yield_ + + def getYield(self): + return self.__yield_ + + def setFixed(self, fixed, decimals): + if not isinstance(fixed, bool): + raise ValueError, _("Fixed must be boolean object") + self.__fixed = fixed + self.updateYield(decimals) + + def getFixed(self): + return self.__fixed + + measure = property(getMeasure, None, None, + """Total result of the measure + """) + lines = property(getLines, setLines, None, + """List of measure lines, List of "MeasureLine" instances + """) + label = property(getLabel, setLabel, None, + """Record identifiers that are used in some measure programs + """) + factor = property(getFactor, None, None, + """Factor + """) + yield_ = property(getYield, None, None, + """Yield of a record + """) + fixed = property(getFixed, setFixed,None, + """If fixed is True the yield is not calculated from measure + """) + + def buildMeasure(self, list_lines, type, decimals, recordType): + """setMeasure(self, list_lines, type, decimals) + + list_lines: list of measure lines + [ [linetype, comment, units, length, width, height, formula], ... ] + linetype: + #-#empty string -> Normal + 0 -> Normal + 1 -> Parcial Subtotal + 2 -> Accumulated Subtotal + 3 -> Formula + comment: comment string + units: Number of Units (a) + length: Length (b) + width: Width (c) + height: Height (d) + formula: Can be a formula or a empty string + Valid Operator: '(', ')', '+', '-', '*', '/' and '^' + Valid variable: 'a', 'b', 'c','d' and 'p' (Pi=3.1415926) + type: type of action + M: Set measure + A: Add measure + decimal: budget decimals object + + Sets the measurelines for a record + """ + # TODO: calcutate measure from lines + _parcial = 0 + _total = 0 + _lines = [] + for _line in list_lines: + _type, _comment = _line[0], _line[1] + _units, _length = _line[2], _line[3] + _width, _height = _line[4], _line[5] + _formula = _line[6] + _measure_line = MeasureLine(decimals, _type, _comment, _units, + _length, _width, _height, _formula) + _lines.append(_measure_line) + if type == "M": + self.lines = _lines + elif type == "A": + self.lines.extend(_lines) + else: + raise ValueError, utils.mapping(_("Type must be M or A. Type: $1"), + (type,)) + self.calculateMeasure(decimals, recordType) + + def calculateMeasure(self, decimals, recordType): + #TODO: round acumulated_subtotal and parcial_subtotal + if len(self.lines) > 0: + _acumulated_total = 0.0 + _parcial_total = 0.0 + for line in self.lines: + _parcial = line.parcial + _acumulated_total += _parcial + if line.lineType == 2: + line.setAcumulatedSubtotal(_acumulated_total, decimals) + elif line.lineType == 1: + _parcialSubtotal = _acumulated_total - _parcial_total + line.setParcialSubtotal(_parcialSubtotal, decimals) + _parcial_total = _acumulated_total + self.setMeasure(_acumulated_total, decimals) + _DR = decimals.getDR(recordType) + self.updateYield(decimals, recordType) + def updateYield(self, decimals, recordType): + if not self.fixed: + self.setYield(self.measure, decimals, recordType) + +class MeasureLine(object): + """base.MeasureLine: + + Description: + MeasureLine object + Constructor: + base.MeasureLine(budget, type, comment, units, length, width, height, + formula) + Ancestry: + +-- object + +-- MeasureLine + Atributes: + "lineType": Line type: + #-#empty string -> Normal + 0 -> Normal + 1 -> Parcial Subtotal + 2 -> Accumulated Subtotal + 3 -> Formula, the comment is a formula. + "comment": Descriptive text string + "units": Number of Units (a) + "length": length (b) + "width": Width (c) + "height": Height (d) + "formula": can be a valid formula or a empty string + Valid Operator: '(', ')', '+', '-', '*', '/' and '^' + Valid variable: 'a', 'b', 'c','d'y 'p' (Pi=3.1415926) + "partial" : result of measure line + "parcial_subtotal" + "acumulated_subtotal" + Methods: + __getstate__(self) + __setstate__(self, tuple) + __init__(self, decimals, type, comment, units, length, width, height, + formula) + {get/set}LineType + {get/set}Comment + {get/set}Units + {get/set}Length + {get/set}Width + {get/set}Height + {get/set}Formula + getParcial + {get/set}ParcialSubtotal + {get/set}AcumulatedSubtotal + calculateParcial + eval_formula + """ + __slots__ = ["_MeasureLine__lineType", + "_MeasureLine__comment", + "_MeasureLine__units", + "_MeasureLine__length", + "_MeasureLine__width", + "_MeasureLine__height", + "_MeasureLine__formula", + "_MeasureLine__parcial", + "_MeasureLine__parcial_subtotal", + "_MeasureLine__acumulated_subtotal", + ] + def __getstate__ (self): + return (self.__lineType, self.__comment, self.__units, + self.__length, self.__width, self.__height, self.__formula, + self.__parcial) + def __setstate__(self,tuple): + self.__lineType = tuple[0] + self.__comment = tuple[1] + self.__units = tuple[2] + self.__length = tuple[3] + self.__width = tuple[4] + self.__height = tuple[5] + self.__formula = tuple[6] + self.__parcial = tuple[7] + #self.calculateParcial() + def __init__(self, decimals, type, comment, units, length, width, height, + formula): + self.__parcial = 0.0 + self.__parcial_subtotal = 0.0 + self.__acumulated_subtotal = 0.0 + self.lineType = type + self.comment = comment + self.setUnits(units, decimals) + self.setLength(length, decimals) + self.setWidth(width, decimals) + self.setHeight(height, decimals) + self.setFormula(formula, decimals) + #self.calculateParcial() + def getLineType(self): + return self.__lineType + def getComment(self): + return self.__comment + def getUnits(self): + return self.__units + def getLength(self): + return self.__length + def getWidth(self): + return self.__width + def getHeight(self): + return self.__height + def getFormula(self): + return self.__formula + def getParcial(self): + return self.__parcial + def getParcialSubtotal(self): + return self.__parcial_subtotal + def getAcumulatedSubtotal(self): + return self.__acumulated_subtotal + def setParcialSubtotal(self, parcial_subtotal, decimals): + if not isinstance(parcial_subtotal, float): + raise ValueError, utils.mapping(_(" Parcial Subtotal must be a "\ + "float number. Parcial: $1"), (str(parcial_subtotal),)) + _DS = decimals.DS + parcial_subtotal = round(parcial_subtotal, _DS) + self.__parcial_subtotal = parcial_subtotal + def setAcumulatedSubtotal(self, acumulated_subtotal, decimals): + if not isinstance(acumulated_subtotal, float): + raise ValueError, utils.mapping(_(" Acumulated Subtotal must be "\ + "a float number. Parcial: $1"), + (str(acumulated_subtotal),)) + _DS = decimals.DS + acumulated_subtotal = round(acumulated_subtotal, _DS) + self.__acumulated_subtotal = acumulated_subtotal + def calculateParcial(self, decimals): + _DS = decimals.DS + if self.lineType == 1 or self.lineType == 2: + _parcial = 0.0 + elif self.lineType == 0: # self.formula == "": + if isinstance(self.units, float): + _a = self.units + else: + _a = 0.0 + if isinstance(self.length, float): + _b = self.length + else: + _b = 1.0 + if isinstance(self.width, float): + _c = self.width + else: + _c = 1.0 + if isinstance(self.height, float): + _d = self.height + else: + _d = 1.0 + _parcial = _a * _b * _c * _d + else: + _parcial = self.eval_formula() + _parcial = round(_parcial, _DS) + self.__parcial = _parcial + + def setLineType(self, type): + if not type in [0, 1, 2, 3]: + raise ValueError, utils.mapping(_("Invalid measure line type ($1)"), + (str(type),)) + self.__lineType = type + def setComment(self, comment): + if not isinstance(comment, str): + raise ValueError, utils.mapping(_("Measure Comment must be a "\ + "string ($1)"), (str(comment),)) + self.__comment = comment + def setUnits(self, units, decimals): + if units != "": + if not isinstance(units, float): + raise ValueError, utils.mapping(_("Invalid Measure Units ($1)"), + (str(units),)) + _DN = decimals.DN + units = round(units, _DN) + self.__units = units + try: + self.calculateParcial(decimals) + except AttributeError: + pass + def setLength(self, length, decimals): + if length != "": + if not isinstance(length, float): + raise ValueError, utils.mapping(_("Invalid Measure length ($1)"), + (str(units),)) + _DD = decimals.DD + length = round(length, _DD) + self.__length = length + try: + self.calculateParcial(decimals) + except AttributeError: + pass + def setWidth(self, width, decimals): + if width != "": + if not isinstance(width, float): + raise ValueError, utils.mapping(_("Invalid Measure Width ($1)"), + (str(units),)) + _DD = decimals.DD + width = round(width, _DD) + self.__width = width + try: + self.calculateParcial(decimals) + except AttributeError: + pass + def setHeight(self, height, decimals): + if height != "": + if not isinstance(height, float): + raise ValueError, utils.mapping(_("Invalid Measure Height ($1)"), + (str(height),)) + _DD = decimals.DD + height = round(height, _DD) + self.__height = height + try: + self.calculateParcial(decimals) + except AttributeError: + pass + def setFormula(self, formula, decimals): + if not isinstance(formula, str): + raise ValueError, utils.mapping(_("Formula must be a "\ + "string ($1)"), (str(formula),)) + if re.match(".*[^0123456789\.()\+\-\*/\^abcdp ].*", formula): + raise ValueError, utils.mapping(_("There is invalid characters"\ + "in formula ($1)"), (str(formula),)) + self.__formula = formula + try: + self.calculateParcial(decimals) + except AttributeError: + pass + + lineType = property(getLineType, setLineType, None, + """Type of measure line + """) + comment = property(getComment, setComment, None, + """Text + """) + units = property(getUnits, None, None, + """Number of units + """) + length = property(getLength, None, None, + """Length measure + """) + width = property(getWidth, None, None, + """Width measure + """) + height = property(getHeight, None, None, + """Height measure + """) + formula = property(getFormula, None, None, + """Formula + """) + parcial = property(getParcial, None, None, + """result of measure line + """) + acumulated_subtotal = property(getAcumulatedSubtotal, + None, None, + """Acumulated subtotal + """) + parcial_subtotal = property(getParcialSubtotal, + None, None, + """Parcial subtotal + """) + def eval_formula(self): + """eval_formula() + + formula: + Valid Operator: '(', ')', '+', '-', '*', '/' and '^' + Valid variable: 'a', 'b', 'c','d'y 'p' (Pi=3.1415926) + units: Number of Units (a) + length: Length (b) + width: Width (c) + height: Height (d) + + Evals the formula and return the result + """ + formula = self.formula + a = self.units + b = self.length + c = self.width + d = self.height + if a == "": a = 0.0 + if b == "": b = 0.0 + if c == "": c = 0.0 + if d == "": d = 0.0 + try: + a = float(a) + except: + raise ValueError, _("'a' value must be a float number") + try: + b = float(b) + except: + raise ValueError, _("'b' value must be a float number") + try: + c = float(c) + except: + raise ValueError, _("'c' value must be a float number") + try: + d = float(d) + except: + raise ValueError, _("'d' value must be a float number") + # spaces are erased + formula.replace(" ","") + # operators and varibles are replaced + formula = formula.replace("+", " + ") + formula = formula.replace("-", " - ") + formula = formula.replace("*", " * ") + formula = formula.replace("/", " / ") + formula = formula.replace("^", " ** ") + formula = formula.replace("(", " ( ") + formula = formula.replace(")", " ) ") + formula = formula.replace("a", str(a)) + formula = formula.replace("b", str(b)) + formula = formula.replace("c", str(c)) + formula = formula.replace("d", str(d)) + formula = formula.replace("p", "3.1415926") + _list_formula = formula.split(" ") + _formula2 = "" + for oper in _list_formula: + try: + _float_oper= str(float(oper)) + _formula2 = _formula2 + _float_oper + except ValueError: + _formula2 = _formula2 + oper + _g ={"__builtins__":{}} + try: + return eval(_formula2, _g) + except: + raise ValueError, _("Invalid formula") + +class Decimals(object): + """base.Decimals: + + Description: + Decimals object + Constructor: + base.Decimals(DN=2, DD=2, DSP=2, DS=2, + DFC=3, DFPU=3, DFUO=3, DFA=3, + DRP=3, DRC=3, DRUO=3, DRA=3, + DP=2, DC=2, DPU=2, DUO=2, DEA=2, DES=2, + DIR=2, DIM=2, DIRC=2, DIMC=2, DCD=2, + DIVISA="EUR") + Ancestry: + +-- object + +-- Decimals + Atributes: + "DN": Number of decimal places of the field "equal-size parts" in the + measure lines. + Default: 2 decimal places. + "DD": Number of decimal places of the three dimensions in the + measure lines. + Default: 2 decimal places. + "DSP": Number of decimal places of the subtotal of a measure. + Default: 2 decimal places. + "DS": Number of decimal places of the total sum of a measure. + Default: 2 decimal places. + "DFC": Number of decimal places of the yield factor in a decomposition + of a chapter or subchapter. + Dafault: 3 decimal places. + "DFPU": Number of decimal places of the yield factor in a decomposition + of a unitary budget. + Default: 3 decimal places. + "DFUO": Number of decimal places of the yield factor in a decomposition + of a unit of work. + Default: 3 decimal places. + "DFA": Number of decimal places of the yield factor in a decomposition + of a Auxiliary element. + Default: 3 decimal places. + "DRC": Number of decimal places of the yield in a + decomposition of a chapter or subchapter. + Number of decimal places of the result of the multiplictaion of + the yield (or measure) and the factor in a decomposition of a + chapter or subcharter. + Default: 3 decimal places. + "DRPU": Number of decimal places of the yield in a decomposition + of a unitary budget record. + Number of decumal places of the result of the multiplication of + the factor and the yield in a decompositon of a untitary budget. + Default: 3 decimal places. + "DRUO": Number of decimal places of the yield in a decomposition of a + unit of work. + Decimal places of the result of the multiplication of the yield + and the factor in a descomposition of a unit of work. + Default: 3 decimal places. + "DRA": Number of decimal places of the yield in a decompositon of a + auxiliar element. + Number of decimal places of the result of the multiplication of + the yield and the factor in a descomposition of a auxilar element.Decimales + Default: 3 decimal places. + "DP": Number of decimal places of the price of a budget. + Default: 2 decimal places. + "DC": Number of decimal places of the price of a chapter or subchapter. + Default: 2 decimal places. + "DPU": Number of decimal places of the price of a unitary budget. + Default: 2 decimal places. + "DUO": Number of decimal places of the price of a unit of work. + Default: 2 decimal places. + "DEA": Number of decimal places of the price of a auxiliar element. + Default: 2 decimal places. + "DES": Number of decimal places of the price of the simple elements. + Default: 2 decimal places. + "DIR": Number of decimal places of the resulting amount to multiply + the total yield and the price of the elements of a unit of work or + a auxiliar element. + "DIRC": Number of decimal places of the resulting amount to multiply + the total yield and the price of the elements of a budget, chapter + or a subchapter. + "DCD": Number of decimal places ot the resulting amount to sum the + direct costs of a unit of work (and auxiliar element). + Number of decimal places of the indirect costs. + Default: 2 decimal places. + "DIVISA": monetary unit. + Methods: + __init__(DN=2, DD=2, DSP=2, DS=2, + DFC=3, DFPU=3, DFUO=3, DFA=3, + DRC=3, DRPU=3, DRUO=3, DRA=3, + DP=2, DC=2, DPU=2, DUO=2, DEA=2, DES=2, + DIR=2, DIRC=2, DCD=2, + DIVISA="EUR") + __getitem__(key) + haskey(key) + getD(recordtype) + getDF(recordType) + getDR(recordType) + getDI(recordType) + """ + # TODO: get/set methods + def __init__(self, + DN=2, DD=2, DSP=2, DS=2, + DFC=3, DFPU=3, DFUO=3, DFA=3, + DRC=3, DRPU=3, DRUO=3, DRA=3, + DP=2, DC=2, DPU=2, DUO=2, DEA=2, DES=2, + DIR=2, DIRC=2, DCD=2, + DIVISA="EUR" ): + self.DN = DN + self.DD = DD + self.DSP = DSP + self.DS = DS + self.DFP = 3 + self.DFC = DFC + self.DFPU = DFPU + self.DFUO = DFUO + self.DFA = DFA + self.DRP = 3 + self.DRC = DRC + self.DRPU = DRPU + self.DRUO = DRUO + self.DRA = DRA + self.DP = DP + self.DC = DC + self.DPU = DPU + self.DUO = DUO + self.DEA = DEA + self.DES = DES + self.DIR = DIR + self.DIRC = DIRC + self.DCD = DCD + self.DIVISA = DIVISA + def __getitem__(self, key): + return self.__dict__[key] + def haskey(self, key): + return key in self.__dict__ + def getD(self, recordType): + # DP: budget. + # DC: chapter and subcharter. + # DUO: unit. + # DEA: auxiliar element. + # DES: simple element. + _hierarchy = recordType.hierarchy + if _hierarchy == 0: #budget, type 0, subtipe "OB" + _decimal = self.DP + elif _hierarchy == 1: #chapter/subcharter, type 0, subtipe "" + _decimal = self.DC + else: # other + _type = recordType.type + _subtype = recordType.subtype + if _subtype == "EA": # auxiliar element type 0 subitype "EA" + _decimal = self.DEA + if _subtype == "PU": # unitary budget type 0 subitype "PU" + _decimal = self.DPU + elif (_type in [1, 2, 3] or + _subtype in ["H", "Q", "%", "MC", "MCr", "MM", "MS", "ME", + "MCu", "Mal","ML", "M"] + ): # simple element + _decimal = self.DES + else: # unit type 0, subtipe ["EU", "EC", "EF", "PA"] + _decimal = self.DUO + return _decimal + def getDF(self, recordType): + # Factor: DF + # ->DFP: Budget + # ->DFC: Chapter/Subchapter + # ->DFUO: Unit + # ->DFA: Auxiliar + # ->DFPU: Unitary budget + if recordType.hierarchy == 0: #budget + _decimal = self.DFP + elif recordType.hierarchy == 1: #chapter/subcharter + _decimal = self.DFC + else: # other + if recordType.subtype == "EA": # auxiliar element + _decimal = self.DFA + if recordType.subtype == "PU": # unitary budget element + _decimal = self.DFPU + else: # unit EU EC EF PA + _decimal = self.DFUO + return _decimal + def getDR(self, recordType): + # Yield: DR + # ->DRP: Budget + # ->DRC: Chapter/Subchapter + # ->DRUO: Unit + # ->DRA: Auxiliar + # ->DRPU: Unitary budget + if recordType.hierarchy == 0: #budget + _decimal = self.DRP + elif recordType.hierarchy == 1: #chapter/subcharter + _decimal = self.DRC + else: # other + if recordType.subtype == "EA": # auxiliar element + _decimal = self.DRA + if recordType.subtype == "PU": # unitary budget element + _decimal = self.DRPU + else: # unit + _decimal = self.DRUO + return _decimal + def getDI(self, recordType): + # DIRC: budget, chapter and subcharter. + # DIR: unit, auxiliar element. + _hierarchy = recordType.hierarchy + _subtype = recordType.subtype + if _hierarchy == 0 or _hierarchy == 1 or _subtype == "PU": + #budget, type 0, subtipe "OB" + #chapter/subcharter, type 0, subtipe "" + #unitary budget, type 2, subtype "PU" + _decimal = self.DIRC + else: # other + # auxiliar element type 0 subitype "EA" + # unit type 0, subtipe ["EU", "EC", "EF", "PA", "PU"] + _decimal = self.DIR + return _decimal + +class Sheet(object): + """base.Sheet: + Description: + Sheet of conditions object + Constructor: + base.Sheet(sheet_dict) + Ancestry: + +-- object + +-- Sheet + Atributes: + "sheet_dict": { <Field key> : { <Section key> : <Paragraph key>} + <Field key>: must be in Budget.SheetFields + <Section key>: must be in Budget.SheetSections + <Paragraph key>: must be in Budget.SheetParagraph + Methods: + __getstate__(self) + __setstate__(self, tuple) + __init__(self, sheet_dict={}) + {get/set}Sheet_dict + getFields + getSections + getParagraph + addField + addSection + """ + __slots__ = ["_Sheet__sheet_dict"] + def __getstate__ (self): + return (self.__sheet_dict,) + def __setstate__(self,tuple): + self.__sheet_dict = tuple[0] + def __init__(self): + self.__sheet_dict = {} + def getSheet_dict(self): + return self.__sheet_dict + def setSheet_dict(self, sheet_dict): + if not isinstance(sheet_dict, dict): + raise ValueError, _("sheet_dict must be a dictionay") + self.__sheet_dict = sheet_dict + def getFields(self): + return self.sheet_dict.keys() + def getSections(self, field): + if field in self.__sheet_dict: + return self.__sheet_dict[field].keys() + else: + return None + def getParagraph(self, field, section): + if (field in self.__sheet_dict and + section in self.__sheet_dict[field]): + return self.__sheet_dict[field][section] + else: + return None + def addField(self, field, section_dict): + if not isinstance(field, str): + raise ValueError, _("sheet field must be a string") + if not isinstance(section_dict, dict): + raise ValueError, _("section_dict must be a dictionary") + self.__sheet_dict[field] = section_dict + def addSection(self, field, section, paragraph): + if not isinstance(field, str): + raise ValueError, _("sheet field must be a string") + if not isinstance(section, str): + raise ValueError, _("sheet section must be a string") + if not isinstance(paragraph, str): + raise ValueError, _("sheet paragraph must be a string") + if not field in self.__sheet_dict: + self.addField(field, { }) + _field = self.__sheet_dict[field] + _field[section] = paragraph + sheet_dict = property(getSheet_dict, setSheet_dict, None, + """Sheet dictionary { <Field key> : { <Section key> : <Paragraph key>}""") + +class Budget(object): + """base.Budget: + + Description: + Budget objetc + Constructor: + base.Budget() + Ancestry: + +-- object + +-- Budget + Atributes: + "filename": file name of the budget file (FIEBDC) + "__records": Dictionary with the budget records. + { "code" : Record object, } + "__synonyms": Dictionary with the records synonums. + { "code" : ["synonym",],} + Each record code can have synonym codes. + "__root": The root record code. + "__title_list": List with the Headers and list of Titles for prices and + decimal places. + [ "Header", ["Title1", "Title2", ... ] ] + The records can have diferent prices for diferent ages, geografical + places, ... + The Headers is the type of hierarchy of the prices + Each Title have a group of Prices and a Decimals definition + "__decimals": List with the decimal places used to round the + result of the calculations with prices and measures + The values are Decimals objects + The <0> objets is the default Decimals (seted in FIEBDC-3), + The others keys are for the diferent groups of Prices + "__percentages": Dictionary with the percentages + keys: + "CI" Indirect Cost + "GG" General expenses + "BI" Industrial benefit + "BAJA" Low (what this do here?) + "IVA" Tax + "__file_owner" + "__comment" + "__date" + "__budgetType" A integer. Type of data in budget + 0 -> Undefined + 1 -> Base data. + 2 -> Budget. + 3 -> Certificate. + 4 -> Base date update. + "__budgetCerficateOrder" Only valid if budgetType is 3. + "__budgetCerficateDate" Only valid if budgetType is 3 + "__title_index": A integer. The active group of Prices and Decimals. + "__sheet_sections": Dictionary whith de sheet sections + "__sheet_fields": Dictionary whith sheet fields + "__sheet_paragraphs": Dictionary whith sheet paragraphs + "__companys": Dictionary whith companys object + { company_code: company_object } + "__tec_info": Dictionary whith tecnical information + {ti_code : ["desciption text", "unit"]} + "__labels": Label dictionary { "label": [ "code", ], } + Methods: + iter + iterPreOrder + iterPostOrder + getRoot(self) + hasPath(self, path) + getchildren(self, code) + setOwner(self, owner) + setDate(self, date) + setComment(self, comment) + setBudgetType(self, type) + setCertificateOrder(self, order) + setCertificateDate(self, date) + setTitleList(self, title) + getTitleList(self) + getActiveTitle(self) + setDecimals(self, dictionary) + getDecimals(self, decimal="All", N=None) + setPercentages(self, dictionary) + getPercentages(self, percentage="All") + getAllParents(self, code) + getAllchildren(self, code) + getNDecomposition(self, code, N) + getDecomposition(self,code) + getMeasure(self, path) + getStrYield + getStrFactor + setTree(sef, code, child_code, position, factor, yield_, total, + list_lines, label, type) + eval_formula(self, formula, a, b, c, d) + getText(self, code) + setText(self, code, text) + setRecord(self, code, synonyms, hierarchy, unit, sumary, ... + hasRecord(self, code) + getRecord + addPriceToRecord + getStrPriceFromRecord + getCode(self, path) + getAmount + getStrAmount + setSheetSection(self, sheet_code, sheet_title) + hasSheetSection(self, section) + setSheetSections(self,dictionary) + setSheetField(self, field_code, field_title) + hasSheetField(self, field) + getSheetField(self, field) + setSheetFields(self, field_dict) + setSheetParagraph(self, paragraph_code, paragraph_text) + hasSheetParagraph(self, paragraph) + getSheetParagraph(self, paragraph) + setSheetParagraphs(self, paragraph_dict) + setSheetRecord(self, record_code,field, section_dict) + addFile(self, record_code, filename) + setCompany(self, code, summary, name, offices, cif, web, email ) + getCompany + getCompanyKeys + addTecInfo(self, ti_code, text, unit) + hasTecInfo(self, ti_code) + getTecInfo(self, ti_code) + setTecnicalInformation(self, _record_code, _ti_dict) + changeCode(self, record_code, new_rocord_code) + addLabel + setParametricSelectComment + setParametricSummary + setParametricText + """ + + + def __init__(self): + """__init__(self) + + Initialize the budget atributes + """ + self.__title_index = 0 + self.__decimals = [Decimals(), Decimals()] + self.__percentages = { "CI" : "" ,"GG": "", "BI": "", + "BAJA": "", "IVA" : ""} + self.__title_list = [ "", [ ] ] + self.__root = None + self.__file_owner = "" + self.__comment = "" + self.__budgetCerficateOrder = None + self.__budgetCerficateDate = None + self.__date = (0,0,0) + self.__budgetType = 0 + self.__records = { } + self.__synonyms = { } + self.__sheet_sections = { } + self.__sheet_fields = { } + self.__sheet_paragraphs = { } + self.__companys = { } + self.__tec_info = { } + self.__labels = { } + + def __getstate__(self): + return (self.__title_index, self.__decimals, self.__percentages, + self.__title_list, self.__root, self.__file_owner, + self.__records, self.__synonyms, self.__sheet_sections, + self.__sheet_fields, self.__sheet_paragraphs,self.__companys, + self.__tec_info, self.__labels) + + def __setstate__(self, tuple): + self.__title_index = tuple[0] + self.__decimals = tuple[1] + self.__percentages = tuple[3] + self.__title_list = tuple[4] + self.__root = tuple[4] + self.__file_owner = tuple[5] + self.__records = tuple[6] + self.__synonyms = tuple[7] + self.__sheet_sections = tuple[8] + self.__sheet_fields = tuple[9] + self.__sheet_paragraphs = tuple[10] + self.__companys = tuple[11] + self.__tec_info = tuple[12] + self.__labels = tuple[13] + + def iter(self): + for record in self.__records: + yield record + def iterPreOrder(self, recordCode, codes=[]): + _children = self.getchildren(recordCode) + for _child in _children: + if not _child in codes: + codes.append(_child) + self.iterPreOrder(_child, codes) + return codes + def iterPostOrder(self, recordCode, codes=[]): + _children = self.getchildren(recordCode) + for _child in _children: + if not _child in codes: + self.iterPreOrder(_child, codes) + codes.append(_child) + return codes + + def getRoot(self): + """getRoot(self) + + Returns the root record code + """ + return self.__root + + def hasPath(self, path): + """hasPath(self, path) + + path: The path of the record in the budget, It is a tuple. + Tests if the path is valid in the budget + """ + try: + self.getCode(path) + return True + except ValueError: + return False + + def getchildren(self, code): + """getchildren(self, code) + + code: a record code. + Return a list whith the child codes of a record + """ + _record = self.__records[code] + _children = _record.children + _child_code = [ _child.code for _child in _children ] + return _child_code + def setOwner(self, owner): + """setOwner(self, owner) + + owner: data owner + Set the data owner. + """ + if isinstance(owner, basestring): + self.__file_owner = owner + else: + raise TypeError, _("Owner must be a string") + + def setDate(self, date): + """setOwner(self, date) + + date (_y, _m, _d) + Set the date when de file was generated + """ + if isinstance(date, tuple) and len(date) == 3 and \ + isinstance(date[0], int) and isinstance(date[1], int) and \ + isinstance(date[2], int) and date[1] in range(13) and \ + date[2] in range(32): + if date[1] != 0 and date[2] != 0: + datetime.date(*date) + self.__date = date + else: + raise TypeError, _("Invalid Date: %s" % str(date)) + + def setComment(self, comment): + """setOwner(self, comment) + + comment: text to comment the budged + Set the comment. + """ + if isinstance(comment, basestring): + self.__comment = comment + else: + raise TypeError, _("Comment must be a string") + + def setBudgeType(self, budget_type): + """setOwner(self, budget_type) + + budget_type: type of data in budget + 0 -> Undefined + 1 -> Base data. + 2 -> Budget. + 3 -> Budget certificate. + 4 -> Base date update. + Set the budget type. + """ + if budget_type in [1, 2, 3, 4]: + self.__budgetType = budget_type + else: + raise ValueError, _("Budget type must be 1, 2, 3 or 4.") + + def setCertificateOrder(self, certificate_order, certificate_date): + """setOwner(self, budget_type) + + certificate_order: certificate number + certificate_date: certificate date + Set the certificate order and date. + """ + if isinstance(certificate_order, int): + self.__budgetCerficateOrder = certificate_order + else: + raise ValueError, _("Certificate order must be a integer.") + + def setCertificateDater(self, certificate_date): + """setCertidicateDate(self, certificate_date) + + Set the certificate date. + """ + if isinstance(certificate_date, tuple) and \ + len(certificate_date) == 3 and \ + isinstance(certificate_date[0], int) and \ + isinstance(certificate_date[1], int) and \ + isinstance(certificate_date[2], int): + datetime.date(*certificate_date) + self.__budgetCerficateDate = certificate_date + else: + raise ValueError, _("Budget certificate Date must be a valid Date.") + + def setTitleList(self, title_list): + """setTitleList(self, title_list) + + title_list: [ "Header", ["Title1", "Title2", ... ] ] + Set the header and titles for the price groups and decimals. + """ + title_list[0] = str(title_list[0]) + if isinstance(title_list, list) and isinstance(title_list[1], list): + for i in range(len(title_list[1])): + title_list[1][i] = str(title_list[1][i]) + self.__title_list = title_list + else: + raise TypeError, _("Invalid title list format") + + def getTitleList(self): + """ getTitleList(self) + + Returns the header and titles for the price groups and decimals. + """ + return self.__title_list + + def getActiveTitle(self): + """getActiveTitle(self) + + Returns the active Title of price group + """ + return self.__title_index + + def setDecimals(self, dictionary, N): + """setDecimals(self, dictionary, N) + + dictionay: the decimal dictionary + N: the price group + Sets the Decimals for a price group. + """ + if N == -1 or N == len(self.__decimals): + _default_decimals = self.__decimals[0] + self.__decimals.append(_default_decimals) + elif N < len(self.__decimals): + _default_decimals = self.__decimals[N] + else: + raise IndexError, _("Invalid Index Title") + for _decimal in dictionary: + if dictionary[_decimal] == "": + dictionary[_decimal] = eval("_default_decimals." + _decimal) + decimals = Decimals(dictionary["DN"], dictionary["DD"], + dictionary["DSP"], dictionary["DS"], + dictionary["DFC"], + dictionary["DFPU"], dictionary["DFUO"], + dictionary["DFA"], dictionary["DRC"], + dictionary["DRPU"], dictionary["DRUO"], + dictionary["DRA"], dictionary["DP"], + dictionary["DC"], dictionary["DPU"], + dictionary["DUO"], dictionary["DEA"], + dictionary["DES"], dictionary["DIR"], + dictionary["DIRC"], dictionary["DCD"], + dictionary["DIVISA"]) + self.__decimals[N] = decimals + def getDecimals(self, decimal="All", N=None): + """getDecimals(self,decimal="All",N=None) + + decimal: + "All": Return a Decimals objet for a price group + "keys": Return the keys of a Decimal object + key: Return a Decimal value for a price group + N: the price group None,1,2,.. + None: Return the active price group + """ + if N is None: N = self.getActiveTitle() + if decimal == "All": + return self.__decimals[N+1] + elif decimal == "keys": + return self.__decimals[N+1].keys + elif self.__decimals[N+1].haskey(decimal): + return self.__decimals[N+1][decimal] + else: + raise KeyError, _("Decimal Key error") + + def setPercentages(self, dictionary): + """setPercentages(self, dictionary): + + dictionary: the percentage dictionary + Sets the percentage dictionary. + """ + _default_percentages = self.__percentages + for percentage in dictionary: + if dictionary[percentage] == 0: + dictionary[percentage] = "" + elif dictionary[percentage] == "": + dictionary[percentage] = _default_percentages[percentage] + _percentages = { "CI": dictionary["CI"], + "GG": dictionary["GG"], + "BI": dictionary["BI"], + "BAJA": dictionary["BAJA"], + "IVA" : dictionary["IVA"]} + self.__percentages = _percentages + + def getPercentages(self, key="All"): + """getPercentages(self, percentage="All") + + key: + "All": Return the Percentages dictionary + "keys": Return the keys of a Percentages object + key: Return a Percentages value for the key + """ + if key == "All": + return self.__percentages + elif key == "keys": + return self.__percentages.keys + elif key in self.__percentages: + return self.__percentages[key] + else: + raise KeyError, _("Invalid Percentage key") + + def getAllParents(self,code): + """getAllParents(self,code) + + code: a record code. + Returns a list with all the parents of a record + All record which the record is in its descomposition list, + including the parents of the parents + """ + if code in self.__records: + _parents = self.__records[code].parents + if len(_parents) == 0: return [ ] + for _antecesor in _parents[:]: + _parents = _parents + self.getAllParents(_antecesor) + return _parents + else: + return [ ] + + def getAllchildren(self,code): + """getAllchildren(self,code + + code: a record code. + Returns a list with all the children of a record, including + the children of the children + """ + if code in self.__records: + _children = self.__records[code].children + _children = [ _child.code for _child in _children ] + for _child in _children[:]: + _children = _children + self.getAllchildren(_child) + return _children + else: + return [ ] + + def getNDecomposition(self, code, N): + """getDecomposition(self,path) + + path: the path for a record + Returns the Decomposition object of a record + """ + _record = self.getRecord(code) + _decomposition_list = _record.children + _decomposition = _decomposition_list[N] + return _decomposition + + def getDecomposition(self, path): + """getDecomposition(self,path) + + path: the path for a record + Returns the Decomposition object of a record + """ + if path == (0,): + _type = self.getRecord(self.__root).recordType + return Decomposition( 0, self.__root, + [Measure(self.getDecimals(), _type, + 0.0, [], "", 1.0, 1.0)]) + else: + return self.getNDecomposition(self.getCode(path[:-1]), path[-1]) + + def getMeasure(self, path): + """getMeasure(self, path) + + path: the path for a record + Return the measute object of a record + """ + _decomposition = self.getDecomposition(path) + _measure = _decomposition.budgetMeasures[0] + return _measure + + def getStrYield(self, measure, recordType): + #_DR = measure.getDR(self.getDecimals()) + _DR = self.getDecimals().getDR(recordType) + _yield = ("%." + str(_DR) + "f" ) % measure.yield_ + return _yield + + def getStrFactor(self, measure, recorType): + _DF = self.getDecimals().getDF(recordType) + #_DF = measure.getDF(self.getDecimals()) + _factor = ("%." + str(_DF) + "f" ) % measure.factor + return _factor + + def setTree(self, code, child_code, position, factor, yield_, total, + list_lines, label, type): + """setTree(self, code, child_code, position, factor,yield_, total, + list_lines, label, type) + + code: the parent record code + child_code: child record code + position: position of child record in record parent record + decomposition. Position == -1 -> new child + factor: + yield_: + total: total measure (float) + list_lines: list of measure lines + [ [linetype, comment, units, length, width, height], ... ] + linetype: + empty string -> Normal + 1 -> Parcial Subtotal + 2 -> Accumulated Subtotal + 3 -> Formula, the comment is a formula. + comment: Can be a descriptive text or a formula + Valid Operator: '(', ')', '+', '-', '*', '/' and '^' + Valid variable: 'a', 'b', 'c','d'y 'p' (Pi=3.1415926) + units: Number of Units (a) + length: Length (b) + width: Width (c) + height: Height (d) + label: Record Identifiers that are used by some measure programs. + type: type of action + M: Set measure + A: Add measure + Sets the decomposition of a record in a child record + """ + if not utils.is_valid_code(code)[0]: + raise ValueError, utils.mapping(_("Invalid parent code: $1"), + (code,)) + if not utils.is_valid_code(child_code)[0]: + raise ValueError, utils.mapping(_("Invalid child code: $1"), + (code,)) + if not isinstance(position, int): + raise ValueError, utils.mapping(_("Invalid position in measure "\ + "$1, in code $2"), (parent_code, position)) + # Test circular references + _all_parent_list = self.getAllParents(code) + [ code ] + _all_child_list = self.getAllchildren(child_code) + [ child_code ] + for _parent_code in _all_parent_list: + if _parent_code in _all_child_list: + # TODO: change return to except + print utils.mapping(_("Circular Decomposition, parent code: "\ + "$1, child code: $2, repeated code: $3"), + (code, child_code, _parent_code)) + return + # Creating reference to parent code in child record + if child_code in self.__records: + _child_record = self.__records[child_code] + else: + _child_record = self.setRecord(child_code, [], -1, "", "", [], [], + "", "") + if code in self.__records: + code = self.__records[code].code + _child_record.appendParent(code) + child_code = self.__records[child_code].code + if code in self.__records: + # if the code exits retake previous values. + _record = self.__records[code] + _child_number = len(_record.children) + if position == -1: + position = _child_number + if position == _child_number: + # The record do not have the child + if not isinstance(factor, float): factor = 1.0 + if not isinstance(yield_, float): yield_ = 1.0 + if not isinstance(total, float): total = 0.0 + if not isinstance(list_lines, list): list_lines = [] + _child = _record.appendChild(child_code, self.getDecimals(), + factor, yield_, total, list_lines, type, label) + elif position < _child_number: + # The record have the child + _child = _record.children[position] + if child_code != "" and child_code != _child.code: + _child.code = child_code + if factor != "" : + if not isinstance(factor, float): + factor == 1.0 + _child.budgetMeasures[0].setFactor(factor, + self.getDecimals(), _record.recordType) + if yield_ != "": + if not isinstance(yield_, float): + yield_ = 1.0 + _child.budgetMeasures[0].setYield(yield_, + self.getDecimals(), _record.recordType) + _measure = _child.budgetMeasures[0] + if total != "": + if not isinstance(total, float): + yield_ = 0.0 + _measure.setMeasure(total, self.getDecimals()) + if isinstance(list_lines, list) and len(list_lines) > 0: + _measure.buildMeasure(list_lines, type, self.getDecimals(), + _record.recordType) + if isinstance(label, str) and label != "" : + _measure.label = label + else: + # TODO: change return for except + print utils.mapping(_("Error: Invalid child position in " + "decomposition. Parent code: $1 Child code: $2 "\ + "Position: $3"), (code, child_code, position)) + return + else: + if child_code == "" : + print utils.mapping(_("Error: Empty child code. Parent code: "\ + "$1 Position: $2"), (code, position)) + return + if position == -1: + position = 0 + elif position != 0: + print utils.mapping(_("Error: Invalid child position in "\ + "decomposition. Parent code: $1 Child code: $2 "\ + "Position: $3"), (code, child_code, position)) + return + if not isinstance(factor, float): + factor == 1.0 + if not isinstance(yield_, float): + yield_ = 1.0 + _record = self.setRecord(code, [], "", "", "", [], [], + "", "") + _child = _record.appendChild(child_code, self.getDecimals(), + factor, yield_, total, list_lines, type, label) + _child.budgetMeasures[0] = measure + + def eval_formula(self, formula, a, b, c, d): + """eval_formula(self, formula, a, b, c, d) + + formula: + Valid Operator: '(', ')', '+', '-', '*', '/' and '^' + Valid variable: 'a', 'b', 'c','d'y 'p' (Pi=3.1415926) + units: Number of Units (a) + length: Length (b) + width: Width (c) + height: Height (d) + + Evals the formula and return the result + """ + if a == "": a = 0.0 + if b == "": b = 0.0 + if c == "": c = 0.0 + if d == "": d = 0.0 + try: + a = float(a) + except: + raise ValueError, _("'a' value must be a float number") + try: + b = float(b) + except: + raise ValueError, _("'b' value must be a float number") + try: + c = float(c) + except: + raise ValueError, _("'c' value must be a float number") + try: + d = float(d) + except: + raise ValueError, _("'d' value must be a float number") + # spaces are erased + sre.sub("[ ]","",formula) + # operators and varibles are replaced + formula = formula.replace("+", " + ") + formula = formula.replace("-", " - ") + formula = formula.replace("*", " * ") + formula = formula.replace("/", " / ") + formula = formula.replace("^", " ** ") + formula = formula.replace("(", " ( ") + formula = formula.replace(")", " ) ") + formula = formula.replace("a", str(a)) + formula = formula.replace("b", str(b)) + formula = formula.replace("c", str(c)) + formula = formula.replace("d", str(d)) + formula = formula.replace("p", "3.1415926") + _list_formula = formula.split(" ") + _formula2 = "" + for oper in _list_formula: + try: + _float_oper= str(float(oper)) + _formula2 = _formula2 + _float_oper + except ValueError: + _formula2 = _formula2 + oper + _g = {"__builtins__":{}} + try: + return eval(_formula2, _g) + except: + raise ValueError, _("Invalid formula") + + def getText(self,code): + """getText(self,code) + + code: the record code + Returns the description text of a record + """ + if code in self.__records: + return self.__records[code].text + else: + raise IndexError, _("Invalid code") + + def setText(self,code,text): + """setText(self,code,text) + + code: the parent record code + text: the descripion text + Sests the description text of a record + """ + if not utils.is_valid_code(code)[0]: + raise ValueError, utils.mapping(_("Invalid record: $1"), (code,)) + if not code in self.__records: + _record = self.setRecord(code, [], "", "", "", [], [], + "", "") + _record.text = text + else: + _record = self.__records[code] + _record.text = text + + def setRecord(self, code, synonyms, hierarchy, unit, summary, price, date, + type, subtype): + """setRecord(self, code, synonyms, hierarchy, unit, summary, price, + date, type, subtype) + + code: Code string + synonyms: List of synonym codes of the record + hierarchy: + 0 -> root + 1 -> Chapter/Subchapter + 2 -> Other + unit: unit of measure record + summary: Short description of a record + price: List of prices + date: List of dates + "type" and "subtype": + 0 Without classifying + EA Auxiliary element + EU Unitary element + EC Complex element + EF Functional element + OB Construction site + PA Cost overrun + PU Unitary budget + 1 Labourforce + H Labourforce + 2 Machinery and auxiliary equipment + Q Machinery + % Auxiliary equipment + 3 Building materials + MC Cement + MCr Ceramic + MM Wood + MS Iron and steel + ME Energy + MCu Copper + MAl Aluminium + ML Bonding agents + M Others materials + Hierarchy type subtype + 0->root -> 0 -> None,OB + 1->[sub]chapter -> 0 -> None,PU + 2->Other -> 0 -> None,EA,EU,EC,EF,PA + 1 -> None,H + 2 -> None,Q,% + 3 -> None,MC,MCr,MM,MS,ME,MCu,Mal,ML,M + Adds a record in the budget + """ + # hierarchy + if hierarchy == 0 : + # is the root record + if self.__root is None: + self.__root = code + else: + print _("Only can be one root record") + return + # retake previous values. + # TODO: test synonyms + _budget = self + if not code in self.__records: + if code[-1] == "$": + _record = ParametricRecord(_budget.getDecimals(), code, + synonyms, hierarchy, + unit, summary, [], type, subtype, + [], "") + else: + _record = Record(_budget.getDecimals(), code, synonyms, + hierarchy, unit, + summary, [], type, subtype,[], "") + self.__records[code] = _record + _prices = [[price[i], date[i]] for i in range(len(price))] + _record.setPrices(_prices, self.getDecimals()) + else: + _record = self.__records[code] + code = _record.code + if len(synonyms) != 0 and synonyms[0] == "": + synonyms = _record.synonyms + if unit == "": + unit = _record.unit + if summary == "": + summary = _record.summary + #TODO: test empty price list + if len(price) == 0 or price[0] == "": + _prices = _record.prices + else: + _prices = [ [price[i], date[i]] for i in range(len(price))] + if type == "": + type = _record.recordType.type + _record.synonyms = synonyms + _record.unit = unit + _record.summary = summary + _record.setPrices(_prices, self.getDecimals()) + _record.recordType.hierarchy = hierarchy + _record.recordType.type = type + _record.recordType.subtype = subtype + return _record + + def hasRecord(self,code): + """hasRecord(self,code) + + code: Code record + Return True if the budget have this record code. + """ + if code in self.__records: + return True + else: + return False + + def getRecord(self, code): + """getRecord(self, code) + + code: Code record + Return the Record object + """ + return self.__records[code] + + def addPriceToRecord(self, price_date, record): + """addPriceToRecord(self, price, record) + + Add a price to the price list of the record. + price must fulfill: + - must be a list with two items + - the first item: price must be a float + """ + record.addPrice(price_date, self.getDecimals()) + + def getStrPriceFromRecord(self, index_price, record): + _price = record.getPrice(index_price) + _D = self.getDecimals().getD(record.recordType) + _price = ("%." + str(_D) + "f" ) % _price + return _price + + def getCode(self, path): + """getCode(self, path) + + path: path record in the budget. + Return the code record + """ + if isinstance(path, tuple) and len(path)>= 1: + if path[0] == 0: + _code = self.__root + for i in path[1:]: + if isinstance(i, int): + _record = self.__records[_code] + _children_list = _record.children + try: + _child = _children_list[i] + except: + raise ValueError, _("This record does not exits") + _code = _child.code + else: + raise ValueError, _("Path item must be a integer") + return _code + else: + raise ValueError, _("This record does not exits") + else: + raise ValueError, utils.mapping(_("Path must be a not empty "\ + "tuple: $1"), (str(path),)) + + def getAmount(self, path): + """def getAmount(self,path) + + path: record path + Calculate the record amount + """ + if len(path) == 1: + # root: amount is the root price + _root = self.getRecord(self.getRoot()) + _amount = _root.getPrice(self.__title_index) + return _amount + else: + _parent_code = self.getCode(path[:-1]) + _parent_record = self.getRecord(_parent_code) + _child_number = path[-1] + + _decomposition = _parent_record.children[_child_number] + _factor = _decomposition.budgetMeasures[0].factor + _yield = _decomposition.budgetMeasures[0].yield_ + _child_code = _decomposition.code + _child_record = self.getRecord(_child_code) + _price = _child_record.getPrice(self.getActiveTitle()) + _DR = self.getDecimals().getDR(_parent_record.recordType) + _total_yield = round(_factor * _yield, _DR) + _DI = self.getDecimals().getDI(_parent_record.recordType) + _amount = round(_total_yield * _price, _DI) + return _amount + + def getStrAmount(self, path): + """def getStrAmount(self, path) + + path: record path + Calculate the string record amount + """ + if len(path) == 1: #root + _root = self.getRecord(self.getRoot()) + _amount = self.getStrPriceFromRecord(self.__title_index, _root) + return _amount + else: + _parent_code = self.getCode(path[:-1]) + _parent_record = self.getRecord(_parent_code) + _amount = self.getAmount(path) + _DI = self.getDecimals().getDI(_parent_record.recordType) + _amount = ("%." + str(_DI) + "f") % _amount + return _amount + + def setSheetSection(self,sheet_code,sheet_title): + if not isinstance(sheet_code, str): + raise ValueError, _("The sheet code must be a string") + if not isinstance(sheet_title, str): + raise ValueError, _("The sheet title must be a string") + self.__sheet_sections[sheet_code] = sheet_title + def hasSheetSection(self, section): + return section in self.__sheet_sections + def getSheetSection(self, section): + return self.__sheet_sections[section] + def setSheetSections(self,dictionary): + if not isinstance(dictionary, dict): + raise ValueError, _("The sheet sections must be a dictionary") + for sheet_code in dictionary.keys(): + self.setSheetSection(sheet_code, dictionary[sheet_code]) + def setSheetField(self, field_code, field_title): + if not isinstance(field_code, str): + raise ValueError, _("The field code must be a string") + if not isinstance(field_title, str): + raise ValueError, _("The field title must be a string") + self.__sheet_fields[field_code] = field_title + def hasSheetField(self, field): + return field in self.__sheet_fields + def getSheetField(self, field): + return self.__sheet_fields[field] + def setSheetFields(self, field_dict): + if not isinstance(field_dict, dict): + raise ValueError, _("The sheet field must be a dictionary") + for field_code in field_dict.keys(): + self.setSheetField( field_code, field_dict[field_code]) + def setSheetParagraph(self, paragraph_code, paragraph_text): + if not isinstance(paragraph_code, str): + raise ValueError, _("The paragraph code must be a string") + if not isinstance(paragraph_text, str): + raise ValueError, _("The paragraph text must be a string") + self.__sheet_paragraphs[paragraph_code] = paragraph_text + def hasSheetParagraph(self, paragraph): + return paragraph in self.__sheet_paragraphs + def getSheetParagraph(self, paragraph): + return self.__sheet_paragraphs[paragraph] + def setSheetParagraphs(self, paragraph_dict): + if not isinstance(paragraph_dict, dict): + raise ValueError, _("The paragraph dict must be a dictionary") + for paragraph_code in paragraph_dict.keys(): + self.setSheetParagraph( paragraph_code, paragraph_dict[paragraph_code]) + def setSheetRecord(self, record_code, field, section_dict): + if not isinstance(record_code, str): + raise ValueError, _("The record_code code must be a string") + if not isinstance(field, str): + raise ValueError, _("The field must be a string") + if not isinstance(section_dict, dict): + raise ValueError, _("The section dict must be a dictionary") + #-# + # TODO: Add a empty record? + if not self.hasRecord(record_code): + print utils.mapping(_("Error: The budget do not have this record "\ + "code and can not be added the sheet text in the field $1. "\ + "Record Code: $2"), ( field, record_code)) + return + #-# + if not self.hasSheetField(field): + self.setSheetField(field, "") + for section, paragraph in section_dict.iteritems(): + if not self.hasSheetParagraph(paragraph): + self.setSheetParagraph(paragraph,"") + if not self.hasSheetSection(section): + self.setSheetSection(section, "") + _sheet = self.getRecord(record_code).getSheet() + _sheet.addSection(field, section, paragraph) + def addFile(self, record_code, filepath, type, description): + if not isinstance(record_code, str): + raise ValueError, _("The record_code code must be a string") + if not isinstance(filepath, str): + raise ValueError, _("The filename must be a string") + #-# + # TODO: Add a empty record? + if not self.hasRecord(record_code): + print utils.mapping(_("Error: The budget do not have the record "\ + "code $1 and can not be added the file: $2"), + (record_code, filepath)) + return + #-# + _record = self.getRecord(record_code) + _record.addFile(filepath, type, description) + def setCompany(self, company_code, sumamary, name, offices, + cif, web, email): + if not isinstance(company_code, str): + raise ValueError, _("The company code must be a string") + if not isinstance(sumamary, str): + raise ValueError, _("The summary must be a string") + if not isinstance(name, str): + raise ValueError, _("The name must be a string") + if not isinstance(offices, list): + raise ValueError, _("The name must be a list") + _offices = [] + for _office in offices: + if not isinstance(_office, list): + raise ValueError, _("The office must be a list") + if not len(_office) == 10: + raise ValueError, _("The office must be a 10 items list") + for _item in _office[:7] + _office[9:10]: + if not isinstance(_item, str): + raise ValueError, _("This office item must be a "\ + "string") + for _item in _office[7:8]: + if not isinstance(_item, list): + raise ValueError, _("This office item must be a "\ + "list") + _offices.append(Office(_office[0], + _office[1], + _office[2], + _office[3], + _office[4], + _office[5], + _office[6], + _office[7], + _office[8], + _office[9])) + if not isinstance(cif, str): + raise ValueError, _("The name must be a string") + if not isinstance(web, str): + raise ValueError, _("The web must be a string") + if not isinstance(email, str): + raise ValueError, _("The email must be a string") + + self.__companys[company_code] = Company(company_code, sumamary, name, + _offices, cif, web, email) + def getCompany(self, company_code): + return self.__companys[company_code] + def getCompanyKeys(self): + return self.__companys.keys() + def addTecInfo(self, ti_code, text, unit): + if not isinstance(ti_code, str): + raise ValueError, _("The tecnical info code must be a string") + if not isinstance(text, str): + raise ValueError, _("The tecnical info description must be a "\ + "string") + if not isinstance(unit, str): + raise ValueError, _("The tecnical info unit must be a string") + self.__tec_info[ti_code] = [text, unit] + def hasTecInfo(self, ti_code): + return ti_code in self.__tec_info + def getTecInfo(self, ti_code): + return self.__tec_info[ti_code] + def setTecnicalInformation(self, record_code, ti_dict): + """setTecnicalInformation(record_code, ti_dict) + + Sets the tecnical information to a record + record_code: the record code + ti_dict: {ti_code : ti_value} + """ + # TODO: setTecnicalInformation + pass + def changeCode(self, record_code, new_record_code): + """changeCode(self, record_code, new_record_code): + + Change the record code for a new recor code. + """ + if self.hasRecord(record_code) and not self.hasRecord(new_record_code): + _record = self.__records[code] + _record.code = new_record_code + _parents = _record.parents + for _parent in _parents: + _decomposition_list = self.__records[_parent].children + for _decomposition in _decomposition_list: + if _decomposition.code == record_code: + _decomposition.code = new_record_code + break + _children = self.getchildren(record_code) + for _child in _children: + _parents_list = self.__records[_child].parents + for index in range(len(_parents_list)): + if _parents_list[index] == record_code: + _parents_list[index] = new_record_code + break + self.__records[new_record_code] = _record + del self.__records[record_code] + # TODO: attachment files + + def addLabel(self, record_code, label): + """addLabel(self, record_code, label) + + Add a label to a record + """ + if not isinstance(label,str): + raise ValueError, _("The label must be a string") + if self.hasRecord(record_code): + _record = self.__records[record_code] + _record.addLabel(label) + if not label in self.__labels: + self.__labels[label] = [record_code] + else: + _codes = self.__labels[label] + if not record_code in _codes: + _codes.append(record_code) + def setParametricSelectComment(self, record_code, comment): + """setParametricSelectComment(self, record_code, comment) + + Sets Paramtric Record Select Comment + """ + if not isinstance(record_code, str): + raise ValueError, _("The record_code code must be a string") + if not isinstance(comment, str): + raise ValueError, _("The parametric select comment must be a "\ + "string") + if not self.hasRecord(record_code): + print utils.mapping(_("Error: The budget do not have the record "\ + "code $1 and can not be added the Parametric select comment: "\ + "$2"), + (record_code, comment)) + return + _record = self.getRecord(record_code) + if not isinstance(_record, ParametricRecord): + print utils.mapping(_("Error: The Record $1 is not a "\ + "Parametric Record and can not have Parametric comment"), + (record_code,)) + else: + _record.select_comment = comment + + def setParametricSummary(self, record_code, summary): + """setParametricSummary(self, record_code, summary) + + Sets parametric record summary + """ + if not isinstance(record_code, str): + raise ValueError, _("The record_code code must be a string") + if not isinstance(summary, str): + raise ValueError, _("The summary record must be a string") + if not self.hasRecord(record_code): + print utils.mapping(_("Error: The budget do not have the record "\ + "code $1 and can not be seted the summary: $2"), + (record_code, summary)) + return + _record = self.getRecord(record_code) + if not isinstance(_record, ParametricRecord): + print utils.mapping(_("Error: The Record $1 is not a "\ + "Parametric Record and can not have Parametric summary"), + (record_code,)) + else: + self.getRecord(record_code).parametric_summary = summary + + def setParametricText(self, record_code, text): + """setParametricText(self, record_code, text) + + Sets parametric record text + """ + if not isinstance(record_code, str): + raise ValueError, _("The record_code code must be a string") + if not isinstance(text, str): + raise ValueError, _("The text record must be a string") + if not self.hasRecord(record_code): + print utils.mapping(_("Error: The budget do not have the record "\ + "code $1 and can not be seted the text: $2"), + (record_code, text)) + return + _record = self.getRecord(record_code) + if not isinstance(_record, ParametricRecord): + print utils.mapping(_("Error: The Record $1 is not a "\ + "Parametric Record and can not have Parametric text"), + (record_code,)) + else: + self.getRecord(record_code).parametric_text = text + +class Office(object): + """base.Office: + + Description: + Office of a company + Constructor: + base.Office(type, subname, address, postal_code, town, province, + country, phone, fax, contact_person) + Ancestry: + +-- object + +-- Office + Atributes: + "officeType" : type of Office + are defined: + "C" Central. + "D" Local Office. + "R" performer. + "subname" : name of Office or Performer + "address" : + "postal_code" : + "town" : + "province" : + "country" : + "phone" : list of phone numbers + "fax" : list of fax numbers + "contact_person" : name of contact person + "values": + Methods: + __getstate__(self) + __setstate__(self, tuple) + __init__(self, measure, lines, label) + {get/set}OfficeType + {get/set}Subname + {get/set}Address + {get/set}PostalCode + {get/set}Town + {get/set}Province + {get/set}Country + {get/set}Phone + {get/set}Fax + {get/set}ContactPerson + getValues + """ + __slots__ = ["_Office__officeType", + "_Office__subname", + "_Office__address", + "_Office__postal_code", + "_Office__town", + "_Office__province", + "_Office__country", + "_Office__phone", + "_Office__fax", + "_Office__contact_person", + ] + def __getstate__ (self): + return ( self.__officeType, + self.__subname, + self.__address, + self.__postal_code, + self.__town, + self.__province, + self.__country, + self.__phone, + self.__fax, + self.__contact_person) + def __setstate__(self,tuple): + self.__officeType = tuple[0] + self.__subname = tuple[1] + self.__address = tuple[2] + self.__postal_code = tuple[3] + self.__town = tuple[4] + self.__province = tuple[5] + self.__country = tuple[6] + self.__phone = tuple[7] + self.__fax = tuple[8] + self.__contact_person = tuple[9] + + def __init__(self, type, subname, address, postal_code, town, province, + country, phone, fax, contact_person): + self.officeType = type + self.subname = subname + self.address = address + self.postal_code = postal_code + self.town = town + self.province = province + self.country = country + self.phone = phone + self.fax = fax + self.contact_person = contact_person + def getOfficeType(self): + return self.__officeType + def setOfficeType(self, type): + self.__officeType = type + def getSubname(self): + return self.__subname + def setSubname(self, subname): + self.__subname = subname + def getAddress(self): + return self.__address + def setAddress(self, address): + self.__address = address + def getPostalCode(self): + return self.__postal_code + def setPostalCode(self, postal_code): + self.__postal_code = postal_code + def getTown(self): + return self.__town + def setTown(self, town): + self.__town = town + def getProvince(self): + return self.__province + def setProvince(self, province): + self.__province = province + def getCountry(self): + return self.__country + def setCountry(self, country): + self.__country = country + def getPhone(self): + return self.__phone + def setPhone(self, phone): + self.__phone = phone + def getFax(self): + return self.__fax + def setFax(self, fax): + self.__fax = fax + def getContactPerson(self): + return self.__contact_person + def setContactPerson(self, contact_person): + self.__contact_person = contact_person + def getValues(self): + return {"officeType": self.officeType, + "subname": self.subname, + "address": self.address, + "postal code": self.postal_code, + "town": self.town, + "province": self.province, + "country": self.country, + "phone": self.phone, + "fax": self.fax, + "contact person": self.contact_person, + } + officeType = property(getOfficeType, setOfficeType, None, + """Type of office + """) + subname = property(getSubname, setSubname, None, + """Name of office + """) + address = property(getAddress, setAddress, None, + """Adress + """) + postal_code = property(getPostalCode, setPostalCode, None, + """Postal code + """) + town = property(getTown, setTown, None, + """Town + """) + province = property(getProvince, setProvince, None, + """Province + """) + country = property(getCountry, setCountry, None, + """Country + """) + phone = property(getPhone, setPhone, None, + """Phone numbers + """) + fax = property(getFax, setFax, None, + """Fax numbers + """) + contact_person = property(getContactPerson, setContactPerson, None, + """Contact Person + """) + values = property(getValues, None, None, + """Dictionary with comapany values + """) + +class Company(object): + """base.Company: + + Description: + Company object + __slots__ attribute, __getstate__ and __setstate__ method are defined + to use less ram memory. + Constructor: + base.Company(code, summary, name, offices, cif, web, email) + Ancestry: + +-- object + +-- Company + Atributes: + "code": code to indentifie the company in the buget + "summary": short name + "name": long name + "offices": List of Offices + "cif": CIF + "web": web page + "email": email + "values": + Methods: + __getstate__(self) + __setstate__(self, tuple) + __init__(self, measure, lines, label) + {get/set}Code + {get/set}Summary + {get/set}Name + {get/set}Offices + {get/set}Cif + {get/set}Web + {get/set}Email + getValues + """ + __slots__ = ["_Company__code", + "_Company__summary", + "_Company__name", + "_Company__offices", + "_Company__cif", + "_Company__web", + "_Company__email", + ] + def __getstate__ (self): + return ( self.__code, + self.__summary, + self.__name, + self.__offices, + self.__cif, + self.__web, + self.__email) + def __setstate__(self,tuple): + self.__code = tuple[0] + self.__summary = tuple[1] + self.__name = tuple[2] + self.__offices = tuple[3] + self.__cif = tuple[4] + self.__web = tuple[5] + self.__email = tuple[6] + + def __init__(self, code, summary, name, offices, cif, web, email): + self.code = code + self.summary = summary + self.name = name + self.offices = offices + self.cif = cif + self.web = web + self.email = email + def getCode(self): + return self.__code + def setCode(self, code): + self.__code = code + def getSummary(self): + return self.__summary + def setSummary(self, summary): + self.__summary = summary + def getName(self): + return self.__name + def setName(self, name): + self.__name = name + def getOffices(self): + return self.__offices + def setOffices(self, offices): + self.__offices = offices + def getCif(self): + return self.__cif + def setCif(self, cif): + self.__cif = cif + def getWeb(self): + return self.__web + def setWeb(self, web): + self.__web = web + def getEmail(self): + return self.__email + def setEmail(self, email): + self.__email = email + def getValues(self): + return {"code": self.code, + "summary": self.summary, + "name": self.name, + "cif": self.cif, + "web": self.web, + "email": self.email} + code = property(getCode, setCode, None, + """Company code + """) + summary = property(getSummary, setSummary, None, + """Company summary + """) + name = property(getName, setName, None, + """Company name + """) + offices = property(getOffices, setOffices, None, + """List of Offices + """) + cif = property(getCif, setCif, None, + """CIF + """) + web = property(getWeb, setWeb, None, + """Web page + """) + email = property(getEmail, setEmail, None, + """Email + """) + values = property(getValues, None, None, + """Dictionary with comapany values + """) + +class File(object): + """base.Company: + + Description: + File object + Constructor: + base.File(name, type, description) + Ancestry: + +-- object + +-- File + Atributes: + "name": name + "fileType": type of file + "description": description file + Methods: + __getstate__(self) + __setstate__(self, tuple) + __init__(self, path,type, description) + {get/set}Name + {get/set}FileType + {get/set}Description + getValues + """ + __slots__ = ["_File__name", + "_File__fileType", + "_File__description", + + ] + def __getstate__ (self): + return (self.__name, + self.__description, + self.__fileType, + ) + def __setstate__(self,tuple): + self.__name = tuple[0] + self.__fileType = tuple[1] + self.__description = tuple[2] + def __init__(self, name, type, description): + self.name = name + self.fileType = type + self.description = description + def getName(self): + return self.__name + def setName(self, name): + self.__name = name + def getFileType(self): + return self.__fileType + def setFileType(self, type): + self.__fileType = type + def getDescription(self): + return self.__description + def setDescription(self, description): + self.__description = description + def getValues(self): + return {"name": self.name, + "fileType": self.fileType, + "description": self.description, + } + name = property(getName, setName, None, + """File name + """) + fileType = property(getFileType, setFileType, None, + """FileType + """) + description = property(getDescription, setDescription, None, + """File description + """) + values = property(getValues, None, None, + """Dictionary with file values + """) + +class RecordType(object): + """base.RecordType: + + Description: + Record Type object + "hierarchy": + -1 -> temporarily unfixed + 0 -> root + 1 -> Chapter/Subchapter + 2 -> Other + "type" and "subtype": + 0 Without classifying + EA Auxiliary element + EU Unitary element + EC Complex element + EF Functional element + OB Construction site + PA Cost overrun + PU Unitary budget + 1 Labourforce + H Labourforce + 2 Machinery and auxiliary equipment + Q Machinery + % Auxiliary equipment + 3 Building materials + MC Cement + MCr Ceramic + MM Wood + MS Iron and steel + ME Energy + MCu Copper + MAl Aluminium + ML Bonding agents + M Others materials + Hierarchy type subtype + 0->root -> 0 -> None,OB + 1->[sub]chapter -> 0 -> None,PU + 2->Other -> 0 -> None,EA,EU,EC,EF,PA + 1 -> None,H + 2 -> None,Q,% + 3 -> None,MC,MCr,MM,MS,ME,MCu,Mal,ML,M + Constructor: + base.File(hierarchy,type,subtype) + Ancestry: + +-- object + +-- RecordType + Atributes: + "hierarchy": hierarchy + "type": type + "subtype": subtype + Methods: + __getstate__(self) + __setstate__(self, tuple) + __init__(self, hierarchy, type, subtype) + {get/set}Hierarchy + {get/set}Type + {get/set}Subtype + """ + __slots__ = ["_RecordType__hierarchy", + "_RecordType__type", + "_RecordType__subtype", + ] + def __getstate__ (self): + return (self.__hierarchy, + self.__type, + self.__subtype, + ) + def __setstate__(self,tuple): + self.__hierarchy = tuple[0] + self.__type = tuple[1] + self.__subtype = tuple[2] + def __init__(self, hierarchy, type, subtype): + self.hierarchy = hierarchy + self.type = type + self.subtype = subtype + def getHierarchy(self): + return self.__hierarchy + def setHierarchy(self, hierarchy): + if not hierarchy in [-1, 0 , 1 ,2]: + raise ValueError, utils.mapping(_("Invalid Hierarchy ($1) "\ + "The hierarchy must be -1, 0, 1 or 2"), (str(hierarchy))) + self.__hierarchy = hierarchy + def getType(self): + return self.__type + def setType(self, type): + if not type in ["", 0, 1, 2, 3] : + raise ValueError, utils.mapping(_("Invalid type ($1),"\ + "the type must be (empty string,0,1,2,3)"),(str(type))) + self.__type = type + def getSubtype(self): + return self.__subtype + def setSubtype(self, subtype): + if not subtype in ["", "OB", "PU", "EA", "EU", "EC", "EF", "PA", "H", + "Q", "%", "MC", "MCr", "MM", "MS", "ME", "MCu", + "Mal","ML","M"]: + raise ValueError, utils.mapping(_("Invalid subtype ($1), The "\ + "subtype must one in (empty string, EA, "\ + "EU, EC, EF, OB, PA, PU, H, Q, %, MC, MCr, "\ + "MM, MS, ME, MCu, MAl, ML, M)"), (str(subtype))) + self.__subtype = subtype + hierarchy = property(getHierarchy, setHierarchy, None, + """Record Hierarchy + -1 -> temporarily unfixed + 0 -> root + 1 -> Chapter/Subchapter + 2 -> Other + """) + type = property(getType, setType, None, + """Record Type + 0 Without classifying + 1 Labourforce + 2 Machinery and auxiliary equipment + 3 Building materials + """) + subtype = property(getSubtype, setSubtype, None, + """Record Subtype + None + EA Auxiliary element + EU Unitary element + EC Complex element + EF Functional element + OB Construction site + PA Cost overrun + PU Unitary budget + H Labourforce + Q Machinery + % Auxiliary equipment + MC Cement + MCr Ceramic + MM Wood + MS Iron and steel + ME Energy + MCu Copper + MAl Aluminium + ML Bonding agents + M Others materials + """)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Generic/config.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,46 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File config.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. + +"""config module + +Unused module +""" +class Config(object): + """config.Config: + + Description: + Config object + Ancestry: + +-- object + +-- Config + Atributes: + "": + Methods: + + """ + def __init__(self): + self.__path = "" + def _getPath(self): + return self.__path + def _setPath(self, path): + self.__path = path + path = property(_getPath, _setPath, None, + """Base path where find all the program files needed""")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Generic/durusdatabase.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,46 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File durus.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. + +# Modules +import os.path +# Durus Modules +from durus.file_storage import FileStorage +from durus.connection import Connection + +class DurusFile(object): + def __init__(self, file, new): + self.__file = file + if new: + if os.path.exists(self.__file): + os.remove(self.__file) + self.__connection = Connection(FileStorage(self.__file)) + self.__root = self.__connection.get_root() + + def close(self): + self.__connection.get_storage().close() + + def getBudget(self): + return self.__root["budget"] + + def setBudget(self, budget): + self.__root["budget"] = budget + self.__connection.commit() +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Generic/fiebdc.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,2126 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File fiebdc.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. + +# specifications in http://www.fiebdc.org + +# Modules +import time +import re +import calendar +import os.path + +# pyArq-Presupuestos modules +import base +from Generic import utils +from Generic import globals + +class Read(object): + """fiebdc.Read: + + Description: + Reads and parses a fiebdc file + Constructor: + fiebdc.Read(filename=None, budget=None) + Ancestry: + +-- object + +-- Read + Atributes: + "__budget": budget ("base.Budget" object) + "__file_format": File format of the fiebdc file + "__format_list": List of file format that can be readed + "__character_sets_dict": Dictionary with the character sets supported + "__character_set": character_set of the file + "__generator": program which the file is created + "__cancel": Boolean value, True mean that the read process must stop + "__filename": The filename of the fiebdc file that is readed + "__pattern": re compiled pattern dict + Methods: + __init__(self, filename=None, budget=None) + cancel(self) + eraseControlCharacters(self, string) + validateCode(self, code) + parseDate(self, date) + parseRecord(self,record) + _parseV(self, field_list) + _parseC(self, field_list) + _parseDY(self, field_list) + _parseMN(self, field_list) + _parseT(self, field_list) + _parseK(self, field_list) + _parseW(self, field_list) + _parseL(self, field_list) + _parseQ(self, field_list) + _parseJ(self, field_list) + _parseG(self, field_list) + _parseE(self, field_list) + _parseX(self, field_list) + _parseF(self, field_list) + readFile(self, budget=None, filename=None) + """ + def __init__(self, filename=None, budget=None): + """def __init__(self, filename=None, budget=None) + + Sets the instance attributes + """ + self.__budget = budget + self.__filename = filename + if not self.__budget is None: + self.__budget.filename = self.__filename + self.__cancel = False + self.__format_list = ["FIEBDC-3/95", "FIEBDC-3/98", "FIEBDC-3/2002", + "FIEBDC-3/2004", "FIEBDC-3/2007"] + # ANSI->¿"ISO-8859-15" or "latin1 ISO-8859-1" or "cp1252 windows-1252"? + # 850 -> IBM850 -> cp850 + # 437 -> IBM437 -> cp437 + self.__character_sets_dict = {"ANSI" : "cp1252", + "850" : "850", + "437" : "cp437"} + self.__file_format = "FIEBDC-3/2007" + self.__generator = globals.version + self.__character_set = "850" + self.__pattern = { + "control_tilde" : re.compile("((\r\n)| |\t)+~"), + "control_vbar" : re.compile("((\r\n)| |\t)+\|"), + "control_backslash" : re.compile(r"((\r\n)| |\t)+\\"), + "valid_code" : re.compile("[^A-Za-z0-9ñÑ.$#%&_]"), + "special_char": re.compile("[#%&]"), + "no_float": re.compile("[^0-9.]"), + "formula" : re.compile(".*[^0123456789\.()\+\-\*/\^abcdp ].*"), + "comment": re.compile("#.*\r\n"), + "empty_line": re.compile(r"(\r\n) *\r\n"), + "space_before_backslash" : re.compile(r"( )+\\"), + "space_after_backslash" : re.compile(r"\\( )+"), + "start_noend_backslash" : re.compile("(\r\n\\\.*[^\\\])\r\n"), + "end_oper": re.compile("(\+|-|\*|/|/^|@|&|<|>|<=|>=|=|!) *\r\n"), + "matricial_var" : re.compile("(\r\n *[%|\$][A-ZÑ].*=.*,) *\r\n"), + "descomposition" : re.compile("^([^:]+):(.*)$"), + "var" : re.compile("^([$%][A-ZÑ][()0-9, ]*)=(.*)$"), + "after_first_tilde" : re.compile("^[^~]*~"), + "end_control" : re.compile("((\r\n)| |\t)+$"), + } + + def cancel(self): + """def cancel(self) + + Sets the "__cancel" attribute to True, It stops the read process. + """ + self.__cancel = True + + def eraseControlCharacters(self, string): + """eraseControlCharacters(self,string) + + Return a copy of the string with the blank characters (32), + tabs (9) and end of line (13 and 10) before of the separators + '~', '|' erased. + Before separator \ not deleted because it affects the reading of the + record ~P + """ + # "control_tilde" : "((\r\n)| |\t)+~" + string = self.__pattern["control_tilde"].sub("~",string) + # "control_vbar" : "((\r\n)| |\t)+\|" + string = self.__pattern["control_vbar"].sub("|",string) + # "control_backslash" : r"((\r\n)| |\t)+\\" + #string = self.__pattern["control_backslash"].sub(r"\\",string) + return string + + def validateCode(self, code): + """validateCode(self, code) + + Test if the code have invalid characters and try to erase it, + if it is posible return a valid code else return a empty string. + """ + if not isinstance(code, str): + print _("Invalid code, it must be a string") + return "" + # Valid chararcter: A-Z a-z 0-9 ñ Ñ . $ # % & _ + # "valid_code" : "[^A-Za-z0-9ñÑ.$#%&_]" + _code = self.__pattern["valid_code"].sub("", code) + if _code != code: + print utils.mapping(_("The code '$1' have invalid characters."), + (code,)) + code = _code + # the lasts characters can not be <#> or <##> + # <##> -> root record in FIEFDC-3 + # <#> -> chapter record in FIEFDC-3 + if len(code) > 0: + while code[-1] == "#": + code = code[:-1] + if len(code) > 20: + code = code[:20] + # only one charecter # % or & + if sum([code.count(c) for c in '#%&']) > 1: + print utils.mapping(_("The code '$1' contains special "\ + "characters repeated."),(code,)) + _i = min([code.find(c) for c in '#%&']) + code = code[:_i+1] + \ + self.__pattern["special_char"].sub("", code[_i+1:]) + return code + + def parseDate(self, date): + """parseDate(self, date) + + date: in the format: + uneven len: add a Leading 0 + len = 8 DDMMYYYY + len <= 6 DDMMYY “80/20”. >80 -> >1980 <80 -> <2080 + len < 5 MMYY + len < 3 YY + Test date string and return a tuple (YYYY, MM, DD) + or None if the date format is invalid + """ + # All characters must be numbers, len <= 8 and not empty string + if not date.isdigit() or len(date) > 8 or date == "": + return None + else: + if len(date)%2 == 1: # uneven len: add a leading 0 + date = "0" + date + if len(date) == 8: + _d = int(date[:2]) + _m = int(date[2:4]) + _y = int(date[4:8]) + elif len(date) <= 6: + _y = int(date[-2:]) + if _y < 80: _y = 2000 + _y + else: _y = 1900 + _y + if len(date) == 6: + _d = int(date[:2]) + _m = int(date[2:4]) + elif len(date) == 4: + _d = 0 + _m = int(date[:2]) + elif len(date) == 2: + _d = 0 + _m = 0 + if not _d in range(1,31): _d = 0 + if not _m in range(1,12): _m = 0 + if _m == 0: _d = 0 + if _m != 0 and _d != 0: + if calendar.monthrange(_y, _m)[1] < _d: + _d = 0 + return (_y, _m, _d) + + def parseRecord(self,record): + """parseRecord(self,record) + + record: the record line readed from the file whith the format: + type|field|field|subfield\subfield|... + [a] nothing or "a" + {a} zero or more #-#twice#-# "a" + <a> one or more #-#twice#-# "a" + Types: V C D Y M N T K L Q J G E X B F A + V: Property and Version + 1- [File_Owner] + 2- Format_Version[\DDMMYYYY] + 3- [Program_Generator] + 4- [Header]\{Title\} + 5- [Chaters_set] + 6- [Comment] + C: Record: + 1- Code{\Code} + 2- [Unit] + 3- [Summary] + 4- {Price\} + 5- {Date\} + 6- [Type] + D or Y: DECOMPOSITION or ADD DECOMPOSITION + 1- Parent Code + 2- <Child Code\ [Factor]\ [Yield]> + M or N: MEASURE or ADD MEASURE + 1- [Parent Code\]Child Code + 2- {Path\} + 3- TOTAL MEASURE + 4- {Type\Comment\Unit\Length\Width\Height\} + 5- [Label] + T: Text + 1- Code + 2- Description text + K: Coefficients + 1- { DN \ DD \ DS \ DR \ DI \ DP \ DC \ DM \ DIVISA \ } + 2- CI \ GG \ BI \ BAJA \ IVA + 3- { DRC \ DC \ DRO \ DFS \ DRS \ DFO \ DUO \ DI \ DES \ DN \ + DD \ DS \ DIVISA \ } + 4- [ n ] + L: Sheet of Conditions 1 + A) + 1- Empty + 2- {Section Code\Section Title} + B) + 1- Record Code + 2- {Section Code\Section Text} + 3- {Section Code\RTF file} + 4- {Section Code\HTM file} + Q: Sheet of Conditions 2 + 1- Record Code + 2- {Section Code\Paragraph key\{Field key;}\}| + J: Sheet of Conditions 3 + 1- Paragraph code + 2- [Paragraph text] + 3- [RTF file] + 4- [HTML file] + G: Grafic info + 1- <grafic_file.ext\> + E: Company + 1- company Code + 2 [ summary ] + 3- [ name ] + 4- { [ type ] \ [ subname ] \ [ address ] \ [ postal_code ] + \ [ town ] \ [ province ] \ [ country ] \ { phone; } + \ { fax; } \ {contact_person; } \ } + 5- [ cif ] \ [ web ] \ [ email ] \ + X: Tecnical information + A) + 1- Empty + 2- < TI_Code \ TI_Descitption \ TI_Unit > + B) + 1- Record_code + 2- < TI_Code \ TI_value > + F: #-#Adjunto#-# File + 1- Record code + 2- { Type \ { Filenames; } \ [Description] } + B: Change code + 1- Record Code + 2- New code + A: Labels + 1- Record Code + 2- <Label\> + """ + # TODO: ~L ~J RTF and HTML files + # TODO: test ~Q ~J ~G + # TODO: ~P. Registro tipo Descripción Paramétrica. + # TODO: ~O. Registro tipo Relación Comercial. + # TODO: test records + _field_list = record.split("|") + self._record_number = self._record_number +1 + _budget = self.__budget + if _field_list[0] == "V": + self._record_V_number += 1 + self._parseV(_field_list) + elif _field_list[0] == "C": + self._record_C_number += 1 + self._parseC(_field_list) + elif _field_list[0] == "D": + self._record_D_number += 1 + self._parseDY(_field_list) + elif _field_list[0] == "Y": + self._record_Y_number += 1 + self._parseDY(_field_list) + elif _field_list[0] == "M": + self._record_M_number += 1 + self._parseMN(_field_list) + elif _field_list[0] == "N": + self._record_N_number += 1 + self._parseMN(_field_list) + elif _field_list[0] == "T": + self._record_T_number += 1 + self._parseT(_field_list) + elif _field_list[0] == "K": + self._record_K_number += 1 + self._parseK(_field_list) + elif _field_list[0] == "W": + self._record_W_number += 1 + self._parseW(_field_list) + elif _field_list[0] == "L": + self._record_L_number += 1 + self._parseL(_field_list) + elif _field_list[0] == "Q": + self._record_Q_number += 1 + self._parseQ(_field_list) + elif _field_list[0] == "J": + self._record_J_number += 1 + self._parseJ(_field_list) + elif _field_list[0] == "G": + self._record_G_number += 1 + self._parseG(_field_list) + elif _field_list[0] == "E": + self._record_E_number += 1 + self._parseE(_field_list) + elif _field_list[0] == "O": + self._record_O_number += 1 + elif _field_list[0] == "P": + self._record_P_number += 1 + self._parseP(_field_list) + elif _field_list[0] == "X": + self._record_X_number += 1 + self._parseX(_field_list) + elif _field_list[0] == "B": + self._record_B_number += 1 + self._parseB(_field_list) + elif _field_list[0] == "F": + self._record_F_number += 1 + self._parseF(_field_list) + elif _field_list[0] == "A": + self._record_A_number += 1 + self._parseA(_field_list) + else: + self._record_Unknow_number += 1 + + def _parseV(self, field_list): + """_parseV(self, field_list) + + field_list: field list of the record + 0- V :Property and Version + 1- [File_Owner] + 2- Format_Version[\DDMMYYYY] + 3- [Program_Generator] + 4- [Header]\{Title\} + 5- [Chaters_set] + 6- [Comment] + 7- [Data type] + 8- [Number budget certificate] + 9- [Date budget certificate] + """ + if self._record_number != 1: + print utils.mapping(_("The 'V' record (Property and Version) "\ + "must be the first record in the file but it is the "\ + "number: $1"), (self._record_number,)) + print _("The default values were taken and this V record is "\ + "ignored") + return + # _____number of fields_____ + # Any INFORMATION after last field separator is ignored + if len(field_list) > 10: + field_list = field_list[:10] + # If there are no sufficient fields, the fields are added + # with empty value:"" + else: + field_list = field_list + [""]*(10-len(field_list)) + # control character are erased: end of line, tab, space + # only leading and trailing whitespace in owner, generator, comment + # _____Fields_____ + _record_type = self.delete_control_space(field_list[0]) + _owner = field_list[1].strip() + _owner = self.delete_control(_owner) + _version_date = self.delete_control_space(field_list[2]) + _generator = field_list[3].strip() + _generator = self.delete_control(_generator) + _header_title = field_list[4].strip() + _header_title = self.delete_control(_header_title) + _character_set = self.delete_control_space(field_list[5]) + _comment = field_list[6].strip("\t \n\r") + _data_type = self.delete_control_space(field_list[7]) + _number_certificate = self.delete_control_space(field_list[8]) + __date_certificate = self.delete_control_space(field_list[9]) + # _____Owner_____ + self.__budget.setOwner(_owner) + # _____Version-Date_____ + _version_date = _version_date.split("\\") + _file_format = _version_date[0] + if _file_format in self.__format_list: + self.__file_format = _file_format + print _("FIEBDC format: %s" % _file_format) + if len(_version_date) > 1: + _date = _version_date[1] + if _date != "": + _parsed_date = self.parseDate(_date) + if _parsed_date is not None: + self.__budget.setDate(_parsed_date) + # _____Generator_____ + # ignored field + print _("FIEBDC file generated by %s" % _generator) + # _____Header_Title_____ + _header_title = _header_title.split("\\") + _header_title = [_title.strip() for _title in _header_title] + _header = _header_title.pop(0) + _title = [ ] + for _title_index in _header_title: + if _title_index != "": + _title.append(_title_index) + if _header != "": + self.__budget.setTitleList([ _header, _title ]) + # _____Characters_set_____ + # field parsed in readFile method + # _____Comment_____ + if _comment != "": + self.__budget.setComment(_comment) + # _____Data type_____ + # 1 -> Base data. + # 2 -> Budget. + # 3 -> Budget certificate. + # 4 -> Base date update. + try: + _data_type = int(_data_type) + except ValueError: + _data_type = "" + if _data_type == 3: + # _____Number budget certificate_____ + try: + _number_certificate = int(_number_certificate) + except ValueError: + _number_certificate = "" + # _____Date budget certificate_____ + if _date_certificate != "": + _parsed_date_certificate = self.parseDate(_date_certificate) + if _parsed_date_certificate is None: + _date_certificate = "" + else: + _date_certificate = _parsed_date_certificate + self.__budget.setBudgetype(_data_type) + self.__budget.setCertificateOrder(_number_certificate) + self.__budget.setCertificateDate(_parsed_date_cerfificate) + elif _data_type != "": + self.__budget.setBudgeType(_data_type) + self.num_valid_record = self.num_valid_record + 1 + + def _parseK(self, field_list): + """_parseK(self, field_list) + + field_list: field list of the record + 0- K: Coefficients + 1- { DN \ DD \ DS \ DR \ DI \ DP \ DC \ DM \ DIVISA \ } + 2- CI \ GG \ BI \ BAJA \ IVA + 3- + A){ DRC \ DC \ DRO \ DFS \ DRS \ DFO \ DUO \ DI \ DES \ DN \ + DD \ DS \ DIVISA \ } + B){ DRC \ DC \ \ DFS \ DRS \ \ DUO \ DI \ DES \ DN \ + DD \ DS \ DSP\ DEC\ DIVISA \ } + 4- [ n ] + """ + # _____Number of fields_____ + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + # The last field is ignored, pyArq hate dll's + if len(field_list) > 4: + field_list = field_list[1:4] + # The record must have 3 fields + else: + field_list = field_list[1:] + [""]*(4-len(field_list)) + # control character are erased: end of line, tab, space + # _____Fields_____ + _field0 = self.delete_control_space(field_list[0]) + _field1 = self.delete_control_space(field_list[1]) + _field2 = self.delete_control_space(field_list[2]) + # _____Field 1_____ + if len(_field1) > 0 and _field1[-1] == "\\": + _field1 = _field1[:-1] + # if there are a \ character at the end it must be erased + _percentages = _field1.split("\\") + if len(_percentages) > 5: + _percentages = _percentages[:5] + # If there are no sufficient subfields, the subfields are added + # with empty value:"" + else: + _percentages = _percentages + [""]*(5-len(_percentages)) + _percentage_titles = [ "CI", "GG", "BI", "BAJA", "IVA" ] + _percentage_dict = {} + for _percentage_index in range(len(_percentages)): + try: + _percentage = int(_percentages[_percentage_index]) + except ValueError: + _percentage = "" + _percentage_dict[_percentage_titles[_percentage_index]] = \ + _percentage + self.__budget.setPercentages(_percentage_dict) + # _____Field 0 and 1_____ + # Default number of decimal places + # Number of titles in ~V record + _title_num = len(self.__budget.getTitleList()[1]) + if _title_num == 0: _title_num = 1 + # If the field 2 is empty, the field 0 is readed + if _field2 == "": + # _____Field 0_____ + if _field0[-1] == "\\": + _field0 = _field0[:-1] + # if there are a \ character at the end it must be erased + _decimal_list = _field0.split("\\") + _decimal_index = 0 + if len(_decimal_list)%9 != 0: + # if it is not multiple of 9, empty subfield are added + _decimal_list = _decimal_list + [""]*(9 - \ + len(_decimal_list)%9) + # The number of decimal values is the same as the numbers of + # titles in the V record + if len(_decimal_list)//9 > _title_num: + _decimal_list = _decimal_list[:_title_num*9] + elif len(_decimal_list)//9 < _title_num: + _decimal_list = _decimal_list + _decimal_list[-9:] * \ + (_title_num-(len(_decimal_list)//9)) + while _decimal_index <= len(_decimal_list)-9: + _decimals = _decimal_list[_decimal_index:(_decimal_index + 9)] + _forlist = range(len(_decimals)-1) + for _index in range(len(_decimals)): + try: + #TODO: test this + _decimals[_index] = int(_decimals[_index]) + except ValueError: + _decimals[_index] = "" + _DN = _decimals[0] + _DD = _decimals[1] + _DS = _decimals[2] + _DR = _decimals[3] + _DI = _decimals[4] + _DP = _decimals[5] + _DC = _decimals[6] + _DM = _decimals[7] + _DIVISA = _decimals[8] + _percentage_dict = {"DN" : _DN, + "DD" : _DD, + "DSP" : _DS, + "DS" : _DS, + "DFC" : _DR, + "DFPU" : _DR, + "DFUO" : _DR, + "DFA" : _DR, + "DRC" : _DR, + "DRPU" : _DR, + "DRUO" : _DR, + "DRA" : _DR, + "DP" : _DC, + "DC" : _DC, + "DPU" : _DC, + "DUO" : _DC, + "DEA" : _DC, + "DES" : _DC, + "DIR" : _DI, + "DIRC" : _DI, + "DCD" : _DP, + "DIVISA": _DIVISA } + _decimal_index = _decimal_index + 9 + self.__budget.setDecimals(_percentage_dict, + (_decimal_index//9)) + else: + # _____Field 3_____ + if _field2[-1] == "\\": + _field2 = _field2[:-1] + # if there are a \ character at the end it must be erased + _decimal_list = _field2.split("\\") + # test if the Divisa subfield is 12 or 14 position + # Divisa is the only Alphanumeric subfield + # "no_float": "[^0-9.]" + if len(_decimal_list) >= 13 and \ + self.__pattern["no_float"].search(_decimal_list[12]): + _multiple = 13 + elif len(_decimal_list) >= 15 and \ + self.__pattern["no_float"].search(_decimal_list[14]): + _multiple = 15 + else: + if self.__file_format == "FIEBDC-3/2002": + _multiple = 13 + elif self.__file_format == "FIEBDC-3/2004": + _multiple = 13 + elif self.__file_format == "FIEBDC-3/2007": + _multiple = 15 + else: + _multiple = 15 + _decimal_index = 0 + if len(_decimal_list)%_multiple != 0 : + # if it is not multiple of _multiple, empty subfield are added + _decimal_list = _decimal_list + \ + [""]*(_multiple-len(_decimal_list)%_multiple) + # The number of decimal values is the same as the numbers of + # titles in the V record + if len(_decimal_list)//_multiple > _title_num: + _decimal_list = _decimal_list[:_title_num*_multiple] + elif len(_decimal_list)//_multiple < _title_num: + _decimal_list = _decimal_list + [_decimal_list[-_multiple:]]*\ + (_title_num-(len(_decimal_list)//_multiple)) + while _decimal_index <= len(_decimal_list)-_multiple: + _decimals = _decimal_list[_decimal_index:(_decimal_index +\ + _multiple)] + for _index in range(len(_decimals)-1): + try: + _decimals[_index] = int(_decimals[_index]) + except: + _decimals[_index] = "" + if _multiple == 13: + _DRC = _decimals[0] + _DC = _decimals[1] + _DRO = _decimals[2] + _DFS = _decimals[3] + _DRS = _decimals[4] + _DFO = _decimals[5] + _DUO = _decimals[6] + _DI = _decimals[7] + _DES = _decimals[8] + _DN = _decimals[9] + _DD = _decimals[10] + _DS = _decimals[11] + _DIVISA = _decimals[12] + _percentage_dict = { + "DN" : _DN, + "DD" : _DD, + "DSP" : _DS, + "DS" : _DS, + "DFC" : _DFS, + "DFPU" : _DRC, + "DFUO" : _DFS, + "DFA" : _DFS, + "DRC" : _DRS, + "DRPU" : _DRC, + "DRUO" : _DRS, + "DRA" : _DRS, + "DP" : _DC, + "DC" : _DC, + "DPU" : _DC, + "DUO" : _DUO, + "DEA" : _DES, + "DES" : _DES, + "DIR" : _DI, + "DIRC" : _DC, + "DCD" : _DI, + "DIVISA": _DIVISA, + } + else: # _multiple == 15: + _DRC = _decimals[0] + _DC = _decimals[1] + _DRO = _decimals[2] + _DFS = _decimals[3] + _DRS = _decimals[4] + _DFO = _decimals[5] + _DUO = _decimals[6] + _DI = _decimals[7] + _DES = _decimals[8] + _DN = _decimals[9] + _DD = _decimals[10] + _DS = _decimals[11] + _DSP = _decimals[12] + _DEC = _decimals[13] + _DIVISA = _decimals[14] + _percentage_dict = { + "DN" : _DN, + "DD" : _DD, + "DSP" : _DSP, + "DS" : _DS, + "DFC" : _DFS, + "DFPU" : _DRC, + "DFUO" : _DFS, + "DFA" : _DFS, + "DRC" : _DRS, + "DRPU" : _DRC, + "DRUO" : _DRS, + "DRA" : _DRS, + "DP" : _DC, + "DC" : _DC, + "DPU" : _DC, + "DUO" : _DUO, + "DEA" : _DEC, + "DES" : _DES, + "DIR" : _DI, + "DIRC" : _DC, + "DCD" : _DI, + "DIVISA": _DIVISA} + _decimal_index = _decimal_index + 13 + self.__budget.setDecimals(_percentage_dict, + (_decimal_index//13)) + self.num_valid_record = self.num_valid_record +1 + + def _parseC(self, field_list): + """_parseC(self, field_list) + + field_list: field list of the record + 0- C: Record + 1- Code{\Code} + 2- [Unit] + 3- [Summary] + 4- {Price\} + 5- {Date\} + 6- [Type] + """ + # _____number of fields_____ + # Any INFORMATION after last field separator is ignored + if len(field_list) > 7: + field_list = field_list[:7] + # If there are no sufficient fields, the fields are added + # with empty value:"" + else: + field_list = field_list + [""]*(7-len(field_list)) + # control character are erased: en of line, tab, space + # _____Fields_____ + _record_type = field_list[0] + _codes = self.delete_control_space(field_list[1]) + _unit = self.delete_control_space(field_list[2]) + _summary = self.delete_control(field_list[3]) + _prices = self.delete_control_space(field_list[4]) + _dates = self.delete_control_space(field_list[5]) + _type = self.delete_control_space(field_list[6]) + # _____Code_____ + _codes = _codes.split("\\") + if len(_codes) > 0: + # parse the hierarchy of the first code + # hierarchy: 0->root, 1->Chapter/subchapter, 2->other + if len(_codes[0]) > 2 and _codes[0][-2:] == "##": + _hierarchy = 0 + elif len(_codes[0]) > 1 and _codes[0][-1:] == "#": + _hierarchy = 1 + else: + _hierarchy = 2 + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + # maximun len 20 characters + _codes = [self.validateCode(_code) for _code in _codes] + # empty codes are ignored + while "" in _codes: + _codes.remove("") + if len(_codes) > 0: + #TODO: test this + _code = _codes[0] + _synonyms = _codes + else: + print _("Record C without a valid code") + return + # _____Unit_____ + # nothing to do + # _____Summary_____ + # nothing to do + # _____Price_____ and _____Dates_____ + # last \ is erased + if len(_dates) > 0 and _dates[-1] == "\\": + _dates = _dates[:-1] + if len(_prices) > 0 and _prices[-1] == "\\": + _prices = _prices[:-1] + _dates = _dates.split("\\") + _prices = _prices.split("\\") + # number of prices = number of titles in "V" line + # if there are no sufficient prices it takes the last price defined + _title_num = len(self.__budget.getTitleList()[1]) + if _title_num == 0: _title_num = 1 + if len(_prices) > _title_num: _prices = _prices[:_title_num] + elif len(_prices) < _title_num: + _prices = _prices + [_prices[-1]]*(_title_num-len(_prices)) + # number of dates = number of prices + # if there are no sufficient dates it takes the last date defined + if len(_dates) > len(_prices): _dates = _dates[:len(_prices)] + elif len(_dates) < len(_prices): + _dates = _dates + [_dates[-1]]*(len(_prices)-len(_dates)) + for _index in range(len(_prices)): + # TODO: lack to specify the number of decimals of the price + try: + _prices[_index] = float(_prices[_index]) + except: + _prices[_index] = 0.0 + _parsed_date = self.parseDate(_dates[_index]) + if _parsed_date is None: + _dates[_index] = "" + else: + _dates[_index] = _parsed_date + # _____Type_____ + # 0 Without classifying + # EA Auxiliary element + # EU Unitary element + # EC Complex element + # EF Functional element + # OB Construction site + # PA Cost overrun + # PU Unitary budget + # 1 Labourforce + # H Labourforce + # 2 Machinery and auxiliary equipment + # Q Machinery + # % Auxiliary equipment + # 3 Building materials + # MC Cement + # MCr Ceramic + # MM Wood + # MS Iron and steel + # ME Energy + # MCu Copper + # MAl Aluminium + # ML Bonding agents + # M Others materials + # Hierarchy type subtype + # 0->root -> 0 -> None,OB + # 1->[sub]chapter -> 0 -> None,PU + # 2->Other -> 0 -> None,EA,EU,EC,EF,PA + # 1 -> None,H + # 2 -> None,Q,% + # 3 -> None,MC,MCr,MM,MS,ME,MCu,Mal,ML,M + if _hierarchy == 0: + if _type == "OB": + _subtype = _type + _type = 0 + elif _type == "0" or _type == "": + _subtype = "" + _type = 0 + else: + print utils.mapping(_("Incorrect type ($1) in the code $2"), + (str(_type), _code)) + _type = 0 + _subtype = "" + elif _hierarchy == 1: + if _type == "PU": + _subtype = _type + _type = 0 + elif _type == "0" or _type == "": + _subtype = "" + _type = 0 + else: + print utils.mapping(_("Incorrect type ($1) in the code $2"), + (str(_type), _code)) + _type = 0 + _subtype = "" + else: + if _type == "EA" or _type == "EU" or _type == "EC" or \ + _type == "EF" or _type == "PA": + _subtype = _type + _type = 0 + elif _type == "H": + _subtype = _type + _type = 1 + elif _type == "Q" or _type == "%": + _subtype = _type + _type = 2 + elif _type == "MC" or _type == "MCr" or _type == "MM" or \ + _type == "MS" or _type == "ME" or _type == "MCu" or \ + _type == "Mal" or _type == "ML" or _type == "M": + _subtype = _type + _type = 3 + elif _type == "0" or _type == "1" or _type == "2" or \ + _type == "3": + _subtype = "" + _type = int(_type) + elif _type == "": + _subtype = "" + _type = 0 + else: + print utils.mapping(_("Incorrect type ($1) in the code $2"), + (str(_type), _code)) + _type = 0 + _subtype = "" + self.__budget.setRecord(_code, _synonyms, _hierarchy, + _unit, _summary, _prices, _dates, _type, _subtype) + self.num_valid_record = self.num_valid_record + 1 + + def _parseDY(self, field_list): + """_parseDY(self, field_list) + + field_list: field list of the record + 0- D or Y: DECOMPOSITION or ADD DECOMPOSITION + 1- Parent Code + 2- <Child Code\ [Factor]\ [Yield]> + """ + # _____number of fields_____ + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[:3] + # If there are no sufficient fields, the fields are added + # with empty value:"" + else: + field_list = field_list + [""]*(3-len(field_list)) + # control character are erased: end of line, tab, space + # _____Fields_____ + _record_type = field_list[0] + _code = self.delete_control_space(field_list[1]) + _children = self.delete_control_space(field_list[2]) + # _____Code_____ + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _code = self.validateCode(_code) + # _____children_____ + # TODO: test the number of decimals in factor an yield values + _children = _children.split( "\\" ) + _children_list = [ ] + _child_index = 0 + while _child_index < len(_children)-3: + # _____subfields_____ + _child_code = _children[_child_index] + _factor = _children[_child_index+1] + _yield = _children[_child_index+2] + # _____child_code_____ + _child_code = self.validateCode(_child_code) + # _____factor_____ + if _factor != "": + try: + _factor = float(_factor) + except ValueError: + print utils.mapping(_("ValueError loadig the "\ + "descomposition of the record $1, the factor "\ + "of the child $2 must be a float number and "\ + "can not be $3, seted default value 1.0"), + (_code, _child_code, _factor)) + _factor = 1.0 + #____yield___ + if _yield != "": + try: + _yield = float(_yield) + except ValueError: + print utils.mapping(_("ValueError loading the "\ + "descomposition of the record $1, the yield of "\ + "the child $2, must be a float number and can"\ + "not be $3, seted default value 1.0"), + (_code, _child_code, _factor)) + _yield = 1.0 + if _child_code != "" and _code != "": + _children_list.append([_child_code, _factor, _yield ]) + if _record_type == "D": + _position = _child_index / 3 + else: #_record_type == "Y" + _position = -1 + self.__budget.setTree(_code, _child_code, _position, _factor, + _yield, "", "", "", "") + _child_index = _child_index + 3 + self.num_valid_record = self.num_valid_record +1 + + def _parseT(self, field_list): + """_parseT(self, field_list) + + field_list: field list of the record + 0- T: Text + 1- Record code + 2- Description text + """ + # _____Number of fields_____ + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:] + if len(field_list) != 2: + return + # control character are erased: end of line, tab, space + # _____Fields_____ + _code = self.delete_control_space(field_list[0]) + _text = field_list[1] + # _____Code_____ + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _code = self.validateCode(_code) + # _____Text_____ + self.__budget.setText(_code, _text) + self.num_valid_record = self.num_valid_record + 1 + + def _parseMN(self, field_list): + """_parseMN(self, field_list) + + field_list: field list of the record + 0- M or N: MEASURE or ADD MEASURE + 1- [Parent Code\]Child Code + 2- {Path\} + 3- TOTAL MEASURE + 4- {Type\Comment\Unit\Length\Width\Height\} + 5- [Label] + """ + + # _____Number of fields_____ + # Any INFORMATION after last field separator is ignored + # The record must have 6 fields + if len(field_list) > 6: + field_list = field_list[:6] + # If there are no sufficient fields, the fields are added + # with empty value:"" + else: + field_list = field_list + [""]*(6-len(field_list)) + # control character are erased: end of line, tab, space + # _____Fields_____ + _record_type = field_list[0] + _codes = self.delete_control_space(field_list[1]) + _path = self.delete_control_space(field_list[2]) + _total = self.delete_control_space(field_list[3]) + _lines = self.delete_control(field_list[4]) + _label = self.delete_control_space(field_list[5]) + # _____Codes_____ + _code_list = _codes.split( "\\" ) + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + if len(_code_list) == 2: + _parent_code = self.validateCode(_code_list[0]) + if _parent_code == "": + _parent_code = None + _child_code = self.validateCode(_code_list[1]) + elif len(_code_list) == 1: + _child_code = self.validateCode(_code_list[0]) + _parent_code = None + else: + print utils.mapping(_("Invalid codes in $1 record, codes $2"), + (_record_type, _codes)) + return + if _child_code == "": + print utils.mapping(_("Empty child code in $1 record, codes: "\ + "$2"), (_record_type, _codes)) + return + # _____Path_____ + # TODO: path=0, no-estructured measures + _path_list = _path.split( "\\" ) + if len(_path_list) > 0: + while _path_list[-1] == "": + _path_list = _path_list[:-1] + _path = _path_list[-1] + try: + _path = int(_path) + except ValueError: + print utils.mapping(_("Invalid path in $1 record, "\ + "codes $2"), (_record_type, _codes)) + return + if _path > 0: + _path -= 1 + else: + _path = 0 + # _____Total_____ + try: + _total = float(_total) + except ValueError: + print utils.mapping(_("Invalid Total Measure value in $1 "\ + "record, codes $2"), (_record_type, _codes)) + return + # _____Measure lines_____ + _lines = _lines.split( "\\" ) + _line_index = 0 + _line_list = [ ] + while _line_index < len(_lines)-6: + _linetype = _lines[_line_index] + if _linetype == "": + _linetype = 0 + elif _linetype == "1" or _linetype == "2" or \ + _linetype == "3": + _linetype = int(_linetype) + else: + _linetype = 0 + _comment= _lines[_line_index + 1] + if _linetype == 3: + # "formula": ".*[^0123456789\.()\+\-\*/\^abcdp ].*" + if self.__pattern["formula"].match(_comment): + print utils.mapping(_("The comment is not a formula or "\ + "its have invalid characters, in the $1 record, "\ + "codes $2"), (_record_type, _codes)) + return + else: + _formula = _comment + _comment = "" + else: + _formula = "" + _units = _lines[_line_index + 2] + _length = _lines[_line_index + 3] + _width = _lines[_line_index + 4] + _height = _lines[_line_index + 5] + try: + if _units != "": _units = float(_units) + if _length != "": _length = float(_length) + if _width != "": _width = float(_width) + if _height != "": _height = float(_height) + except ValueError: + print utils.mapping("The measure values are not float "\ + "numbers, code $1", (_codes,)) + return + _line_list.append([_linetype, _comment, _units, + _length, _width, _height, _formula]) + _line_index = _line_index + 6 + self.__budget.setTree(_parent_code, _child_code, _path, "", "", + _total, _line_list, _label, _record_type) + self.num_valid_record = self.num_valid_record + 1 + + def _parseW(self, field_list): + """_parseW(self, field_list) + + field_list: field list of the record + 0- W: Geografical field + 1- Field Code + 2- Field + """ + # _____Number of fields_____ + # Any INFORMATION after last field separator is ignored + # The record must have 2 fields + if len(field_list) >= 2: + field_list = field_list[1:2] + else: + return + # control character are erased: end of line, tab, space + # _____Fields_____ + _code_fields = field_list[0] + # last \ is erased + if len(_code_fields) and _code_fields[-1] == "\\": + _code_fields = _code_fields[:-1] + _code_fields = _code_fields.split("\\") + _field_dict = {} + _field_index = 0 + while _field_index < len(_code_fields)-1: + # _____subfields_____ + _field_code = _code_fields[_field_index] + _field_title = _code_fields[_field_index+1] + # control character are erased: end of line, tab, space + # _____section_code_____ + #"control": "[\t \n\r]" + _field_code = self.delete_control_space(_field_code) + # _____section_title_____ + if _field_code != "": + _field_dict[_field_code] = _field_title + _field_index = _field_index + 2 + self.__budget.setSheetFields(_field_dict) + self.num_valid_record = self.num_valid_record +1 + + def _parseL(self, field_list): + """_parseL(self, field_list) + + field_list: field list of the record + 0- L: Sheet of Conditions 1 + A: + 1- Empty + 2- {Section Code\Section Title} + B: + 1- Record Code + 2- {Section Code\Section Text} + 3- {Section Code\RTF file} + 4- {Section Code\HTM file} + """ + # _____Number of fields_____ + # The record must have at least 3 fields + if len(field_list) < 3: + return + _code = field_list[1] + if _code == "": + # A: Section Titles + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:3] + # _____Fields_____ + _section_codes = field_list[1] + # last \ is erased + if len(_section_codes) and _section_codes[-1] == "\\": + _section_codes = _section_codes[:-1] + _section_codes = _section_codes.split("\\") + _section_dict = {} + _section_index = 0 + while _section_index < len(_section_codes)-1: + # _____subfields_____ + _section_code = _section_codes[_section_index] + + _section_title = _section_codes[_section_index+1] + # control character are erased: end of line, tab, space + # _____section_code_____ + _section_code = self.delete_control_space(_section_code) + # _____section_title_____ + _section_title = self.delete_control_space(_section_title) + if _section_code != "": + _section_dict[_section_code] = _section_title + _section_index = _section_index + 2 + self.__budget.setSheetSections(_section_dict) + self.num_valid_record = self.num_valid_record +1 + + else: + # Any INFORMATION after last field separator is ignored + # The record must have 5 fields + if len(field_list) > 5: + field_list = field_list[0:5] + field_list = field_list[1:] + # _____Fields_____ + # _____Record Code_____ + _record_code = self.delete_control_space(field_list[0]) + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _record_code = self.validateCode(_record_code) + _scodes_text = field_list[1] + if _scodes_text == "": + # TODO: rtf and html files + print "Html and rtf files not implemented in ~L record" + else: + # _____Section-code_Section-text_____ + # last \ is erased + if len(_scodes_text) and _scodes_text[-1] == "\\": + _scodes_text = _scodes_text[:-1] + _scodes_text = _scodes_text.split("\\") + _paragraph_dict = {} + _section_dict = {} + _section_index = 0 + while _section_index < len(_scodes_text)-1: + # _____subfields_____ + _section_code = _scodes_text[_section_index] + _section_text = _scodes_text[_section_index+1] + # control character are erased: end of line, tab, space + # _____section_code_____ + _section_code = self.delete_control_space(_section_code) + # _____section_text_____ + if _section_code != "" and _section_text != "": + #-# paragraph #-# + _paragraph_code = _record_code + _section_code + "*" + _paragraph_dict[ _paragraph_code ] = _section_text + _section_dict[_section_code] = _paragraph_code + _section_index = _section_index + 2 + self.__budget.setSheetParagraphs(_paragraph_dict) + self.__budget.setSheetRecord(_record_code, "*", _section_dict) + self.num_valid_record = self.num_valid_record +1 + + def _parseQ(self, field_list): + """_parseQ(self, field_list) + + field_list: field list of the record + 0- Q: Sheet of Conditions 2 + 1- Record Code + 2- {Section Code\Paragraph key\{Field key;}\}| + """ + # _____Number of fields_____ + # The record must have at least 3 fields + if len(field_list) < 3: + return + _code = field_list[1] + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:] + # _____Fields_____ + # _____Record Code_____ + _record_code = self.delete_control_space(field_list[0]) + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _record_code = self.validateCode(_record_code) + _scodes_pkey = field_list[1] + # last \ is erased + if len(_scodes_pkey) and _scodes_pkey[-1] == "\\": + _scodes_pkey = _scodes_pkey[:-1] + _scodes_pkey = _scodes_pkey.split("\\") + _field_dict = {} + _section_index = 0 + while _section_index < len(_scodes_pkey) -1: + # _____subfields_____ + _section_code = _scodes_pkey[_section_index] + _paragraph_key = _scodes_text[_section_index+1] + _field_keys = _scodes_text[_section_index+2] + # control character are erased: end of line, tab, space + # _____section_code_____ + _section_code = self.delete_control_space(_section_code) + # _____section_text_____ + _paragraph_key = self.delete_control_space(_paragraph_key) + # _____Fields keys_____ + _field_keys = self.delete_control_space(_field_keys) + # last ; is erased + if len(_field_keys) and _field_keys[-1] == ";": + _field_keys = _field_keys[:-1] + _field_keys_list = _scodes_pkey.split(";") + for _field_key in _field_keys_list: + if _field_key != "" and _section_code != "" and \ + _paragraph_key != "": + if _field_key in _field_dict: + _section_dict = _field_dict[_field_key] + else: + _section_dict = {} + _field_dict[_field_key] = _section_dict + _section_dict[_section_code] = _paragraph_code + _section_index = _section_index + 3 + for _field, _section_dict in _field_dict.iteritems(): + self.__budget.setSheetRecord(_record_code, _field, _section_dict) + self.num_valid_record = self.num_valid_record +1 + + def _parseJ(self, field_list): + """_parseJ(self, field_list) + + field_list: field list of the record + 0- J: Sheet of Conditions 3 + 1- Paragraph code + 2- [Paragraph text] + 3- [RTF file] + 4- [HTML file] + """ + # _____Number of fields_____ + # The record must have at least 3 fields + if len(field_list) < 3: + return + # Any INFORMATION after last field separator is ignored + # The record must have 5 fields + if len(field_list) > 5: + field_list = field_list[0:5] + field_list = field_list[1:] + # _____Fields_____ + # _____Paragraph code_____ + _paragraph_code = self.delete_control_space(field_list[0]) + # _____Paragraph text_____ + _paragraph_text = field_list[1] + if _paragraph_text == "": + # TODO: rtf and html files + print "Html and rtf files not implemented in ~J record" + else: + self.__budget.setSheetParagraph(paragraph_code, paragraph_text) + self.num_valid_record = self.num_valid_record +1 + + def _parseG(self, field_list): + """_parseG(self, field_list) + + field_list: field list of the record + 0- G: Grafic info + 1- record code + 2- <grafic_file.ext\> + """ + # _____Number of fields_____ + # The record must have at least 3 fields + if len(field_list) < 3: + return + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:] + # _____Fields_____ + # _____Record Code_____ + _record_code = self.delete_control_space(field_list[0]) + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _record_code = self.validateCode(_record_code) + # _____Grafic files_____ + _grafic_files = self.delete_control(field_list[1]) + # _____subfields_____ + # last \ is erased + if len(_grafic_files) and _grafic_files[-1] == "\\": + _grafic_files = _grafic_files[:-1] + _grafic_file_list = _grafic_files.split("\\") + _tested_grafic_file_list = [] + for _grafic_file in _grafic_file_list: + _path = os.path.dirname(self.__filename) + _grafic_file_path = os.path.join(_path, _grafic_file) + if os.path.exists(_grafic_file_path): + _tested_grafic_file_list.append(_grafic_file_path) + else: + _name_ext = os.path.splitext(_grafic_file) + _grafic_file_name = _name_ext[0] + _grafic_file_ext = _name_ext[1] + _grafic_file_name_u = _grafic_file_name.upper() + _grafic_file_name_l = _grafic_file_name.lower() + _grafic_file_ext_u = _grafic_file_ext.upper() + _grafic_file_ext_l = _grafic_file_ext.lower() + _uu = _grafic_file_name_u + _grafic_file_ext_u + _ul = _grafic_file_name_u + _grafic_file_ext_l + _lu = _grafic_file_name_l + _grafic_file_ext_u + _ll = _grafic_file_name_l + _grafic_file_ext_l + _grafic_file_path_uu = os.path.join(_path, _uu) + _grafic_file_path_ul = os.path.join(_path, _ul) + _grafic_file_path_lu = os.path.join(_path, _lu) + _grafic_file_path_ll = os.path.join(_path, _ll) + if os.path.exists(_grafic_file_path_uu): + _tested_grafic_file_list.append(_grafic_file_path_uu) + elif os.path.exists(_grafic_file_path_ul): + _tested_grafic_file_list.append(_grafic_file_path_ul) + elif os.path.exists(_grafic_file_path_lu): + _tested_grafic_file_list.append(_grafic_file_path_lu) + elif os.path.exists(_grafic_file_path_ll): + _tested_grafic_file_list.append(_grafic_file_path_ll) + else: + print utils.mapping(_("The file $1 do not exist"), + (_grafic_file_path,)) + if len(_grafic_file_list) > 0: + for _grafic_file in _tested_grafic_file_list: + self.__budget.addFile(_record_code, _grafic_file, "img", "") + self.num_valid_record = self.num_valid_record +1 + + def _parseE(self, field_list): + """_parseE(self, field_list) + + field_list: field list of the record + 0- E: Company + 1- company Code + 2 [ summary ] + 3- [ name ] + 4- { [ type ] \ [ subname ] \ [ address ] \ [ postal_code ] + \ [ town ] \ [ province ] \ [ country ] \ { phone; } + \ { fax; } \ {contact_person; } \ } + 5- [ cif ] \ [ web ] \ [ email ] \ + """ + + # _____Number of fields_____ + # Any INFORMATION after last field separator is ignored + # The record must have 6 fields + if len(field_list) > 6: + field_list = field_list[1:6] + # If there are no sufficient fields, the fields are added + # with empty value:"" + else: + field_list = field_list[1:] + [""]*(6-len(field_list)) + # _____Fields_____ + # _____company Code_____ + _company_code = self.delete_control_space(field_list[0]) + if _company_code == "": + return + # _____Summary_____ + + _sumamary = self.delete_control(field_list[1]) + # _____Name_____ + _name = self.delete_control(field_list[2]) + # _____local_offices_____ + _local_offices = self.delete_control(field_list[3]) + # _____subfields of local_offices_____ + # last \ is erased + if len(_local_offices) and _local_offices[-1] == "\\": + _local_offices = _local_offices[:-1] + _local_offices_list = _local_offices.split("\\") + # If there are no sufficent subfields, the subfields are added + # whith empty value + _nsub = len(_local_offices_list) % 10 + if _nsub != 0: + _local_offices_list = _local_offices_list + \ + [""]*(10-len(field_list)) + _local_offices = [] + _local_offices_index = 0 + while _local_offices_index < len(_local_offices_list)-9: + # _____subfields_____ + _type = _local_offices_list[_local_offices_index] + _subname = _local_offices_list[_local_offices_index+1] + _address = _local_offices_list[_local_offices_index+2] + _postal_code = _local_offices_list[_local_offices_index+3] + _town = _local_offices_list[_local_offices_index+4] + _province = _local_offices_list[_local_offices_index+5] + _country = _local_offices_list[_local_offices_index+6] + _phone = _local_offices_list[_local_offices_index+7] + # last ; is erased + if len(_phone) and _phone[-1] == ";": + _phone = _phone[:-1] + _phone_list = _phone.split(";") + _fax = _local_offices_list[_local_offices_index+8] + # last ; is erased + if len(_fax) and _fax[-1] == ";": + _fax = _fax[:-1] + _fax_list = _fax.split(";") + _contact_person = _local_offices_list[_local_offices_index+9] + if _type != "" or _subname != "" or _address != "" or \ + _postal_code != "" or _town != "" or _province != "" or \ + _country != "" or _phone != "" or _fax != "" or \ + _contact_person != "": + _local_offices.append([_type, _subname, _address, + _postal_code, _town, _province, + _country, _phone_list, _fax_list, + _contact_person]) + _local_offices_index = _local_offices_index + 10 + # _____cif web email_____ + _c_w_e = self.delete_control_space(field_list[4]) + # last \ is erased + if len(_c_w_e) and _c_w_e[-1] == "\\": + _c_w_e = _c_w_e[:-1] + _c_w_e_list = _c_w_e.split("\\") + # _____subfields_____ + # If there are no sufficient fields, the fields are added + # with empty value:"" + _c_w_e_list = _c_w_e_list + [""]*(3-len(_c_w_e_list)) + _cif = _c_w_e_list[0] + _web = _c_w_e_list[1] + _email = _c_w_e_list[2] + self.__budget.setCompany(_company_code, _sumamary, _name, + _local_offices, _cif, _web, _email) + self.num_valid_record = self.num_valid_record +1 + + def _parseX(self, field_list): + """_parseX(self, field_list) + + field_list: field list of the record + A) + 0- X: Tecnical information + 1- Empty + 2- < TI_Code \ TI_Descitption \ TI_Unit > + B) + 0- X: Tecnical information + 1- Record_code + 2- < TI_Code \ TI_value > + """ + # Tecnical information + # The record must have at least 3 fields + if len(field_list) < 3: + return + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:] + # _____Fields_____ + # "control": "[\t \n\r]" + _field_1 = self.delete_control_space(field_list[0]) + _field_2 = self.delete_control_space(field_list[1]) + if _field_1 == "": + # A) + _field_2_list = _field_2.split("\\") + _ti_index = 0 + while _ti_index < len(_field_2_list)-3: + _ti_code = _field_2_list[_ti_index] + _ti_description = _field_2_list[_ti_index+1] + _ti_unit = _field_2_list[_ti_index+2] + if _ti_code != "": + self.__budget.addTecInfo(_ti_code, _ti_description, + _ti_unit) + _ti_index = _ti_index + 3 + else: + # B) + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _record_code = self.validateCode(_field_1) + _field_2_list = _field_2.split("\\") + _ti_index = 0 + _ti_dict = {} + while _ti_index < len(_field_2_list)-2: + _ti_code = _field_2_list[_ti_index] + _ti_value = _field_2_list[_ti_index+1] + if _ti_code != "" and _ty_value != "": + _ti_dict[_ti_code] = _ty_value + _ti_index = _ti_index + 2 + self.__budget.setTecnicalInformation(_record_code, _ti_dict) + self.num_valid_record = self.num_valid_record +1 + + def _parseF(self, field_list): + """_parseF(self, field_list) + + field_list: field list of the record + 0- F: Files + 1- Record code + 2- { Type \ { Filenames; } \ [Description] } + """ + + # _____Number of fields_____ + # The record must have at least 3 fields + if len(field_list) < 3: + return + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:] + # _____Fields_____ + # _____Record Code_____ + _record_code = self.delete_control_space(field_list[0]) + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _record_code = self.validateCode(_record_code) + # _____Grafic files_____ + _files = self.delete_control(field_list[1]) + # _____subfields_____ + # last \ is erased + if len(_files) and _files[-1] == "\\": + _files = _files[:-1] + _files_list = _files.split("\\") + # adding empty subfiels if necesary + if len(_files_list)%3 > 0: + _files_list.extend[""]*(3 - len(_files_list)%3) + _file_index = 0 + _tested_files_list = [] + while _file_index < len(_files_list)-3: + _type = _files_list[_file_index].replace(" ","") +## _types = { +## "0": _("others"), +## "1": _("características técnicas y de fabricación"), +## "2": _("manual de colocación, uso y mantenimiento"), +## "3": _("certificado/s de elementos y sistemas"), +## "4": _("normativa y bibliografía"), +## "5": _("tarifa de precios"), +## "6": _("condiciones de venta"), +## "7": _("carta de colores"), +## "8": _("ámbito de aplicación y criterios selección"), +## "9": _("cálculo de elementos y sistemas"), +## "10": _("presentación, datos generales, objetivos, etc. de "\ +## "empresa"), +## "11": _("certificado/s de empresa"), +## "12": _("obras realizadas")} + _types = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12"] + if not _type in _types: + _type = "0" + _filenames = _files_list[_file_index + 1] + _description = _files_list[_file_index + 2] + _file_index += 3 + if len(_filenames) and _filenames[-1] == ";": + _files = _files[:-1] + _filenames_list = _files.split(";") + _path = os.path.dirname(self.__filename) + for _filename in filenames_list: + _file_path = os.path.join(_path, _filename) + if os.path.exists(_file_path): + _tested_files_list.append([_file_path, _type, + _description]) + else: + _name_ext = os.path.splitext(_filename) + _file_name = _name_ext[0] + _file_ext = _name_ext[1] + _file_name_u = _file_name.upper() + _file_name_l = _file_name.lower() + _file_ext_u = _file_ext.upper() + _file_ext_l = _file_ext.lower() + _uu = _file_name_u + _file_ext_u + _ul = _file_name_u + _file_ext_l + _lu = _file_name_l + _file_ext_u + _ll = _file_name_l + _file_ext_l + _file_path_uu = os.path.join(_path, _uu) + _file_path_ul = os.path.join(_path, _ul) + _file_path_lu = os.path.join(_path, _lu) + _file_path_ll = os.path.join(_path, _ll) + if os.path.exists(_file_path_uu): + _tested_files_list.append([_file_path_uu, _type, + _description]) + elif os.path.exists(_grafic_file_path_ul): + _tested_files_list.append([_file_path_ul, _type, + _description]) + elif os.path.exists(_grafic_file_path_lu): + _tested_files_list.append([_file_path_lu, _type, + _description]) + elif os.path.exists(_grafic_file_path_ll): + _tested_files_list.append([_file_path_ll, _type, + _description]) + else: + print utils.mapping(_("The file $1 do not exist"), + (_file_path,)) + if len(_tested_files_list) > 0: + for _file in _tested_file_list: + self.__budget.addFile(_record_code, _file[0], file[1], file[2]) + self.num_valid_record = self.num_valid_record +1 + + def _parseB(self, field_list): + """_parseB(self, field_list) + + field_list: field list of the record + 0- B: Change code + 1- Record Code + 2- New code + """ + # _____Number of fields_____ + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:] + if len(field_list) != 2: + return + # control character are erased: end of line, tab, space + # _____Fields_____ + _code = self.delete_control_space(field_list[0]) + _new_code = self.delete_control_space(field_list[1]) + # _____Codes_____ + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _code = self.validateCode(_code) + _new_code = self.validateCode(_new_code) + # change code + self.__budget.changeCode(_code, _new_code) + self.num_valid_record = self.num_valid_record + 1 + + def _parseA(self, field_list): + """_parseA(self, field_list) + + field_list: field list of the record + 0- A: Labels + 1- Record Code + 2- <Label\> + """ + # _____Number of fields_____ + # Any INFORMATION after last field separator is ignored + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:] + if len(field_list) != 2: + return + # control character are erased: end of line, tab, space + # _____Fields_____ + # "control": "[\t \n\r]" + _code = self.delete_control_space(field_list[0]) + _labels = self.delete_control_space(field_list[1]) + # _____Codes_____ + # "#" and "##" characters at the end of the code are erased + # invalid characters are also erased + _code = self.validateCode(_code) + # _____Labels_____ + # last \ is erased + # TODO: change the others parsers to this: + while len(_labels) > 0 and _labels[-1] == "\\": + _labels = _labels[:-1] + # replace "_" to " " + _labels = _labels.replace("_"," ") + _label_list = _labels.split("\\") + for _label in _label_list: + self.__budget.addLabel(_code, _label) + self.num_valid_record = self.num_valid_record + 1 + + def _parseP(self, field_list): + """_parseP(self, field_list) + + field_list: Parametric record + A) Global paremetric record + 0- P: Parametric + 1- Empty + 2- [Parametric description] + 3- [library.DLL] + B) Family Parametric record + 0- P: Parametric + 1- Family Code + 2- [Parametric description] + """ + # TODO: Use global parametric record + if len(field_list) > 2: + # delete control caracters and spaces + _family_code = self.delete_control_space(field_list[1]) + if _family_code == "": # A)Global paremetric record + # The record must have 3 or 4 fields + if len(field_list) > 4: + field_list = field_list[0:4] + field_list = field_list[1:] + if len(field_list) == 2: + field_list.append("") + if len(field_list) != 3: + return + else: # B)Family Parametric record + # The record must have 3 fields + if len(field_list) > 3: + field_list = field_list[0:3] + field_list = field_list[1:] + if len(field_list) != 2: + print _("PyArq hates parametric DLLs") + return + else: + return + # _____Description_____ + _description = field_list[1] + if _description == "": + print _("PyArq hates parametric DLLs") + return + # Adding last end of line + _description = _description + "\r\n" + # Delete comments + # "comment" : "#.*\r\n" + _description = self.__pattern["comment"].sub("\r\n",_description) + # Tabs to spaces + _description = _description.replace("\t"," ") + # Delete empty lines + # "empty_line": r"(\r\n) *\r\n" + while self.__pattern["empty_line"].search(_description): + _description = self.__pattern["empty_line"].sub( + lambda x: x.groups()[0], _description) + # Delete spaces before and after / + # "space_before_backslash" : r"( )+\\" + _description = self.__pattern["space_before_backslash"].sub( + r"\\",_description) + # "space_after_backslash" : r"\\( )+" + _description = self.__pattern["space_after_backslash"].sub( + r"\\",_description) + # Join lines that start but not end with / + _description = "\r\n" + _description # add leading end of line + # "start_noend_backslash": "(\r\n\\\.*[^\\\])\r\n" + while self.__pattern["start_noend_backslash"].search(_description): + _description = self.__pattern["start_noend_backslash"].sub( + lambda x: x.groups()[0], _description) + # Join lines that end with a + - * / ^ and @ & < > <= >= = <> ! + # "end_oper" : "(\+|-|\*|/|/^|@|&|<|>|<=|>=|=|!) *\r\n" + _description = self.__pattern["end_oper"].sub( + lambda x: x.groups()[0], _description) + # Join lines for matricial vars + # matricial_var : "(\r\n *[%|\$][A-ZÑ].*=.*,) *\r\n" + while self.__pattern["matricial_var"].search(_description): + _description = self.__pattern["matricial_var"].sub( + lambda x: x.groups()[0], _description) + _description = _description[2:] # remove leading end of line + #_description = re.sub(r"\\( )+",r"\\",_description) + _lines = _description.split("\r\n") + _final_description = "" + _pass_line = 0 + for index in range(len(_lines)): + _line = _lines[index] + # Parse lines + if len(_line) != 0: # Delete empty lines + if _pass_line > 0: + _pass_line = _pass_line -1 + _line = "" + elif _line.isspace(): + _line = "" + elif _line[0] != "\\": + # Delete spaces out "" delimiter + _list = _line.split('"') + _final_line = "" + for index1 in range(len(_list)): + if index1 % 2 != 0: + _parcial_line = '"' + _list[index1] + else: + _parcial_line = '"' + _list[index1].replace(" ","") + _final_line = _final_line + _parcial_line + _line = _final_line[1:] + _lines[index] = _line + # parse data + if len(_line) > 2 and _line[:2] == "::": + # Delete spaces out " delimiter + #print "__PRECIO__" + _line[2:] + pass + elif len(_line) > 2 and _line[:2] == "%:": + # Delete spaces out " delimiter + #print "__%AUX__" + _line[2:] + pass + elif len(_line) > 3 and _line[:2] == "%%:": + # Delete spaces out " delimiter + #print "__%%AUX__" + _line[2:] + pass + elif self.__pattern["var"].search(_line): + # Delete spaces out " delimiter + #print "line =", _line + while _line.count('"') % 2 == 1 and \ + index + _pass_line + 1 < len(_lines) -1: + _line = _line + _lines[index + _pass_line + 1] + _pass_line = _pass_line + 1 + _search = self.__pattern["var"].search(_line) + if _search is not None: + _var = _search.groups()[0] + " = " + _search.groups()[1] + #print "__VAR__" + str(_var) + pass + else: + #print "no __VAR__", _line + pass + elif self.__pattern["descomposition"].search(_line): + # Delete spaces out " delimiter + #_patern = "(^[^:]*):(.*)$" + _search = self.__pattern["descomposition"].search(_line) + if _search is not None: + _var = _search.groups()[0] + ":" + _search.groups()[1] + #print "__Descomposición__" + str(_var) + pass + else: + #print "no __Descomposición__", _line + pass + else: + print "Parametric: code: " + _family_code + print "******* Desconocido *** : " + _line + if index-10 > 0: print "-11 :", _lines[index-11] + if index-10 > 0: print "-10 :", _lines[index-10] + if index-9 > 0: print "-9 :", _lines[index-9] + if index-8 > 0: print "-8 :", _lines[index-8] + if index-7 > 0: print "-7 :", _lines[index-7] + if index-6 > 0: print "-6 :", _lines[index-6] + if index-5 > 0: print "-5 :", _lines[index-5] + if index-4 > 0: print "-4 :", _lines[index-4] + if index-3 > 0: print "-3 :", _lines[index-3] + if index-2 > 0: print "-2 :", _lines[index-2] + if index-1 > 0: print "-1 :", _lines[index-1] + print "-0 :", _lines[index-0] + pass + else: + _parameter_list = _line.split("\\")[1:-1] + if len(_parameter_list) >= 2: + if _parameter_list[0] == "C" or \ + _parameter_list[0] == "COMENTARIO": + #print "__COMENTARIO__" + _parameter_list[1] + self.__budget.setParametricSelectComment( + _family_code, _parameter_list[1]) + elif _parameter_list[0] == "R" or \ + _parameter_list[0] == "RESUMEN": + #print "__RESUMEN__" + _parameter_list[1] + self.__budget.setParametricSummary(_family_code, + _parameter_list[1]) + elif _parameter_list[0] == "T" or \ + _parameter_list[0] == "TEXTO": + #print "__TEXTO__" + _parameter_list[1] + self.__budget.setParametricText(_family_code, + _parameter_list[1]) + elif _parameter_list[0] == "P" or \ + _parameter_list[0] == "PLIEGO": + #print "__PLIEGO__" + str(_parameter_list[1:]) + pass + elif _parameter_list[0] == "K" or \ + _parameter_list[0] == "CLAVES": + #print "__CLAVES__" + str(_parameter_list[1:]) + pass + elif _parameter_list[0] == "F" or \ + _parameter_list[0] == "COMERCIAL": + #print "__COMERCIAL__" + str(_parameter_list[1:]) + pass + else: + #print "==PARAMETRO==" + str(_parameter_list[:]) + pass + _final_description = _final_description + _line + "\r\n" + + #print _line + # Delete last empty line + _description = _final_description[:-2] + _lines = _description.split("\r\n") + for _line in _lines: + pass + #print _line + self.num_valid_record = self.num_valid_record + 1 + + def readFile(self, budget=None, filename=None, interface=None): + """readFile(self, budget=None, filename=None) + + filename: the filename of the fiebdc file + budget: base.obra object + interface: a object to send messages + must have printf(message) progress(percent) + recordStatistics(...) + Return the budget objetc or None if the file can be readed + """ + if filename != None and budget != None: + self.__filename = filename + self.__budget = budget + self.__budget.filename = self.__filename + if self.__filename is None or self.__budget is None or \ + self.__cancel == True: + return None + if not os.path.exists(self.__filename): + return None + _time = time.time() + try: + _file = open(self.__filename, 'r') + except IOError: + print utils.mapping("IOError: $1", (self.__filename,)) + return None + self.__budget.filename = self.__filename + self._record_number = 0 + self.num_valid_record = 0 + self._record_V_number = 0 + self._record_C_number = 0 + self._record_D_number = 0 + self._record_Y_number = 0 + self._record_M_number = 0 + self._record_N_number = 0 + self._record_T_number = 0 + self._record_K_number = 0 + self._record_W_number = 0 + self._record_L_number = 0 + self._record_Q_number = 0 + self._record_J_number = 0 + self._record_G_number = 0 + self._record_E_number = 0 + self._record_O_number = 0 + self._record_P_number = 0 + self._record_X_number = 0 + self._record_B_number = 0 + self._record_F_number = 0 + self._record_A_number = 0 + self._record_Unknow_number = 0 + print utils.mapping(_("Loading file $1"), (self.__filename,)) + _filesize = float(os.path.getsize(self.__filename)) + interface.progress(_file.tell() / _filesize) + _buffer = _file.read(1000) + # set codepage from V record + _record_list = _buffer.split("~") + registro_V = _record_list[1] + # ~V|[PROPIEDAD_ARCHIVO]|VERSION_FORMATO[\DDMMAAAA]|[PROGRAMA_EMISION]| + # [CABECERA]\{ ROTULO_IDENTIFICACION \}|[JUEGO_CARACTERES]| + # [COMENTARIO]|[TIPO INFORMACIÓN]|[NÚMERO CERTIFICACIÓN]| + # [FECHA CERTIFICACIÓN ] | + registro_V = registro_V.split("|") + if registro_V[0] == "V": + #_codepage = registro_V[5] + if len(registro_V) > 5: + _version = registro_V[5].strip() + # remove leading spaces + if _version in self.__character_sets_dict: + self.__character_set = self.__character_sets_dict[_version] + else: + print utils.mapping(_("This codepage do not exist in "\ + "FIEBDC3! Default codepage: $1"), + (self.__character_set,)) + else: + print utils.mapping(_("This V record dot have a codepage! "\ + "Default codepage: $1"), + (self.__character_set,)) + else: + print utils.mapping(_("Not 'V' record in File! Default codepage: "\ + "$1"), (self.__character_set,)) + if self.__character_set != "utf8": + _buffer = unicode(_buffer, self.__character_set) + _buffer = _buffer.encode("utf8") + # Any INFORMATION between the beginning of the file and the + # beginning of the first registry “~” is ignored + #"after_first_tilde" : "^[^~]*~" + _buffer = self.__pattern["after_first_tilde"].sub("",_buffer) + while _buffer != "" and self.__cancel != True: + #-# the blank characters (32), tabs (9) and end of line (13 and 10) + # before the separators '~', '|' are erased. + # Before separator \ not deleted because it affects the reading of + # the record ~P + _buffer = self.eraseControlCharacters(_buffer) + _record_list = _buffer.split("~") + # The last record can be incomplete unless it is the last one of + # the file + if len(_record_list) > 1: + # not the end + _last_record = _record_list.pop() + else: + # the end record + # The blank characters (32), tabs (9) and end of line + # (13 and 10) at the end of the file are ignored. + #"end_control" : "((\r\n)| |\t)+$" + _record_list[-1] = self.__pattern["end_control"].sub("", + _record_list[-1]) + _last_record = "" + for record in _record_list: + if self.__cancel == True: + break + self.parseRecord(record) + interface.progress(_file.tell() / _filesize) + _buffer2 = _file.read(100000) + if self.__character_set != "utf8": + _buffer2 = unicode(_buffer2, self.__character_set) + _buffer2 = _buffer2.encode("utf8") + _buffer = _last_record + _buffer2 + _file.close() + if self.__cancel == True: + print _("Cancelled process") + return None + else: + print utils.mapping(_("Time to load: $1 seconds"), + (("%.2f" %(time.time()-_time)),)) + print utils.mapping(_("Records/Valid Records: $1/$2"), + (self._record_number, self.num_valid_record)) + if self._record_O_number > 0: + print utils.mapping(_("$1 unsuported record type O: "\ + "Comercial Relationship"), (self._record_O_number,)) + if self.num_valid_record == 0: + print _("This file is not a valid FIBDC3 file") + return None + _str = "" + for type in \ + [("V", self._record_V_number), + ("C", self._record_C_number), + ("D", self._record_D_number), + ("Y", self._record_Y_number), + ("M", self._record_M_number), + ("N", self._record_N_number), + ("T", self._record_T_number), + ("K", self._record_K_number), + ("W", self._record_W_number), + ("L", self._record_L_number), + ("Q", self._record_Q_number), + ("J", self._record_J_number), + ("G", self._record_G_number), + ("E", self._record_E_number), + ("O", self._record_O_number), + ("P", self._record_P_number), + ("X", self._record_X_number), + ("B", self._record_B_number), + ("F", self._record_F_number), + ("A", self._record_A_number), + ("?", self._record_Unknow_number)]: + _str = _str + "%s: %s\n" %(type[0], type[1]) + print _str + self._testBudget(self.__budget) + return self.__budget + + def _testBudget(self, budget): + """testBudget(self,budget) + + budget: base.obra object + Test and repair budget object after read it from bc3 file + """ + # TODO: more to do here + print _("Testing budget ...") + # Add price to records without price + _iter = budget.iter() + _titlelist = budget.getTitleList()[1] + if len(_titlelist) == 0: + _titlenum = 1 + else: + _titlenum = len(_titlelist) + for _code in _iter: + _record = budget.getRecord(_code) + _prices = _record.getPrices() + _len_prices = len(_prices) + if _titlenum > _len_prices: + _leftprices = _titlenum - _len_prices + for _index in range(0,_leftprices): + _root = budget.getRecord(budget.getRoot()) + _price = [0.0, _root.getDate(_len_prices + _index)] + budget.addPriceToRecord(_price,_record) + print _("End Test") + + def delete_control_space(self, text): + text = self.delete_control(text) + text = text.replace(" ", "") + return text + + def delete_control(self, text): + text = text.replace("\t", "") + text = text.replace("\r", "") + text = text.replace("\n", "") + return text
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Generic/globals.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,94 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File globals.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. + +# module for global variables +import os +# path: Paths where find the program files needed + +version = "pyArq-Presupuestos v0.0.0" +path = { + "HOME" : "", + "APPDATA" : "", + "ICON" : "/images/pyArq-Presupuestos.svg", + "CHAPTER-ICON" : "/images/chapter.svg", + "UNIT-ICON" : "/images/unit.svg", + "MATERIAL-ICON" : "/images/material.svg", + "MACHINERY-ICON" : "/images/machinery.svg", + "LABOURFORCE-ICON": "/images/labourforce.svg", + "MENU-ICON": "/images/menu.svg", + "CONNECTED-ICON": "/images/connected.svg", + "DISCONNECTED-ICON": "/images/disconnected.svg", + "CLOSE-ICON": "/images/close.svg", + "DESCRIPTION-ICON": "/images/description.svg", + "SHEET-ICON": "/images/sheet.svg", + "DECOMPOSITION-ICON" : "/images/decomposition.svg", + "MEASURE-ICON" : "/images/measure.svg", + "ACUMULATEDLINE-ICON" : "/images/acumulatedline.svg", + "PARCIALLINE-ICON" : "/images/parcialline.svg", + "NORMALLINE-ICON" : "/images/normalline.svg", + "CALCULATEDLINE-ICON" : "/images/calculatedline.svg", + "ARROW-ICON": "/images/arrow.svg", + "IMAGE-ICON": "/images/image.svg", + "DXF-ICON": "/images/dxf.svg", + "DURUS-DATABASE": "/pyArq-Presupuestos/durus/", + "BUDGET": "/pyArq-Presupuestos/budget/", + "THROBBER-ICON": "/images/throbber.png", + "THROBBER-GIF": "/images/throbber.gif", + "BUDGET-ICON": "/images/budget.svg", + "PYARQ-ICON": "/images/pyArq.png", + } + +color = { + "ACTIVE" : "#CDD7FF", # blue + "INDEX-EVEN" : "#C4C4C4", # dark grey + "INDEX-UNEVEN" : "#DDDDDD", # grey + "EVEN" : "#E6E6E6", # dark white + "UNEVEN": "#FFFFFF", # white + "CHAPTER-EVEN": "#D8E6E6", # dark cian + "CHAPTER-UNEVEN": "#F0FFFF", # cian + "TEXT": "#000000", # black + "CALCULATED-TEXT": "#FF00FF", # + "SUBTOTAL": "#FAC8C8", + "SUBTOTAL-PARCIAL": "#ADD8E6", + } +desktop = { + "autodetect" : True, + "desktop" : "", + "browser" : "firefox", + "mailapp" : "evolution", + "imageapp" : "gthumb", + "cadapp" : "qcad", + } + +def getAppPath(key): + return path["APPDATA"] + path[key] +def getHomePath(key): + return path["HOME"] + path[key] +if os.name == 'posix': + path["HOME"] = os.environ.get('HOME') +elif sys.platform == 'win32': + path["HOME"] = os.environ.get('HOMEPATH') + # TODO: Mac Os, + # TODO: Test in diferents os + +#-# +path["BUDGET"] = "/pyArq-Presupuestos/" +#-#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Generic/openwith.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,137 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File openwith.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## This file is based in gtkgui_helpers.py and common/helpers.py from gajim +## +## Copyright (C) 2003-2008 Yann Leboulanger <asterix AT lagaule.org> +## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com> +## Nikos Kouremenos <kourem AT gmail.com> +## Copyright (C) 2006 Alex Mauer <hawke AT hawkesnest.net> +## Copyright (C) 2006-2007 Travis Shirk <travis AT pobox.com> +## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org> +## Copyright (C) 2007 Lukas Petrovicky <lukas AT petrovicky.net> +## James Newton <redshodan AT gmail.com> +## Julien Pivotto <roidelapluie AT gmail.com> +## Copyright (C) 2007-2008 Stephan Erb <steve-e AT h3c.de> +## Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com> +## Jonathan Schleifer <js-gajim AT webkeks.org> +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## 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 Gajim. If not, see <http://www.gnu.org/licenses/>. +## +# Modules +import subprocess +import os + +# pyArq-Presupuestos modules +import globals + +# from gtkgui_helpers.py +def autodetect_desktop(): + # recognize the environment and sets it in globals + if os.name == 'nt': + globals.desktop["desktop"] = "windows" + else: + _processes = get_running_processes() + if 'gnome-session' in _processes: + globals.desktop["desktop"] = "gnome" + elif 'startkde' in _processes: + globals.desktop["desktop"] = "kde" + elif 'startxfce4' in _processes or 'xfce4-session' in _processes: + globals.desktop["desktop"] = "xfce" + else: + globals.desktop["desktop"] = "" + +def get_running_processes(): + '''returns running processes or None (if not /proc exists)''' + if os.path.isdir('/proc'): + # under Linux: checking if 'gnome-session' or + # 'startkde' programs were run before gajim, by + # checking /proc (if it exists) + # + # if something is unclear, read `man proc`; + # if /proc exists, directories that have only numbers + # in their names contain data about processes. + # /proc/[xxx]/exe is a symlink to executable started + # as process number [xxx]. + # filter out everything that we are not interested in: + files = os.listdir('/proc') + + # files that doesn't have only digits in names... + files = filter(str.isdigit, files) + + # files that aren't directories... + files = [f for f in files if os.path.isdir('/proc/' + f)] + + # processes owned by somebody not running gajim... + # (we check if we have access to that file) + files = [f for f in files if os.access('/proc/' + f +'/exe', os.F_OK)] + + # be sure that /proc/[number]/exe is really a symlink + # to avoid TBs in incorrectly configured systems + files = [f for f in files if os.path.islink('/proc/' + f + '/exe')] + + # list of processes + processes = [os.path.basename(os.readlink('/proc/' + f +'/exe')) for f in files] + + return processes + return [] + +# from common/helpers.py + +def exec_command(command): + subprocess.Popen('%s &' % command, shell=True).wait() + +def build_command(executable, parameter): + # we add to the parameter (can hold path with spaces) + # "" so we have good parsing from shell + parameter = parameter.replace('"', '\\"') # but first escape " + command = '%s "%s"' % (executable, parameter) + return command + +def launch_file(kind, uri): + # kind = "url" ,"mail", "image", "dxf" + _desktop = globals.desktop["desktop"] + if _desktop == "windows": + try: + os.startfile(uri) # if pywin32 is installed we open + except Exception: + pass + else: + if kind == 'mail' and not uri.startswith('mailto:'): + uri = 'mailto:' + uri + if _desktop == "gnome": + command = 'gnome-open' + elif _desktop == "kde": + command = 'kfmclient exec' + elif _desktop == "xfce": + command = 'exo-open' + else: + if kind == 'url': + command = globals.desktop["browser"] + elif kind == 'mail': + command = globals.desktop["mailapp"] + elif kind == 'image': + command = globals.desktop["imageapp"] + elif kind == 'dxf': + command = globals.desktop["cadapp"] + else: # if no app is configured + return + command = build_command(command, uri) + try: + exec_command(command) + except Exception: + pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Generic/utils.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,165 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File utils.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. + +# Modules +import re +import imghdr + +# add wmf to imghdr +def test_wmf(h, f): + """wmf image library""" + if h[:6] == "\xd7\xcd\xc6\x9a\x00\x00": + return 'wmf' +imghdr.tests.append(test_wmf) + +# add dxf to imghdr +def test_dxf(h, f): + """AutoCAD DXF: Drawing Interchange Format""" + if isinstance(f,file): + _pos = f.tell() + f.seek(0) + _h = f.read(128) + f.seek(-32, 2) + _l = f.read(32) + f.seek(_pos) + else: + _h = h + _l = h[-32:] + _h = _h.replace("\r","") + _l = _l.replace("\r","") + if (" 0\nSECTION\n 2\nHEADER\n" in _h or\ + " 0\nSECTION\n 2\nCLASSES\n" in _h or\ + " 0\nSECTION\n 2\nTABLES\n" in _h or\ + " 0\nSECTION\n 2\nBLOCKS\n" in _h or\ + " 0\nSECTION\n 2\nENTITIES\n" in _h or\ + " 0\nSECTION\n 2\nOBJECTS\n" in _h or\ + " 0\nSECTION\n 2\nTHUMBNAILIMAGE\n" in _h) and \ + _l[-19:] == " 0\nENDSEC\n 0\nEOF\n": + return 'dxf' +imghdr.tests.append(test_dxf) + + +def mapping(string, tuple): + """mapping(string, tuple) + + string: a message string + tuple: a truple with string items + Return the string replacing the $[n] words whith its corresponding value + from the tuple. + It is used because the gettext module can not #-#supotr#-# strings as: + "Invalid type (%s) in record: %s" %(type, record) + """ + for _index in range(len(tuple)): + string = string.replace("$" + str(_index+1), str(tuple[_index])) + return string + +def eliminate_duplicates(list): + """eliminate_duplicates(list) + + Return a copy of the list without duplicate values + """ + _result = [ ] + for item in list: + if item not in _result: + _result.append(item) + return _result + +def is_valid_code(code): + """is_valid_code(code) + + code: a string code + Funtion to test if a record code is valid + A valid code must fulfill: + - Be a not empty string + - The valid characters are the defined in MSdos 6.0 including .$#%&_ + What it means? I am not sure, so I test if all the character + are in cp850 + - Cannot contain the following characters + <~> separator of records if FIEBDC-3 + <|> separator of fields if FIEBDC-3 + <\> separator of subfield in FIEBDC-3 + <\t> tab -> control character + < > space -> control character + <\n> end of line -> control character + <\r> end of line -> control character + - Cannot end with <#> or <##>, root and chapter code record + It return a tuple (is_valid, code) + is_valid (True/False) + True: the code is valid + False: the code is not valid + code(False/code) + False: the code is not valid and can not be corrected + code: the code or the corrected code + """ + _is_valid = True + if not isinstance(code, str): + return False, False + if code == "": + return False, False + try: + _unicode_code = unicode(code, "utf8") + _code_cp850 = _unicode_code.encode("cp850") + _unicode_code = unicode(_code_cp850, "cp850") + _code_utf8 = _unicode_code.encode("utf8") + except UnicodeError: + return False, False + if _code_utf8 != code: + _is_valid = False + if _code_utf8 == "": + return False, False + code = _code_utf8 + _code2 = re.sub("[\t \n\r~|\\\]","",code) + if _code2 != code: + if _code2 == "": + return False, False + _is_valid = False + code = _code2 + if code[-1] == "#": + _is_valid = False + while code[-1] == "#": + code = code[:-1] + if code == "": + return False, False + return _is_valid, code + +def getFiletype(filename, h=None): + """getFiletype(filename, h=None): + + filename: the filename to test + h: raw string, if h is not None the filename is ignored and h is assumed + to contain the byte stream to test + """ + _type = imghdr.what(filename, h) + _image_types = ["rgb", "gif", "pbm", "pgm", "ppm", "tiff", "rast", "xbm", + "jpeg", "bmp", "png", "wmf"] + if _type in _image_types: + return "image" + elif _type == "dxf": + return "dxf" +## _video_types = ["avi", "mpg", "mkv", "ogm"] +## elif _type in _video_types: +## return "video" +## elif _type == "pdf": +## return "pdf" +## elif _type == "ppt" or _type == "odp": +## return "presentation" + else: + return None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Gtk/__init__.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +## +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. +# +# define __all__ so 'from Gtk import *' works +# +__all__ = [ + 'gui', + 'importFiebdc', + ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Gtk/gui.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,4509 @@ +# -*- coding: utf-8 -*- +## File gui.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. +## + +"""Gui module + +The MainWindow class contain the toplevel WINDOW, +this window have a notebook with a page for each budget. +Each budget or notebook page is showed by the Page class, this class contain +the main widget showed in a page notebook. +The main widget can show the budget information in several panes. +This panes are ordened in gtk.Paned represented for the class Paned which can +have 2 viewes represented for the View class or other gtk.Paned that have other +viewes or more gtk.Paned. +The view can have diferente type of widgets to show the budget information. +The DecompositionList class show the decompositon list information of a record +The Measure class show de measure information of a record +The TextWindow class show the long description of a record +The Sheet class class show the sheet of condition information of a record + +The views can send signal to the others. +All the viewes ordered in panes can be or not be connected to the others, +if there are connecteded to the others when the user change the active code in +one of the panes the active code change in the others. + +""" +# TODO: Config file + +# Standar Modules +import os +import time +import pygtk +pygtk.require('2.0') +import gtk +import gobject +import weakref + +# pyArq-Presupuestos Modules +from Gtk import importFiebdc +from Generic import base +from Generic import fiebdc +from Generic import durusdatabase +from Generic import utils +from Generic import globals +from Generic import openwith + +# Load default icon +if os.path.exists(globals.getAppPath("ICON")): + icon = gtk.gdk.pixbuf_new_from_file(globals.getAppPath("ICON")) + gtk.window_set_default_icon_list(icon) +else: + print utils.mapping(_("The icon file does not exist. '$1'"), + (globals.getAppPath("ICON"),)) + +# Autodetect desktop +if globals.desktop["autodetect"] is True: + openwith.autodetect_desktop() + print utils.mapping(_("pyArq-Presupuestos running on $1"), + (globals.desktop["desktop"],)) + +class MainWindow(object): + """gui.MainWindow: + + Description: + Creates and shows the main window. + This is the interface base class. + Constructor: + gui.MainWindow(): Returns the newly created main window instance + Ancestry: + +-- object + +-- MainWindow + Atributes: + "window": Main window widget ("gtk.Window" object) + "__budget_temp_list": Temporal list of budgets + "__budget_list": List of budgets ("base.Budget" objects) + "__page_list": List of pages ("Page" object) + "__notebook": Notebook widget ("gtk.Notebook" object) + "__general_action_group": the "General" action group + Methods: + __init__(self) + _main(self) + _addBudget(self, budget) + _appendPage(self) + _testBudgetList(self) + _menuitemImportFiebdc(self, widget) + _menuitemImportPriceDatabase(self, widget) + _menuitemOpenPriceDatabase(self, widget) + _menuitemOpen + _menuitemClose(self, widget) + _menuitemText(self, widget) + _delete_event(self, widget, event) + _destroy(self, widget) + """ + # TODO:* Can choose open budget in new window + # TODO:* gtk.Action for menu and toolbar + # TODO:* Can choose show more than one notebook in the same window or + # TODO: can show basedata notebook in a side pane + __ui = '''<ui> + <menubar name="MenuBar"> + <menu action="File"> + <menuitem action="ImportFiebdc"/> + <menuitem action="Close"/> + </menu> + <menu action="View"> + <menuitem action="Text"/> + </menu> + <menu action="Test"> + <menuitem action="ImportFiebdcPriceDatabase"/> + <menuitem action="OpenPriceDatabase"/> + </menu> + </menubar> + <toolbar name="ToolBar"> + <toolitem action="ImportFiebdc"/> + <separator/> + <toolitem action="Close"/> + <separator name="sep1"/> + </toolbar> + </ui>''' + + def __init__(self): + """def __init__(self) + + Initialize the atributes "__budget_list" and "__page_list" without data. + Creates the widgets "window" and "__notebook". + """ + self.__budget_temp_list = [] + self.__budget_list = [] + self.__page_list = [] + # Main window + self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) + self.window.set_default_size(771, 570) + self.window.set_title("Presupuestos") + self.window.set_border_width(0) + self.window.connect("destroy", self._destroy) + self.window.connect("delete_event", self._delete_event) + # Vertical box + _vbox1 = gtk.VBox(False, 0) + self.window.add(_vbox1) + _vbox1.show() + #Uimanager + _uimanager = gtk.UIManager() + _accelgroup = _uimanager.get_accel_group() + self.window.add_accel_group(_accelgroup) + _general_action_group = gtk.ActionGroup("General") + self.__general_action_group = _general_action_group + _general_action_group.add_actions( + [("File", None, _("_File"), None), + ("ImportFiebdc", gtk.STOCK_OPEN, _('_Import Fiebdc'), "", 'NPI', + self._menuitemImportFiebdc), + ("Close", gtk.STOCK_CLOSE, _("_Close"), None, 'NPI', + self._menuitemClose), + ("View", None, _("_View")), + ("Text", None, _("_Text"), None, 'NPI', + self._menuitemText), + ("Test", None, _("_Test")), + ('ImportFiebdcPriceDatabase', gtk.STOCK_OPEN, + _("Import Fiebdc _price database"), "", "NPI", + self._menuitemImportPriceDatabase ), + ("OpenPriceDatabase", gtk.STOCK_OPEN, _('_Open price database'), + "", 'NPI', self._menuitemOpenPriceDatabase), + ]) + _uimanager.insert_action_group(_general_action_group, 0) + _uimanager.add_ui_from_string(self.__ui) + _menu_bar = _uimanager.get_widget("/MenuBar") + _vbox1.pack_start(_menu_bar, False, False, 0) + _toolbar = _uimanager.get_widget("/ToolBar") + _toolbar.get_settings().set_long_property("gtk-toolbar-icon-size", + gtk.ICON_SIZE_SMALL_TOOLBAR, "pyArq-Presupuestos:toolbar") + _vbox1.pack_start(_toolbar, False, False, 0) + # Notebook + self.__notebook = gtk.Notebook() + _vbox1.pack_start(self.__notebook, True, True, 0) + self.__notebook.set_tab_pos(gtk.POS_TOP) + self.__notebook.set_show_tabs(True) + self.__notebook.set_show_border(True) + self.__notebook.set_scrollable(True) + self.__notebook.show() + self._main() + + def _main(self): + """def main(self) + + Shows window and starts the GTK+ event processing loop. + """ + self.window.show() + gtk.main() + + def _addBudget(self, budget): + """def _addBudget(self, budget) + + budget: "base.Budget" object + + Appends a budget in the "__budget_list" + """ + if budget != None: + _budget = budget + if _budget in self.__budget_temp_list: + self.__budget_temp_list.remove(_budget) + self.__budget_list.append(_budget) + + def _appendPage(self): + """def _appendPage(self) + + Creates a new page (instance of "Page class") from the last budget in + __budget_list, appends this page in the "__page_list" and shows the + page widget in the notebook widget. + """ + _last_budget = self.__budget_list[-1] + _page = Page(_last_budget) + self.__notebook.append_page(_page.widget, _page.title) + self.__page_list.append(_page) + + def _testBudgetList2(self): + """def _testBudgetList2(self) + + Test if the number of budgets ("__budget_list") is greater + than the number of pages ("__page_list"), if it is greater + appendPage method is called to create a page to show the new budget + and save the budget in a durus file. + """ + if len(self.__budget_list) > len(self.__page_list): + self._appendPage() + #-# in test mode + # TODO: It must be in a thread + _last_budget = self.__budget_list[-1] + _path = globals.getHomePath("DURUS-DATABASE") + _file_whit_path_bc3 = _last_budget.filename + _filename_bc3 = _file_whit_path_bc3.split("/")[-1] + _filename = _filename_bc3.split(".")[-2] + _file = _path + _filename + ".durus" + print utils.mapping(_("Saving file: $1"), (_file,)) + _time = time.time() + _durus_file = durusdatabase.DurusFile(_file,True) + _durus_file.setBudget(_last_budget) + _durus_file.close() + print utils.mapping(_("Saving time: $1 seconds"), + (("%.2f" %(time.time()-_time) ),)) + #-# + return False + return True + + def _menuitemImportFiebdc(self, widget): + """def _menuitemImportFiebdc(self, widget) + + widget: the widget where the event is emitted from + Callback to open a budget file. + Inits a timeout to test if a budgets is appended to "__budget_list" + calling _testBudgetList method if it is true. + + Creates and shows a window to open a budget file. + """ + _budget = base.Budget() + self.__budget_temp_list.append(_budget) + _budget_file = fiebdc.Read() + _read_method = _budget_file.readFile + _filename = "file" + _exit_method = _budget_file.cancel + _file_window = importFiebdc.FileSelectionWindow(self, + _read_method, _budget, _filename, _exit_method) + + def _menuitemImportPriceDatabase(self, widget): + """def _menuitemImportPriceDatabase(self, widget) + + widget: the widget where the event is emitted from + Callback to open a budget file. + Inits a timeout to test if a budgets is appended to "__budget_list" + calling _testBudgetList method if it is true. + + Creates and shows a window to open a budget file. + """ + #TODO: change timeout, it is deprecated + #TODO: the .durus file must be direted saved + gobject.timeout_add(100, self._testBudgetList2) + _budget = base.Budget() + self.__budget_temp_list.append(_budget) + _budget_file = fiebdc.Read() + _read_method = _budget_file.readFile + _filename = "file" + _exit_method = _budget_file.cancel + _file_window = importFiebdc.FileSelectionWindow(self, + _read_method, _budget, _filename, _exit_method) + + def _menuitemOpenPriceDatabase(self, widget): + """def _menuitemImportPriceDatabase(self, widget) + + widget: the widget where the event is emitted from + Callback to open a budget file. + Inits a timeout to test if a budgets is appended to "__budget_list" + calling _testBudgetList method if it is true. + + Creates and shows a window to open a budget file. + """ + _openDialog = OpenDurusDatabase(self._OpenDurusDatabase) + _openDialog.main() + + def _OpenDurusDatabase(self, file): + """def _menuitemImportFiebdc(self, widget) + + widget: the widget where the event is emitted from + + Callback to open a budget file from a durus file. + """ + _file = file + print utils.mapping(_("Loading file: $1:"), (_file,)) + _time = time.time() + _durus_file = durusdatabase.DurusFile(_file,False) + _budget = _durus_file.getBudget() + _durus_file.close() + print utils.mapping(("Loadig time: $1 seconds"), + (("%.2f" %(time.time()-_time)),)) + self.__budget_list.append(_budget) + _page = Page(_budget) + self.__notebook.append_page(_page.widget, _page.title) + self.__page_list.append(_page) + + def _menuitemClose(self, widget): + """def _menuitemClose(self, widget) + + widget: the widget where the event is emitted from + + Callback to close a budget file. + """ + _page_num = self.__notebook.get_current_page() + if _page_num == -1: + return + _page = self.__page_list.pop(_page_num) + if isinstance(_page, Page): + #not loading budget + self.__budget_list.pop(_page_num) + _page.clear() + self.__notebook.remove_page(_page_num) + + def _menuitemText(self, widget): + """_menuitemText(self, widget) + + widget: the widget where the event is emitted from + + Creates and shows a window showing text description + using a instance of TextWindow class. + """ + _page_num = self.__notebook.get_current_page() + if _page_num == -1: + return + _budget = self.__budget_list[_page_num] + _page = self.__page_list[_page_num] + _code = _page.getActiveCode() + _concepto = _budget.getRecord(_code) + _text = _concepto.text + _window = TextWindow(_code, _text) + _window.main() + + def _delete_event(self, widget, event): + """_delete_event(self, widget, event) + + widget: the widget where the event is emitted from + event: the "gtk.gdk.Event" + + Method connected to "delete_event" signal of main window widget + This signal is emitted when a user press the close titlebar button. + It Returns True so the signal "destroy" is emitted. + """ + for _page in self.__page_list: + _page.clear() + return False # -> destroy + + def _destroy(self, widget): + """_destroy(self, widget) + + widget: the widget where the event is emitted from + Method connected to "destroy" signal of main window widget + + This signal is emited when the method connected to "delete_event" + signal returns True or when the program call the destroy() method of + the gtk.Window widget. + The window is closed and the GTK+ event processing loop is ended. + """ + gtk.main_quit() + + def getNotebook(self): + return self.__notebook + def getPageList(self): + return self.__page_list + def getBudgetList(self): + return self.__budget_list + +class EmptyPage(object): + """ + """ + def __init__(self, mainWindow, readFileMethod, budget, filename, + cancelMethod): + """def __init__(self, mainWindow, readFileMethod, budget, filename, + cancelMethod) + + """ + self.__mainWindow = mainWindow + self.__readFileMethod = readFileMethod + self.__budget = budget + self.__filename = filename + self.__cancelMethod = cancelMethod + self.__children = None + self.__cancel = [False, False] + self.__progress = 0.0 + self.__widget = gtk.VBox() + self.__main_item = None + self.__widget.show() + self.__throbber = gtk.Image() + self.__throbber.set_from_file(globals.getAppPath("THROBBER-ICON")) + self.__throbber.show() + self.__animationThobber = gtk.gdk.PixbufAnimation( + globals.getAppPath("THROBBER-GIF")) + self.__quietThobber = self.__throbber.get_pixbuf() + self.__budget_icon = gtk.gdk.pixbuf_new_from_file_at_size( + globals.getAppPath("BUDGET-ICON"), 16, 16) + _filename = os.path.basename(filename) + _rootfilename = os.path.splitext(_filename)[0] + if not _rootfilename == "": + _filename = _rootfilename + _titleLabel = gtk.Label(_filename) + _titleLabel.show() + self.__title = gtk.HBox() + self.__title.add(self.__throbber) + self.__title.add(_titleLabel) + self.__statusbar = gtk.Statusbar() + self.__statuscontext = self.__statusbar.get_context_id("Statusbar") + self.__statusbar.show() + _align = gtk.Alignment(0.5, 0.5, 0, 0) + _iconVbox = gtk.VBox() + _pyArqIcon = gtk.Image() + _pyArqIcon.set_from_file(globals.getAppPath("PYARQ-ICON")) + _pyArqIcon.show() + _iconVbox.pack_start(_pyArqIcon, True, True, 0) + _link = gtk.LinkButton("http://pyarq.obraencurso.es", + "http://pyarq.obraencurso.es") + _iconVbox.pack_start(_link, True, True, 0) + _link.show() + _iconVbox.show() + _align.add(_iconVbox) + _align.show() + self.__widget.pack_start(_align, True, True, 0) + _progressframe = gtk.Frame() + _progressframe.set_shadow_type(gtk.SHADOW_IN) + _progressframe.show() + self.__progress_bar = gtk.ProgressBar() + self.__progress_bar.show() + _progressframe.add(self.__progress_bar) + self.__statusbar.pack_start(_progressframe, False, False, 0) + self.__widget.pack_end(self.__statusbar, False, True, 0) + self.__main_item = None + + def run(self): + self.__statusbar.push(self.__statuscontext, _("Time: 0s")) + self.__throbber.set_from_animation(self.__animationThobber) + self._launchChildren() + self._launchTimeout() + + def progress(self, percent): + _progress = str(int(round(100 * percent,0))) + self.__progress = percent + + def stopLoading(self): + self.__throbber.set_from_pixbuf(self.__budget_icon) + self.__progress_bar.hide() + self.__statusbar.pop(self.__statuscontext) + + def _launchChildren(self): + """_launchChildren(self) + + Launch the thread to read the file + """ + if self.__children is None: + self.__children = importFiebdc.Thread(self, self.__mainWindow, + self.__readFileMethod, self.__budget, self.__filename, + self.__cancelMethod) + self.__children.start() + + def _launchTimeout(self): + """def _launchTimeout(self) + + Launch the timeouts: + 1- update progress bar + 2- update time label + 3- If the other timetouts are stoped the window is closed + """ + gobject.timeout_add(500, self._updateProgressBar) + gobject.timeout_add(1000, self._updateLabel, time.time()) + self.__cancel = [False, False] + gobject.timeout_add(1000, self._autoClose) + + def _updateProgressBar(self): + """def _updateProgressBar(self) + + update progress bar in a timeout + If the thread end or is canceled the timeout is stoped + """ + if self.__children is None or self.__children.isCanceled() == True: + self.__cancel[0] = True + return False + else: + self.__progress_bar.set_fraction(self.__progress) + _text = "%s%%" %str(int(round(100 * self.__progress,0))) + self.__progress_bar.set_text(_text) + return True + + def _updateLabel(self, _time): + """def _updateProgressBar(self) + + update time label in a timeout + If the thread end or is canceled the timeout is stoped + """ + if self.__children is None or self.__children.isCanceled() == True: + self.__cancel[1] = True + return False + else: + _time = time.time() - _time + _text = utils.mapping(_("Time: $1"), ("%.0f" %_time,)) + self.__statusbar.pop(self.__statuscontext) + self.__statusbar.push(self.__statuscontext, _text) + return True + + def _autoClose(self): + """def _updateProgressBar(self) + + If the time label and progress bar timeouts are stoped the window is + closed and ist tiemeout is stoped + """ + if self.__cancel == [ True, True ]: + return False + else: + return True + + def closeWindow(self): + """def closeWindow(self) + + Sets the __children atribute to None + This causes that the timeouts is ended. + This method is called from thread when it is finished + TODO: it must called threadFinished or somethig + """ + self.__children = None + self.stopLoading() + _page = Page(self.__budget) + _children = self.__widget.get_children() + for _child in _children: + self.__widget.remove(_child) + self.__widget.pack_start(_page.widget, True, True, 0) + _noteBook = self.__mainWindow.getNotebook() + _pageIndex = _noteBook.page_num(self.__widget) + self.__mainWindow.getPageList()[_pageIndex] = _page + def threadCanceled(self): + """def threadCanceled(self) + + Sets the __children atribute to None + This causes that the timeouts is ended. + This method is called from thread when is canceled + TODO: it must called threadFinished or somethig + """ + self.__children = None + self.stopLoading() + + def clear(self): + """def clear(self) + + Cancel thread + """ + self.__children.cancel() + + def getWidget(self): + """def getWidget(self) + + Return de main widget to show in the page + """ + return self.__widget + + def getTitle(self): + """def getTtle(self) + + Return the title of the page, a gtk.Label objetc + """ + return self.__title + + widget = property(getWidget, None, None, + "Main widget showed in the pane") + title = property(getTitle, None, None, + "Page Title") + +class Page(object): + """gui.Page: + + Description: + It creates and shows a page in the notebook from a budget object. + The page can show the budget information in several panes ordered + according to "panes_list" information. + Constructor: + gui.Page(budget, active_code=None): + budget: budget to be showed in this page (base.Budget object) + active_code: the code of the active record + Returns the newly created Page instance + Ancestry: + +-- object + +-- Page + Atributes: + "budget": Read-Write. Budget to show in the page. (base.obra object) + "panes_list": Read. info list for create the panes + ej: [ "v", pane1, pane2 ] , [ "h", pane1, pane2 ] + [ "v", [ "h", pane1, pane2 ], [ "h", pane1, pane2 ] ] + pane types: + * "DecompositionList": its creates a "DecompositionList" object + * "RecordDescription" : its creates a "Description" objetc + * "Measure": its creates a "Measure" objetc + * "FileView": its creates a "FileView" objet + * "CompanyView": its creates a "CompanyView" object + "widget": Read. Notebook page Widget. (a gtk.VBox instance) + "title": Read. Notebook page title (gtk.Label object) + "__active_path_record": The active path record + "__main_item": main item in the page, can be a View object or a Paned + object + Methods: + __init__(self, budget=None, active_code=None) + propagateMessageFrom(self, message, path, arg=None) + sendMessageTo(self, pane, message, path, arg=None) + clear(self) + getItem(self,path) + setMainItem(self, item) + itemsFactory(self, list_paned, path=(0,)) + setActivePathRecord(self, path_record) + getTitle(self) + getWidget(self) + setBudget(self, budget) + getBudget(self) + getPanesList(self) + """ + # TODO: * The panes can be ordered as the user wishes + # TODO: * Panes in windows + # TODO: * pane types + # TODO: * General budget properties (is better a dialog?) + + def __init__(self, budget, path_record=(0,)): + """def __init__(self, budget=None, active_code=None) + + budget: "base.Budget" object + active_code: the code of the active record + Sets the atributes + * __panes_list: info to create the panes + * budget (base.Budget object) + * active_code + """ + #TODO: __panes_list should come from config file... + self.__widget = gtk.VBox() + self.__panes_list = [ "v", "DecompositionList", [ "v", "Measure", + "RecordDescription" ]] + self.__main_item = None + self.setBudget(budget) + self.setActivePathRecord(path_record) + self.__widget.show() + + def propagateMessageFrom(self, message, path, arg=None): + """def propagateMessageFrom(self, message, path, arg=None) + + message: string message + path: tuple that represents the pane path which emits the message + arg: arguments for the message + if message is "change_active" arg is the path record + + The panes are connectted to this method to send messages to other panes + """ + _budget = self.__budget + if message == "change_active" and _budget.hasPath(arg): + self.sendMessageTo(self.__main_item, message, path, arg) + elif message == "autoclose": + self._closeItem(path) + elif message == "split h": + self._splitItem(path, "h") + elif message == "split v": + self._splitItem(path, "v") + + def sendMessageTo(self, pane, message, path, arg=None): + """def sendMessageTo(self, pane,message, path, arg=None) + pane: the receiver pane + message: string message + path: tuple that represents the pane path which emits the message + arg: arguments for the message + + Sends a message to a pane + """ + if not pane.path == path: + pane.runMessage(message, path, arg) + + def clear(self): + """def clear(self) + + Clear atributes + """ + self.propagateMessageFrom("clear", (0,)) + + del self.__budget + del self.__panes_list + del self.__widget + del self.__title + del self.__active_path_record + del self.__main_item + + def getItem(self,path): + """def getItem(self, path + + Return the item whith the path "path", it can return a Paned instance + or a View instance + """ + _item = self.__main_item + if len(path) == 1: + return _item + else: + return _item.getItem(path[1:]) + + def setMainItem(self, item): + """setMainItem(self,item) + + Sets a new main item in the page + """ + if not self.__main_item is None: + _old_main_widget = self.__main_item.widget + self.__widget.remove(_old_main_widget) + self.__main_item = item + _main_widget = self.__main_item.widget + _main_widget.show() + self.__widget.pack_start(_main_widget, True, True, 0) + + def _splitItem(self, path, orientation): + """_splitItem(self, path, orientation) + + Splits the item that is identifies by the path and the orientation + """ + _item = self.getItem(path) + _parent = self.getItem(path[:-1]) + _item.setPath(path+ (0,)) + _item_clone0 = _item.getClone(path + (0,)) + _item_clone1 = _item.getClone(path + (1,)) + _paned = Paned(orientation, path, _item_clone0, _item_clone1) + if len(path) > 1: + _parent.setItem(path[-1], [_paned]) + else: + self.setMainItem(_paned) + + def _closeItem(self, path): + """_closeItem(self, path) + + Closes the item that is identifies by the path + """ + _item = self.getItem(path) + if len(path) > 1: + # There are more than one item + _parent = self.getItem(path[:-1]) + _brothers = [ _brother for _brother in _parent] + _brothers.remove(_item) + _brother = _brothers[0] + + _parent.widget.remove(_brother.widget) + _brother.path = path[:-1] + if len(path) > 2: + _grandparent = self.getItem(path[:-2]) + _grandparent.setItem(path[-2], [_brother]) + _parent.widget.destroy() + _parent.clear() + _item.clear() + else: + _grandparent = self + _grandparent.setMainItem(_brother) + _parent.widget.destroy() + _parent.clear() + _item.clear() + else: + # Thre is only one item in the page, it can not be closed + pass + + def itemsFactory(self, list_paned, path=(0,)): + """def itemsFactory(self, list_paned, path(0,)) + + list_paned: list in "__panes_list" format + [ "v" or "h", panel1_type, panel2_type] + which contains the info for create the widgets. + panel types: + * "DecompositionList" + * "RecordDescription" + * "Measure" + * "Sheet of Conditions" + * "FileView" + * "CompanyView" + path: tuple that represents the item path in the page + + Creates the items and widgets and returns the main item + """ + if not isinstance(list_paned , list): + raise ValueError, _("The value must be a list") + if list_paned[0] == "v" or list_paned[0] == "h": + if len(list_paned) != 3: + raise ValueError, _("Incorrect len") + if not isinstance(list_paned[1],list): + list_paned[1] = [list_paned[1]] + if not isinstance(list_paned[2],list): + list_paned[2] = [list_paned[2]] + _item1 = self.itemsFactory(list_paned[1],path + (0,)) + _item2 = self.itemsFactory(list_paned[2],path + (1,)) + _item = Paned(list_paned[0], path, _item1, _item2) + elif list_paned[0] == "DecompositionList": + _item = View( "DecompositionList", self.__budget, + weakref.ref(self), path, self.__active_path_record) + elif list_paned[0] == "RecordDescription": + _item = View( "RecordDescription", self.__budget,weakref.ref(self), + path, self.__active_path_record) + elif list_paned[0] == "Measure": + _item = View( "Measure", self.__budget, weakref.ref(self), path, + self.__active_path_record) + elif list_paned[0] == "Sheet of Conditions": + _item = Sheet(sef.__budget, weakref.ref(self), path, + self.__active_path_record) + elif list_paned[0] == "FileView": + _item = FileView(sef.__budget, weakref.ref(self), path, + self.__active_path_record) + elif list_paned[0] == "CompanyView": + _item = CompanyView(sef.__budget, weakref.ref(self), path, + self.__active_path_record) + else: + _item = None + raise ValueError, utils.mapping(_("Incorrect item $1"), + (str(list_paned[0]),)) + return _item + + def setActivePathRecord(self, path_record): + """def setActivePathRecord(self, path_record) + + path_record: the active record path + + Sets the active record path + """ + if self.__budget.hasPath(path_record): + self.__active_path_record = path_record + else: + raise ValueError, utils.mapping(_("The budget does not have the "\ + "path record: $1"), (str(path_record),)) + + def getTitle(self): + """def getTtle(self) + + Return the title of the page, a gtk.Label objetc + """ + return self.__title + + def getWidget(self): + """def getWidget(self) + + Return de main widget to show in the pane + """ + return self.__widget + + def setBudget(self, budget): + """def setBudget(self, budget) + + budget: a base.Budget object + + Sets the budget and the active code atributes, + creates the page title and the widgets in the pane and + shows the main widget. + """ + if budget is None: + self.clear() + return + self.__budget = budget + self.setActivePathRecord((0,)) + ## Todo: change page title + self.__title = gtk.Label(self.__budget.getCode( + self.__active_path_record)) + _panes_list = self.__panes_list + self.__main_item = self.itemsFactory(_panes_list) + _main_widget = self.__main_item.getWidget() + _main_widget.show() + self.__widget.pack_start(_main_widget, True, True, 0) + + def getBudget(self): + """def getBudget(self) + + Return de budget, a "base.Budget" object. + """ + return self.__budget + + def getPanesList(self): + """def getPanesList(self) + + Return the panes list, info list for create the panes. + """ + return self.__panes_list + + budget = property(getBudget, setBudget, None, + "Budget to show, base.Budget object") + widget = property(getWidget, None, None, + "Main widget showed in the pane") + title = property(getTitle, None, None, + "Page Title") + panes_list = property(getPanesList, None, None, + "Info list for create the panes") + +class View(object): + """gui.View: + + Description: + It creates a view to show the budget info + Constructor: + View(view_type, budget, wr_page, path, active_path_record) + Ancestry: + +-- object + +-- Paned + Atributes: + "path": the tuple that identifies the view in the main notebook page + "widget": the main gtk widget to show in a view object, + a gtk.VBox object + "__view_type": the object type to show + * DecompositionList + * Description + * Measure + * Sheet of conditions + * FileView + * CompanyView + "__wr_page": weak reference to the page where the view must be showed + "__budget": the budget to show + "__view ": the object to show: + * DecompositionList object + * Description object + * Measure object + * Sheet object + * FileView object + * Comapany View + "__connected": boolean value, True means that the View object sends and + receives signals from/to others views + "__connected_button": a button to switch __connected True or False + Methods: + __init__(self) + getItem(self, path) + _closeItem(self, close_button) + _change_combo(self, combobox) + propagateMessgeFrom(self, message, path, arg=None) + runMessage(self, message, path, arg=None) + getWidget(self) + getPath(self) + setPath(self) + getClone(self, newpath) + clear(self) + """ + def __init__(self, view_type, budget, wr_page, path, active_path_record): + + """def __init__(self, view_type, budget, wr_page, path, + active_path_record) + view_type: the object type to show + * DecompositionList + * Description + * Measure + * Sheet + * FileView + * CompanyView + budget: the budget to show + wr_page: weak reference to the page where the view must be showed + path: the position or path of the view in the page notebook + active_path_record: the record path that must be showed + + Creates and shows a new view + """ + self.__active_path_record = active_path_record + self.__view_type = view_type + self.__wr_page = wr_page + self.__budget = budget + self.__path = path + self.__connected = True + # view_type liststore + _liststore = gtk.ListStore(str) + _liststore.append([_("Decomposition")]) #0 + _liststore.append([_("Description")]) #1 + _liststore.append([_("Measure")]) #2 + _liststore.append([_("Sheet of Conditions")]) #3 + _liststore.append([_("Files")]) #4 + _liststore.append([_("Companies")]) #5 + _combobox = gtk.ComboBox(_liststore) + _cell = gtk.CellRendererText() + _combobox.pack_start(_cell, True) + _combobox.add_attribute(_cell, 'text', 0) + _vbox = gtk.VBox() + _vbox.show() + _toolitem = gtk.ToolItem() + _toolitem.set_expand(True) + _toolitem.add(_vbox) + _toolitem.show() + self.__widget = gtk.Toolbar() + self.__widget.insert(_toolitem, 0) + _hbox = gtk.HBox() + if view_type == "DecompositionList": + self.__view = DecompositionList(budget, weakref.ref(self), + path, active_path_record) + _combobox.set_active(0) + _view_icon = gtk.Image() + _view_icon.set_from_file(globals.getAppPath("DECOMPOSITION-ICON")) + elif view_type == "RecordDescription": + self.__view = Description(budget, weakref.ref(self), + path, active_path_record) + _combobox.set_active(1) + _view_icon = gtk.Image() + _view_icon.set_from_file(globals.getAppPath("DESCRIPTION-ICON")) + elif view_type == "Measure": + self.__view = Measure(budget, weakref.ref(self), + path, active_path_record) + _combobox.set_active(2) + _view_icon = gtk.Image() + _view_icon.set_from_file(globals.getAppPath("MEASURE-ICON")) + elif view_type == "Sheet of Conditions": + self.__view = Sheet(budget, weakref.ref(self), + path, active_path_record) + _combobox.set_active(3) + _view_icon = gtk.Image() + _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) + elif view_type == "FileView": + self.__view = FileView(budget, weakref.ref(self), + path, active_path_record) + _combobox.set_active(4) + _view_icon = gtk.Image() + _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) + elif view_type == "CompanyView": + self.__view = CompanyView(budget, weakref.ref(self), path, + active_path_record) + _combobox.set_active(5) + _view_icon = gtk.Image() + _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) + + else: + raise ValueError, _(utils.mapping("Invalid type of View: $1", + view_type)) + _view_icon.show() + _combobox.connect("changed", self._change_combo) + _combobox.show() + _vbox.pack_start(_hbox,False) + _vbox.pack_start(self.__view.widget, True, True) + _hbox.pack_start(_view_icon, False, False,0) + _hbox.pack_start(_combobox, False, False,0) + _invisible = gtk.HBox() + _invisible.show() + _hbox.pack_start(_invisible, True, False,0) + _icon_menu = gtk.Image() + _icon_menu.set_from_file(globals.getAppPath("MENU-ICON")) + _icon_menu.show() + _menu_button = gtk.ToolButton() + _menu_button.set_icon_widget(_icon_menu) + _menu_button.connect("clicked", self._menu_view) + _menu_button.show() + _icon_connected = gtk.Image() + _icon_connected.set_from_file(globals.getAppPath("CONNECTED-ICON")) + _icon_connected.show() + _hbox.pack_start(_menu_button, False, False, 0) + self.__connected_button = gtk.ToolButton() + self.__connected_button.set_icon_widget(_icon_connected) + self.__connected_button.connect("clicked", self._connected) + self.__connected_button.show() + _hbox.pack_start(self.__connected_button, False, False, 0) + _icon_close = gtk.Image() + _icon_close.set_from_file(globals.getAppPath("CLOSE-ICON")) + _icon_close.show() + _close_button = gtk.ToolButton() + _close_button.set_icon_widget(_icon_close) + _close_button.connect("clicked", self._closeItem) + _close_button.show() + _hbox.pack_start(_close_button, False, False, 0) + _hbox.show() + self.__widget.show() + + def getItem(self, path): + """def getItem(self, path) + + Return itself. + """ + return self + + def _closeItem(self, close_button): + """_closeItem(self, widget) + + Method connected to the "clicked" signal of the _close_button widget + Send the "autoclose" message to the page to close this view + """ + self.propagateMessageFrom( "autoclose", self.__path) + + def _change_combo(self, combobox): + """_change_combo(self, combobox) + + Method connected to the "changed" signal of the _combobox widget + It changes the view type to the type selected in the combobox + """ + _index = combobox.get_active() + _budget = self.__view.budget + _wr_page = self.__view.page + _path = self.__view.path + _path_record = self.__view.active_path_record + _toolitem = self.__widget.get_nth_item(0) + _vbox= _toolitem.get_children()[0] + _hbox = _vbox.get_children()[0] + _combobox = _hbox.get_children()[1] + _hbox.remove(_combobox) + _invisible = _hbox.get_children()[1] + _hbox.remove(_invisible) + _menu_button = _hbox.get_children()[1] + _hbox.remove(_menu_button) + _connected_button = _hbox.get_children()[1] + _hbox.remove(_connected_button) + _close_button = _hbox.get_children()[1] + _hbox.remove(_close_button) + _vbox.remove(self.__view.widget) + _vbox.remove(_hbox) + _hbox.destroy() + _view_icon = gtk.Image() + if _index == 0: + self.__view = DecompositionList(_budget, _wr_page, _path, + _path_record) + + _view_icon.set_from_file(globals.getAppPath("DECOMPOSITION-ICON")) + self.__view_type = "DecompositionList" + elif _index == 1: + self.__view = Description(_budget, _wr_page, _path, + _path_record) + _view_icon.set_from_file(globals.getAppPath("DESCRIPTION-ICON")) + self.__view_type = "RecordDescription" + elif _index == 2: + self.__view = Measure(_budget, _wr_page, _path, + _path_record) + _view_icon.set_from_file(globals.getAppPath("MEASURE-ICON")) + self.__view_type = "Measure" + elif _index == 3: + self.__view = Sheet(_budget, _wr_page, _path, + _path_record) + _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) + self.__view_type = "Sheet of Conditions" + elif _index == 4: + self.__view = FileView(_budget, _wr_page, _path, + _path_record) + _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) + self.__view_type = "FileView" + elif _index == 5: + self.__view = CompanyView(_budget, _wr_page, _path, + _path_record) + _view_icon.set_from_file(globals.getAppPath("SHEET-ICON")) + self.__view_type = "CompanyView" + _view_icon.show() + _hbox = gtk.HBox() + _hbox.pack_start(_view_icon, False, False,0) + _hbox.pack_start(_combobox, False, False,0) + _hbox.pack_start(_invisible, True, False,0) + _hbox.pack_start(_menu_button, False, False, 0) + _hbox.pack_start(_connected_button, False, False, 0) + _hbox.pack_start(_close_button, False, False, 0) + _hbox.show() + _vbox.pack_start(_hbox, False, False, 0) + _vbox.pack_start(self.__view.widget, True, True, 0) + + def _menu_view(self, widget): + """_menu_view(self, widget) + + Method connected to the "clicked" signal of the __connected_button + It shows a popup menu with some options + """ + _menu_view = gtk.Menu() + _item_leftright = gtk.MenuItem("Split View Left/Right") + _menu_view.append(_item_leftright) + _item_leftright.connect_object("activate", self._split_view, "h") + _item_leftright.show() + _item_topbottom = gtk.MenuItem("Split View Top/Bottom") + _menu_view.append(_item_topbottom) + _item_topbottom.connect_object("activate", self._split_view, "v") + _item_topbottom.show() + _item_close = gtk.MenuItem("close view") + _menu_view.append(_item_close) + _item_close.connect_object("activate", self._closeItem, None) + _item_close.show() + _menu_view.popup(None, None, None, 0, 0) + + def _split_view(self, orientation): + """_menu_view(self, orientation) + + orientation: orientation split, "h" or "v" + + Method connected to the "activate" signal of the _item_leftright and + _item_topbottom menu items. + It sends the "split" message to the page to splits the view in the + specified orientation + """ + self.propagateMessageFrom( "split " + orientation, self.__path) + + def _connected(self, widget): + """_connected(self, widget) + + Method connected to the "clicked" signal of the _menu_button + It changes the __connected atribute to True or False, if the + _connected atribute is False the view do not send and receive messages + to/from others views + """ + if self.__connected: + _icon = gtk.Image() + _icon.set_from_file(globals.getAppPath("DISCONNECTED-ICON")) + _icon.show() + self.__connected_button.set_icon_widget(_icon) + self.__connected = False + else: + _icon = gtk.Image() + _icon.set_from_file(globals.getAppPath("CONNECTED-ICON")) + _icon.show() + self.__connected_button.set_icon_widget(_icon) + self.__connected = True + + def propagateMessageFrom(self, message, path, arg=None): + """def propagateMessageFrom(self, message, path, arg=None) + + message: string message + path: tuple that represents the pane path which emits the message + arg: arguments for the message + The panes are connectted to this method to send messages to other panes + """ + if self.__connected or message == "autoclose" or \ + message == "split h" or message == "split v": + self.__wr_page().propagateMessageFrom(message, path, arg) + + def runMessage(self, message, path, arg=None): + """def runMessage(self, message, path, arg=None) + + message: the message type + "change_active": change the active record + "clear": clear instance + path: tuple that identifies the pane in the notebook page + arg: tuple whit two items: + 0: record path in the budget + 1: record code + This method receives a message and executes its corresponding action + """ + if self.__connected: + self.__view.runMessage(message, path, arg) + if message == "change_active": + if self.__budget.hasPath(arg): + _path_record = arg + self.__active_path_record = _path_record + + def getWidget(self): + """def getWidget(self) + + Return de pane widget + """ + return self.__widget + + def getPath(self): + """def getPath(self) + + return the tuple that identifies the pane in the notebook page + """ + return self.__view.path + + def setPath(self, path): + """def setPath(self) + + set the tuple that identifies the pane in the notebook page + """ + self.__path = path + self.__view.path = path + + def getClone(self, new_path): + """getClone(self, new_path) + + new_path: the path that identifies the clone view in the page + + return a clone of itself + """ + return View(self.__view_type, self.__budget, self.__wr_page, + new_path, self.__active_path_record) + + def clear(self): + """clear(self) + + Clear the intance atributes + """ + del self.__wr_page + del self.__budget + del self.__path + del self.__widget + del self.__view + del self.__connected + del self.__connected_button + + path = property(getPath, setPath, None, + "path that identifies the item in the notebook page") + widget = property(getWidget, None, None, "View widget") + +class Paned(object): + """gui.Paned: + + Description: + It creates and shows gtk.Hpaned or gtk.Vpaned to show in page budget + Constructor: + Paned(orientation, widget1, widget2) + orientation: The orientation of the pane separator, can be "v" or "h" + widget1: the top or left pane widget + widget2: the botton or right pane widget + Returns the newly created Paned instance + Ancestry: + +-- object + +-- Paned + Atributes: + "widget": Pane widget("gtk.VPaned" or "gtk.HPaned" object) + "__orientation": The orientation of de gtk.Paned, can be "v" or "h" + "__items": list of items showed in the paned, its can be View or Paned + instances + "__path": the paned path in the page + Methods: + __init__(self) + __getitem__(self, item) + getClone(self, new_path) + getItem(self, path) + runMessage(self, messge, path, arg=None) + getWidget(self) + {get/set}Path + clear(self) + """ + # TODO: *control the position paned separator. Now is always 200 pixels + # TODO: can be with a float(0.0-1.0) aspect ratio + # TODO: 0.0 no space for widget1 + # TODO: 1.0 all the space for widget1 + # TODO: *control the position pane separator when the size of the window + # TODO: change with the same ascpect ratio + + def __init__(self, orientation, path, item1, item2): + """def __init__(self, oritentation, path, item1, item2) + + orientation: The orientation of de gtk.Paned, can be "v" or "h" + path: the paned path in the page + item1: the top or left pane object + item2: the bottom or right pane object + + Creates and shows a new gtk.Paned + """ + self.__orientation = orientation + if not isinstance(item1.widget, gtk.Widget) or \ + not isinstance(item2.widget, gtk.Widget): + raise ValueError, _("The item must be a widget object.") + if orientation == "v": + self.__widget = gtk.VPaned() + elif orientation == "h": + self.__widget = gtk.HPaned() + else: + raise ValueError, _("Invalid orientation.") + self.__widget.pack1(item1.widget,True,False) + self.__widget.pack2(item2.widget,True,False) + self.__widget.set_position(200) + self.__widget.show() + self.__items = [item1, item2] + self.__path = path + + def __getitem__(self, item): + """__getitem__(self, item) + + Called to implement evaluation of self[key]. + The accepted keys should be integers 0 or 1. + """ + return self.__items[item] + + def getClone(self, new_path): + """getClone(self, new_path) + + Return a clone Paned instance with the path new_path + """ + return Paned(self.__orientation, new_path, + self.__items[0].getClone(new_path + (0,)), + self.__items[1].getClone(new_path + (1,))) + + def getItem(self,path): + """def getItem(self, path) + + Return the item whith the specified path. + """ + _item = self.__items[path[0]] + if len(path) == 1: + return _item + else: + return _item.getItem(path[1:]) + + def setItem(self, path, item_list): + """def setItem(self, path, item_list) + + Sets the first item in the item_list whith the especified path and + remove the old item in this position. + """ + item = item_list[0] + if path == 0 or path == 1: + _old_item = self.__items[path] + self.__widget.remove(_old_item.widget) + self.__items[path] = item + if path == 0: + self.__widget.pack1(item.widget,True,False) + else: + self.__widget.pack2(item.widget,True,False) + return True + return False + + def runMessage(self, message, path, arg=None): + """def runMessage(self, message, page_path, arg=None) + + message: the message type + "change_active": change the active record + "clear": clear instance + page_path: tuple that identifies the pane in the notebook page + arg: arguments + + This method receives a message and send this to the items of the paned + """ + for _item in self.__items: + if not _item.path == path: + _item.runMessage(message, path, arg) + + def getWidget(self): + """def getWidget(self) + + Return de gtk.Paned widget + """ + return self.__widget + + def getPath(self): + """def getPath(self) + + Return de Paned path in the notebook page + """ + return self.__path + + def setPath(self, path): + """def setPath(self) + + sets the tuple that identifies the pane in the notebook page + """ + self.__path = path + self.__items[0].path = path + (0,) + self.__items[1].path = path + (1,) + + def clear(self): + del self.__widget + del self.__orientation + del self.__items + del self.__path + + widget = property(getWidget, None, None, "gtk.Paned widget") + path = property(getPath, setPath, None, "Pane path in the notebook page") + +class TreeView(object): + """gui.Treeviev: + + Description: + It creates the columns in a treeview, is the base class for + DescompositionList and Measure classes + Constructor: + TreView(args) + args: list of tuples, the tuple items are: + 0.type: + * index column + * float column + * text column + * calculated column + * calculated text + * type column + 1. clicked method + 2. width + 3. text color + 4. backgruound colors + 5. model column index + Ancestry: + +-- object + +-- TreeView + Atributes: + "columns": list of columns (gtk.TreeViewColumn isntances) + Methods: + __init__(self) + __getitem__(self, item) + createColumn(self, args) + createTextBaseColumn(self,args) + createBaseColumn(self,args) + """ + + def __init__(self, args): + """__init__(self, args) + + args: list of tuples, the tuple items are: + 0.type: + * index column + * float column + * text column + * calculated column + * Calculated text + * type column + 1. clicked method + 2. width + 3. text color + 4. backgruound colors + 5. model column index + + Create the columns form the args info calling creatheColumn to create + each column + """ + self.columns = [ self.createColumn(arg) for arg in args ] + self.columns.append(self.createColumn(("END",))) + + def createColumn(self, args): + """createColumn(self, args) + + args: tuple with the args + 0.type: + * index column + * float column + * text column + * calculated column + * calculated text + * type column + 1. clicked method + 2. width + 3. text color + 4. backgruound colors + 5. model column index + + Return a column created whith the arg info + """ + if args[0] == "INDEX": + _index_column = self.createBaseColumn(args) + _text_index_cell = gtk.CellRendererText() + _text_index_cell.set_property('foreground-gdk', + gtk.gdk.color_parse(globals.color["TEXT"])) + _pixbuf_index_cell = gtk.CellRendererPixbuf() + _arrow_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("ARROW-ICON")) + _pixbuf_index_cell.set_property("pixbuf", _arrow_icon) + _index_column.pack_start(_text_index_cell, True) + _index_column.pack_start(_pixbuf_index_cell, True) + _index_column.set_cell_data_func(_text_index_cell, + self.colorCell, + [gtk.gdk.color_parse(globals.color["INDEX-UNEVEN"]), + gtk.gdk.color_parse(globals.color["INDEX-EVEN"])]) + return _index_column + elif args[0] == "TEXT": + _column, _cell = self.createTextBaseColumn(args) + _column.add_attribute(_cell, 'text', args[5]) + return _column + elif args[0] == "FLOAT": + _column, _cell = self.createTextBaseColumn(args) + _column.add_attribute(_cell, 'text', args[5]) + _column.get_cell_renderers()[0].set_property('xalign', 1.0) + return _column + elif args[0] == "CALCULATED": + _column, cell = self.createTextBaseColumn(args) + _column.get_cell_renderers()[0].set_property('xalign', 1.0) + return _column + elif args[0] == "CALCULATEDTEXT": + _column, cell = self.createTextBaseColumn(args) + return _column + elif args[0] == "TYPE": + _column = self.createBaseColumn(args) + _type_cell1 = gtk.CellRendererPixbuf() + _type_cell2 = gtk.CellRendererText() + _type_cell2.set_property('foreground-gdk', args[3]) + _column.pack_start(_type_cell1, True) + _column.pack_start(_type_cell2, True) + _column.add_attribute(_type_cell2, 'text', args[5]) + _column.set_cell_data_func(_type_cell1, + self.colorCell, args[4]) + _column.set_cell_data_func(_type_cell2, + self.colorCell, args[4]) + return _column + elif args[0] == "PIXBUF": + _column = self.createBaseColumn(args) + _type_cell1 = gtk.CellRendererPixbuf() + _column.pack_start(_type_cell1, True) + _column.set_cell_data_func(_type_cell1, + self.colorCell, args[4]) + return _column + elif args[0] == "END": + _end_column = gtk.TreeViewColumn() + _end_column.set_clickable(False) + _end_cell = gtk.CellRendererText() + _end_cell.set_property('cell-background-gdk', + gtk.gdk.color_parse(globals.color["UNEVEN"])) + _end_column.pack_start(_end_cell, True) + return _end_column + return None + + def createTextBaseColumn(self,args): + """createTextBaseColumn(self,args) + + args: tuple with the args + 0.type: + * float column + * text column + * calculated column + * calculated text + 1. clicked method + 2. width + 3. text color + 4. backgruound colors + 5. model column index + + Return a column and its CellREndererText + """ + _column = self.createBaseColumn(args) + _cell = gtk.CellRendererText() + _cell.set_property('foreground-gdk', args[3]) + _column.pack_start(_cell, True) + _column.set_cell_data_func(_cell, self.colorCell, args[4]) + return _column, _cell + + def createBaseColumn(self,args): + """createBaseColumn(self,args) + + args: tuple with the args + 0.type: + * index column + * float column + * text column + * calculated column + * calculated text column + * type column + 1. clicked method + 2. width + 3. text color + 4. backgruound colors + 5. model column index + + Return a column + """ + _column = gtk.TreeViewColumn() + _column.set_clickable(True) + _column.connect("clicked", args[1]) + _column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + _column.set_fixed_width(args[2]) + _column.set_resizable(True) + return _column + +class DecompositionList(TreeView): + """gui.DecompositionList: + + Description: + Class to show a budget Decomposition List + Constructor: + DecompositionList(budget, page, path) + budget: budget showed ("base.Budget" object) + page: weak reference from Page instance which creates this class + path: tuple that represents the view path in the Page + Returns the newly created DecompositionList instance + Ancestry: + +-- object + +-- TreeView + +-- DecompositionList + Atributes: + "budget": Budget to show, base.obra instance. + "widget or __scrolled_window": Window that contains the table, + (gtk.ScrolledWindow) + "path": Pane page identifier + "page": weak reference from Page instance which creates this class + "__active_color": background color of the active cell, a + gtk.gdk.Color object + "__chapter_background_colors": background colors of the Code + column cells when there is a chapter record, + list of gtk.gdk.Color objects [even cell, uneven cell] + "__methond_message": Method to send messages to the page + "__liststore": list model which store the list data + (gtk.ListStore object) + "__treeview": widget for displaying decomposition lists (gtk.TreeView) + "__index_column": Index column (gtk.TreeViewColumn object) + "__code_column": Record code column (gtk.TreeViewColumn) + "__unit_column": Unit of measure column (gtk.TreeViewColumn) + "__description_column": record's short description column + (gtk.TreeViewColumn) + "__measure_column": Measure column (gtk.TreeViewColumn) + "__price_column": Price column (gtk.TreeViewColumn) + "__amount_column": Amount column(gtk.TreeViewColumn) + "__end_column": End empty column (gtk.TreeViewColumn) + "__treeselection": active selection + "__selection_control": state of the selection control (True/False) + "__cursor": cursor position in the table + Methods: + __init__(self, budget) + treeviewCursorChanged(self, treeview) + treeviewClickedEvent(self, widget, event) + treeviewKeyPressEvent(self, widget, event) + moveCursor(self, treeview, step, count) + controlSelection(self, selection) + selectAll(self, column) + setColumnsHeaders(self) + setListstoreValues(self, puntero, treeiter=None) + colorCell(self, column, cell_renderer, tree_model, iter, lcolor) + _claculateAmount(self, row_path, tree_model) + showParentRecord(self, column) + showMessageRecord(self, camino,_code): + showRowRecord(self, treeview, path, column) + runMessage(self, messagem path, arg=None) + _clear(self) + getWidget(self) + {get/set}Path + {get/seg}Page + getBudget(self) + getActivePathRecord(self) + """ + + def __init__(self, budget, page, path, path_record=(0,)): + """def __init__(self, budget, page, path) + + budget: budget showed ("base.Budget" object) + page: weak reference from Page instance which creates this class + path: tuple that represents the path of the List in the Page + + Sets the init atributes + Creates the init list values in self.__liststore from the budget + showing the top record descomposition + Creates the list in self.__treeview + * Creates the columns and cell + * Sets te the column headers values + * Sets the selection properties + * Connects the events + """ + # TODO: to group all columns in a dicctionary + # Budget + if not isinstance(budget, base.Budget): + raise ValueError, _("Argument must be a Budget object") + self.__budget = budget + self.__page = page + self.__path = path + # ListStore + self.__liststore = gtk.ListStore(object + #, int, int, str, str, str, str, str,str + ) + if path_record is None: + print _("DecompositionList.__init__: Record path can not be None") + path_record = (0,) + self.__active_path_record = path_record + self.setListstoreValues(self.__active_path_record) + # Treeview + self.__treeview = gtk.TreeView(self.__liststore) + self.__treeview.set_enable_search(False) + self.__treeview.set_reorderable(False) + self.__treeview.set_headers_clickable(True) + self.__treeview.show() + # Scrolled_window + self.__scrolled_window = gtk.ScrolledWindow() + self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, + gtk.POLICY_AUTOMATIC) + self.__scrolled_window.add(self.__treeview) + # colors + _text_color = gtk.gdk.color_parse(globals.color["TEXT"]) + _background_color = [ + gtk.gdk.color_parse(globals.color["UNEVEN"]), + gtk.gdk.color_parse(globals.color["EVEN"])] + self.__chapter_background_colors = [ + gtk.gdk.color_parse(globals.color["CHAPTER-UNEVEN"]), + gtk.gdk.color_parse(globals.color["CHAPTER-EVEN"])] + super(DecompositionList,self).__init__( + [("INDEX",self.selectAll,42), + ("CALCULATEDTEXT", self.showParentRecord, + gtk.Label("A"*10).size_request()[0] +10, + _text_color, _background_color), + ("PIXBUF", self.showParentRecord, 26, _text_color, + _background_color), + ("CALCULATEDTEXT", self.showParentRecord, + gtk.Label(_("a"*4)).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATEDTEXT", self.showParentRecord, + gtk.Label("a"*30).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATED", self.showParentRecord, + gtk.Label("a"*10).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATED", self.showParentRecord, + gtk.Label("a"*10).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATED", self.showParentRecord, + gtk.Label("a"*10).size_request()[0] +10, + gtk.gdk.color_parse(globals.color["CALCULATED-TEXT"]), + _background_color), + ]) + self.__index_column = self.columns[0] + self.__code_column = self.columns[1] + self.__type_column = self.columns[2] + self.__unit_column = self.columns[3] + self.__description_column = self.columns[4] + self.__measure_column = self.columns[5] + self.__price_column = self.columns[6] + self.__amount_column = self.columns[7] + self.__end_column = self.columns[8] + # Index column + self.__treeview.append_column(self.__index_column) + # Code column + self.__treeview.append_column(self.__code_column) + # Type column + self.__treeview.append_column(self.__type_column) + self.chapter_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("CHAPTER-ICON")) + self.unit_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("UNIT-ICON") ) + self.material_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("MATERIAL-ICON") ) + self.machinery_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("MACHINERY-ICON")) + self.labourforce_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("LABOURFORCE-ICON")) + self.__type_column.get_cell_renderers()[0].set_property("pixbuf", + self.labourforce_icon) + + # Unit column + self.__treeview.append_column(self.__unit_column) + # Description column + self.__treeview.append_column(self.__description_column) + # Measure Column + self.__treeview.append_column(self.__measure_column) + # Price column + self.__treeview.append_column(self.__price_column) + # Amount column + self.__treeview.append_column(self.__amount_column) + # End Column + self.__treeview.append_column(self.__end_column) + # Connect + self.__treeview.connect("row-activated", self.showRowRecord) + self.__treeview.connect("move-cursor", self.moveCursor) + self.__treeview.connect("key-press-event", self.treeviewKeyPressEvent) + self.__treeview.connect("button-press-event", self.treeviewClickedEvent) + self.__treeview.connect("cursor-changed", self.treeviewCursorChanged) + # control selection + self.__treeselection = self.__treeview.get_selection() + self.__treeselection.set_mode(gtk.SELECTION_MULTIPLE) + self.__treeselection.set_select_function(self.controlSelection) + self.__selection_control = True + if len(self.__liststore) > 0: + self.__treeview.set_cursor_on_cell((0,),self.__unit_column, + self.__unit_column.get_cell_renderers()[0],True) + self.__treeview.grab_focus() + self.__cursor = self.__treeview.get_cursor() + # Show + self.setColumnsHeaders() + self.__scrolled_window.show() + + def treeviewCursorChanged(self, treeview): + """def treeviewCursorChanged(self, treeview) + + treeview: treewiew widget + Method connected to "cursor-changed" signal + The "cursor-changed" signal is emitted when the cursor moves or is set + Sets the new cursor position in self.__cursor, it is used to avoid + unnecessary changes in cursor position. + """ + event = gtk.get_current_event() + (_cursor_path, _column) = treeview.get_cursor() + if event is None or event.type != gtk.gdk.BUTTON_RELEASE: + if not _column is self.__index_column: + self.__cursor = treeview.get_cursor() + + def treeviewClickedEvent(self, widget, event): + """def treeviewClickedEvent(self, widget, event) + + widget: treewiew widget + event: clicked event + Method connected to "button-press-event" signal + The "button-press-event" signal is emitted when a mouse button is + pressed. + Returns TRUE to stop other handlers from being invoked for the event. + Returns FALSE to propagate the event further. + + The events in end column are ignored. + If the user click in a row of the index column the cursor is moved to + this row but not to the index column + """ + if event.button == 1: + path_at_pos = self.__treeview.get_path_at_pos(int(event.x), + int(event.y)) + if not path_at_pos is None: + _path_cursor, _column, _x, _y = path_at_pos + if _column == self.columns[-1]: + return True + if _column is self.columns[0]: + self.__cursor[0] == _path_cursor + return False + + def treeviewKeyPressEvent(self, widget, event): + """def treeviewKeyPressEvent(self, widget, event) + + widget: treewiew widget + event: Key Press event + Method connected to "key-press-event" signal + The "key-press-event" signal is emitted when the user presses a key + on the keyboard. + Returns :TRUE to stop other handlers from being invoked for the event. + Returns :FALSE to propagate the event further. + + If the user press the right cursor button and the cursor is in the + amount column or pres the left cursor button and the cursor is + in the code column the event is estoped, else the event is propagated. + """ + (_cursor_path, _column) = self.__treeview.get_cursor() + if (event.keyval == gtk.keysyms.Right \ + and _column == self.columns[-2]) \ + or (event.keyval == gtk.keysyms.Left \ + and _column == self.columns[1]): + return True + return False + + def moveCursor(self, treeview, step, count): + """def treeviewKeyPressEvent(self, widget, event) + + treeview: the treeview that received the signal + step: the movement step size + count: the number of steps to take + + Method connected to "move-cursor" signal + The "move-cursor" signal is emitted when the user moves the cursor + using the Right, Left, Up or Down arrow keys or the Page Up, + Page Down, Home and End keys. + + Returns :TRUE if the signal was handled. + """ + return False + + def controlSelection(self, selection): + """def controlSelection(self, selection) + + selection: treeselection + + Method connected to set_selection_function() + This method is called before any node is selected or unselected, + giving some control over which nodes are selected. + The selection function should return TRUE if the state + of the node may be toggled, and FALSE if the state of the node should + be left unchanged. + + The selection only run if the user click in the index column, else + the previous selection is erased. + """ + _column = self.__treeview.get_cursor()[1] + if _column is self.columns[0] \ + or self.__selection_control == False: + return True + else: + self.__selection_control = False + self.__treeselection.unselect_all() + self.__selection_control = True + return False + + def selectAll(self, column): + """def selectAll(self, column) + + column: index column + Method connected to "clicked" event in the index column + If the user clickes in the index column header selecs or deselects + all rows + """ + (_model, _pathlist) = self.__treeselection.get_selected_rows() + # it avoid to set cursor in the index column + self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) + self.__selection_control = False + if len(_pathlist) == 0: + # select all + self.__treeselection.select_all() + else: + # unselect all + self.__treeselection.unselect_all() + self.__selection_control = True + + def setColumnsHeaders(self): + """def setColumnsHeaders(self) + + Sets the headers column values + """ + _path_record = self.__active_path_record + _number = _path_record[-1] + _budget = self.__budget + _code = _budget.getCode(_path_record) + _decomposition = _budget.getDecomposition(_path_record) + _stryield = _budget.getStrYield(_decomposition.budgetMeasures[0], + _budget.getRecord(_code).recordType) + _record = _budget.getRecord(_code) + _unit = _record.unit + _description = _record.summary + _price = _budget.getStrPriceFromRecord(self.budget.getActiveTitle(), + _record) + # TODO: round to decimal places in amount + _amount = float(_stryield) * float(_price) + if len(_path_record) == 1: # root record + _amount = _price + else: + _parent_code = self.budget.getCode(self.__active_path_record[:-1]) + _parent_record = self.__budget.getRecord(_parent_code) + _amount = _budget.getStrAmount(self.__active_path_record) + + self.__code_column.set_title(_("Code") + chr(10) + "[" + _code + "]") + self.__unit_column.set_title(_("Unit") + chr(10) + "[" + _unit + "]") + self.__description_column.set_title( + _("Description") + chr(10) + "[" + _description + "]") + self.__measure_column.set_title( + _("Measure") + chr(10) + "[" + _stryield + "]") + self.__price_column.set_title( + _("Price") + chr(10) + "[" + _price + "]") + self.__amount_column.set_title( + _("Amount") + chr(10) + "[" + str(_amount) + "]") + + + def setListstoreValues(self, path_record): + """def setListstoreValues(self, path_record) + + path_record: Record path in the budget + Sets the liststore record values from a path record + """ + self.__liststore.clear() + _budget = self.__budget + if not _budget.hasPath(path_record): + raise ValueError, _("Invalid path") + else: + _parent_code = _budget.getCode(path_record) + for N,_code in enumerate(_budget.getchildren(_parent_code)): + _decomposition = _budget.getNDecomposition(_parent_code, N) + _record = _budget.getRecord(_code) + _values = [_record, + #_record.hierarchy, + #_record.type, + #_record.subtype, + #_code, + #_record.unit, + #_record.summary, + #_decomposition.yield_, + #_decomposition.budget[0].yield_, + #_record.prices[_budget.getActiveTitle()].prices] + #_record.getPrice(_budget.getActiveTitle()) + ] + _treeiter = self.__liststore.append(_values) + + def colorCell(self, column, cell_renderer, tree_model, iter, lcolor): + """def colorCell(self, column, cell_renderer, tree_model, iter, lcolor) + + column: the gtk.TreeViewColumn in the treeview + cell_renderer: a gtk.CellRenderer + tree_model: the gtk.TreeModel + iter: gtk.TreeIter pointing at the row + lcolor: list with 2 gtk colors for even and uneven record + + Method connected to "set_cell_data_func" of many column + The set_cell_data_func() method sets the data function (or method) + to use for the column gtk.CellRenderer specified by cell_renderer. + This function (or method) is used instead of the standard attribute + mappings for setting the column values, and should set the attributes + of the cell renderer as appropriate. func may be None to remove the + current data function. The signature of func is: + -def celldatafunction(column, cell, model, iter, user_data) + -def celldatamethod(self, column, cell, model, iter, user_data) + where column is the gtk.TreeViewColumn in the treeview, cell is the + gtk.CellRenderer for column, model is the gtk.TreeModel for the + treeview and iter is the gtk.TreeIter pointing at the row. + + The method sets cell background color and text for all columns. + """ + _row_path = tree_model.get_path(iter) + _number = _row_path[-1] + _record = tree_model[_row_path][0] + if column is self.__index_column: + cell_renderer.set_property('text', str(_number + 1)) + self.__index_column.get_cell_renderers()[1].set_property( + 'cell-background-gdk', lcolor[_number % 2]) + elif column is self.__code_column: + # if the record is a chapter + if tree_model.get_value(iter, 0).recordType.hierarchy == 1: + lcolor = self.__chapter_background_colors + _code = _record.code + cell_renderer.set_property('text', _code) + elif column is self.__unit_column: + _unit = _record.unit + cell_renderer.set_property('text', _unit) + elif column is self.__description_column: + _summary = _record.summary + cell_renderer.set_property('text', _summary) + elif column is self.__measure_column: + _parent_code = self.budget.getCode(self.__active_path_record) + _parent_record = self.__budget.getRecord(_parent_code) + _decomposition = _parent_record.children[_number] + _stryield = self.__budget.getStrYield( + _decomposition.budgetMeasures[0], _parent_record.recordType) + cell_renderer.set_property('text', _stryield) + elif column is self.__price_column: + _price = self.budget.getStrPriceFromRecord( + self.budget.getActiveTitle(), _record) + cell_renderer.set_property('text', _price) + elif column is self.__amount_column: + _parent_code = self.budget.getCode(self.__active_path_record) + _parent_record = self.__budget.getRecord(_parent_code) + _amount = self.budget.getStrAmount( + self.__active_path_record + (_number,)) + cell_renderer.set_property('text', str(_amount)) + elif column is self.__type_column: + _hierarchy = tree_model[_row_path][0].recordType.hierarchy + _type = tree_model[_row_path][0].recordType.type + _subtype = tree_model[_row_path][0].recordType.subtype + if _hierarchy == 1: + cell_renderer.set_property("pixbuf",self.chapter_icon) + else: + if _type == 0: + cell_renderer.set_property("pixbuf",self.unit_icon) + elif _type == 1: + cell_renderer.set_property("pixbuf", + self.labourforce_icon) + elif _type == 2: + cell_renderer.set_property("pixbuf", + self.machinery_icon) + else: + cell_renderer.set_property("pixbuf",self.material_icon) + if self.__treeview.get_cursor() == (_row_path,column): + cell_renderer.set_property('cell-background-gdk', + gtk.gdk.color_parse(globals.color["ACTIVE"])) + else: + cell_renderer.set_property('cell-background-gdk', + lcolor[_number % 2]) + + def showParentRecord(self, column): + """def showParentRecord(self, column) + + column: the column that is clicked + Method connected to "clicked" event of many columns + Show the parent record + """ + _budget = self.__budget + if len(self.__active_path_record) == 1: + # The active record is the root record + # This avoid to move the cursor to the clicked column + self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) + else: + _path_record = self.__active_path_record[:-1] + _parent = self.__active_path_record[-1] + self.__active_path_record = _path_record + self.setColumnsHeaders() + self.setListstoreValues(self.__active_path_record) + arg = ( _path_record ) + _page = self.__page() + _page.propagateMessageFrom("change_active", self.__path, arg) + self.__treeview.set_cursor(_parent, self.__cursor[1]) + self.__cursor = self.__treeview.get_cursor() + + def showMessageRecord(self, record_path): + """def showMessageRecord(self, record_path) + + record_path: the path of the record to show + Method connected to "change_active" message + Show the record especified in the "change_active" message + """ + _budget = self.__budget + self.__active_path_record = record_path + self.setColumnsHeaders() + self.setListstoreValues(self.__active_path_record) + self.__treeview.set_cursor((0,)) + + def showRowRecord(self, treeview, treeview_path, column): + """def showRowRecord(self, treeview, treeview_path, column) + + treeview: treview to show + treeview_path: the path of the record to show + code: the code of the record to show + + Method connected to "row-activated" event + The "row-activated" signal is emitted when the row_activated() method + is called or the user double clicks a treeview row. + "row-activated" is also emitted when a non-editable row is selected + and one of the keys: Space, Shift+Space, Return or Enter is pressed. + Show the especified record + """ + if not (column is self.__end_column) and \ + not (column is self.__index_column): + _budget = self.__budget + _model = treeview.get_model() + _iter = _model.get_iter(treeview_path) + _code = _model.get_value(_iter, 0).code + #_code = _model.get_value(_iter, 4) + _path_record = self.__active_path_record + treeview_path + if self.__budget.hasPath(_path_record): + # if this record path is valid + self.__active_path_record = _path_record + self.setColumnsHeaders() + self.setListstoreValues(self.__active_path_record) + self.__treeview.set_cursor((0,)) + _arg = ( _path_record ) + _page = self.__page() + _page.propagateMessageFrom("change_active", self.__path, + _arg ) + + def runMessage(self, message, path, arg=None): + """def runMessage(self, message, path, arg=None) + + message: the message type + "change_active": change the active record + "clear": clear instance + path: tuple that identifies the pane in the notebook page + arg: tuple whit two items: + 0: record path in the budget + 1: record code + This method receives a message and executes its corresponding action + """ + _budget = self.__budget + if message == "change_active": + if _budget.hasPath(arg): + _path_record = arg + self.showMessageRecord( _path_record) + elif message == "clear": + self._clear() + + def _clear(self): + """def _clear(self) + + it deletes the __budget value + this would not be necessary if there were not circular references, + which are pending to fix + """ + del self.__budget + + def getWidget(self): + """def getWidget(self) + + return the main widget (gtk.ScrolledWindow) + """ + return self.__scrolled_window + + def getPath(self): + """def getPath(self) + + return the tuple that identifies the pane in the notebook page + """ + return self.__path + + def setPath(self, path): + """def setPath(self) + + sets the tuple that identifies the pane in the notebook page + """ + self.__path = path + + def getPage(self): + """def getPage(self) + + return the Page + """ + return self.__page + + def setPage(self,page): + """def setPage(self) + + set the Page + """ + self.__page = page + + def getBudget(self): + """def getBudget(self) + + return the Budget objet + """ + return self.__budget + + def getActivePathRecord(self): + """def getActivePathRecord(self) + + return the Active Path Record + """ + return self.__active_path_record + + widget = property(getWidget, None, None, + "Pane configuration list") + path = property(getPath, setPath, None, + "path that identifie the item in the page notebook") + page = property(getPage, setPage, None, + "weak reference from Page instance which creates this class") + budget = property(getBudget, None, None, + "Budget object") + active_path_record = property(getActivePathRecord, None, None, + "Active path record") + +class Measure(TreeView): + """gui.Measure: + + Description: + Class to show a Measure List + Constructor: + Measure(budget, page, path) + budget: budget showed ("base.Budget" object) + page: weak reference from Page instance which creates this class + path: tuple that represents the path of the List in the Page + Returns the newly created DecompositionList instance + Ancestry: + +-- object + +-- TreeView + +-- DecompositionList + Atributes: + "budget": Budget to show, base.obra instance. + "__active_path_record": path of the active record in the budget + "widget or __scrolled_window": Window that contains the table, + (gtk.ScrolledWindow) + "path": Pane page identifier + "page": weak reference from Page instance which creates this class + "__active_color": The background color of the active cell as a + gtk.gdk.Color object + "__chapter_background_colors": The background colors of the Code + column cells when there is a chapter record + as a list of gtk.gdk.Color objects [even cell, uneven cell] + "__methond_message": Method to send messages to the page + "__liststore": list model which store the list data + (gtk.ListStore object) + "__treeview": widget for displaying decomposition lists (gtk.TreeView) + "__index_column": Index column (gtk.TreeViewColumn object) + "__code_column": Record code column (gtk.TreeViewColumn) + "__unit_column": Unit of measure column (gtk.TreeViewColumn) + "__description_column": record's short description column + (gtk.TreeViewColumn) + "__measure_column": Measure column (gtk.TreeViewColumn) + "__price_column": Price column (gtk.TreeViewColumn) + "__amount_column": Amount column(gtk.TreeViewColumn) + "__end_column": End empty column (gtk.TreeViewColumn) + "__treeselection": active selection + "__selection_control": state of the selection control (True/False) + "__cursor": Situation of the cursor in the table + Methods: + __init__(self, budget, page, path, path_record=(0,)) + setListstoreValues(self, path_record) + setColumnsHeaders(self) + controlSelection(self, selection) + showMessageRecord(self, record_path) + treeviewCursorChanged(self, treeview) + moveCursor(self, treeview, step, count) + treeviewClickedEvent(self, widget, event) + treeviewKeyPressEvent(self, widget, event) + runMessage(self, message, path, arg=None) + selectAll(self, column) + colorCell(self, column, cell_renderer, tree_model, iter, lcolor) + _clear(self) + getWidget(self) + {get/set}Path + {get/set}Page + getBudget(self) + getActivePathRecord(self) + """ + + def __init__(self, budget, page, path, path_record=(0,)): + """def __init__(self, budget, page, path, path_record=(0,)) + + budget: budget: budget showed ("base.Budget" object) + page: weak reference from Page instance which creates this class + path: tuple that represents the path of the List in the Page + path_record: path of the active record in the budget + + Sets the init atributes + Creates the init list values in self.__liststore from the budget + showing the top record from the record with path path_record + Creates the list in self.__treeview + * Creates the columns and cell + * Sets te the column headers values + * Sets the selection properties + * Connects the events + """ + # Seting init args + if not isinstance(budget, base.Budget): + raise ValueError, _("Argument must be a Budget object") + self.__budget = budget + self.__page = page + self.__path = path + if not isinstance(path_record, tuple): + print _("Record path must be a tuple") + path_record = (0,) + self.__active_path_record = path_record + # ListStore + self.__liststore = gtk.ListStore(object) + self.setListstoreValues(self.__active_path_record) + # Treeview + self.__treeview = gtk.TreeView(self.__liststore) + self.__treeview.set_enable_search(False) + self.__treeview.set_reorderable(False) + self.__treeview.set_headers_clickable(True) + self.__treeview.show() + # Scrolled_window + self.__scrolled_window = gtk.ScrolledWindow() + self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, + gtk.POLICY_AUTOMATIC) + self.__scrolled_window.add(self.__treeview) + # colors + _text_color = gtk.gdk.color_parse(globals.color["TEXT"]) + _calculated_text =gtk.gdk.color_parse(globals.color["CALCULATED-TEXT"]) + _background_color = [ + gtk.gdk.color_parse(globals.color["UNEVEN"]), + gtk.gdk.color_parse(globals.color["EVEN"])] + self.__chapter_background_colors = [ + gtk.gdk.color_parse(globals.color["CHAPTER-UNEVEN"]), + gtk.gdk.color_parse(globals.color["CHAPTER-EVEN"])] + super(Measure,self).__init__( + [("INDEX",self.selectAll,42), + ("PIXBUF", self.passMethod, + gtk.Label("A"*4).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATEDTEXT", self.passMethod, + gtk.Label("A"*12).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATED", self.passMethod, + gtk.Label("A"*5).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATED", self.passMethod, + gtk.Label("A"*7).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATED", self.passMethod, + gtk.Label("A"*7).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATED", self.passMethod, + gtk.Label("A"*7).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATEDTEXT", self.passMethod, + gtk.Label("A"*12).size_request()[0] +10, + _text_color, _background_color), + ("CALCULATED", self.passMethod, + gtk.Label("A"*7).size_request()[0] +10, + _calculated_text, _background_color), + ("CALCULATED", self.passMethod, + gtk.Label("A"*7).size_request()[0] +10, + _calculated_text, _background_color), + ]) + self.__index_column = self.columns[0] + self.__linetype_column = self.columns[1] + self.__comment_column = self.columns[2] + self.__units_column = self.columns[3] + self.__length_column = self.columns[4] + self.__width_column = self.columns[5] + self.__height_column = self.columns[6] + self.__formula_column = self.columns[7] + self.__parcial_column = self.columns[8] + self.__subtotal_column = self.columns[9] + self.__end_column = self.columns[10] + # Index column + self.__treeview.append_column(self.__index_column) + # Linetype column + self.__treeview.append_column(self.__linetype_column) + self.calculatedline_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("CALCULATEDLINE-ICON")) + self.normalline_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("NORMALLINE-ICON") ) + self.parcialline_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("PARCIALLINE-ICON") ) + self.acumulatedline_icon = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("ACUMULATEDLINE-ICON")) + # Comment column + self.__treeview.append_column(self.__comment_column) + # Units column + self.__treeview.append_column(self.__units_column) + # Length column + self.__treeview.append_column(self.__length_column) + # Width_column + self.__treeview.append_column(self.__width_column) + # Height column + self.__treeview.append_column(self.__height_column) + # Formula column + self.__treeview.append_column(self.__formula_column) + # Parcial column + self.__treeview.append_column(self.__parcial_column) + # Subtotal column + self.__treeview.append_column(self.__subtotal_column) + # End Column + self.__treeview.append_column(self.__end_column) + # Connect + self.__treeview.connect("move-cursor", self.moveCursor) + self.__treeview.connect("key-press-event", self.treeviewKeyPressEvent) + self.__treeview.connect("button-press-event", self.treeviewClickedEvent) + self.__treeview.connect("cursor-changed", self.treeviewCursorChanged) + # control selection + self.__treeselection = self.__treeview.get_selection() + self.__treeselection.set_mode(gtk.SELECTION_MULTIPLE) + self.__treeselection.set_select_function(self.controlSelection) + self.__selection_control = True + self.__treeview.set_cursor_on_cell((1,), self.columns[1], + self.columns[1].get_cell_renderers()[0],True) + self.__treeview.grab_focus() + self.__cursor = self.__treeview.get_cursor() + # Show + self.setColumnsHeaders() + self.__scrolled_window.show() + + def passMethod(self, args): + pass + + def setListstoreValues(self, path_record): + """def setListstoreValues(self, path_record) + + path_record: Record path in the budget + Sets the liststore record values from a path record + """ + self.__liststore.clear() + _budget = self.__budget + if not _budget.hasPath(path_record): + raise ValueError, _("Invalid path") + else: + _measure = _budget.getMeasure(path_record) + if isinstance(_measure, base.Measure): + _lines = _measure.lines + for _line in _lines: + _values = [ + _line, +## _line.type, +## _line.comment, +## _line.units, +## _line.length, +## _line.width, +## _line.height + ] + _treeiter = self.__liststore.append(_values) + else: + raise ValueError, utils.mapping(_("measure must be a Measure "\ + "object. Type: $1"), (type(_measure),)) + def setColumnsHeaders(self): + """def setColumnsHeaders(self) + + Sets the headers column values + """ + _measure = self.__budget.getMeasure(self.__active_path_record) + _DS = self.__budget.getDecimals("DS") + _total = _measure.measure + _total_str = ("%." + str(_DS) + "f" ) % _total + self.columns[1].set_title(_("Type")) # Σ parcial Σ total + self.columns[2].set_title(_("Comment")) + self.columns[3].set_title(_("N\n(a)")) + self.columns[4].set_title(_("Length\n(b)")) + self.columns[5].set_title(_("Width\n(c)")) + self.columns[6].set_title(_("Height\n(d)")) + self.columns[7].set_title(_("Formula")) + self.columns[8].set_title(_("Parcial\n[%s]" % _total_str)) + self.columns[9].set_title(_("Subtotal")) + def controlSelection(self, selection): + """def controlSelection(self, selection) + + selection: treeselection + + Method connected to set_selection_function() + This method is called before any node is selected or unselected, + giving some control over which nodes are selected. + The selection function should return TRUE if the state + of the node may be toggled, and FALSE if the state of the node should + be left unchanged. + + The selection only run if the user click in the index column, else + the previous selection is erased. + """ + _column = self.__treeview.get_cursor()[1] + if _column is self.columns[0] \ + or self.__selection_control == False: + return True + else: + self.__selection_control = False + self.__treeselection.unselect_all() + self.__selection_control = True + return False + + def showMessageRecord(self, record_path): + """def showMessageRecord(self, record_path) + + record_path: the path of the record to show + Method connected to "change_active" message + Show the record especified in the "change_active" message + """ + _budget = self.__budget + self.__active_path_record = record_path + self.setColumnsHeaders() + self.setListstoreValues(self.__active_path_record) + self.__treeview.set_cursor((0,)) + + def treeviewCursorChanged(self, treeview): + """def treeviewCursorChanged(self, treeview) + + treeview: treewiew widget + Method connected to "cursor-changed" signal + The "cursor-changed" signal is emitted when the cursor moves or is set + Sets the new cursor position in self.__cursor, it is used to avoid + unnecessary changes in cursor position. + """ + event = gtk.get_current_event() + (_cursor_path, _column) = treeview.get_cursor() + if event is None or event.type != gtk.gdk.BUTTON_RELEASE: + if not _column is self.__index_column: + self.__cursor = treeview.get_cursor() + + def moveCursor(self, treeview, step, count): + """def treeviewKeyPressEvent(self, widget, event) + + treeview: the treeview that received the signal + step: the movement step size + count: the number of steps to take + + Method connected to "move-cursor" signal + The "move-cursor" signal is emitted when the user moves the cursor + using the Right, Left, Up or Down arrow keys or the Page Up, + Page Down, Home and End keys. + + Returns :TRUE if the signal was handled. + """ + return False + + def treeviewClickedEvent(self, widget, event): + """def treeviewClickedEvent(self, widget, event) + + widget: treewiew widget + event: clicked event + Method connected to "button-press-event" signal + The "button-press-event" signal is emitted when a mouse button is + pressed. + Returns TRUE to stop other handlers from being invoked for the event. + Returns FALSE to propagate the event further. + + The events in end column are ignored. + If the user click in a row of the index column the cursor is moved to + this row but not to the index column + """ + if event.button == 1: + path_at_pos = self.__treeview.get_path_at_pos(int(event.x), + int(event.y)) + if not path_at_pos is None: + _path_cursor, _column, _x, _y = path_at_pos + if _column == self.columns[-1]: + return True + if _column is self.columns[0]: + self.__cursor[0] == _path_cursor + return False + + def treeviewKeyPressEvent(self, widget, event): + """def treeviewKeyPressEvent(self, widget, event) + + widget: treewiew widget + event: Key Press event + Method connected to "key-press-event" signal + The "key-press-event" signal is emitted when the user presses a key + on the keyboard. + Returns :TRUE to stop other handlers from being invoked for the event. + Returns :FALSE to propagate the event further. + + If the user press the right cursor button and the cursor is in the + amount column or pres the left cursor button and the cursor is + in the code column the event is estoped, else the event is propagated. + """ + (_cursor_path, _column) = self.__treeview.get_cursor() + if (event.keyval == gtk.keysyms.Right \ + and _column == self.columns[-2]) \ + or (event.keyval == gtk.keysyms.Left \ + and _column == self.columns[1]): + return True + return False + + def runMessage(self, message, path, arg=None): + """def runMessage(self, message, path, arg=None) + + message: the message type + "change_active": change the active record + "clear": clear instance + path: tuple that identifies the pane in the notebook page + arg: tuple whit two items: + 0: record path in the budget + 1: record code + This method receives a message and executes its corresponding action + """ + _budget = self.__budget + if message == "change_active": + if _budget.hasPath(arg): + _path_record = arg + self.showMessageRecord( _path_record) + elif message == "clear": + self._clear() + + def selectAll(self, column): + """def selectAll(self, column) + + column: index column + Method connected to "clicked" event in the index column + If the user clickes in the index column header selecs or deselects + all rows + """ + (_model, _pathlist) = self.__treeselection.get_selected_rows() + # it avoid to set cursor in the index column + self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) + self.__selection_control = False + if len(_pathlist) == 0: + # select all + self.__treeselection.select_all() + else: + # unselect all + self.__treeselection.unselect_all() + self.__selection_control = True + + def colorCell(self, column, cell_renderer, tree_model, iter, lcolor): + """def colorCell(self, column, cell_renderer, tree_model, iter, lcolor) + + column: the gtk.TreeViewColumn in the treeview + cell_renderer: a gtk.CellRenderer + tree_model: the gtk.TreeModel + iter: gtk.TreeIter pointing at the row + lcolor: list with 2 gtk colors for even and uneven record + + Method connected to "set_cell_data_func" of many column + The set_cell_data_func() method sets the data function (or method) + to use for the column gtk.CellRenderer specified by cell_renderer. + This function (or method) is used instead of the standard attribute + mappings for setting the column values, and should set the attributes + of the cell renderer as appropriate. func may be None to remove the + current data function. The signature of func is: + -def celldatafunction(column, cell, model, iter, user_data) + -def celldatamethod(self, column, cell, model, iter, user_data) + where column is the gtk.TreeViewColumn in the treeview, cell is the + gtk.CellRenderer for column, model is the gtk.TreeModel for the + treeview and iter is the gtk.TreeIter pointing at the row. + + The method sets cell background color for all columns + and text for index and amount columns. + """ + _row_path = tree_model.get_path(iter) + _number = _row_path[-1] + if column is self.__index_column: + cell_renderer.set_property('text', str(_number + 1)) + self.__index_column.get_cell_renderers()[1].set_property( + 'cell-background-gdk', lcolor[_number % 2]) + elif column is self.__linetype_column: + _measure = tree_model[_row_path][0] + _type = _measure.lineType + if _type == 0: + cell_renderer.set_property("pixbuf",self.normalline_icon) + elif _type == 1: + cell_renderer.set_property("pixbuf",self.parcialline_icon) + elif _type == 2: + cell_renderer.set_property("pixbuf", + self.acumulatedline_icon) + else: #elif _type == 3: + cell_renderer.set_property("pixbuf", + self.calculatedline_icon) + + elif column is self.__comment_column: + _measure = tree_model[_row_path][0] + _comment = str(_measure.comment) + cell_renderer.set_property('text', _comment) + elif column is self.__units_column: + _measure = tree_model[_row_path][0] + _units = _measure.units + if isinstance(_units, float): + _DN = self.__budget.getDecimals("DN") + _units = ("%." + str(_DN) + "f" ) % _units + cell_renderer.set_property('text', _units) + elif column is self.__length_column: + _measure = tree_model[_row_path][0] + _length = _measure.length + if isinstance(_length, float): + _DD = self.__budget.getDecimals("DD") + _length = ("%." + str(_DD) + "f" ) % _length + cell_renderer.set_property('text', _length) + elif column is self.__width_column: + _measure = tree_model[_row_path][0] + _width = _measure.width + if isinstance(_width, float): + _DD = self.__budget.getDecimals("DD") + _width = ("%." + str(_DD) + "f" ) % _width + cell_renderer.set_property('text', _width) + elif column is self.__height_column: + _measure = tree_model[_row_path][0] + _height = _measure.height + if isinstance(_height, float): + _DD = self.__budget.getDecimals("DD") + _height = ("%." + str(_DD) + "f" ) % _height + cell_renderer.set_property('text', _height) + elif column is self.__formula_column: + _measure = tree_model[_row_path][0] + _formula = _measure.formula + cell_renderer.set_property('text', _formula) + elif column is self.__parcial_column: + _measure_line = tree_model[_row_path][0] + _parcial = _measure_line.parcial + _type = _measure_line.lineType + if _type == 1 or _type == 2: + _parcial = "" + else: + if isinstance(_parcial, float): + _DS = self.__budget.getDecimals("DS") + _parcial = ("%." + str(_DS) + "f" ) % _parcial + cell_renderer.set_property('text', _parcial) + elif column is self.__subtotal_column: + _measure_line = tree_model[_row_path][0] + _type = _measure_line.lineType + if _type == 1 or _type == 2: + if _type == 1: + _color = gtk.gdk.color_parse( + globals.color["SUBTOTAL-PARCIAL"]) + _subtotal = _measure_line.parcial_subtotal + else: #elif _type == 2: + _color = gtk.gdk.color_parse(globals.color["SUBTOTAL"]) + _subtotal = _measure_line.acumulated_subtotal + lcolor = [_color, _color] + if isinstance(_subtotal, float): + _DS = self.__budget.getDecimals("DS") + _subtotal= ("%." + str(_DS) + "f" ) % _subtotal + cell_renderer.set_property('text', _subtotal) + else: + cell_renderer.set_property('text', "") + + if self.__treeview.get_cursor() == (_row_path,column): + cell_renderer.set_property('cell-background-gdk', + gtk.gdk.color_parse(globals.color["ACTIVE"])) + else: + cell_renderer.set_property('cell-background-gdk', + lcolor[_number % 2]) + + def _clear(self): + """def _clear(self) + + it deletes the __budget value + this would not be necessary if there were not circular references, + which are pending to fix + """ + del self.__budget + + def getWidget(self): + """def getWidget(self) + + return the main widget (gtk.ScrolledWindow) + """ + return self.__scrolled_window + + def getPath(self): + """def getPath(self) + + return the tuple that identifies the pane in the notebook page + """ + return self.__path + + def setPath(self, path): + """def setPath(self) + + sets the tuple that identifies the pane in the notebook page + """ + self.__path = path + def getPage(self): + """def getPage(self) + + return the Page + """ + return self.__page + + def setPage(self,page): + """def setPage(self) + + set the Page + """ + self.__page = page + + def getBudget(self): + """def getBudget(self) + + return the Budget objet + """ + return self.__budget + + def getActivePathRecord(self): + """def getActivePathRecord(self) + + return the Active Path Record + """ + return self.__active_path_record + + widget = property(getWidget, None, None, + "Pane configuration list") + path = property(getPath, setPath, None, + "Path that identifies the item in the page notebook") + page = property(getPage, setPage, None, + "Weak reference from Page instance which creates this class") + budget = property(getBudget, None, None, + "Budget object") + active_path_record = property(getActivePathRecord, None, None, + "Active Code") + +class Description(object): + """gui.Description + + Description: + Class to show a description text of a record in a pane + Constructor: + Description(budget, code) + budget: budget + code: code record + Ancestry: + +-- object + +-- Description + Atributes: + "widget": the main widget (gtk.ScrolledWindow object) + "path": the tuple that identifies the pane in the notebook page + TODO + "budget": The budget (base.obra objetc) + "active_code": The active code of the record + "__textbuffer": The textbuffer of the textview that contain + the record text. + "__label": The gtk.label with the title of the pane + Methods: + __init__(self, budget, code) + setActiveCode(self, code) + runMessage(self, message, nt, arg=None) + _clear(self) + getWidget(self) + {get/set}Path + {get/seg}Page + getBudget(self) + getActviCode(self) + """ + # TODO: make standar: "DecompositonList and Description" + def __init__(self, budget, page, path, path_record=(0,)): + """def __init__(self, budget, page, path, path_record=(0,)) + + budget: the budget (base.obra object) + page: weak reference from Page instance which creates this class + path: the path position of the description in the page + path_record: the path of the active record + + Creates an shows the scroledwindow that contain the description text + of the record to be showed in a pane. + """ + self.__budget = budget + self.__page = page + self.__path = path + self.__active_path_record = path_record + _budget = budget + _text = _budget.getRecord(self.__budget.getCode( + self.__active_path_record)).text + _scrollwindow = gtk.ScrolledWindow() + _scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, + gtk.POLICY_AUTOMATIC) + _textview = gtk.TextView() + _textview.set_wrap_mode(gtk.WRAP_WORD) + self.__textbuffer = _textview.get_buffer() + self.__textbuffer.set_text(_text) + _textview.show() + _hbox = gtk.HBox() + _hbox.pack_start(_textview, True, True, 5) + _hbox.show() + _vbox = gtk.VBox() + self.__label = gtk.Label(utils.mapping(_("Description text of the "\ + "record $1"), (self.__budget.getCode( + self.__active_path_record),))) + self.__label.set_alignment(0, 0) + self.__label.show() + _vbox.pack_start(self.__label, False, False, 5) + _vbox.pack_start(_hbox, True, True, 5) + _vbox.show() + _scrollwindow.add_with_viewport(_vbox) + _scrollwindow.show() + self.__widget = _scrollwindow + + + def setActivePathRecord(self, path_record): + """def setActivePathRecord(self, path_record)) + + path_record: active path record + Set the new path code to show its description text. + """ + _budget = self.__budget + self.__active_path_record = path_record + _code = _budget.getCode(self.__active_path_record) + self.__label.set_text(utils.mapping(_("Description text of the record "\ + "$1"), (_code,))) + _text = _budget.getRecord(_code).text + self.__textbuffer.set_text(_text) + + def runMessage(self, message, path, arg=None): + """def runMessage(self, message, path, arg=None) + + message: the message type + "change_active": change the active record + "clear": clear instance + path: tuple that identifies the pane in the notebook page + arg: tuple whit two items: + 0: record path in the budget + 1: record code + This method receives a message and executes its corresponding action + """ + _budget = self.__budget + if message == "change_active": + if _budget.hasPath(arg): + self.setActivePathRecord(arg) + elif message == "clear": + self._clear() + + def _clear(self): + """def _clear(self) + + Delete all instance atributes + """ + del self.__widget + del self.__path + del self.__budget + del self.__active_code + del self.__textbuffer + del self.__label + + def getWidget(self): + """def getWidget(self) + + return the main widget (gtk.ScrolledWindow) + """ + return self.__widget + + def getPath(self): + """def getPath(self) + + return the tuple that identifies the pane in the notebook page + """ + return self.__path + + def setPath(self, path): + """def setPath(self) + + sets the tuple that identifies the pane in the notebook page + """ + self.__path = path + + def getPage(self): + """def getPage(self) + + return the weak reference from Page instance + """ + return self.__page + + def setPage(self, page): + """def setPage(self) + + set the weak reference from Page instance + """ + self.__page = page + + def getBudget(self): + """def getBudget(self) + + return the budget object + """ + return self.__budget + + def getActivePathRecord(self): + """def getActivePathRecord(self) + + return the Active Path Record + """ + return self.__active_path_record + + path = property(getPath, setPath, None, + "Path that identifie the item in the page notebook") + widget = property(getWidget, None, None, + "The main widget (gtk.ScrolledWindow)") + page = property(getPage, setPage, None, + "Weak reference from Page instance which creates this class") + budget = property(getBudget, None, None, + "Budget object") + active_path_record = property(getActivePathRecord, None, None, + "Active Path Record") + +class Sheet(object): + """gui.Sheet + + Description: + Class to show a sheeet of conditions text of a record in a pane + Constructor: + Sheet(budget, code) + budget: budget object + code: code record + Ancestry: + +-- object + +-- Sheet + Atributes: + "widget": the main widget (gtk.ScrolledWindow object) + "path": the tuple that identifies the pane in the notebook page + "budget": The budget (base.obra objetc) + "active_path_record": The active path record + "page": weak reference from Page instance which creates this class + + "__textbuffer": The textbuffer of the textview that contain + the record text. + "__label": The gtk.label with the title of the pane + "__field_liststore": the field liststore + "__field_treeview": the field treeview + "__field_selection": the field selected in field treview + "__section_liststore": the section liststore + "__section_treeview": the section treeview + "__section_selection": the section selected in the section treeview + Methods: + __init__(self, budget, code) + setFields(self) + setSection(self) + setText(self) + field_controlSelection(self, selection) + section_controlSelection(self, selection) + runMessage(self, message, nt, arg=None) + _clear(self) + getWidget(self) + {get/set}Path + {get/set}Page + getBudget(self) + getActviPathRecord(self) + """ + def __init__(self, budget, page, path, path_record=(0,)): + """def __init__(self, budget, page, path, path_record=(0,)) + + budget: the budget (base.obra object) + page: weak reference from Page instance which creates this class + path: the path position of the description in the page + path_record: the path of the active record + Creates an shows the scroledwindow that contain the description text + of the record to be showed in a pane. + """ + self.__budget = budget + self.__page = page + self.__path = path + self.__active_path_record = path_record + _budget = budget + + _main_box = gtk.VBox() + + self.__label = gtk.Label(utils.mapping(_("Sheet of Conditions of the "\ + "record $1"), (self.__budget.getCode( + self.__active_path_record),))) + self.__label.set_alignment(0, 0) + self.__label.show() + + _frame = gtk.Frame() + _frame.set_shadow_type(gtk.SHADOW_IN) + _frame_box = gtk.VBox() + _list_box = gtk.HBox() + + self.__field_liststore = gtk.ListStore(str, str) + self.__field_treeview = gtk.TreeView(self.__field_liststore) + _field_treeselection = self.__field_treeview.get_selection() + _field_treeselection.set_mode(gtk.SELECTION_SINGLE) + self.__field_selection = None + _field_treeselection.set_select_function( + self.field_controlSelection) + self.__field_treeview.show() + _fieldcode_cell = gtk.CellRendererText() + _field_column = gtk.TreeViewColumn(_("Field")) + _field_column.pack_start(_fieldcode_cell, False) + _field_cell = gtk.CellRendererText() + _field_column.pack_end(_field_cell, True) + _field_column.add_attribute(_fieldcode_cell, "text", 0) + _field_column.add_attribute(_field_cell, "text", 1) + self.__field_treeview.append_column(_field_column) + _field_scrollwindow = gtk.ScrolledWindow() + _field_scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, + gtk.POLICY_AUTOMATIC) + _field_scrollwindow.add(self.__field_treeview) + _field_scrollwindow.show() + + self.__section_liststore = gtk.ListStore(str, str) + self.__section_treeview = gtk.TreeView(self.__section_liststore) + _section_treeselection = self.__section_treeview.get_selection() + _section_treeselection.set_mode(gtk.SELECTION_SINGLE) + self.__section_selection = None + _section_treeselection.set_select_function( + self.section_controlSelection) + self.__section_treeview.show() + _sectioncode_cell = gtk.CellRendererText() + _section_column = gtk.TreeViewColumn(_("Section")) + _section_column.pack_start(_sectioncode_cell, False) + _section_column.add_attribute(_sectioncode_cell, "text", 0) + _section_cell = gtk.CellRendererText() + _section_column.pack_end(_section_cell, True) + _section_column.add_attribute(_section_cell, "text", 1) + self.__section_treeview.append_column(_section_column) + _section_scrollwindow = gtk.ScrolledWindow() + _section_scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, + gtk.POLICY_AUTOMATIC) + _section_scrollwindow.add(self.__section_treeview) + _section_scrollwindow.show() + + _list_box.pack_start(_field_scrollwindow, True, True, 5) + _list_box.pack_start(_section_scrollwindow, True, True, 5) + _list_box.show() + + _scrollwindow = gtk.ScrolledWindow() + _scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, + gtk.POLICY_AUTOMATIC) + _textview = gtk.TextView() + _textview.set_wrap_mode(gtk.WRAP_WORD) + self.__textbuffer = _textview.get_buffer() + _textview.show() + _hbox = gtk.HBox() + _hbox.pack_start(_textview, True, True, 5) + _hbox.show() + + _frame_box.pack_start(self.__label, False, False, 5) + _frame_box.pack_start(_list_box, False, False, 5) + _frame_box.show() + _frame.add(_frame_box) + _frame.show() + _main_box.pack_start(_frame, False) + + + _vbox = gtk.VBox() + _vbox.pack_start(_hbox, True, True, 5) + _vbox.show() + _main_box.pack_start(_scrollwindow, True, True, 5) + _main_box.show() + + _scrollwindow.add_with_viewport(_vbox) + _scrollwindow.show() + self.__widget = _main_box + + self.setFields() + + def setFields(self): + """setFields(self) + + Set the fields items in the field treeview + """ + _record = self.__budget.getRecord(self.__budget.getCode( + self.__active_path_record)) + _sheet = _record.getSheet() + _field_list = _sheet.getFields() + self.__field_liststore.clear() + for _field in _field_list: + _field_text = self.__budget.getSheetField(_field) + _iter = self.__field_liststore.append([_field, _field_text]) + _treeselection = self.__field_treeview.get_selection() + _treeselection.select_path(0) + + def setSection(self): + """setSection(self) + + Set the section items in the section treeview + """ + self.__section_liststore.clear() + if not self.__field_selection is None: + _record = self.__budget.getRecord(self.__budget.getCode( + self.__active_path_record)) + _sheet = _record.getSheet() + _section_list = _sheet.getSections(self.__field_selection) + for _section in _section_list: + _section_text = self.__budget.getSheetSection(_section) + _iter = self.__section_liststore.append([_section, _section_text]) + _treeselection = self.__section_treeview.get_selection() + _treeselection.select_path(0) + + def setText(self): + """setText(self) + + Set the text in the textview + """ + if not self.__section_selection is None and\ + not self.__field_selection is None: + _record = self.__budget.getRecord(self.__budget.getCode( + self.__active_path_record)) + _sheet = _record.getSheet() + _paragraph_code = _sheet.getParagraph(self.__field_selection, + self.__section_selection) + _paragraph = self.__budget.getSheetParagraph(_paragraph_code) + self.__textbuffer.set_text(_paragraph) + else: + self.__textbuffer.set_text("") + + def field_controlSelection(self, selection): + """def controlSelection(self, selection) + + selection: treeselection + + Method connected to set_selection_function() in field treeview + This method is called before any node is selected or unselected, + giving some control over which nodes are selected. + The selection function should return TRUE if the state + of the node may be toggled, and FALSE if the state of the node should + be left unchanged. + + When a user select a row in the field treeview the section treeview is + reloaded to show the sections of this field and already the text sheet. + """ + _treeiter = self.__field_liststore.get_iter(selection) + self.__field_selection = self.__field_liststore.get_value(_treeiter, 0) + self.setSection() + return True + + def section_controlSelection(self, selection): + """def controlSelection(self, selection) + + selection: treeselection + + Method connected to set_selection_function() in sector treeview + This method is called before any node is selected or unselected, + giving some control over which nodes are selected. + The selection function should return TRUE if the state + of the node may be toggled, and FALSE if the state of the node should + be left unchanged. + + When a user select a row in the field treeview the text sheet for this + section in showed + """ + _treeiter = self.__section_liststore.get_iter(selection) + self.__section_selection = self.__section_liststore.get_value(_treeiter, 0) + self.setText() + return True + + def setActivePathRecord(self, path_record): + """def setActivePathRecord(self, path_record)) + + path_record: active path record + + Set the new path code to show its sheet of condition text. + """ + self.__field_selection = None + self.__field_liststore.clear() + self.__section_selection = None + self.__section_liststore.clear() + self.__textbuffer.set_text("") + _budget = self.__budget + self.__active_path_record = path_record + _code = _budget.getCode(self.__active_path_record) + self.__label.set_text(utils.mapping(_("Sheet2 of Conditions of the "\ + "record $1"), (_code,))) + self.setFields() + + def runMessage(self, message, path, arg=None): + """def runMessage(self, message, path, arg=None) + + message: the message type + "change_active": change the active record + "clear": clear instance + path: tuple that identifies the pane in the notebook page + arg: tuple whit two items: + 0: record path in the budget + 1: record code + This method receives a message and executes its corresponding action + """ + _budget = self.__budget + if message == "change_active": + if _budget.hasPath(arg): + self.setActivePathRecord(arg) + elif message == "clear": + self._clear() + + def _clear(self): + """def _clear(self) + + Deletes all the instance atributes + """ + del self.__page + del self.__widget + del self.__path + del self.__budget + del self.__active_code + del self.__textbuffer + del self.__label + del self.__textbuffer + del self.__label + del self.__field_liststore + del self.__field_treeview + del self.__field_selection + del self.__section_liststore + del self.__section_treeview + del self.__section_selection + + def getWidget(self): + """def getWidget(self) + + return the main widget (gtk.ScrolledWindow) + """ + return self.__widget + + def getPath(self): + """def getPath(self) + + return the tuple that identifies the pane in the notebook page + """ + return self.__page + + def setPath(self, path): + """def setPath(self) + + sets the tuple that identifies the pane in the notebook page + """ + self.__path = path + + def getPage(self): + """def getPage(self) + + return the weak reference from Page instance + """ + return self.__page + + def setPage(self, page): + """def setPage(self) + + set the weak reference from Page instance + """ + self.__page = page + + def getBudget(self): + """def getBudget(self) + + return the budget object + """ + return self.__budget + + def getActivePathRecord(self): + """def getActivePathRecord(self) + + return the Active Path Record + """ + return self.__active_path_record + + path = property(getPath, setPath, None, + "Path that identifie the item in the page notebook") + widget = property(getWidget, None, None, + "Lista de configuracion de vistas") + page = property(getPage, setPage, None, + "Weak reference from Page instance which creates this class") + budget = property(getBudget, None, None, + "Budget object") + active_path_record = property(getActivePathRecord, None, None, + "Active Path Record") + +class FileView(object): + """gui.FileView + + Description: + Class to show the file icons of a record in a pane + Constructor: + Description(budget, code) + budget: budget + code: code record + Ancestry: + +-- object + +-- Description + Atributes: + "widget": the main widget (gtk.ScrolledWindow object) + "__icon_box": the box that contains the icon + "path": the tuple that identifies the pane in the notebook page + "budget": The budget (base.obra objetc) + "active_code": The active code of the record + Methods: + __init__(self, budget, code) + setActiveCode(self, code) + runMessage(self, message, nt, arg=None) + _clear(self) + getWidget(self) + {get/set}Path + {get/seg}Page + getBudget(self) + getActviCode(self) + """ + + def __init__(self, budget, page, path, path_record=(0,)): + """def __init__(self, budget, page, path, path_record=(0,)) + + budget: the budget (base.obra object) + page: weak reference from Page instance which creates this class + path: the path position of the description in the page + path_record: the path of the active record + + Creates an shows the scroledwindow that contain icon files + of the record to be showed in a pane. + """ + self.__budget = budget + self.__page = page + self.__path = path + self.__active_path_record = path_record + self.__active_code = budget.getCode(self.__active_path_record) + _budget = budget + _record = self.__budget.getRecord(self.__budget.getCode( + self.__active_path_record)) + + self.__icon_box = self.getIconBox(_record) + _scrollwindow = gtk.ScrolledWindow() + _scrollwindow.set_policy(gtk.POLICY_ALWAYS, + gtk.POLICY_NEVER) + + self.__icon_box.show() + _scrollwindow.add_with_viewport(self.__icon_box) + _scrollwindow.show() + self.__widget = _scrollwindow + + def getIconBox(self, record): + """getIconBox(self, record) + + record: the active record object + + Creates and returns the box whith te icon files of the active record. + """ + ## TODO: add others filetypes: avi, pdf, ppt... + _files = record.getFiles() + _hbox = gtk.HBox() + _frame = gtk.Frame() + _frame.set_shadow_type(gtk.SHADOW_IN) + for _file in _files: + _path = os.path.dirname(self.__budget.filename) + _file_path = os.path.join(_path, _file.name) + _filetype = utils.getFiletype(_file_path) + _box = gtk.VBox() + if _filetype == "image": + _event_box = gtk.EventBox() + try: + _image_pixbuf = gtk.gdk.pixbuf_new_from_file(_file_path) + _image_pixbuf = _image_pixbuf.scale_simple(64, 64, + gtk.gdk.INTERP_BILINEAR) + except: + _image_pixbuf = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("IMAGE-ICON")) + _image_pixbuf = _image_pixbuf.scale_simple(64, 64, + gtk.gdk.INTERP_BILINEAR) + _image_icon = gtk.Image() + _image_icon.set_from_pixbuf(_image_pixbuf) + _image_icon.show() + _event_box.add(_image_icon) + _box.pack_start(_event_box, False, False, 5) + _event_box.connect("button-press-event", self.launchFile, + "image", _file_path) + _event_box.show() + + elif _filetype == "dxf": + _event_box = gtk.EventBox() + _dxf_icon = gtk.Image() + _dxf_pixbuf = gtk.gdk.pixbuf_new_from_file( + globals.getAppPath("DXF-ICON")) + _dxf_pixbuf = _dxf_pixbuf.scale_simple(64, 64, + gtk.gdk.INTERP_BILINEAR) + _dxf_icon.set_from_pixbuf(_dxf_pixbuf) + _dxf_icon.show() + _event_box.add(_dxf_icon) + _box.pack_start(_event_box, False, False, 5) + _event_box.connect("button-press-event", self.launchFile, + "dxf", _file_path) + _event_box.show() + _label_event_box = gtk.EventBox() + _label = gtk.Label(_file.name) + _label_event_box.add(_label) + _label_event_box.show() + _label.show() + _box.pack_start(_label_event_box, False, False, 5) + _box.show() + _hbox.pack_start(_box, False, False, 5) + _hbox.show() + _frame.add(_hbox) + return _frame + + def launchFile(self, widget, event, kind, file_path): + """launchFile(self, widget, event, kind, file_path) + + widget: the widget that emit the signal + event: the event that emit the signal + king: kind of file + file_path: the path file to be launch + + Launch the file if a double click emit the signal. + Method connected to "button-press-event" signal in images event box + """ + if event.type is gtk.gdk._2BUTTON_PRESS: + openwith.launch_file(kind, file_path) + + def setActivePathRecord(self, path_record): + """def setActivePathRecord(self, path_record)) + + path_record: active path record + Set the new path code to show its description text. + """ + _budget = self.__budget + self.__active_path_record = path_record + _code = _budget.getCode(self.__active_path_record) + _record = self.__budget.getRecord(_code) + self.__icon_box.destroy() + self.__icon_box = self.getIconBox(_record) + self.__icon_box.show() + self.__widget.add_with_viewport(self.__icon_box) + + def runMessage(self, message, path, arg=None): + """def runMessage(self, message, path, arg=None) + + message: the message type + "change_active": change the active record + "clear": clear instance + path: tuple that identifies the pane in the notebook page + arg: tuple whit two items: + 0: record path in the budget + 1: record code + This method receives a message and executes its corresponding action + """ + _budget = self.__budget + if message == "change_active": + if _budget.hasPath(arg): + self.setActivePathRecord(arg) + elif message == "clear": + self._clear() + + def _clear(self): + """def _clear(self) + + Delete all instance atributes + """ + del self.__hbox + del self.__widget + del self.__path + del self.__budget + del self.__active_code + + def getWidget(self): + """def getWidget(self) + + return the main widget (gtk.ScrolledWindow) + """ + return self.__widget + + def getPath(self): + """def getPath(self) + + return the tuple that identifies the pane in the notebook page + """ + return self.__path + + def setPath(self, path): + """def setPath(self) + + sets the tuple that identifies the pane in the notebook page + """ + self.__path = path + + def getPage(self): + """def getPage(self) + + return the weak reference from Page instance + """ + return self.__page + + def setPage(self, page): + """def setPage(self) + + set the weak reference from Page instance + """ + self.__page = page + + def getBudget(self): + """def getBudget(self) + + return the budget object + """ + return self.__budget + + def getActivePathRecord(self): + """def getActivePathRecord(self) + + return the Active Path Record + """ + return self.__active_path_record + + path = property(getPath, setPath, None, + "Path that identifie the item in the page notebook") + widget = property(getWidget, None, None, + "The main widget (gtk.ScrolledWindow)") + page = property(getPage, setPage, None, + "Weak reference from Page instance which creates this class") + budget = property(getBudget, None, None, + "Budget object") + active_path_record = property(getActivePathRecord, None, None, + "Active Path Record") + + +class TextWindow(object): + """gui.TextWindow + + Description: + Class to show a description text of a record in a new gtk window + Constructor: + TextWindow(code, text) + code: code of the record + text: description text of the record + Ancestry: + +-- object + +-- TextWindow + Atributes: + Methods: + __init__(self, code, text) + main(self) + destroy(self, widget) + """ + + def __init__(self, code, text): + """def __init__(self, code, text) + + code: code of the record + text: description text of the record + Creates an shows the window. + """ + _window = gtk.Window(gtk.WINDOW_TOPLEVEL) + _window.set_resizable(True) + _window.set_default_size(700, 300) + _window.set_title(utils.mapping(_("$1 text"), (code,))) + _window.set_border_width(0) + _box1 = gtk.VBox(False, 0) + _window.add(_box1) + _box1.show() + _sw = gtk.ScrolledWindow() + _sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + _textview = gtk.TextView() + _textview.set_wrap_mode(gtk.WRAP_WORD) + _textbuffer = _textview.get_buffer() + _sw.add(_textview) + _sw.show() + _textview.show() + _box1.pack_start(_sw) + _textbuffer.set_text(text) + _window.connect("destroy", self.destroy) + _window.show() + + def main(self): + """def main(self) + + Starts the GTK+ event processing loop. + """ + gtk.main() + + def destroy(self, widget): + """destroy(self, widget) + widget: the widget where the event is emitted from + Method connected to "destroy" signal of window widget + This signal is emited when the method connected to "delete_event" + signal returns True or when the program call the destroy() method of + the gtk.Window widget. + The window is closed and the GTK+ event processing loop is ended. + """ + gtk.main_quit() + +class CompanyView(object): + """gui.CompanyView: + + Description: + Class to show the company records of a budget + Constructor: + CompanyView(budget, page, path) + budget: budget showed ("base.Budget" object) + page: weak reference from Page instance which creates this class + path: tuple that represents the path of the List in the Page + Returns the newly created CompanyView instance + Ancestry: + +-- object + +-- CompanyView + Atributes: + "budget": Budget to show, base.obra instance. + "active_path_record" + "widget": Window that contains the main widget, + (gtk.ScrolledWindow) + "path": Pane page identifier + "page": weak reference from Page instance which creates this class + "__methond_message": Method to send messages to the page + Methods: + __init__(self, budget, page, path, path_record=(0,)) + runMessage(self, message, path, arg=None) + _clear(self) + getWidget(self) + {get/set}Path + {get/set}Page + getBudget(self) + getActivePathRecord(self) + """ + + def __init__(self, budget, page, path, path_record=(0,)): + """def __init__(self, budget, page, path, path_record=(0,)) + + budget: budget: budget showed ("base.Budget" object) + page: weak reference from Page instance which creates this class + path: tuple that represents the path of the List in the Page + path_record: path of the active record in the budget + + Sets the init atributes + Creates the + + """ + self.__selection = None + # Seting init args + if not isinstance(budget, base.Budget): + raise ValueError, _("Argument must be a Budget object") + self.__budget = budget + self.__page = page + self.__path = path + self.__active_path_record = path_record + # HVox + self.__hbox = gtk.HPaned() + self.__hbox.set_position(230) + # TreeStore + self.__treestore = gtk.TreeStore(str, str) + self.setTreeStoreValues() + # Select Treeview + self.__select_treeview = gtk.TreeView(self.__treestore) + self.__select_treeview.set_enable_search(False) + self.__select_treeview.set_reorderable(False) + self.__select_treeview.set_headers_visible(False) + self.__select_treeview.show() + # Scrolled_window + self.__scrolled_window = gtk.ScrolledWindow() + self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, + gtk.POLICY_AUTOMATIC) + self.__scrolled_window.add(self.__select_treeview) + # colors + _text_color = gtk.gdk.color_parse(globals.color["TEXT"]) + _background_color = [ + gtk.gdk.color_parse(globals.color["UNEVEN"]), + gtk.gdk.color_parse(globals.color["EVEN"])] + self.__code_column = gtk.TreeViewColumn() + self.__code_column.set_clickable(True) + self.__code_column.set_fixed_width(200) + _code_cell = gtk.CellRendererText() + _code_cell.set_property('foreground-gdk', _text_color) + self.__code_column.pack_start(_code_cell, True) + self.__code_column.add_attribute(_code_cell, 'text', 0) + _summary_cell = gtk.CellRendererText() + _summary_cell.set_property('foreground-gdk', _text_color) + self.__code_column.pack_start(_summary_cell, True) + self.__code_column.add_attribute(_summary_cell, 'text', 1) + # Index column + self.__select_treeview.append_column(self.__code_column) + # control selection + self.__treeselection = self.__select_treeview.get_selection() + self.__treeselection.set_mode(gtk.SELECTION_SINGLE) + self.__treeselection.set_select_function(self.controlSelection) + # Show + self.setColumnsHeaders() + self.__scrolled_window.show() + # Option View + self.__option_View = OptionView("") + # Selection + self.__select_treeview.set_cursor((0,), None, False) + self.__select_treeview.grab_focus() + # + self.__hbox.add1(self.__scrolled_window) + self.__hbox.add2(self.__option_View.widget) + self.__hbox.show() + self.__widget = self.__hbox + + def setOptions(self, type): + if type == "company": + _options = [("code", _("Code"), "string", + _("""Code that define the company""")), + ("summary", _("Summary"), "string", + _("""Summary of the company name""")), + ("name", _("Name"), "string", + _("""Complete name""")), + ("cif", _("CIF"), "string", + _("""Fiscal identifier number""")), + ("web", _("Web"), "string", + _("""Company web page""")), + ("email", _("Email"), "string", + _("""Company email""")), + ] + self.__option_View.setOptions(_options) + elif type == "office": + _options = [("type", _("Type"), "string", + _("""Type of Office: + C: Central office + D: Local office + R: Performer""")), + ("subname", _("Name"), "string", + _("Office name")), + ("address", _("Address"), "string",""), + ("postal code", _("Postal code"), "string",""), + ("town", _("Town"), "string",""), + ("province", _("Province"), "string",""), + ("country", _("Country"), "string",""), + ("phone", _("Phone"), "list", + _("Phone numbers of the office")), + ("fax", _("Fax"), "list", + _("Fax numbers of the office")), + ("contact person", _("Contact person"), "string", + _("Contact persons in the office")), + ] + self.__option_View.setOptions(_options) + else: + print _("Unknow Option Type") + def setOptionValues(self, company_key): + self.__option_View.setValues(_values) + + def setTreeStoreValues(self): + """def setListstoreValues(self) + + Sets the treestore values from the budget + """ + _budget = self.__budget + _company_keys = _budget.getCompanyKeys() + for _company_key in _company_keys: + _company = _budget.getCompany(_company_key) + _values = [_company_key, _company.summary] + _treeiter = self.__treestore.append(None, _values) + _offices = _company.offices + for _office in _offices: + # TODO: Test offices + _values = [_office.officeType, _office.subname] + self.__treestore.append(_treeiter, _values) + + def setColumnsHeaders(self): + """def setColumnsHeaders(self) + + Sets the headers column values + """ + #self.columns[1].set_title(_("Type")) # Σ parcial Σ total + #self.columns[2].set_title(_("Comment")) + #self.columns[3].set_title(_("N")) + #self.columns[4].set_title(_("Length")) + #self.columns[5].set_title(_("Width")) + #self.columns[6].set_title(_("Height")) + pass + + def controlSelection(self, selection): + """def controlSelection(self, selection) + + selection: selection + + Method connected to set_selection_function() + This method is called before any node is selected or unselected, + giving some control over which nodes are selected. + The selection function should return TRUE if the state + of the node may be toggled, and FALSE if the state of the node should + be left unchanged. + + The selection changes the company/office in the option treeview + """ + if len(selection) == 1: + # The selection is a company + _company_key = self.__treestore[selection][0] + _company = self.__budget.getCompany(_company_key) + _selection = "company" + _values = _company.values + else: + # The selection is a office + _company_key = self.__treestore[selection[:1]][0] + _company = self.__budget.getCompany(_company_key) + _selection = "office" + _office = _company.offices[selection[1]] + _values = _office.values + if not self.__selection == _selection: + self.__selection = _selection + self.setOptions(_selection) + self.__option_View.setValues(_values) + + return True + + def showMessageRecord(self, record_path): + """def showMessageRecord(self, record_path) + + record_path: the path of the record to show + Method connected to "change_active" message + Show the record especified in the "change_active" message + """ + self.__active_path_record = record_path + + def runMessage(self, message, path, arg=None): + """def runMessage(self, message, path, arg=None) + + message: the message type + "change_active": change the active record + "clear": clear instance + path: tuple that identifies the pane in the notebook page + arg: tuple whit two items: + 0: record path in the budget + 1: record code + This method receives a message and executes its corresponding action + """ + _budget = self.__budget + if message == "change_active": + if _budget.hasPath(arg): + _path_record = arg + self.showMessageRecord( _path_record) + pass + elif message == "clear": + self._clear() + + def colorCell(self, column, cell_renderer, tree_model, iter, lcolor): + """def colorCell(self, column, cell_renderer, tree_model, iter, lcolor) + + column: the gtk.TreeViewColumn in the treeview + cell_renderer: a gtk.CellRenderer + tree_model: the gtk.TreeModel + iter: gtk.TreeIter pointing at the row + lcolor: list with 2 gtk colors for even and uneven record + + Method connected to "set_cell_data_func" of many column + The set_cell_data_func() method sets the data function (or method) + to use for the column gtk.CellRenderer specified by cell_renderer. + This function (or method) is used instead of the standard attribute + mappings for setting the column values, and should set the attributes + of the cell renderer as appropriate. func may be None to remove the + current data function. The signature of func is: + -def celldatafunction(column, cell, model, iter, user_data) + -def celldatamethod(self, column, cell, model, iter, user_data) + where column is the gtk.TreeViewColumn in the treeview, cell is the + gtk.CellRenderer for column, model is the gtk.TreeModel for the + treeview and iter is the gtk.TreeIter pointing at the row. + + The method sets cell background color for all columns + and text for index and amount columns. + """ + _row_path = tree_model.get_path(iter) + _number = _row_path[-1] + if column is self.__index_column: + cell_renderer.set_property('text', str(_number + 1)) + self.__index_column.get_cell_renderers()[1].set_property( + 'cell-background-gdk', lcolor[_number % 2]) + if self.__treeview.get_cursor() == (_row_path,column): + cell_renderer.set_property('cell-background-gdk', + gtk.gdk.color_parse(globals.color["ACTIVE"])) + else: + cell_renderer.set_property('cell-background-gdk', + lcolor[_number % 2]) + + def _clear(self): + """def _clear(self) + + it deletes the __budget value + this would not be necessary if there were not circular references, + which are pending to fix + """ + del self.__budget + + def getWidget(self): + """def getWidget(self) + + return the main widget (gtk.ScrolledWindow) + """ + return self.__widget + + def getPath(self): + """def getPath(self) + + return the tuple that identifies the pane in the notebook page + """ + return self.__path + + def setPath(self, path): + """def setPath(self) + + sets the tuple that identifies the pane in the notebook page + """ + self.__path = path + def getPage(self): + """def getPage(self) + + return the Page + """ + return self.__page + + def setPage(self,page): + """def setPage(self) + + set the Page + """ + self.__page = page + + def getBudget(self): + """def getBudget(self) + + return the Budget objet + """ + return self.__budget + + def getActivePathRecord(self): + """def getActivePathRecord(self) + + return the Active Path Record + """ + return self.__active_path_record + + active_path_record = property(getActivePathRecord, None, None, + "Active path record") + widget = property(getWidget, None, None, + "main widget") + path = property(getPath, setPath, None, + "Path that identifies the item in the page notebook") + page = property(getPage, setPage, None, + "Weak reference from Page instance which creates this class") + budget = property(getBudget, None, None, + "Budget object") + + +class OptionView(object): + """gui.OptionView: + + Description: + It creates a treeview whith the column "Option Name" "Value" + and "Type" to show and edit Options + Constructor: + OptionView(option_list) + option_list: list of options + (option_name, type) + Ancestry: + +-- object + +-- OptionView + Atributes: + "__liststore" + "__treeview" + "__option_column" + "__value_column" + "__type_column" + "__treeselection" + "__widget": Main windget + "__option_list" + "__option_dict" + "__description_label" + "option_types" + "widget": __widget + Methods: + __init__(self, option_list) + createColumn(self, args) + createTextBaseColumn(self,args) + createBaseColumn(self,args) + """ + + def __init__(self, option_list): + """__init__(self, option_list) + + """ + self.__option_dict = {} + self.__option_list = [] + self.option_types = {"boolean" : _("Boolean"), + "integer": _("Integer"), + "string": _("Text"), + "color" : _("Color"), + "list" : _("List")} + # ListStore + self.__liststore = gtk.ListStore(str, str, str, str, str) + # Treeview + self.__treeview = gtk.TreeView(self.__liststore) + self.__treeview.set_enable_search(False) + self.__treeview.set_reorderable(False) + self.__treeview.set_headers_clickable(False) + # vbox + _vbox = gtk.VBox() + # Scrolled_window + _scrolled_window = gtk.ScrolledWindow() + _scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, + gtk.POLICY_AUTOMATIC) + _scrolled_window.add(self.__treeview) + _scrolled_window.show() + _vbox.pack_start(_scrolled_window) + # colors + _text_color = gtk.gdk.color_parse(globals.color["TEXT"]) + _background_color = [ + gtk.gdk.color_parse(globals.color["UNEVEN"]), + gtk.gdk.color_parse(globals.color["EVEN"])] + # Option Column + self.__option_column = gtk.TreeViewColumn() + self.__option_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + self.__option_column.set_fixed_width(150) + self.__option_column.set_resizable(True) + _option_cell = gtk.CellRendererText() + _option_cell.set_property('foreground-gdk', _text_color) + self.__option_column.pack_start(_option_cell, True) + self.__option_column.set_cell_data_func(_option_cell, self.colorCell, + _background_color) + self.__option_column.set_title(_("Option name")) + self.__option_column.add_attribute(_option_cell, 'text', 1) + self.__treeview.append_column(self.__option_column) + # Value Column + self.__value_column = gtk.TreeViewColumn() + self.__value_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + self.__value_column.set_fixed_width(275) + self.__value_column.set_resizable(True) + _value_cell = gtk.CellRendererText() + _value_cell.set_property('foreground-gdk', _text_color) + self.__value_column.pack_start(_value_cell, True) + self.__value_column.set_cell_data_func(_value_cell, self.colorCell, + _background_color) + self.__value_column.set_title(_("Value")) + self.__value_column.add_attribute(_value_cell, 'text', 2) + self.__treeview.append_column(self.__value_column) + # Type Column + self.__type_column = gtk.TreeViewColumn() + self.__type_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + self.__type_column.set_fixed_width(70) + self.__type_column.set_resizable(True) + _type_cell = gtk.CellRendererText() + _type_cell.set_property('foreground-gdk', _text_color) + self.__type_column.pack_start(_type_cell, True) + self.__type_column.set_cell_data_func(_type_cell, self.colorCell, + _background_color) + self.__type_column.set_title(_("Type")) + self.__treeview.append_column(self.__type_column) + # End Column + _end_column = gtk.TreeViewColumn() + _end_column.set_clickable(False) + _end_cell = gtk.CellRendererText() + _end_cell.set_property('cell-background-gdk', + gtk.gdk.color_parse(globals.color["UNEVEN"])) + _end_column.pack_start(_end_cell, True) + self.__treeview.append_column(_end_column) + # Connect + self.__treeview.connect("key-press-event", self.treeviewKeyPressEvent) + self.__treeview.connect("button-press-event", self.treeviewClickedEvent) + # control selection + self.__treeselection = self.__treeview.get_selection() + self.__treeselection.set_mode(gtk.SELECTION_MULTIPLE) + self.__treeselection.set_select_function(self.controlSelection) + # labels + _frame = gtk.Frame() + _frame.set_shadow_type(gtk.SHADOW_OUT) + _vbox2 = gtk.VBox() + _frame.add(_vbox2) + _alignement = gtk.Alignment(xalign=0, yalign=0, xscale=0, yscale=0) + _alignement.set_padding(0, 0, 12, 0) + _label = gtk.Label() + _label.set_markup("<b>" + _("Description:") + "</b>") + _label.show() + _alignement.add(_label) + _alignement.show() + _alignement2 = gtk.Alignment(xalign=0, yalign=0, xscale=0, yscale=0) + _alignement2.set_padding(0, 0, 24, 0) + self.__description_label = gtk.Label() + self.__description_label.show() + _alignement2.add(self.__description_label) + _alignement2.show() + _vbox2.pack_start(_alignement, False) + _vbox2.pack_start(_alignement2, False) + _vbox2.show() + _frame.show() + _vbox.pack_start(_frame, False) + # Show + self.__treeview.show() + _vbox.show() + self.__widget = _vbox + + def treeviewKeyPressEvent(self, widget, event): + """def treeviewKeyPressEvent(self, widget, event) + + widget: treewiew widget + event: Key Press event + Method connected to "key-press-event" signal + The "key-press-event" signal is emitted when the user presses a key + on the keyboard. + Returns :TRUE to stop other handlers from being invoked for the event. + Returns :FALSE to propagate the event further. + + If the user press the right cursor button and the cursor is in the + value column or pres the left cursor button and the cursor is + in the value column the event is estoped, else the event is propagated. + """ + (_cursor_path, _column) = self.__treeview.get_cursor() + if (event.keyval == gtk.keysyms.Right \ + and _column == self.__value_column) \ + or (event.keyval == gtk.keysyms.Left \ + and _column == self.__value_column): + return True + else: + _description = self.__liststore[_cursor_path][4] + self.__description_label.set_text(_description) + return False + + def treeviewClickedEvent(self, widget, event): + """def treeviewClickedEvent(self, widget, event) + + widget: treewiew widget + event: clicked event + Method connected to "button-press-event" signal + The "button-press-event" signal is emitted when a mouse button is + pressed. + Returns TRUE to stop other handlers from being invoked for the event. + Returns FALSE to propagate the event further. + + The cursos is moved to value column. + """ + path_at_pos = self.__treeview.get_path_at_pos(int(event.x), + int(event.y)) + if not path_at_pos is None: + _path_cursor, _column, _x, _y = path_at_pos + _description = self.__liststore[_path_cursor][4] + self.__description_label.set_text(_description) + if _column == self.__value_column: + return False + else: + self.__treeview.set_cursor(_path_cursor,self.__value_column, + True) + self.__treeview.grab_focus() + return True + return True + + def controlSelection(self, selection): + """def controlSelection(self, selection) + + selection: treeselection + + Method connected to set_selection_function() + This method is called before any node is selected or unselected, + giving some control over which nodes are selected. + The selection function should return TRUE if the state + of the node may be toggled, and FALSE if the state of the node should + be left unchanged. + + Return False so none row is selected + """ + return False + + + def colorCell(self, column, cell_renderer, tree_model, iter, lcolor): + """def colorCell(self, column, cell_renderer, tree_model, iter, lcolor) + + column: the gtk.TreeViewColumn in the treeview + cell_renderer: a gtk.CellRenderer + tree_model: the gtk.TreeModel + iter: gtk.TreeIter pointing at the row + lcolor: list with 2 gtk colors for even and uneven record + + Method connected to "set_cell_data_func" of the column + The set_cell_data_func() method sets the data function (or method) + to use for the column gtk.CellRenderer specified by cell_renderer. + This function (or method) is used instead of the standard attribute + mappings for setting the column values, and should set the attributes + of the cell renderer as appropriate. func may be None to remove the + current data function. The signature of func is: + -def celldatafunction(column, cell, model, iter, user_data) + -def celldatamethod(self, column, cell, model, iter, user_data) + where column is the gtk.TreeViewColumn in the treeview, cell is the + gtk.CellRenderer for column, model is the gtk.TreeModel for the + treeview and iter is the gtk.TreeIter pointing at the row. + + The method sets cell background color for all columns + and text for type column. + """ + _row_path = tree_model.get_path(iter) + _number = _row_path[-1] + if self.__treeview.get_cursor() == (_row_path,column): + cell_renderer.set_property('cell-background-gdk', + gtk.gdk.color_parse(globals.color["ACTIVE"])) + else: + cell_renderer.set_property('cell-background-gdk', + lcolor[_number % 2]) + if column is self.__type_column: + _type = self.option_types[tree_model[_row_path][3]] + cell_renderer.set_property('text', _type) + + def setOptions(self, option_list): + """setOptions(self, option_list) + + option_list: list of tuples + (option, option name, type) + option: option identifier + option name: a string with the option name + Description: a string with the option description + type: can be "boolean" + "integer" + "string" + "color" + Sets the Options in the treeview rows + """ + self.__option_dict = {} + self.__option_list = [] + self.__liststore.clear() + if isinstance(option_list, list): + for _option in option_list: + if isinstance(_option, tuple) and len(_option) == 4: + _option_key = _option[0] + _option_name = _option[1] + _option_type = _option[2] + _option_description = _option[3] + if isinstance(_option_key, str) and \ + (isinstance(_option_name, str) or\ + isinstance(_option_name, unicode))and \ + _option_type in self.option_types.keys(): + self.__liststore.append([_option_key, _option_name, "", + _option_type, _option_description]) + self.__option_dict[_option_key] = [_option_name, "", + _option_type, _option_description] + self.__option_list.append(_option_key) + else: + print _("Option values must be strings") + else: + print _("Option must be a tuple with 4 items") + else: + print _("Option list must be a list") + return + def setValues(self, values): + """setValues(self, values) + + values: dictionary {option : value} + + Sets the Options values + """ + if isinstance(values, dict): + for _option, _value in values.iteritems(): + if _option in self.__option_dict: + _type = self.__option_dict[_option][2] + if _type == "boolean": + if isinstance(_value, bool): + _num = self.__option_list.index(_option) + _iter = self.__liststore.get_iter((_num,)) + self.__liststore.set_value(_iter, 2, _value) + self.__option_dict[_option][1] = _value + else: + print _("Icorrect type, must be boolean") + elif _type == "integer": + try: + _value = int(_value) + except ValueError: + print _("Icorrect type, must be integer") + else: + _num = self.__option_list.index(_option) + _iter = self.__liststore.get_iter((_num,)) + self.__liststore.set_value(_iter, 2, _value) + self.__option_dict[_option][1] = _value + elif _type == "string": + if isinstance(_value, str): + _num = self.__option_list.index(_option) + _iter = self.__liststore.get_iter((_num,)) + self.__liststore.set_value(_iter, 2, _value) + self.__option_dict[_option][1] = _value + else: + print _("Icorrect type, must be string") + elif _type == "list": + if isinstance(_value, list): + _num = self.__option_list.index(_option) + _iter = self.__liststore.get_iter((_num,)) + _str_value = "" + for _item_value in _value: + _str_value = _str_value + _item_value + "," + if _str_value[-1] == ",": + _str_value = _str_value[:-1] + self.__liststore.set_value(_iter, 2, _str_value) + self.__option_dict[_option][1] = _value + else: + print _("Icorrect type, must be list") + elif _type == "color": + if isinstance(_value, str): + try: + _color = gtk.gdk.color_parse(_value) + except ValueError: + print _("Icorrect type, must be a parseable " \ + "color") + else: + _num = self.__option_list.index(_option) + _iter = self.__liststore.get_iter((_num,)) + self.__liststore.set_value(_iter, 2, _value) + self.__option_dict[_option][1] = _value + else: + print _("Type must be boolean, integer, string or "\ + "color") + else: + print _("Value must be in the option dict") + else: + print _("Values must be a dict") + self.__treeview.set_cursor((0),self.__value_column, False) + self.__treeview.grab_focus() + (_cursor_path, _column) = self.__treeview.get_cursor() + _description = self.__liststore[_cursor_path][4] + self.__description_label.set_text(_description) + + def getWidget(self): + """def getWidget(self) + + return the main widget (gtk.ScrolledWindow) + """ + return self.__widget + widget = property(getWidget, None, None, + "The main widget (gtk.ScrolledWindow)") + + +class OpenDurusDatabase(object): + """gui.OpenFiebdc + + Description: + Class to show a dialog to open a durus price database + Constructor: + OpenDurusDatabase() + Ancestry: + +-- object + +-- OpenDurusDatabase + Atributes: + "_openMethod": The method to open the file + "__file": the filename to open + "__window": the File Selection window + Methods: + __init__(self) + setActiveCode(self, code) + """ + def __init__(self, openMethod): + self.__openMethod = openMethod + self.__file = None + self.__window = gtk.FileSelection("Abrir Archivo") + self.__window.connect("destroy", self.destroy) + self.__window.ok_button.connect("clicked", self._openFile) + self.__window.cancel_button.connect("clicked", + lambda w: self.__window.destroy()) + self.__window.set_filename(globals.getHomePath("DURUS-DATABASE")) + self.__window.show() + + def destroy(self, widget): + gtk.main_quit() + + def main(self): + gtk.main() + + def _openFile(self, w): + self.__file = self.__window.get_filename() + _filename = os.path.basename(self.__file) + _filename_list = _filename.split(".") + _filename_ext = _filename_list[-1] + if _filename == "": + print _("No file selected") + elif len(_filename_list) < 2 or _filename_ext != "durus": + print _("The filename must have durus extension") + else: + try: + self.__openMethod(self.__window.get_filename()) + self.__window.destroy() + except IOError: + print utils.mapping("IOError, $1", (self.__file,))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Gtk/importFiebdc.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,456 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File importFiebdc.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. + +# Modules +import sys +import time +import os.path +import pygtk +pygtk.require('2.0') +import gtk +import gobject +import threading +gobject.threads_init() + +from Generic import utils +from Generic import globals +import gui + +class FileSelectionWindow(object): + """importFiebdc.FileSelectionWindow: + + Description: + Class to show the selection file window + Constructor: + importFiebdc.FileSelectionWindow(mainWindow, readFileMethod, + budget, arg_List, cancelMethod) + Ancestry: + +-- object + +-- FileSelectionWindow + Atributes: + "__mainWindow": gui.MainWindow object + "__readFileMethod": Method to read the selected file + "__budget": Budget object + "__filename": "file" + "__cancelMethod": Method to cancel the read method + "__file": The selected file + "__window": The selection file window + Methods: + __init__(self, mainWindow, readFileMethod, budget + arg_List, cancelMethod) + destroy(self, widget) + main(self) + _launchProgressWindow(self, _file) + _openFile(self, w) + _openFile2(Self, filename) + """ + + def __init__(self, mainWindow, readFileMethod, budget, filename, + cancelMethod): + """def __init__(self, mainWindow, readFileMethod, budget, + filename, cancelMethod) + + mainWindow: gui.MainWindow object + readFileMethod: Method to read the selected file + budget: base.Budget object + filename: "file" + cancelMethod: Method to cancel the read method + Sets the init atributes, creates the file selection window + Connects the events: + * clicked ok button: _openFile + * clicked cancel button: destroy window + * destroy event: _destroy + """ + # TODO: Add file filter + self.__mainWindow = mainWindow + self.__readFileMethod = readFileMethod + self.__budget = budget + self.__filename = filename + self.__cancelMethod = cancelMethod + self.__file = None + self.__window = gtk.FileChooserDialog(title=_("Open File"), + action=gtk.FILE_CHOOSER_ACTION_OPEN, + buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN,gtk.RESPONSE_OK)) + self.__window.set_default_response(gtk.RESPONSE_OK) + self.__window.set_filename(globals.getHomePath("BUDGET")) + if self.__window.run() == gtk.RESPONSE_OK: + self._openFile(self.__window.get_filename()) + self.__window.destroy() + + def _launchProgressWindow(self, file): + """def _launchProgressWindow(self, file) + + Launch the progress window + """ + self.__filename = file + + _emptyPage = gui.EmptyPage(self.__mainWindow, self.__readFileMethod, + self.__budget, self.__filename, + self.__cancelMethod) + self.__mainWindow.getNotebook().append_page(_emptyPage.widget, + _emptyPage.title) + self.__mainWindow.getPageList().append(_emptyPage) + _emptyPage.run() + + def _launchProgressTab(self, file): + """def _launchProgressTab(self, file) + + Launch the progress window + """ + self.__filename = file + print "abriendo fichero", self.__filename + + def _openFile(self, filename): + """def _openFile(self, filename) + + filename: the filename to open + If the selected file has a bc3 extension + _launchProgressWindow is called + """ + _file = filename + if sys.getfilesystemencoding(): + _file = _file.decode(sys.getfilesystemencoding()) + #-# + _file = _file.encode("utf-8") + #-# + self.__file = _file + _filename = os.path.basename(self.__file) + _filename_ext = _filename.split(".")[-1] + if _filename_ext != "bc3" and _filename_ext != "BC3": + print _("The file must have 'bc3' extension") + else: + self.__window.destroy() + if self.__file: + # TODO: the file exits? is it not binary?, can it be readed? + self._launchProgressWindow(self.__file) + + + +class ProgressWindow(object): + """importFiebdc.ProgressWindow: + + Description: + Class to show the progress window and launch a thread to read + the database file + Constructor: + importFiebdc.ProgressWindow(mainWindow, readFileMethod, budget, + filename, cancelMethod) + Ancestry: + +-- object + +-- ProgressWindow + Atributes: + "__mainWindow": + "__readFileMethod": + "__budget": + "__filename": + "__cancelMethod": + "__children": Thread instance + "__cancel": list with boolean values + "__window": progress window widget + "__progress_bar": probres bar widget + "__label": label widget + Methods: + closeWindow(self) + __init__(self, mainWindow, readFileMethod, budget + filename, cancelMethod) + closeWindow(self) + main(self) + _autoClose(self) + _updateLabel(self, _time) + _updateProgressBar(self) + _launchTimeout(self) + _launchChildren(self, mainWindow, readFileMethod, budget + filename, cancelMethod) + _cancelChildren(self,widget=None) + _destroy(self, widget) + _delete_event(self, widget, event) + + """ + def __init__(self, mainWindow, readFileMethod, budget, + filename, cancelMethod): + """def __init__(self, mainWindow, readFileMethod, budget + filename, cancelMethod) + + mainWindow: gui.MainWindow object + readFileMethod: Method to read the selected file + budget: base.Budget object + filenamer: "file" + cancelMethod: Method to cancel the read method + Sets the init atributes, creates the progress window + Connects the events: + * destroy signal: self._destroy + * delete_event signal: self._delete_event + * clicked cancel button: self._cancelChildren + """ + self.__mainWindow = mainWindow + self.__readFileMethod = readFileMethod + self.__filename = filename + self.__budget = budget + self.__cancelMethod = cancelMethod + self.__children = None + self.__cancel = [False, False] + self.__window = gtk.Window() + self.__window.set_title(_("Loading file ...")) + self.__window.connect("destroy", self._destroy) + self.__window.connect("delete_event", self._delete_event) + _Vbox1 = gtk.VBox(False, 0) + self.__window.add(_Vbox1) + _align = gtk.Alignment(0.5, 0.5, 0, 0) + _align.show() + _Vbox1.pack_start(_align, False, False, 5) + self.__progress_bar = gtk.ProgressBar() + self.__progress_bar.show() + _align.add(self.__progress_bar) + self.__label = gtk.Label() + self.__label.set_text(_("Time: 0s")) + self.__label.show() + _Vbox1.add(self.__label) + self.__throbber = gtk.Image() + self.__throbber.set_from_file(globals.getAppPath("THROBBER-ICON")) + _Vbox1.add(self.__throbber) + self.__throbber.show() + self.__animation = gtk.gdk.PixbufAnimation(globals.getAppPath("THROBBER-GIF")) + _pixbuf = self.__throbber.get_pixbuf() + self.__throbber.set_from_animation(self.__animation) + _Hbox1 = gtk.HBox(False, 0) + _Vbox1.add(_Hbox1) + _button1 = gtk.Button(_("Cancel")) + _button1.connect("clicked", self._cancelChildren) + _button1.show() + _Hbox1.pack_start(_button1, True, True, 0) + _Hbox1.show() + _Vbox1.show() + + def main(self): + """def main(self) + + Launch the thread + Launch the timeouts + Shows window and starts the GTK+ event processing loop. + """ + + self._launchChildren() + self._launchTimeout() + self.__window.show() + gtk.main() + + def closeWindow(self): + """def closeWindow(self) + + Sets the __children atribute to None + This causes that the timiouts is ended and then the window is + closed. + This method is called from thread when it is finished + """ + self.__children = None + + def _launchTimeout(self): + """def _launchTimeout(self) + + Launch the timeouts: + 1- update progress bar + 2- update time labal + 3- If the other timetouts are stoped the window is closed + """ + gobject.timeout_add(100, self._updateProgressBar) + gobject.timeout_add(1000, self._updateLabel, time.time()) + self.__cancel = [False, False] + gobject.timeout_add(1000, self._autoClose) + + def _updateProgressBar(self): + """def _updateProgressBar(self) + + update progress bar in a timeout + If the thread end or is canceled the timeout is stoped + """ + if self.__children is None or self.__children.isCanceled() == True: + self.__cancel[0] = True + return False + else: + self.__progress_bar.pulse() + return True + + def _updateLabel(self, _time): + """def _updateProgressBar(self) + + update time label in a timeout + If the thread end or is canceled the timeout is stoped + """ + if self.__children is None or self.__children.isCanceled() == True: + self.__cancel[1] = True + return False + else: + _time = time.time() - _time + self.__label.set_text(utils.mapping(_("Time: $1"), + ("%.0f" %_time,))) + return True + + def _autoClose(self): + """def _updateProgressBar(self) + + If the time label and progress bar timeouts are stoped the window is + closed and ist tiemeout is stoped + """ + if self.__cancel == [ True, True ]: + self.__window.destroy() + return False + else: + return True + + def _launchChildren(self): + """_launchChildren(self) + + Launch the thread to read the file + """ + if self.__children is None: + self.__children = Thread(self, self.__mainWindow, + self.__readFileMethod, self.__budget, self.__filename, + self.__cancelMethod) + self.__children.start() + + def _cancelChildren(self,widget=None): + """_cancelChildren(self,widget=None) + + Method connected to "clicked" singal of cancel button + Stops the thread and close the window + """ + if self.__children: + self.__children.cancel() + self.__window.destroy() + + def _delete_event(self, widget, event): + """_delete_event(self, widget, event) + + widget: the widget where the event is emitted from + event: the "gtk.gdk.Event" + Method connected to "delete_event" signal of window widget + This signal is emitted when a user press the close titlebar button. + Stops the thread if exits. + Returns True so the signal "destroy" is emitted. + """ + if self.__children: + self._cancelChildren() + return True + + def _destroy(self, widget): + """_destroy(self, widget) + + widget: the widget where the event is emitted from + Method connected to "destroy" signal of window widget + This signal is emited when the method connected to "delete_event" + signal returns True or when the program call the destroy() method of + the gtk.Window widget. + The window is closed and the GTK+ event processing loop is ended. + """ + gtk.main_quit() + +class Thread(threading.Thread): + """importFiebdc.Thread: + + Description: + Thread class to read a file without freeze the gui + Constructor: + importFiebdc.Thread(page, mainWindow, + readFileMethod, arg_tuple, cancelMethod) + Ancestry: + +--threading.Thread + +-- importFiebdc.Thread + Atributes: + "__page": The page instanca that launch the thread + "__mainWindow": gui.MainWindow instance + "__readFileMethod": Method to read the selected file + "__arg_tuple": ("file", base.Budget()) + "__cancelMethod": Method to cancel the read method + "__cancel": Boolean value, True: the thread is stoped + Methods: + __init__(self, page, mainWindow, + readFileMethod, arg_tuple, cancelMethod) + run(self) + cancel(self) + isCanceled(self) + """ + + def __init__(self, page, mainWindow, + readFileMethod, budget, filename, cancelMethod): + """def __init__(self, page, mainWindow, + readFileMethod, budget, filename, cancelMethod) + + page: The page instance that launch the thread + mainWindow: gui.Mainwindow object + readFileMethod: Method to read the selected file + budget: base.Budget object + filename: "file" + cancelMethod: Method to cancel the read method + Sets the instance atributes. + """ + super(Thread, self).__init__() + self.__page = page + self.__mainWindow = mainWindow + self.__readFileMethod = readFileMethod + self.__budget = budget + self.__filename = filename + self.__cancelMethod = cancelMethod + self.__cancel = False + + def run(self): + """run(self) + + + """ + _result = self.__readFileMethod(self.__budget, self.__filename, + self.__page) + if _result is None: + self.__page.threadCanceled() + else: + _mainWindow = self.__mainWindow + _mainWindow._addBudget(_result) + self.__page.closeWindow() + self.clear() + + def cancel(self): + """cancel(self) + + Sets the "__cancel" atribute to True and call "__cancelMethod" to stop + read the file + """ + self.__cancel = True + self.__cancelMethod() + + def isCanceled(self): + """isCanceled(self) + + Return True if the thread has been canceled + """ + return self.__cancel + + def clear(self): + del self.__page + del self.__mainWindow + del self.__readFileMethod + del self.__budget + del self.__filename + del self.__cancelMethod + del self.__cancel + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/__init__.py Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +# +# this file is needed for Python's import mechanism +# +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/acumulatedline.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,273 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images" + sodipodi:docname="acumulatedline.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1874"> + <linearGradient + inkscape:collect="always" + id="linearGradient17756"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop17758" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop17760" /> + </linearGradient> + <linearGradient + id="linearGradient14825"> + <stop + style="stop-color:#767676;stop-opacity:1;" + offset="0" + id="stop14827" /> + <stop + style="stop-color:#767676;stop-opacity:0;" + offset="1" + id="stop14829" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient12879"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop12881" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop12883" /> + </linearGradient> + <linearGradient + id="linearGradient11894"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop11896" /> + <stop + id="stop12873" + offset="0.5" + style="stop-color:#000000;stop-opacity:0.49803922;" /> + <stop + style="stop-color:#000000;stop-opacity:0.24705882;" + offset="0.75" + id="stop12875" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop11898" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient12879" + id="linearGradient12885" + x1="27.034161" + y1="12.910394" + x2="17.256927" + y2="3.1346524" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.066667,0,0,1.0666666,-43.235618,-4.6997925)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient14825" + id="linearGradient16775" + x1="13.375" + y1="12.875" + x2="6.5" + y2="5.75" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-24.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17764" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-24.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17768" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-21.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17772" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-18.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17776" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-15.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17786" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-24.25,1.9375)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17788" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-21.25,1.9375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17790" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-18.25,1.9375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17792" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-15.25,1.9375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17802" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-24.25,4.4375)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17804" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-21.25,4.4375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17806" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-18.25,4.4375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17808" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-15.25,4.4375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="16" + inkscape:cx="0.18483036" + inkscape:cy="2.0462504" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1280" + inkscape:window-height="946" + inkscape:window-x="0" + inkscape:window-y="26" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <text + xml:space="preserve" + style="font-size:17.83880806px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans" + x="-0.59733981" + y="13.004562" + id="text17828" + transform="scale(0.812785,1.2303376)"><tspan + sodipodi:role="line" + x="-0.59733981" + y="13.004562" + id="tspan17832" + style="font-family:DejaVu Serif">Σ</tspan></text> + <text + xml:space="preserve" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans" + x="8.9375" + y="15.875" + id="text17836"><tspan + sodipodi:role="line" + id="tspan17838" + x="8.9375" + y="15.875">a</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/arrow.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg4577" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="arrow.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs4579"> + <linearGradient + id="linearGradient4569"> + <stop + style="stop-color:#80816b;stop-opacity:0.30612245;" + offset="0" + id="stop4571" /> + <stop + style="stop-color:#80816b;stop-opacity:1" + offset="1" + id="stop4573" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient4569" + id="radialGradient6362" + cx="3.60168" + cy="12.820313" + fx="3.60168" + fy="12.820313" + r="6.7462344" + gradientTransform="matrix(1.507507,0,0,1.064345,22.984622,1.5158803e-2)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient4569" + id="radialGradient3142" + cx="-18.011438" + cy="10.731354" + fx="-18.011438" + fy="10.731354" + r="6.2614384" + gradientTransform="matrix(1,0,0,1.1311795,0,-1.0453368)" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="16" + inkscape:cx="9.2960851" + inkscape:cy="4.1362293" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1280" + inkscape:window-height="946" + inkscape:window-x="0" + inkscape:window-y="26" /> + <metadata + id="metadata4582"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + sodipodi:type="star" + style="opacity:1;fill:url(#radialGradient3142);fill-opacity:1;fill-rule:nonzero;stroke:#020300;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="path2164" + sodipodi:sides="3" + sodipodi:cx="-15.5" + sodipodi:cy="7.9375" + sodipodi:r1="7.312767" + sodipodi:r2="3.6563835" + sodipodi:arg1="-0.0085468004" + sodipodi:arg2="1.0386508" + inkscape:flatsided="true" + inkscape:rounded="0.04" + inkscape:randomized="0" + d="M -8.1875001,7.875 C -8.1831699,8.3816249 -18.661208,14.551123 -19.102123,14.301561 C -19.543038,14.051998 -19.646961,1.8930017 -19.210377,1.6359393 C -18.773792,1.3788769 -8.1918302,7.3683751 -8.1875001,7.875 z " + transform="translate(21.690078,0)" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/budget.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,633 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:docname="x-office-spreadsheet.svg" + inkscape:version="0.47 r22583" + sodipodi:version="0.32" + id="svg13684" + height="48.000000px" + width="48.000000px" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.1"> + <defs + id="defs3"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 24 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="48 : 24 : 1" + inkscape:persp3d-origin="24 : 16 : 1" + id="perspective114" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient5060" + id="radialGradient6719" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)" + cx="605.71429" + cy="486.64789" + fx="605.71429" + fy="486.64789" + r="117.14286" /> + <linearGradient + inkscape:collect="always" + id="linearGradient5060"> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0" + id="stop5062" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop5064" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient5060" + id="radialGradient6717" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)" + cx="605.71429" + cy="486.64789" + fx="605.71429" + fy="486.64789" + r="117.14286" /> + <linearGradient + id="linearGradient5048"> + <stop + style="stop-color:black;stop-opacity:0;" + offset="0" + id="stop5050" /> + <stop + id="stop5056" + offset="0.5" + style="stop-color:black;stop-opacity:1;" /> + <stop + style="stop-color:black;stop-opacity:0;" + offset="1" + id="stop5052" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5048" + id="linearGradient6715" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)" + x1="302.85715" + y1="366.64789" + x2="302.85715" + y2="609.50507" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient6687" + id="linearGradient6746" + gradientUnits="userSpaceOnUse" + x1="-20.750000" + y1="29.000000" + x2="-19.500000" + y2="18.750000" /> + <linearGradient + inkscape:collect="always" + id="linearGradient6687"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop6689" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop6691" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient6687" + id="linearGradient6744" + gradientUnits="userSpaceOnUse" + x1="-20.750000" + y1="29.000000" + x2="-19.500000" + y2="18.750000" /> + <linearGradient + id="linearGradient6719"> + <stop + style="stop-color:#73d216;stop-opacity:1;" + offset="0" + id="stop6721" /> + <stop + style="stop-color:#d5f7b3;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop6723" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient6719" + id="linearGradient6742" + gradientUnits="userSpaceOnUse" + x1="-17.863041" + y1="30.827509" + x2="-20.821646" + y2="25.015009" /> + <linearGradient + id="linearGradient6711"> + <stop + style="stop-color:#5b8ccb;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop6713" /> + <stop + style="stop-color:#3465a4;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop6715" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient6711" + id="linearGradient6740" + gradientUnits="userSpaceOnUse" + x1="-16.387411" + y1="24.453547" + x2="-9.7352734" + y2="28.195539" /> + <linearGradient + id="linearGradient6699"> + <stop + style="stop-color:#ff7171;stop-opacity:1.0000000;" + offset="0.0000000" + id="stop6701" /> + <stop + style="stop-color:#cc0000;stop-opacity:1.0000000;" + offset="1.0000000" + id="stop6703" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient6699" + id="linearGradient6738" + gradientUnits="userSpaceOnUse" + x1="-22.976406" + y1="18.516047" + x2="-14.360273" + y2="33.016045" /> + <linearGradient + inkscape:collect="always" + id="linearGradient4542"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop4544" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop4546" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient4542" + id="radialGradient4548" + cx="24.306795" + cy="42.07798" + fx="24.306795" + fy="42.07798" + r="15.821514" + gradientTransform="matrix(1.000000,0.000000,0.000000,0.284916,-2.846681e-15,30.08928)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient2456"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop2458" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop2460" /> + </linearGradient> + <linearGradient + id="linearGradient269"> + <stop + id="stop270" + offset="0.0000000" + style="stop-color:#a3a3a3;stop-opacity:1.0000000;" /> + <stop + id="stop271" + offset="1.0000000" + style="stop-color:#4c4c4c;stop-opacity:1.0000000;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient269" + id="radialGradient15656" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.971646,0.000000,0.000000,1.034707,3.240408,0.495684)" + cx="8.8244190" + cy="3.7561285" + fx="8.8244190" + fy="3.7561285" + r="37.751713" /> + <linearGradient + id="linearGradient259"> + <stop + id="stop260" + offset="0.0000000" + style="stop-color:#fafafa;stop-opacity:1.0000000;" /> + <stop + id="stop261" + offset="1.0000000" + style="stop-color:#bbbbbb;stop-opacity:1.0000000;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient259" + id="radialGradient15658" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.963839,0.000000,0.000000,1.043088,-0.124825,-0.151970)" + cx="33.966679" + cy="35.736916" + fx="33.966679" + fy="35.736916" + r="86.708450" /> + <linearGradient + id="linearGradient15662"> + <stop + id="stop15664" + offset="0.0000000" + style="stop-color:#ffffff;stop-opacity:1.0000000;" /> + <stop + id="stop15666" + offset="1.0000000" + style="stop-color:#f8f8f8;stop-opacity:1.0000000;" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient15662" + id="radialGradient15668" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.974777,0.000000,0.000000,1.034091,3.161873,0.559274)" + cx="8.1435566" + cy="7.2678967" + fx="8.1435566" + fy="7.2678967" + r="38.158695" /> + <linearGradient + y2="99.2984" + x2="118.302" + y1="82.0938" + x1="97.2412" + gradientUnits="userSpaceOnUse" + id="aigrd13"> + <stop + id="stop12995" + style="stop-color:#E8F066" + offset="0" /> + <stop + id="stop12997" + style="stop-color:#949941" + offset="1" /> + </linearGradient> + <linearGradient + y2="100.6528" + x2="115.5175" + y1="89.1104" + x1="90.8311" + gradientUnits="userSpaceOnUse" + id="aigrd12"> + <stop + id="stop12988" + style="stop-color:#E8F066" + offset="0" /> + <stop + id="stop12990" + style="stop-color:#777A34" + offset="1" /> + </linearGradient> + <linearGradient + y2="92.6123" + x2="124.8197" + y1="75.1099" + x1="105.0923" + gradientUnits="userSpaceOnUse" + id="aigrd11"> + <stop + id="stop12981" + style="stop-color:#3FA6CC" + offset="0" /> + <stop + id="stop12983" + style="stop-color:#00687A" + offset="1" /> + </linearGradient> + <linearGradient + y2="94.8" + x2="126.1107" + y1="84.7578" + x1="107.8672" + gradientUnits="userSpaceOnUse" + id="aigrd10"> + <stop + id="stop12974" + style="stop-color:#2C7894" + offset="0" /> + <stop + id="stop12976" + style="stop-color:#0E3D47" + offset="1" /> + </linearGradient> + <linearGradient + y2="95.8999" + x2="118.2002" + y1="78.1079" + x1="105.8184" + gradientUnits="userSpaceOnUse" + id="aigrd9"> + <stop + id="stop12967" + style="stop-color:#C1553A" + offset="0" /> + <stop + id="stop12969" + style="stop-color:#803926" + offset="1" /> + </linearGradient> + <linearGradient + y2="98.8832" + x2="118.3481" + y1="81.1763" + x1="106.0254" + gradientUnits="userSpaceOnUse" + id="aigrd8"> + <stop + id="stop12960" + style="stop-color:#C09287" + offset="0" /> + <stop + id="stop12962" + style="stop-color:#803926" + offset="1" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#aigrd8" + id="linearGradient1681" + gradientUnits="userSpaceOnUse" + x1="106.0254" + y1="81.1763" + x2="118.3481" + y2="98.8832" /> + <linearGradient + inkscape:collect="always" + xlink:href="#aigrd9" + id="linearGradient1683" + gradientUnits="userSpaceOnUse" + x1="105.8184" + y1="78.1079" + x2="118.2002" + y2="95.8999" /> + <linearGradient + inkscape:collect="always" + xlink:href="#aigrd10" + id="linearGradient1685" + gradientUnits="userSpaceOnUse" + x1="107.8672" + y1="84.7578" + x2="126.1107" + y2="94.8" /> + <linearGradient + inkscape:collect="always" + xlink:href="#aigrd11" + id="linearGradient1687" + gradientUnits="userSpaceOnUse" + x1="105.0923" + y1="75.1099" + x2="124.8197" + y2="92.6123" /> + <linearGradient + inkscape:collect="always" + xlink:href="#aigrd12" + id="linearGradient1689" + gradientUnits="userSpaceOnUse" + x1="90.8311" + y1="89.1104" + x2="115.5175" + y2="100.6528" /> + <linearGradient + inkscape:collect="always" + xlink:href="#aigrd13" + id="linearGradient1691" + gradientUnits="userSpaceOnUse" + x1="97.2412" + y1="82.0938" + x2="118.302" + y2="99.2984" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient2456" + id="radialGradient2462" + gradientTransform="scale(1.164226,0.85894)" + cx="28.283663" + cy="47.400623" + fx="28.283663" + fy="47.400623" + r="13.804391" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + inkscape:showpageshadow="false" + inkscape:window-y="30" + inkscape:window-x="0" + inkscape:window-height="818" + inkscape:window-width="1272" + inkscape:document-units="px" + inkscape:grid-bbox="true" + showgrid="false" + inkscape:current-layer="layer1" + inkscape:cy="35.847276" + inkscape:cx="14.647948" + inkscape:zoom="11.313708" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + inkscape:grid-points="true" + inkscape:window-maximized="0" /> + <metadata + id="metadata4"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title>Spreadsheet</dc:title> + <dc:creator> + <cc:Agent> + <dc:title>Jakub Steiner</dc:title> + </cc:Agent> + </dc:creator> + <dc:source>http://jimmac.musichall.cz</dc:source> + <dc:subject> + <rdf:Bag> + <rdf:li>spreadheet</rdf:li> + <rdf:li>document</rdf:li> + <rdf:li>office</rdf:li> + </rdf:Bag> + </dc:subject> + <cc:license + rdf:resource="http://creativecommons.org/licenses/publicdomain/" /> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/licenses/publicdomain/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> + </rdf:RDF> + </metadata> + <g + inkscape:groupmode="layer" + inkscape:label="Layer 1" + id="layer1" + style="display:inline"> + <g + style="display:inline" + transform="matrix(2.144924e-2,0,0,2.086758e-2,43.32772,41.1536)" + id="g6707"> + <rect + style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + id="rect6709" + width="1339.6335" + height="478.35718" + x="-1559.2523" + y="-150.69685" /> + <path + style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" + d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z " + id="path6711" + sodipodi:nodetypes="cccc" /> + <path + sodipodi:nodetypes="cccc" + id="path6713" + d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z " + style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /> + </g> + <rect + style="color:#000000;fill:url(#radialGradient15658);fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:0.99999970;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:block;overflow:visible" + id="rect15391" + width="34.996506" + height="40.997345" + x="6.5017405" + y="3.5013213" + ry="1.1490481" + rx="1.1490482" /> + <rect + style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:0.99999970;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:block;overflow:visible" + id="rect15660" + width="32.996056" + height="38.996326" + x="7.5033512" + y="4.5018268" + ry="0.14904855" + rx="0.14904846" /> + <path + id="rect13655" + d="M 10.000000,6.0022030 L 10.000000,10.966297 L 10.000000,41.002203 L 20.000000,41.000000 L 20.000000,11.000000 L 38.000000,11.000000 L 38.000000,6.0022030 L 10.000000,6.0022030 z " + style="color:#000000;fill:#000000;fill-opacity:0.21052630;fill-rule:evenodd;stroke:none;stroke-width:0.60787594;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" + sodipodi:nodetypes="cccccccc" /> + <path + id="path13660" + d="M 37.500415,10.502203 L 10.499583,10.502203" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000001px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path13662" + d="M 37.500755,16.500000 L 10.499230,16.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999970px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path13664" + d="M 37.500755,22.500000 L 10.499230,22.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999970px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path13666" + d="M 37.500755,28.500000 L 10.499230,28.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999970px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path13668" + d="M 37.501332,34.500000 L 10.499823,34.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999964px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path13682" + d="M 37.500755,40.500000 L 10.499230,40.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999970px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path2464" + d="M 37.511644,13.500000 L 10.500000,13.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000001px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path2466" + d="M 37.500755,19.500000 L 10.499230,19.500000" + style="fill:none;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999970px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path2468" + d="M 37.500755,25.500000 L 10.499230,25.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999970px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path2470" + d="M 37.500755,31.500000 L 10.499230,31.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999970px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + id="path2472" + d="M 37.500755,37.500000 L 10.499230,37.500000" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999970px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999982px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789469" + d="M 37.500000,6.4997386 L 37.500000,40.500300" + id="path2485" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789469" + d="M 31.500000,6.4996867 L 31.500000,40.500315" + id="path2487" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789469" + d="M 25.500000,6.4996865 L 25.500000,40.500314" + id="path2489" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789469" + d="M 19.500000,6.4996867 L 19.500000,40.500315" + id="path2491" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.15789469" + d="M 10.500000,6.4996867 L 10.500000,40.500315" + id="path2493" /> + <path + id="path2495" + d="M 37.500227,6.5022030 L 10.499460,6.5022030" + style="fill:#000000;fill-opacity:0.15789469;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:0.19298245" /> + <text + xml:space="preserve" + style="font-size:30px;font-style:normal;font-weight:normal;fill:#000080;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" + x="25.897785" + y="46.762562" + id="text2919"><tspan + sodipodi:role="line" + id="tspan2921" + x="25.897785" + y="46.762562">€</tspan></text> + </g> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="emblem" + style="display:inline" /> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/calculate.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,367 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images" + sodipodi:docname="calculatedline.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1874"> + <linearGradient + inkscape:collect="always" + id="linearGradient17756"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop17758" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop17760" /> + </linearGradient> + <linearGradient + id="linearGradient14825"> + <stop + style="stop-color:#767676;stop-opacity:1;" + offset="0" + id="stop14827" /> + <stop + style="stop-color:#767676;stop-opacity:0;" + offset="1" + id="stop14829" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient12879"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop12881" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop12883" /> + </linearGradient> + <linearGradient + id="linearGradient11894"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop11896" /> + <stop + id="stop12873" + offset="0.5" + style="stop-color:#000000;stop-opacity:0.49803922;" /> + <stop + style="stop-color:#000000;stop-opacity:0.24705882;" + offset="0.75" + id="stop12875" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop11898" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient12879" + id="linearGradient12885" + x1="32.424786" + y1="18.476801" + x2="17.491302" + y2="3.1932461" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.066667,0,0,1.0666666,-18.985618,-4.1372925)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient14825" + id="linearGradient16775" + x1="11.375" + y1="11.8125" + x2="-1.125" + y2="-0.9375" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17764" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17768" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(3,0)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17772" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(6,0)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17776" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(9,0)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17786" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(3.7e-8,2.5)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17788" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(3,2.5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17790" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(6,2.5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17792" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(9,2.5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17802" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(3.8e-8,5)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17804" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(3,5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17806" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(6,5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17808" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(9,5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="16" + inkscape:cx="0.18483036" + inkscape:cy="-0.45374965" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1280" + inkscape:window-height="946" + inkscape:window-x="0" + inkscape:window-y="26" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="opacity:0.98156684;fill:url(#linearGradient12885);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect2164" + width="16" + height="16" + x="0" + y="-3.9866114e-16" + inkscape:transform-center-x="-2.3065355" + inkscape:transform-center-y="2.0662705" /> + <rect + style="opacity:0.98156684;fill:url(#linearGradient16775);fill-opacity:1.0;fill-rule:nonzero;stroke:#767676;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect8016" + width="13" + height="13" + x="1.5" + y="1.5" /> + <rect + style="opacity:0.98156684;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect6046" + width="11.000001" + height="3.0000005" + x="2.4999998" + y="2.4999998" /> + <text + xml:space="preserve" + style="font-size:4px;font-style:normal;font-weight:normal;fill:#00ff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="2.9643564" + y="5.4133668" + id="text7017"><tspan + sodipodi:role="line" + id="tspan7019" + x="2.9643564" + y="5.4133668" + style="font-weight:bold">13.5</tspan></text> + <rect + style="opacity:1;fill:url(#linearGradient17764);fill-opacity:1.0;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect16779" + width="2" + height="2" + x="2.5" + y="7" /> + <rect + style="opacity:1;fill:url(#linearGradient17768);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17766" + width="2" + height="2" + x="5.5" + y="7" /> + <rect + style="opacity:1;fill:url(#linearGradient17772);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17770" + width="2" + height="2" + x="8.5" + y="7" /> + <rect + style="opacity:1;fill:url(#linearGradient17776);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17774" + width="2" + height="2" + x="11.5" + y="7" /> + <rect + style="opacity:1;fill:url(#linearGradient17786);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17778" + width="2" + height="2" + x="2.5" + y="9.5" /> + <rect + style="opacity:1;fill:url(#linearGradient17788);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17780" + width="2" + height="2" + x="5.5" + y="9.5" /> + <rect + style="opacity:1;fill:url(#linearGradient17790);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17782" + width="2" + height="2" + x="8.5" + y="9.5" /> + <rect + style="opacity:1;fill:url(#linearGradient17792);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17784" + width="2" + height="2" + x="11.5" + y="9.5" /> + <rect + style="opacity:1;fill:url(#linearGradient17802);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17794" + width="2" + height="2" + x="2.5" + y="12" /> + <rect + style="opacity:1;fill:url(#linearGradient17804);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17796" + width="2" + height="2" + x="5.5" + y="12" /> + <rect + style="opacity:1;fill:url(#linearGradient17806);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17798" + width="2" + height="2" + x="8.5" + y="12" /> + <rect + style="opacity:1;fill:url(#linearGradient17808);fill-opacity:1;stroke:none;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect17800" + width="2" + height="2" + x="11.5" + y="12" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/calculatedline.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,274 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images" + sodipodi:docname="calculatedline.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1874"> + <linearGradient + inkscape:collect="always" + id="linearGradient17756"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop17758" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop17760" /> + </linearGradient> + <linearGradient + id="linearGradient14825"> + <stop + style="stop-color:#767676;stop-opacity:1;" + offset="0" + id="stop14827" /> + <stop + style="stop-color:#767676;stop-opacity:0;" + offset="1" + id="stop14829" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient12879"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop12881" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop12883" /> + </linearGradient> + <linearGradient + id="linearGradient11894"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop11896" /> + <stop + id="stop12873" + offset="0.5" + style="stop-color:#000000;stop-opacity:0.49803922;" /> + <stop + style="stop-color:#000000;stop-opacity:0.24705882;" + offset="0.75" + id="stop12875" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop11898" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient12879" + id="linearGradient12885" + x1="32.424786" + y1="18.476801" + x2="17.491302" + y2="3.1932461" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.066667,0,0,1.0666666,-18.985618,-4.1372925)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient14825" + id="linearGradient16775" + x1="11.375" + y1="11.8125" + x2="-1.125" + y2="-0.9375" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17764" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17768" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(3,0)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17772" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(6,0)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17776" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(9,0)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17786" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(3.7e-8,2.5)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17788" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(3,2.5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17790" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(6,2.5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17792" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(9,2.5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17802" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(3.8e-8,5)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17804" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(3,5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17806" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(6,5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17808" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(9,5)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="16" + inkscape:cx="0.18483036" + inkscape:cy="9.5462504" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1280" + inkscape:window-height="946" + inkscape:window-x="0" + inkscape:window-y="26" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <text + xml:space="preserve" + style="font-size:17.15044785px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="-1.6760449" + y="13.103662" + id="text2202" + transform="scale(1.0430577,0.9587197)"><tspan + sodipodi:role="line" + id="tspan2204" + x="-1.6760449" + y="13.103662" + style="font-family:DejaVu Sans Mono">ƒ<tspan + style="font-size:8.57522392px" + id="tspan2206" /></tspan></text> + <text + xml:space="preserve" + style="font-size:7.45081091px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="5.4302597" + y="13.621432" + id="text2208" + transform="scale(0.9116194,1.096949)"><tspan + sodipodi:role="line" + id="tspan2210" + x="5.4302597" + y="13.621432">(x)</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/chapter.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg4577" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="chapter.svg"> + <defs + id="defs4579"> + <linearGradient + id="linearGradient4569"> + <stop + style="stop-color:#80816b;stop-opacity:0.30612245;" + offset="0" + id="stop4571" /> + <stop + style="stop-color:#80816b;stop-opacity:1" + offset="1" + id="stop4573" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient4569" + id="radialGradient6362" + cx="3.60168" + cy="12.820313" + fx="3.60168" + fy="12.820313" + r="6.7462344" + gradientTransform="matrix(1.507507,0,0,1.064345,-1.827878,-1.879024)" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="88.791208" + inkscape:cx="5.382146" + inkscape:cy="4.416485" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="588" + inkscape:window-x="133" + inkscape:window-y="218" /> + <metadata + id="metadata4582"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="fill:url(#radialGradient6362);fill-opacity:1.0;fill-rule:evenodd;stroke:#020300;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 5.032659,3.3644806 C 4.797451,2.6396411 4.846801,2.4935891 4.131669,2.3508667 L 1.72152,2.6662131 C 1.089491,3.0416257 0.97839896,3.079167 1.113352,3.7924509 L 2.19454,11.315718 C 2.2557273,12.395411 2.6193715,12.771498 3.591075,12.9375 L 14.132659,11.495916 C 14.344112,11.440215 14.454158,11.333811 14.425481,11.158045 L 13.209145,2.598639 C 13.134919,2.4734877 13.068717,2.3435222 12.848748,2.3058172 L 5.032659,3.3644806 z " + id="path2797" + sodipodi:nodetypes="ccccccccccc" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/close.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="close.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1874" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.197802" + inkscape:cx="8" + inkscape:cy="8" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1013" + inkscape:window-height="592" + inkscape:window-x="401" + inkscape:window-y="350"> + <sodipodi:guide + orientation="vertical" + position="24.957426" + id="guide3733" /> + <sodipodi:guide + orientation="vertical" + position="13.469802" + id="guide3735" /> + </sodipodi:namedview> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="opacity:0.98156684;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#767676;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect1958" + width="10.839109" + height="10.801485" + x="2.6608906" + y="2.5" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#808080;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 5.0405941,4.9504949 L 11.049505,11.094554" + id="path2241" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#808080;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 11.049505,4.9504949 L 5.0405941,11.094554" + id="path5150" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/connected.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,285 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="connected.svg"> + <defs + id="defs1874"> + <linearGradient + id="linearGradient3768"> + <stop + style="stop-color:#5e4711;stop-opacity:1;" + offset="0" + id="stop3770" /> + <stop + style="stop-color:#5e4711;stop-opacity:0;" + offset="1" + id="stop3772" /> + </linearGradient> + <linearGradient + id="linearGradient3760"> + <stop + style="stop-color:#4e4e4e;stop-opacity:1;" + offset="0" + id="stop3762" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="1" + id="stop3764" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="linearGradient3782" + x1="8.3515625" + y1="6.0759516" + x2="8.3515625" + y2="3.921875" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-0.5625,-3.125e-2)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4703" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" + gradientTransform="matrix(-1.358415e-6,-1.094489,1.866142,-2.524176e-6,-10.71549,10.65716)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4711" + cx="11.642027" + cy="6.7889361" + fx="11.642027" + fy="6.7889361" + r="1.984375" + gradientTransform="matrix(7.55633e-7,-0.992115,1.653562,1.255268e-6,-0.134412,17.5827)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4765" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-4.761687e-3,0.856555,1.653543,6.744367e-3,-7.99709,-0.99185)" + cx="11.642027" + cy="6.7889361" + fx="11.642027" + fy="6.7889361" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4769" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-1.358415e-6,0.9375,1.866142,2.162118e-6,-18.62174,5.064632)" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="linearGradient4819" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.856564,-8.48047,-14.20431)" + x1="8.3515625" + y1="6.0759516" + x2="8.3515625" + y2="3.921875" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="linearGradient4834" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.856564,9.875,-14.18868)" + x1="8.3515625" + y1="6.0759516" + x2="8.3515625" + y2="3.921875" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4837" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-4.761687e-3,0.856555,1.653543,6.744367e-3,10.34666,-1.0231)" + cx="11.642027" + cy="6.7889361" + fx="11.642027" + fy="6.7889361" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4841" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-1.358415e-6,0.9375,1.866142,2.162118e-6,-0.27799,5.033382)" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4865" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-3.094644e-3,0.63131,1.074646,4.970828e-3,17.18131,0.540194)" + cx="11.642027" + cy="6.7889361" + fx="11.642027" + fy="6.7889361" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4880" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-8.828407e-7,0.690969,1.212815,1.593554e-6,-9.732932,5.203836)" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4893" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-8.828407e-7,0.690969,1.212815,1.593554e-6,-18.83693,1.75669)" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="45.254834" + inkscape:cx="10.24568" + inkscape:cy="7.7953251" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1268" + inkscape:window-height="938" + inkscape:window-x="0" + inkscape:window-y="27" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + id="path2867" + d="M 7.1290698,5.3147795 C 8.5575502,5.3147795 9.7083812,6.5457965 9.7083812,8.0556247 C 9.7083812,9.5654536 8.5575502,10.773437 7.1290698,10.773437 L 7.1290698,9.3914987 C 7.8947348,9.3914987 8.5101182,8.8313861 8.5101182,8.1477539 C 8.5101182,7.4641217 7.8947348,6.9040091 7.1290698,6.9040091 L 7.1290698,5.3147795 z " + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2871" + width="4.9224768" + height="1.5876279" + x="2.4140625" + y="5.3216891" + rx="0" + ry="0" /> + <rect + ry="0" + rx="0" + y="9.3984079" + x="2.4296875" + height="1.380337" + width="4.9588046" + id="rect2873" + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + transform="matrix(0.649905,0,0,-0.631317,-8.787048,18.55914)" + sodipodi:open="true" + sodipodi:end="4.712389" + sodipodi:start="1.562227" + d="M 7.5575825,15.491767 A 0.044194173,0.011048543 0 1 1 7.5572038,15.46967" + sodipodi:ry="0.011048543" + sodipodi:rx="0.044194173" + sodipodi:cy="15.480719" + sodipodi:cx="7.5572038" + id="path4715" + style="opacity:0.98156684;fill:#131313;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="opacity:0.98156684;fill:#131313;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path4746" + sodipodi:cx="7.5572038" + sodipodi:cy="15.480719" + sodipodi:rx="0.044194173" + sodipodi:ry="0.011048543" + d="M 7.5575825,15.491767 A 0.044194173,0.011048543 0 1 1 7.5572038,15.46967" + sodipodi:start="1.562227" + sodipodi:end="4.712389" + sodipodi:open="true" + transform="matrix(0.649905,0,0,-0.631317,3.603396,18.28611)" /> + <path + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 8.8802562,5.291342 C 7.4517758,5.291342 6.3009448,6.522359 6.3009448,8.0321872 C 6.3009448,9.5420161 7.4517758,10.75 8.8802562,10.75 L 8.8802562,9.3680612 C 8.1145912,9.3680612 7.4992078,8.8079486 7.4992078,8.1243164 C 7.4992078,7.4406842 8.1145912,6.8805716 8.8802562,6.8805716 L 8.8802562,5.291342 z " + id="path4947" /> + <rect + ry="0" + rx="0" + y="5.2904391" + x="8.8125" + height="1.5876279" + width="4.609375" + id="rect4949" + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect4951" + width="4.625" + height="1.380337" + x="8.796875" + y="9.3671579" + rx="0" + ry="0" /> + <path + id="path1895" + d="M 2.5793114,5.322592 C 1.150831,5.322592 0,6.553609 0,8.0634372 C 0,9.5732661 1.150831,10.78125 2.5793114,10.78125 L 2.5793114,9.3993112 C 1.8136464,9.3993112 1.198263,8.8391986 1.198263,8.1555664 C 1.198263,7.4719342 1.8136464,6.9118216 2.5793114,6.9118216 L 2.5793114,5.322592 z " + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 13.366001,5.291342 C 14.794481,5.291342 15.945312,6.522359 15.945312,8.0321872 C 15.945312,9.5420161 14.794481,10.75 13.366001,10.75 L 13.366001,9.3680612 C 14.131666,9.3680612 14.747049,8.8079486 14.747049,8.1243164 C 14.747049,7.4406842 14.131666,6.8805716 13.366001,6.8805716 L 13.366001,5.291342 z " + id="path1897" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/decomposition.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1933" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="decomposition.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1935" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="11.098901" + inkscape:cx="-3.24248" + inkscape:cy="7.0931927" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="592" + inkscape:window-x="172" + inkscape:window-y="447" /> + <metadata + id="metadata1938"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="opacity:0.98156684;fill:#d8d8d8;fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect2019" + width="15.000003" + height="14.999993" + x="0.50000006" + y="0.49999911" /> + <rect + y="3.0000057" + x="3" + height="11.999994" + width="12.000002" + id="rect2906" + style="opacity:0.98156684;fill:#f2f2ed;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#919191;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 1,7.4495049 L 15,7.4495049" + id="path2922" /> + <path + id="path2924" + d="M 1,11.323762 L 15,11.323762" + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#919191;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + id="path4696" + d="M 1,3.5 L 15,3.5" + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#646464;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="1.7070312" + y="6.9433594" + id="text2908" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan2910" + x="1.7070312" + y="6.9433594">1 med</tspan><tspan + sodipodi:role="line" + x="1.7070312" + y="10.943359" + id="tspan2918">2 pre</tspan><tspan + sodipodi:role="line" + x="1.7070312" + y="14.943359" + id="tspan2920">3 con</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/description.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1899" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="description.svg"> + <defs + id="defs1901" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.627417" + inkscape:cx="18.120705" + inkscape:cy="8.0546018" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="588" + inkscape:window-x="0" + inkscape:window-y="27" /> + <metadata + id="metadata1904"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Bookman L" + x="0.92097086" + y="15.1" + id="text1907" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan1909" + x="0.92097086" + y="15.1">T</tspan></text> + <text + xml:space="preserve" + style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="10.057447" + y="15.097196" + id="text1911" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan1913" + x="10.057447" + y="15.097196" + style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">1</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/disconnected.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,277 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="disconnected.svg"> + <defs + id="defs1874"> + <linearGradient + id="linearGradient3768"> + <stop + style="stop-color:#5e4711;stop-opacity:1;" + offset="0" + id="stop3770" /> + <stop + style="stop-color:#5e4711;stop-opacity:0;" + offset="1" + id="stop3772" /> + </linearGradient> + <linearGradient + id="linearGradient3760"> + <stop + style="stop-color:#4e4e4e;stop-opacity:1;" + offset="0" + id="stop3762" /> + <stop + style="stop-color:black;stop-opacity:1;" + offset="1" + id="stop3764" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="linearGradient3782" + x1="8.3515625" + y1="6.0759516" + x2="8.3515625" + y2="3.921875" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-0.5625,-3.125e-2)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4703" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" + gradientTransform="matrix(-1.358415e-6,-1.094489,1.866142,-2.524176e-6,-10.71549,10.65716)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4711" + cx="11.642027" + cy="6.7889361" + fx="11.642027" + fy="6.7889361" + r="1.984375" + gradientTransform="matrix(7.55633e-7,-0.992115,1.653562,1.255268e-6,-0.134412,17.5827)" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4765" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-4.761687e-3,0.856555,1.653543,6.744367e-3,-7.99709,-0.99185)" + cx="11.642027" + cy="6.7889361" + fx="11.642027" + fy="6.7889361" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4769" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-1.358415e-6,0.9375,1.866142,2.162118e-6,-18.62174,5.064632)" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="linearGradient4819" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.856564,-8.48047,-14.20431)" + x1="8.3515625" + y1="6.0759516" + x2="8.3515625" + y2="3.921875" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="linearGradient4834" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.856564,9.875,-14.18868)" + x1="8.3515625" + y1="6.0759516" + x2="8.3515625" + y2="3.921875" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4837" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-4.761687e-3,0.856555,1.653543,6.744367e-3,10.34666,-1.0231)" + cx="11.642027" + cy="6.7889361" + fx="11.642027" + fy="6.7889361" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4841" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-1.358415e-6,0.9375,1.866142,2.162118e-6,-0.27799,5.033382)" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4865" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-3.094644e-3,0.63131,1.074646,4.970828e-3,17.18131,0.540194)" + cx="11.642027" + cy="6.7889361" + fx="11.642027" + fy="6.7889361" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4880" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-8.828407e-7,0.690969,1.212815,1.593554e-6,-9.732932,5.203836)" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3760" + id="radialGradient4893" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-8.828407e-7,0.690969,1.212815,1.593554e-6,-18.83693,1.75669)" + cx="4.1979737" + cy="8.1747074" + fx="4.1979737" + fy="8.1747074" + r="1.984375" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="32" + inkscape:cx="14.915072" + inkscape:cy="7.4305016" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1268" + inkscape:window-height="938" + inkscape:window-x="0" + inkscape:window-y="27" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + id="path2867" + d="M 3,5.322592 C 4.4284804,5.322592 5.5793114,6.553609 5.5793114,8.0634372 C 5.5793114,9.5732661 4.4284804,10.78125 3,10.78125 L 3,9.3993112 C 3.765665,9.3993112 4.3810484,8.8391986 4.3810484,8.1555664 C 4.3810484,7.4719342 3.765665,6.9118216 3,6.9118216 L 3,5.322592 z " + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2871" + width="3" + height="1.5876279" + x="1.110223e-15" + y="5.3216891" + rx="0" + ry="0" /> + <rect + ry="0" + rx="0" + y="9.3984079" + x="-8.8817842e-16" + height="1.380337" + width="3" + id="rect2873" + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + transform="matrix(0.649905,0,0,-0.631317,-8.787048,18.55914)" + sodipodi:open="true" + sodipodi:end="4.712389" + sodipodi:start="1.562227" + d="M 7.5575825,15.491767 A 0.044194173,0.011048543 0 1 1 7.5572038,15.46967" + sodipodi:ry="0.011048543" + sodipodi:rx="0.044194173" + sodipodi:cy="15.480719" + sodipodi:cx="7.5572038" + id="path4715" + style="opacity:0.98156684;fill:#131313;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="opacity:0.98156684;fill:#131313;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path4746" + sodipodi:cx="7.5572038" + sodipodi:cy="15.480719" + sodipodi:rx="0.044194173" + sodipodi:ry="0.011048543" + d="M 7.5575825,15.491767 A 0.044194173,0.011048543 0 1 1 7.5572038,15.46967" + sodipodi:start="1.562227" + sodipodi:end="4.712389" + sodipodi:open="true" + transform="matrix(0.649905,0,0,-0.631317,3.603396,18.28611)" /> + <path + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 12.579311,5.291342 C 11.150831,5.291342 10,6.522359 10,8.0321872 C 10,9.5420161 11.150831,10.75 12.579311,10.75 L 12.579311,9.3680612 C 11.813646,9.3680612 11.198263,8.8079486 11.198263,8.1243164 C 11.198263,7.4406842 11.813646,6.8805716 12.579311,6.8805716 L 12.579311,5.291342 z " + id="path4947" /> + <rect + ry="0" + rx="0" + y="5.2904391" + x="12.40625" + height="1.5876279" + width="3.59375" + id="rect4949" + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + style="opacity:0.98156684;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect4951" + width="3.578125" + height="1.380337" + x="12.421875" + y="9.3671579" + rx="0" + ry="0" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/dxf.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,178 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="64px" + height="64px" + id="svg2194" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="dxf.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs2196" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="5.5" + inkscape:cx="32" + inkscape:cy="32" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:document-units="px" + inkscape:grid-bbox="true" + inkscape:window-width="810" + inkscape:window-height="596" + inkscape:window-x="219" + inkscape:window-y="127" /> + <metadata + id="metadata2199"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <text + xml:space="preserve" + style="font-size:45.50760269px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="12.086654" + y="37.602089" + id="text2181" + transform="scale(0.743614,1.3447836)"><tspan + sodipodi:role="line" + id="tspan2183" + x="12.086654" + y="37.602089">dxf</tspan></text> + <text + xml:space="preserve" + style="font-size:2.86312103px" + x="-24.845724" + y="1.160552" + id="text2185" + transform="scale(0.9644206,1.036892)"><tspan + sodipodi:role="line" + id="tspan2187" + x="-24.845724" + y="1.160552"> 0</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="4.7394533" + id="tspan2189">SECTION</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="8.3183546" + id="tspan2191"> 2</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="11.897256" + id="tspan2193">HEADER</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="15.476157" + id="tspan2195"> 9</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="19.055058" + id="tspan2197">$ACADVER</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="22.63396" + id="tspan2199"> 1</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="26.212861" + id="tspan2201">AC1015</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="29.791762" + id="tspan2203"> 9</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="33.370664" + id="tspan2205">$HANDSEED</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="36.949565" + id="tspan2207"> 5</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="40.528466" + id="tspan2209">FFFF</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="44.107368" + id="tspan2211"> 9</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="47.686269" + id="tspan2213">$DIMASZ</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="51.26517" + id="tspan2215"> 40</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="54.844071" + id="tspan2217">2.5</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="58.422973" + id="tspan2219"> 9</tspan><tspan + sodipodi:role="line" + x="-24.845724" + y="62.001874" + id="tspan2273" /></text> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 5,4 L 5,59 L 60,59" + id="path2178" /> + <path + sodipodi:type="star" + id="path2180" + sodipodi:sides="3" + sodipodi:cx="4.9090909" + sodipodi:cy="4.5454545" + sodipodi:r1="3.2727273" + sodipodi:r2="1.6363636" + sodipodi:arg1="-1.5707963" + sodipodi:arg2="-0.52359878" + inkscape:flatsided="true" + inkscape:rounded="0.04" + inkscape:randomized="0" + d="M 4.9090911,1.2727273 C 5.1358323,1.2727273 7.8567265,5.9854546 7.7433559,6.1818182 C 7.6299853,6.3781818 2.1881966,6.3781817 2.074826,6.1818181 C 1.9614554,5.9854544 4.6823499,1.2727272 4.9090911,1.2727273 z " /> + <path + d="M 4.9090911,1.2727273 C 5.1358323,1.2727273 7.8567265,5.9854546 7.7433559,6.1818182 C 7.6299853,6.3781818 2.1881966,6.3781817 2.074826,6.1818181 C 1.9614554,5.9854544 4.6823499,1.2727272 4.9090911,1.2727273 z " + inkscape:randomized="0" + inkscape:rounded="0.04" + inkscape:flatsided="true" + sodipodi:arg2="-0.52359878" + sodipodi:arg1="-1.5707963" + sodipodi:r2="1.6363636" + sodipodi:r1="3.2727273" + sodipodi:cy="4.5454545" + sodipodi:cx="4.909091" + sodipodi:sides="3" + id="path2184" + sodipodi:type="star" + transform="matrix(5.5194721e-3,0.9999848,-0.9999848,5.5194721e-3,63.228302,54.143641)" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/image.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="64px" + height="64px" + id="svg2164" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="image.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs2166" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="5.5" + inkscape:cx="32" + inkscape:cy="32.885771" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:document-units="px" + inkscape:grid-bbox="true" + inkscape:window-width="810" + inkscape:window-height="596" + inkscape:window-x="172" + inkscape:window-y="180" /> + <metadata + id="metadata2169"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <text + xml:space="preserve" + style="font-size:51.40524673px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Penguin Attack" + x="1.7524457" + y="33.194927" + id="text2181" + transform="scale(0.7948849,1.2580438)"><tspan + sodipodi:role="line" + id="tspan2183" + x="1.7524457" + y="33.194927">img</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/labourforce.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg2192" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="labourforce16.svg"> + <defs + id="defs2194"> + <linearGradient + gradientTransform="translate(6.24973e-2,-3.21416e-2)" + y2="24.363636" + x2="44.363636" + y1="33.454544" + x1="20" + gradientUnits="userSpaceOnUse" + id="linearGradient25864" + xlink:href="#linearGradient24945" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="24.363636" + x2="44.363636" + y1="33.454544" + x1="20" + id="linearGradient24951" + xlink:href="#linearGradient24945" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="28.639874" + x2="56.959797" + y1="28.639874" + x1="4.9375" + id="linearGradient24050" + xlink:href="#linearGradient24044" + inkscape:collect="always" /> + <linearGradient + id="linearGradient24044"> + <stop + id="stop24046" + offset="0" + style="stop-color:#f0d228;stop-opacity:1;" /> + <stop + id="stop24048" + offset="1" + style="stop-color:#a0823c;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient24945"> + <stop + id="stop24947" + offset="0" + style="stop-color:#f0faaf;stop-opacity:1;" /> + <stop + id="stop24949" + offset="1" + style="stop-color:#c8a00e;stop-opacity:0;" /> + </linearGradient> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="31.392433" + inkscape:cx="10.851228" + inkscape:cy="7.6277394" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="588" + inkscape:window-x="133" + inkscape:window-y="218" /> + <metadata + id="metadata2197"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <g + inkscape:label="Layer 1" + id="g2276" + transform="matrix(0.30114,0,0,0.30114,-1.4432,-1.44967)"> + <path + sodipodi:nodetypes="ccccscccccscccccsccccccccccccsscsccsccscc" + id="path19543" + d="M 37.116047,12.829971 C 35.073696,12.867289 35.860564,12.84981 33.866047,12.861221 C 31.715149,13.171683 33.188163,12.69954 29.147297,13.517471 C 28.297559,13.76097 27.494283,13.9236 26.584797,14.204971 C 26.198986,14.396321 25.731952,14.59625 25.553547,14.642471 C 25.375143,14.68869 22.539822,16.91233 22.255252,17.111221 C 21.334832,18.120087 19.736673,19.394226 17.741047,21.579971 C 16.964892,22.732691 16.43053,23.199656 16.462638,23.847016 C 15.863265,24.92917 15.30901,27.043315 15.053547,28.642471 C 15.004977,28.514359 15.01188,28.913304 14.991047,29.048721 C 14.603989,31.052311 14.206474,33.272704 14.022297,34.548721 C 13.941949,35.105388 13.632465,35.920673 13.303547,36.361221 L 12.709797,37.079971 C 12.199854,37.25406 11.717467,37.484063 11.209797,37.682244 C 9.9468353,37.845285 9.0913352,38.004025 8.0535464,38.017471 L 6.6472964,38.267471 C 5.9528374,38.377733 5.2626543,38.591414 5.1160464,38.767471 C 4.7646783,39.18942 5.2703129,39.196781 5.8433191,39.426562 C 8.2178046,39.712315 8.2011981,39.758235 10.459796,39.861221 L 14.397297,40.287357 C 15.417166,40.524911 16.23416,40.677035 18.897297,41.173721 C 20.240042,41.473447 21.384605,41.690124 23.618888,42.057244 C 25.719088,42.3938 29.575124,42.901884 32.022297,43.111221 C 35.731512,43.487726 37.187878,43.651239 40.116047,43.954971 C 42.227909,44.074267 44.536276,44.144299 46.522297,44.298721 C 46.778343,44.264698 47.890321,44.434119 49.366047,44.454971 C 51.917634,44.336584 52.548082,44.230526 54.670024,44.224857 L 56.897297,44.236221 L 56.897297,43.204971 C 56.897297,42.52853 56.663988,42.003597 56.272297,41.673721 C 56.172707,41.589848 56.122484,41.482867 56.053547,41.392471 C 56.069882,41.344706 55.974281,41.250485 55.897297,41.142471 C 55.728451,40.703542 55.707413,39.95103 55.741047,38.111221 C 55.773738,36.322864 55.681,35.048721 55.522297,35.048721 C 55.152024,32.882183 54.750457,30.350405 54.334797,28.079971 C 54.35246,27.28688 52.746949,23.369463 51.647297,21.548721 C 50.607454,19.827009 48.961904,18.537412 48.78082,18.142471 C 47.969584,17.208079 46.175911,16.174735 44.928547,15.361221 C 44.644536,15.173786 44.678472,15.142923 44.564911,15.088494 C 43.831872,14.737156 39.931358,12.75304 38.772297,12.829971 C 37.380657,12.817771 38.774765,12.831024 37.116047,12.829971 z " + style="fill:url(#linearGradient24050);fill-opacity:1;stroke:black;stroke-width:0.33207187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <g + transform="translate(7.454545,56)" + id="g19509" /> + <path + style="opacity:0.45622122;fill:url(#linearGradient25864);fill-opacity:1;stroke:black;stroke-width:0.33207187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 37.178547,12.79783 C 35.136196,12.835148 35.923064,12.817669 33.928547,12.82908 C 31.777649,13.139542 33.250663,12.667399 29.209797,13.48533 C 28.360059,13.728829 27.556783,13.891459 26.647297,14.17283 C 26.261486,14.36418 25.794452,14.564109 25.616047,14.61033 C 25.437643,14.656549 22.602322,16.880189 22.317752,17.07908 C 21.397332,18.087946 19.799173,19.362085 17.803547,21.54783 C 17.027392,22.70055 16.49303,23.167515 16.525138,23.814875 C 15.925765,24.897029 15.37151,27.011174 15.116047,28.61033 C 15.067477,28.482218 15.07438,28.881163 15.053547,29.01658 C 14.666489,31.02017 14.268974,33.240563 14.084797,34.51658 C 14.004449,35.073247 13.694965,35.888532 13.366047,36.32908 L 12.772297,37.04783 C 12.262354,37.221919 11.779967,37.451922 11.272297,37.650103 C 10.009335,37.813144 9.1538353,37.971884 8.1160463,37.98533 L 6.7097963,38.23533 C 6.0153373,38.345592 5.3251543,38.559273 5.1785463,38.73533 C 4.8271783,39.157279 5.3328133,39.16464 5.9058193,39.394421 C 8.2803053,39.680174 8.2636983,39.726094 10.522296,39.82908 L 14.459797,40.255216 C 15.479666,40.49277 16.29666,40.644894 18.959797,41.14158 C 20.302542,41.441306 21.447105,41.657983 23.681388,42.025103 C 25.781588,42.361659 29.637624,42.869743 32.084797,43.07908 C 35.794012,43.455585 37.250377,43.619098 40.178547,43.92283 C 42.290407,44.042126 44.598777,44.112158 46.584797,44.26658 C 46.840847,44.232557 47.952817,44.401978 49.428547,44.42283 C 51.980137,44.304443 52.610577,44.198385 54.732527,44.192716 L 56.959797,44.20408 L 56.959797,43.17283 C 56.959797,42.496389 56.726487,41.971456 56.334797,41.64158 C 56.235207,41.557707 56.184987,41.450726 56.116047,41.36033 C 56.132377,41.312565 56.036777,41.218344 55.959797,41.11033 C 55.790947,40.671401 55.769917,39.918889 55.803547,38.07908 C 55.836237,36.290723 55.743497,35.01658 55.584797,35.01658 C 55.214527,32.850042 54.812957,30.318264 54.397297,28.04783 C 54.414957,27.254739 52.809447,23.337322 51.709797,21.51658 C 50.669957,19.794868 49.024407,18.505271 48.843317,18.11033 C 48.032087,17.175938 46.238407,16.142594 44.991047,15.32908 C 44.707037,15.141645 44.740967,15.110782 44.627407,15.056353 C 43.894367,14.705015 39.993857,12.720899 38.834797,12.79783 C 37.443157,12.78563 38.837267,12.798883 37.178547,12.79783 z " + id="path24058" + sodipodi:nodetypes="ccccscccccscccccsccccccccccccsscsccsccscc" /> + </g> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/machinery.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg2316" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="machinery16.svg"> + <defs + id="defs2318" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.696216" + inkscape:cx="1.9440778" + inkscape:cy="5.6437797" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="588" + inkscape:window-x="133" + inkscape:window-y="218" /> + <metadata + id="metadata2321"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <g + inkscape:label="Layer 1" + id="g2391" + transform="matrix(0.238463,0,0,0.238463,0.463623,-3.522174e-3)"> + <path + sodipodi:nodetypes="cssssssssssssssssccccccsscccssccccssssssccsc" + style="fill:#9ea19d" + d="M 42.085372,54.128117 C 41.873165,53.898584 38.130468,53.710785 33.768273,53.710785 C 26.431134,53.710785 25.78022,53.627419 25.078881,52.597898 C 24.624689,51.931172 24.383207,50.598189 24.476537,49.272959 C 24.62702,47.136193 24.571319,47.049623 22.839898,46.729328 C 20.413415,46.280455 17.718685,44.682123 17.718685,43.691771 C 17.718685,41.770171 15.975025,38.320691 14.618367,37.558419 C 12.97006,36.632277 4.4035333,24.786269 4.4035333,23.433092 C 4.4035333,22.939191 3.6158223,21.264174 2.6530633,19.710832 C -1.6529667,12.763362 -0.46023675,7.825742 4.3770073,12.57412 C 6.0355423,14.202186 6.8929153,14.605992 9.1156043,14.805906 C 10.608132,14.940147 12.347814,15.177246 12.981564,15.332792 C 13.791323,15.531538 14.133837,15.360253 14.133837,14.756564 C 14.133837,12.997686 16.608711,12.690384 20.227602,13.999907 C 22.086864,14.672696 25.336489,15.31148 27.448989,15.419428 C 30.347721,15.567552 31.603957,15.891137 32.570201,16.738564 C 33.274368,17.356141 34.527072,18.290348 35.35399,18.814579 C 37.507335,20.179712 39.414773,22.51581 40.752638,25.426472 L 41.914437,27.954075 L 45.682732,27.570396 C 52.080714,26.918968 52.925678,27.485221 53.967368,33.122373 L 54.378668,35.348147 L 58.815313,35.717357 C 61.255468,35.920422 63.492654,36.2482 63.786837,36.445751 C 64.46572,36.901637 64.492776,43.792473 63.817462,44.245961 C 63.540123,44.432202 62.330236,44.783151 61.128826,45.025849 L 58.944444,45.467118 L 60.992929,45.91322 C 63.354474,46.427498 63.793587,46.951896 63.79476,49.259236 C 63.796767,53.202664 63.843053,53.172299 56.731988,53.892916 C 49.366569,54.639309 42.657591,54.747044 42.085372,54.128117 z M 36.614264,45.068281 L 38.459595,45.050653 L 37.054745,43.91174 C 35.924768,42.995667 35.749415,42.570779 36.158533,41.740176 C 36.998425,40.035001 36.740351,37.507227 35.386868,34.181888 C 34.682701,32.451838 34.106565,30.700397 34.106565,30.289795 C 34.106565,28.417147 32.328193,25.66172 30.576162,24.819752 C 28.919688,24.023706 14.47747,20.602393 12.773634,20.602393 C 12.395079,20.602393 12.085352,20.902969 12.085352,21.270339 C 12.085352,22.4856 20.977107,38.96503 21.632822,38.96503 C 26.04041,45.451315 26.072763,45.473637 29.241413,45.135053 C 30.03963,45.110948 29.222243,45.573982 31.493052,45.374166 C 33.294786,45.215625 35.599332,45.077977 36.614264,45.068281 z " + id="path36670" /> + <path + sodipodi:nodetypes="csssssssssssssssssssssccsssssssssssssscccccssscccssssssssccssc" + style="fill:#d6a55b" + d="M 42.149985,53.263811 C 41.157376,52.676854 39.979968,52.612506 37.028773,52.983928 C 32.625034,53.538158 27.191567,53.117218 25.942811,52.125079 C 24.875431,51.277042 24.819759,48.188058 25.851648,47.066862 C 26.396495,46.474861 28.585831,46.089399 33.49079,45.721888 C 37.272268,45.438556 40.423819,45.197902 40.494235,45.187101 C 41.179028,45.082064 40.209778,44.139443 38.575189,43.320784 C 36.585993,42.324523 36.559264,42.271296 36.858198,39.901582 C 37.096985,38.008662 36.875775,36.815422 35.822749,34.316246 C 35.086239,32.568264 34.613255,30.910225 34.771673,30.631716 C 35.28021,29.737671 35.969957,30.684398 36.561451,33.08831 C 37.329171,36.208435 37.919542,36.942607 39.106008,36.252674 C 39.621248,35.95306 40.650125,35.707922 41.392399,35.707922 C 42.499118,35.707922 42.712493,35.482617 42.578092,34.455924 C 42.47027,33.632301 42.107637,33.251524 41.518232,33.343037 C 41.025448,33.419548 40.233642,33.544748 39.75866,33.621259 C 39.217333,33.708457 38.213987,32.690389 37.070023,30.893177 C 35.000245,27.641476 32.380703,25.088917 30.12378,24.124553 C 28.280759,23.337046 13.82383,20.127503 12.119638,20.127503 C 10.641985,20.127503 10.568615,21.279581 11.959187,22.646947 C 12.531161,23.209375 14.868967,27.191977 17.154312,31.497174 C 19.439657,35.802372 21.414473,39.450005 21.54279,39.603027 C 22.038844,40.194586 25.089423,35.658252 25.545874,33.650279 C 23.553755,36.824622 28.482501,58.551358 18.003406,43.127505 C 18.853379,41.477238 15.757837,36.264366 13.927892,36.264366 C 13.37414,36.264366 11.62235,34.219946 9.4513852,31.040078 C 7.4896812,28.16672 5.6347052,25.647946 5.3292152,25.442803 C 5.0237262,25.23766 4.7737802,24.499357 4.7737802,23.802131 C 4.7737802,23.104904 3.8245172,21.094087 2.6643082,19.333649 C 0.89633818,16.651035 0.54397818,15.67095 0.48778818,13.279712 C 0.39929818,9.5134744 1.2291082,9.3788384 4.5139582,12.626474 C 6.8908392,14.976431 7.2512952,15.146887 9.6351702,15.048245 C 11.045572,14.989884 13.006128,15.149475 13.991962,15.402891 C 15.609499,15.818692 15.717624,15.775431 15.100146,14.95951 C 14.723814,14.462235 14.564574,13.794005 14.746279,13.474555 C 15.247691,12.593038 16.720202,12.772604 19.454808,14.048739 C 20.816076,14.68399 23.543023,15.347889 25.514689,15.524069 C 28.532949,15.793769 29.723926,16.236879 33.050083,18.327661 C 37.815109,21.322897 40.325732,23.864289 41.127565,26.504142 L 41.725815,28.47375 L 44.50416,28.118949 L 47.282499,27.764149 L 46.980962,29.402319 C 46.563077,31.672584 47.896333,32.94269 49.274656,31.58737 C 50.135317,30.741072 50.255809,30.736239 50.5385,31.536676 C 50.710367,32.023311 51.237955,32.347121 51.710919,32.256253 C 52.294271,32.144179 52.702688,32.627961 52.980729,33.76037 L 53.390605,35.429701 L 57.37689,35.430875 C 59.569348,35.431522 61.996925,35.624092 62.771509,35.858809 C 64.122054,36.268058 64.179842,36.433108 64.179842,39.881249 C 64.179842,44.180572 64.527593,43.997456 55.985902,44.195943 C 52.485021,44.277295 50.096508,44.55847 50.096508,44.889241 C 50.096508,45.207076 52.694504,45.61135 56.155117,45.832023 C 59.51747,46.046429 62.537264,46.510109 62.940724,46.873932 C 63.340573,47.234497 63.667721,48.202184 63.667721,49.024349 C 63.667721,51.939771 62.908255,52.329199 55.473781,53.225934 C 47.008105,54.247052 43.828037,54.256092 42.149985,53.263811 z M 48.304084,38.748784 C 48.304084,38.25032 47.806748,37.933697 47.023781,37.933697 C 45.709243,37.933697 45.515569,38.310242 46.05073,39.825549 C 46.432778,40.90731 48.304084,40.013107 48.304084,38.748784 z " + id="path36668" /> + <path + sodipodi:nodetypes="cssssssssssssssscccssssscccccsssssccssccssssssssssssssssscccsscccsssc" + style="fill:#d28f2f" + d="M 41.470342,53.263811 C 40.477733,52.676854 39.300325,52.612506 36.34913,52.983928 C 31.945391,53.538158 26.511924,53.117218 25.263168,52.125079 C 24.195788,51.277042 24.140116,48.188058 25.172005,47.066862 C 25.716852,46.474861 27.906188,46.089399 32.811147,45.721888 C 36.592625,45.438556 39.744176,45.197902 39.814592,45.187101 C 39.885009,45.1763 39.942623,44.920424 39.942623,44.618487 C 39.942623,44.31655 39.136032,43.703328 38.150198,43.255772 C 36.348738,42.43793 35.905589,41.64169 36.885609,40.983584 C 37.182755,40.784044 37.277927,39.844246 37.10337,38.833248 C 36.834838,37.277968 36.973183,36.94831 38.135997,36.372644 C 38.874481,36.007047 40.060016,35.707922 40.770518,35.707922 C 41.81734,35.707922 42.031258,35.470469 41.898449,34.455924 C 41.735482,33.211045 40.997787,33.000561 39.363506,33.732642 C 38.755807,34.004861 38.386481,33.680685 38.007552,32.542457 C 37.721127,31.68209 37.334735,30.572265 37.148905,30.076181 C 36.684669,28.836877 37.869781,28.416725 42.619787,28.136612 L 46.577255,27.903236 L 46.288522,29.471862 C 45.883244,31.673613 47.240919,32.918866 48.595013,31.58737 C 49.455674,30.741072 49.576166,30.736239 49.858857,31.536676 C 50.030724,32.023311 50.558312,32.347121 51.031276,32.256253 C 51.624328,32.142314 52.026323,32.643798 52.326543,33.872087 C 52.565976,34.851663 53.014609,35.822853 53.32351,36.030287 C 53.632412,36.237721 55.990919,36.469588 58.564641,36.545548 L 63.244138,36.683657 L 63.244138,39.951784 L 63.244138,43.219911 L 59.147169,43.401937 C 53.263208,43.663357 49.416865,44.252208 49.416865,44.891586 C 49.416865,45.206427 52.032949,45.612504 55.475474,45.832023 C 58.837827,46.046429 61.857621,46.510109 62.261081,46.873932 C 62.66093,47.234497 62.988078,48.202184 62.988078,49.024349 C 62.988078,51.939771 62.228612,52.329199 54.794138,53.225934 C 46.328462,54.247052 43.148394,54.256092 41.470342,53.263811 z M 47.624441,38.748784 C 47.624441,38.25032 47.127105,37.933697 46.344138,37.933697 C 45.0296,37.933697 44.835926,38.310242 45.371087,39.825549 C 45.753135,40.90731 47.624441,40.013107 47.624441,38.748784 z M 20.610046,44.80707 C 19.467663,44.195176 18.945652,43.522441 18.945652,42.662099 C 18.945652,41.972689 18.59997,41.096905 18.17747,40.715915 C 17.75497,40.334924 17.409289,39.790086 17.409289,39.505163 C 17.409289,38.313634 14.533685,35.151511 13.450106,35.151495 C 12.678631,35.151484 12.209692,34.727663 12.00614,33.846458 C 11.840343,33.128696 10.219976,30.8125 8.4053238,28.699355 C 6.4537728,26.426792 4.9040758,24.056709 4.6117648,22.897543 C 4.3399598,21.819692 3.4459048,19.941695 2.6249768,18.724217 C 1.3687448,16.861153 0.010664846,13.196884 2.4846316e-05,11.641739 C -0.0065249537,10.68481 1.2827348,11.346057 2.8565608,13.106822 C 3.8444928,14.212102 5.2401068,15.115462 6.2370828,15.294982 C 21.754134,18.08907 23.954174,18.311832 24.371164,17.131125 C 24.817485,15.86737 27.728547,15.978423 29.297115,17.319043 C 29.99639,17.916697 31.122128,18.516966 31.798755,18.652974 C 34.1505,19.125694 35.81664,20.300418 37.190486,22.454454 C 38.281255,24.164657 38.439757,24.763226 37.942846,25.29564 C 37.448114,25.825714 37.09176,25.641855 36.27878,24.437075 C 34.994868,22.534406 34.13523,22.988351 34.592424,25.327579 L 34.935524,27.083047 L 33.470134,25.582346 C 31.342743,23.403691 28.975835,22.496805 20.614932,20.656846 C 12.997795,18.980566 10.484955,18.689521 10.061217,19.434481 C 9.3901469,20.614269 19.296424,39.5878 20.588214,39.596881 C 21.123385,42.164943 20.849007,41.85479 20.610046,44.80707 z M 6.6547428,20.70141 C 6.6547428,20.404971 6.3090608,20.306561 5.8865608,20.482722 C 5.4640608,20.658882 5.1183788,20.901423 5.1183788,21.021701 C 5.1183788,21.14198 5.4640608,21.24039 5.8865608,21.24039 C 6.3090608,21.24039 6.6547428,20.997849 6.6547428,20.70141 z " + id="path36666" /> + <path + sodipodi:nodetypes="csssssssssssssscccssssssssssssssccssccssccssc" + style="fill:#9f7135" + d="M 41.968167,53.263811 C 40.975558,52.676854 39.79815,52.612506 36.846955,52.983928 C 32.443216,53.538158 27.009749,53.117218 25.760993,52.125079 C 24.693613,51.277042 24.637941,48.188058 25.66983,47.066862 C 26.214677,46.474861 28.404013,46.089399 33.308972,45.721888 C 37.09045,45.438556 40.242001,45.197902 40.312417,45.187101 C 40.382834,45.1763 40.440448,44.920424 40.440448,44.618487 C 40.440448,44.31655 39.633857,43.703328 38.648023,43.255772 C 36.955378,42.48733 36.198682,41.272358 37.412735,41.272358 C 37.774459,41.272358 37.854133,40.528031 37.639894,39.150209 C 37.343088,37.24139 37.443948,36.961707 38.64322,36.367991 C 39.376536,36.004954 40.541812,35.707922 41.232725,35.707922 C 42.134785,35.707922 42.488932,35.403439 42.488932,34.627875 C 42.488932,33.159935 41.706923,32.745691 40.385902,33.513866 C 39.077678,34.274601 38.412191,33.494391 38.399803,31.185397 C 38.388304,29.04113 39.497105,28.373783 43.498318,28.116788 L 47.078097,27.886861 L 46.787852,29.463675 C 46.381095,31.673487 47.73586,32.9217 49.092838,31.58737 C 49.953499,30.741072 50.073991,30.736239 50.356682,31.536676 C 50.528549,32.023311 51.035524,32.347121 51.483302,32.256253 C 52.392369,32.071774 53.870694,35.847459 53.405324,37.165155 C 53.129915,37.944966 55.513287,38.217182 60.669236,37.9948 C 63.206766,37.885353 64.655024,38.734045 63.485903,39.64539 C 62.907482,40.096274 62.875859,40.313915 63.357872,40.526425 C 63.709956,40.681652 63.998024,41.158617 63.998024,41.586349 C 63.998024,42.42442 62.608675,42.894567 60.157115,42.886087 C 57.369388,42.876444 49.91469,44.341373 49.91469,44.898834 C 49.91469,45.204419 52.587697,45.616134 55.973299,45.832023 C 59.335652,46.046429 62.355446,46.510109 62.758906,46.873932 C 63.158755,47.234497 63.485903,48.202184 63.485903,49.024349 C 63.485903,51.939771 62.726437,52.329199 55.291963,53.225934 C 46.826287,54.247052 43.646219,54.256092 41.968167,53.263811 z M 46.585902,41.828802 C 47.210424,41.390276 47.144242,41.287806 46.232037,41.280879 C 45.61491,41.276193 44.967558,41.522758 44.793478,41.828802 C 44.390505,42.537258 45.576962,42.537258 46.585902,41.828802 z M 48.122266,38.748784 C 48.122266,38.25032 47.62493,37.933697 46.841963,37.933697 C 45.527425,37.933697 45.333751,38.310242 45.868912,39.825549 C 46.25096,40.90731 48.122266,40.013107 48.122266,38.748784 z M 60.333807,40.224544 C 60.839552,39.87628 60.653355,39.649513 59.633225,39.371318 C 58.029118,38.933869 57.274098,39.42161 58.379522,40.181206 C 59.304986,40.817143 59.467994,40.820757 60.333807,40.224544 z " + id="path36664" /> + <path + sodipodi:nodetypes="csssssssssssccssccccccsssccsccccccssssssccsssc" + style="fill:#49504f" + d="M 41.232938,53.263811 C 40.240329,52.676854 39.062921,52.612506 36.111726,52.983928 C 31.707987,53.538158 26.27452,53.117218 25.025764,52.125079 C 23.958384,51.277042 23.902712,48.188058 24.934601,47.066862 C 25.479887,46.474384 27.620696,46.098517 32.419442,45.752731 C 36.116055,45.486363 39.440447,45.057908 39.806977,44.800611 C 40.818836,44.090309 45.889968,43.197247 47.785872,43.395472 C 49.027213,43.525259 49.427789,43.815423 49.322236,44.508359 C 49.197764,45.325518 49.95619,45.495214 55.23807,45.832023 C 58.600423,46.046429 61.620217,46.510109 62.023677,46.873932 C 62.423526,47.234497 62.750674,48.202184 62.750674,49.024349 C 62.750674,51.939771 61.991208,52.329199 54.556734,53.225934 C 46.091058,54.247052 42.91099,54.256092 41.232938,53.263811 z M 20.833741,44.199685 C 19.426648,42.554723 19.705353,41.445319 22.402673,37.954448 C 23.2966,36.797527 24.277734,34.879774 24.582969,33.692775 C 25.12724,31.576218 25.188994,31.531372 27.784986,31.367442 L 30.432028,30.109379 L 30.864078,34.747908 C 30.648651,41.00546 31.100277,42.329557 26.134006,44.611019 C 23.469961,46.009215 22.304219,45.918746 20.833741,44.199685 z M 62.409258,41.526102 C 62.409258,41.080499 62.601303,40.715915 62.836029,40.715915 C 63.07075,40.715915 63.262795,40.951536 63.262795,41.239519 C 63.262795,41.527501 63.07075,41.892085 62.836029,42.049706 C 62.601303,42.207328 62.409258,41.971706 62.409258,41.526102 z M 38.494718,40.990487 C 37.514263,39.925178 36.70701,36.470843 37.589461,35.512019 C 37.927461,35.144766 37.75837,33.526104 37.501582,32.935195 C 37.495685,31.698909 38.196257,30.412474 38.226431,29.287768 C 39.271885,28.831241 39.927664,28.586269 43.440979,28.137611 L 46.365452,27.764149 L 50.245733,27.765955 C 53.057701,28.110108 52.367018,30.063433 52.748417,30.619889 C 53.079343,31.36755 53.748283,32.846375 53.668779,33.924512 C 53.534215,35.749275 52.462635,36.057165 50.886146,37.478225 C 49.177694,39.01824 47.387037,39.536084 47.387037,38.49014 C 47.387037,38.184096 46.784024,37.933697 46.047005,37.933697 C 44.956202,37.933697 44.757115,38.142034 44.976569,39.053867 C 45.295478,40.378908 44.427473,40.98459 41.439415,41.522057 C 39.830811,41.811398 39.134567,41.685714 38.494718,40.990487 z M 48.945079,41.411469 C 48.980748,40.724729 52.554094,38.455248 53.062339,38.796544 C 53.320924,38.97019 53.532492,39.723484 53.532492,40.470532 C 53.532492,41.709371 53.329856,41.828802 51.227946,41.828802 C 49.960446,41.828802 48.933157,41.641002 48.945079,41.411469 z " + id="path36662" /> + <path + sodipodi:nodetypes="cssssssssssssssccssccsssccssscccssssccsssccssssccssssssc" + style="fill:#2b312f" + d="M 41.826658,53.327146 C 41.680227,52.849824 39.500065,52.707207 33.918704,52.80984 C 27.340708,52.930801 26.089866,52.817836 25.372137,52.03799 C 23.615269,50.129071 24.72071,47.665912 27.593778,47.087699 C 29.034051,46.797839 29.529263,46.949961 30.17543,47.880744 C 31.030372,49.112261 32.725295,48.902887 32.725295,47.565758 C 32.725295,47.047966 33.943443,46.71341 36.822265,46.440553 C 39.075599,46.226981 40.919235,45.854452 40.919235,45.61271 C 40.919235,45.007918 45.491341,43.997198 46.501607,44.378659 C 46.952136,44.548772 47.666432,45.137925 48.088932,45.687888 C 48.697409,46.479934 49.708879,46.707339 52.954084,46.781708 C 59.963933,46.942349 61.753684,47.295209 62.303656,48.625034 C 63.021865,50.361657 62.092257,52.139453 60.257475,52.538168 C 59.409357,52.722471 57.490356,52.873264 55.993021,52.873264 C 54.495687,52.873264 53.128164,53.123664 52.954084,53.429708 C 52.486261,54.252169 42.081018,54.156263 41.826658,53.327146 z M 48.361632,50.237407 C 47.371066,49.673481 46.790746,49.609676 46.410455,50.022881 C 45.870223,50.609869 45.952224,50.67534 48.088932,51.36298 C 49.564773,51.837938 49.759707,51.033331 48.361632,50.237407 z M 52.698023,50.309735 C 52.698023,50.189456 52.352341,50.091047 51.929841,50.091047 C 51.507341,50.091047 51.16166,50.333588 51.16166,50.630026 C 51.16166,50.926465 51.507341,51.024875 51.929841,50.848715 C 52.352341,50.672555 52.698023,50.430014 52.698023,50.309735 z M 22.079671,42.811143 C 21.453193,40.630111 21.487008,40.465082 22.92501,38.685543 C 23.748866,37.666014 24.687985,35.959222 25.011942,34.892672 C 25.534275,33.173009 30.106676,29.058604 30.455964,30.651526 C 31.044252,33.334407 31.035767,32.210718 30.305899,38.495649 L 30.298624,39.764472 L 30.332072,41.341577 C 29.489121,42.4673 29.2362,43.007546 28.612832,43.435903 C 28.198854,43.720376 27.470449,43.95696 26.994155,43.961646 C 26.517862,43.966333 25.985739,44.220567 25.811659,44.526611 C 25.637579,44.832655 24.873498,45.083054 24.113701,45.083054 C 22.945304,45.083054 22.631609,44.732673 22.079671,42.811143 z M 20.434386,42.85728 C 20.434386,42.551236 20.536012,42.300837 20.660223,42.300837 C 20.784433,42.300837 21.028488,42.551236 21.202568,42.85728 C 21.376648,43.163324 21.275021,43.413724 20.976731,43.413724 C 20.678441,43.413724 20.434386,43.163324 20.434386,42.85728 z M 38.360319,40.358116 C 37.476675,37.832807 38.059934,37.238939 42.084249,36.566458 C 43.273026,36.367809 43.45675,36.495297 43.208156,37.346342 C 43.044707,37.905886 43.143413,38.835592 43.427502,39.412355 C 44.156154,40.89169 43.19693,41.744393 40.804136,41.744393 C 39.187856,41.744393 38.760588,41.502022 38.360319,40.358116 z M 42.96772,33.437486 C 42.96772,33.153302 42.606034,32.527799 42.163971,32.04748 C 41.557271,31.388271 41.117846,31.315118 40.371547,31.74909 C 39.253376,32.399311 39.148366,32.131342 39.913009,30.578941 C 40.614764,29.154224 44.802799,28.967108 44.302815,30.38281 C 44.131843,30.866907 43.991962,31.868505 43.991962,32.608584 C 43.991962,33.348664 43.761508,33.954183 43.479841,33.954183 C 43.198174,33.954183 42.96772,33.721669 42.96772,33.437486 z " + id="path36660" /> + <path + sodipodi:nodetypes="cssccssccssssssssccsssccssssssssssssccssccsssssssccssssc" + style="fill:#101514" + d="M 41.43628,52.868183 C 42.073313,52.735085 42.995131,52.740138 43.484765,52.879412 C 43.974399,53.018686 43.453188,53.127584 42.326521,53.121408 C 41.199854,53.115231 40.799247,53.00128 41.43628,52.868183 z M 46.541775,52.896742 C 46.888497,52.744319 47.579861,52.735041 48.078139,52.876123 C 48.576418,53.017206 48.292733,53.141916 47.447733,53.153255 C 46.602733,53.164596 46.195054,53.049164 46.541775,52.896742 z M 24.018187,51.547832 C 22.903999,50.842712 22.854378,48.62399 23.926737,47.458822 C 24.978692,46.315824 27.731066,46.287068 27.731066,47.419076 C 27.731066,48.717393 30.654861,48.497758 31.434764,47.140854 C 31.957998,46.230513 32.629045,46.027967 35.121834,46.027967 C 37.814139,46.027967 38.058451,46.116 37.218399,46.783424 C 36.353359,47.470698 36.343219,47.584897 37.106039,48.04874 C 37.567215,48.329162 38.008668,49.178605 38.087043,49.93639 C 38.219575,51.217724 38.032359,51.339545 35.412884,51.676483 C 31.021658,52.241318 25.006681,52.173406 24.018187,51.547832 z M 27.218945,48.810185 C 27.218945,48.504141 26.98849,48.253741 26.706824,48.253741 C 26.425157,48.253741 26.194702,48.504141 26.194702,48.810185 C 26.194702,49.116229 26.425157,49.366629 26.706824,49.366629 C 26.98849,49.366629 27.218945,49.116229 27.218945,48.810185 z M 52.032289,51.549265 C 51.75794,51.066946 53.059906,50.479516 54.403256,50.479516 C 54.943549,50.479516 55.385612,50.214338 55.385612,49.890232 C 55.385612,49.566127 55.145023,49.46251 54.850968,49.659974 C 54.556918,49.857437 53.758434,49.621815 53.076565,49.13637 C 51.655649,48.124773 49.693482,47.983763 48.90837,48.836824 C 48.534265,49.243306 47.960361,49.216254 47.013521,48.747507 C 44.440988,47.473939 45.68977,46.584411 50.050226,46.584411 C 51.576352,46.584411 52.825006,46.83481 52.825006,47.140854 C 52.825006,47.446898 53.401143,47.697298 54.105309,47.697298 C 54.809476,47.697298 55.385612,47.446898 55.385612,47.140854 C 55.385612,46.530272 57.897874,46.385655 59.184635,46.922166 C 60.166684,47.331628 60.307799,50.962003 59.354552,51.293509 C 58.089177,51.73356 52.253064,51.937407 52.032289,51.549265 z M 42.07046,45.234103 C 42.07046,44.717926 42.508324,44.358636 43.137378,44.358636 C 44.385443,44.358636 44.209027,45.658919 42.924233,45.929657 C 42.418892,46.036145 42.07046,45.752284 42.07046,45.234103 z M 20.666552,40.567722 C 21.393364,39.750851 21.121339,39.573417 21.213567,39.395645 C 21.305795,39.217873 22.000465,37.632625 22.757278,35.872872 C 24.096991,32.757753 25.370264,31.02183 27.370063,31.082413 C 30.370925,31.173322 29.527061,32.982266 28.14859,37.207586 C 27.65163,38.730879 27.580581,38.920211 26.965093,39.602678 C 26.377562,40.254145 24.916722,41.576419 25.188478,41.576419 C 25.460235,41.576419 22.61698,42.747872 22.318945,42.678317 C 20.728036,42.30703 21.259868,41.469701 20.666552,40.567722 z M 37.145923,39.66137 C 36.58745,38.080058 37.193264,36.849258 38.618021,36.670577 C 39.517239,36.557806 40.02449,36.757853 40.028966,37.227021 C 40.032812,37.629904 40.17492,38.522935 40.34476,39.211534 C 40.617122,40.315816 40.463347,40.463532 39.041391,40.463532 C 38.109812,40.463532 37.309628,40.124892 37.145923,39.66137 z " + id="path36658" /> + <rect + rx="4.3636365" + ry="3.1818182" + y="45.735336" + x="24.573866" + height="7.090909" + width="22.181818" + id="rect25965" + style="opacity:0.60829492;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.41935223;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + style="opacity:0.60829492;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.41935223;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect26856" + width="22.181818" + height="7.090909" + x="40.119324" + y="46.587612" + ry="3.1818182" + rx="4.3636365" /> + <path + sodipodi:nodetypes="cccccc" + id="path29521" + d="M 38.208292,37.769089 C 39.358569,38.003404 40.485976,38.089061 41.550978,37.769089 C 41.95376,35.797761 41.671953,33.826433 41.550978,31.855105 C 40.908154,31.613064 40.265329,31.830172 39.622505,31.855105 C 39.176628,32.185866 38.704974,32.480539 38.465421,33.100155 C 38.024485,34.580346 38.054075,36.161365 38.208292,37.769089 z " + style="fill:#8c8c96;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccccccc" + id="path33069" + d="M 50,31.327695 C 50,31.327695 50,36.327695 50,36.327695 C 50.325272,36.685398 51.036999,36.244129 51.409723,35.327695 L 51.474005,31.888636 C 51.450622,31.384393 51.234095,31.073295 51,30.779764 C 50.622128,30.583014 50.29219,30.649897 50,30.924399 L 50,31.327695 z " + style="fill:#8c8c96;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + sodipodi:nodetypes="cccccccccccc" + id="path37570" + d="M 23.818182,33.681818 L 26.136363,28.863636 L 26.681818,30.409091 L 27.272727,28.863636 L 27.681818,29.863636 L 28.681818,28.863636 L 28.681818,29.863636 L 29.681818,28.863636 L 29.681818,30.318181 L 30.681818,29.318181 L 29.181818,33.318181 L 23.818182,33.681818 z " + style="fill:#101514;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/material.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,1323 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg2440" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="material16.svg"> + <defs + id="defs2442"> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.20759,4.280484)" + gradientUnits="userSpaceOnUse" + id="linearGradient15717" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.22545,4.844725)" + gradientUnits="userSpaceOnUse" + id="linearGradient15715" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.74975,10.45101)" + gradientUnits="userSpaceOnUse" + id="linearGradient15713" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.57061,10.68746)" + gradientUnits="userSpaceOnUse" + id="linearGradient15711" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.57613,11.25672)" + gradientUnits="userSpaceOnUse" + id="linearGradient15709" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.58166,11.82604)" + gradientUnits="userSpaceOnUse" + id="linearGradient15707" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.22043,5.338963)" + gradientUnits="userSpaceOnUse" + id="linearGradient15705" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.29843,11.98136)" + gradientUnits="userSpaceOnUse" + id="linearGradient15703" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.5036,5.183623)" + gradientUnits="userSpaceOnUse" + id="linearGradient15701" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.22596,5.908238)" + gradientUnits="userSpaceOnUse" + id="linearGradient15699" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(39.04149,12.25073)" + gradientUnits="userSpaceOnUse" + id="linearGradient15697" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(40.2315,6.477456)" + gradientUnits="userSpaceOnUse" + id="linearGradient15695" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="47.768186" + x2="64.261038" + y1="47.768186" + x1="12.426889" + gradientUnits="userSpaceOnUse" + id="linearGradient15693" + xlink:href="#linearGradient14721" + inkscape:collect="always" /> + <linearGradient + y2="37.731945" + x2="-3.6983578" + y1="30.163103" + x1="-14.005769" + gradientUnits="userSpaceOnUse" + id="linearGradient15691" + xlink:href="#linearGradient13828" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.20759,4.280484)" + gradientUnits="userSpaceOnUse" + id="linearGradient15657" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.22545,4.844725)" + gradientUnits="userSpaceOnUse" + id="linearGradient15655" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.74975,10.45101)" + gradientUnits="userSpaceOnUse" + id="linearGradient15653" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.57061,10.68746)" + gradientUnits="userSpaceOnUse" + id="linearGradient15651" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.57613,11.25672)" + gradientUnits="userSpaceOnUse" + id="linearGradient15649" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.58166,11.82604)" + gradientUnits="userSpaceOnUse" + id="linearGradient15647" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.22043,5.338963)" + gradientUnits="userSpaceOnUse" + id="linearGradient15645" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.29843,11.98136)" + gradientUnits="userSpaceOnUse" + id="linearGradient15643" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.5036,5.183623)" + gradientUnits="userSpaceOnUse" + id="linearGradient15641" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.22596,5.908238)" + gradientUnits="userSpaceOnUse" + id="linearGradient15639" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(39.04149,12.25073)" + gradientUnits="userSpaceOnUse" + id="linearGradient15637" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(40.2315,6.477456)" + gradientUnits="userSpaceOnUse" + id="linearGradient15635" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="47.768186" + x2="64.261038" + y1="47.768186" + x1="12.426889" + gradientUnits="userSpaceOnUse" + id="linearGradient15633" + xlink:href="#linearGradient14721" + inkscape:collect="always" /> + <linearGradient + y2="37.731945" + x2="-3.6983578" + y1="30.163103" + x1="-14.005769" + gradientUnits="userSpaceOnUse" + id="linearGradient15631" + xlink:href="#linearGradient13828" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="47.768186" + x2="64.261038" + y1="47.768186" + x1="12.426889" + id="linearGradient14727" + xlink:href="#linearGradient14721" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="37.731945" + x2="-3.6983578" + y1="30.163103" + x1="-14.005769" + id="linearGradient13834" + xlink:href="#linearGradient13828" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(81.61876,5.646799)" + gradientUnits="userSpaceOnUse" + id="linearGradient9332" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9328" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9326" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9324" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9322" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9320" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9318" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9316" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.59843,5.124412)" + gradientUnits="userSpaceOnUse" + id="linearGradient9300" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.06755,4.932912)" + gradientUnits="userSpaceOnUse" + id="linearGradient9298" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.88288,4.600081)" + gradientUnits="userSpaceOnUse" + id="linearGradient9296" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.88288,4.600081)" + gradientUnits="userSpaceOnUse" + id="linearGradient9294" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.06755,4.932912)" + gradientUnits="userSpaceOnUse" + id="linearGradient9292" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.38853,3.963864)" + gradientUnits="userSpaceOnUse" + id="linearGradient9290" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.20759,4.280484)" + gradientUnits="userSpaceOnUse" + id="linearGradient9288" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.22545,4.844725)" + gradientUnits="userSpaceOnUse" + id="linearGradient9258" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(78.93443,10.78375)" + gradientUnits="userSpaceOnUse" + id="linearGradient9256" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.74975,10.45101)" + gradientUnits="userSpaceOnUse" + id="linearGradient9254" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.57061,10.68746)" + gradientUnits="userSpaceOnUse" + id="linearGradient9252" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.57613,11.25672)" + gradientUnits="userSpaceOnUse" + id="linearGradient9250" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.58166,11.82604)" + gradientUnits="userSpaceOnUse" + id="linearGradient9248" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.22043,5.338963)" + gradientUnits="userSpaceOnUse" + id="linearGradient9246" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.29843,11.98136)" + gradientUnits="userSpaceOnUse" + id="linearGradient9230" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.5036,5.183623)" + gradientUnits="userSpaceOnUse" + id="linearGradient9228" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9226" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9224" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9222" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9220" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9218" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.22596,5.908238)" + gradientUnits="userSpaceOnUse" + id="linearGradient9202" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9200" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9198" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9196" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9194" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9192" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9190" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(39.04149,12.25073)" + gradientUnits="userSpaceOnUse" + id="linearGradient9174" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(40.2315,6.477456)" + gradientUnits="userSpaceOnUse" + id="linearGradient9172" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9170" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9168" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9166" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9164" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9162" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9146" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9144" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9142" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9140" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9138" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9136" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9134" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + gradientTransform="translate(50.87266,29.07501)" + spreadMethod="pad" + gradientUnits="userSpaceOnUse" + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + id="linearGradient8942" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + id="linearGradient8944"> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0" + id="stop8946" /> + <stop + style="stop-color:#643205;stop-opacity:1;" + offset="1" + id="stop8948" /> + </linearGradient> + <linearGradient + id="linearGradient13828"> + <stop + id="stop13830" + offset="0" + style="stop-color:#b45f3c;stop-opacity:1;" /> + <stop + id="stop13832" + offset="1" + style="stop-color:black;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient14721"> + <stop + id="stop14723" + offset="0" + style="stop-color:#b45f3c;stop-opacity:1;" /> + <stop + id="stop14725" + offset="1" + style="stop-color:#b45a32;stop-opacity:1;" /> + </linearGradient> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.696216" + inkscape:cx="10.235446" + inkscape:cy="4.0291613" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="588" + inkscape:window-x="133" + inkscape:window-y="218" /> + <metadata + id="metadata2445"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <g + inkscape:label="Layer 1" + id="g2825" + transform="matrix(0.244199,0,0,0.244199,0.370708,0.585652)"> + <g + transform="translate(-1.103718,-14.41486)" + id="g15614"> + <rect + transform="matrix(-0.736543,-0.676391,0,1,0,0)" + y="27.665213" + x="-16.330395" + height="11.002351" + width="13.529572" + id="rect3730" + style="opacity:1;fill:url(#linearGradient15631);fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.95430326;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-y="-2.9147578" /> + <rect + transform="matrix(0.965488,-0.260446,-0.725136,-0.688606,0,0)" + y="-47.773937" + x="-23.410841" + height="13.75526" + width="51.681412" + id="rect7060" + style="opacity:1;fill:#b45e3c;fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.88640648;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="7.3636364" + inkscape:transform-center-y="1.2727273" /> + <rect + style="opacity:1;fill:url(#linearGradient15633);fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.83337253;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect1956" + width="51.709148" + height="10.841806" + x="12.489389" + y="42.347282" + transform="matrix(0.965812,-0.259244,0,1,0,0)" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15635);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600295;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9158" + width="4.892199" + height="4.0177379" + x="-15.943752" + y="-43.596188" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088689" + rx="1.2577795" /> + <rect + rx="1.2577792" + ry="2.0088704" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-37.82296" + x="-17.133751" + height="4.0177407" + width="4.8921981" + id="rect9160" + style="opacity:1;fill:url(#linearGradient15637);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600304;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15639);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600319;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9188" + width="4.8921971" + height="4.0177436" + x="-7.9492798" + y="-44.165485" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088718" + rx="1.257779" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15641);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9214" + width="4.8921957" + height="4.0177479" + x="8.3283815" + y="-44.890163" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088739" + rx="1.2577786" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-38.092388" + x="-7.876812" + height="4.017745" + width="4.8921967" + id="rect9216" + style="opacity:1;fill:url(#linearGradient15643);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15645);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9232" + width="4.8921967" + height="4.017745" + x="0.045193601" + y="-44.734779" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-38.2477" + x="0.40642422" + height="4.017745" + width="4.8921967" + id="rect9234" + style="opacity:1;fill:url(#linearGradient15647);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15649);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600319;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9236" + width="4.8921971" + height="4.0177436" + x="8.400897" + y="-38.816994" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088718" + rx="1.257779" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-39.386284" + x="16.39537" + height="4.017745" + width="4.8921967" + id="rect9238" + style="opacity:1;fill:url(#linearGradient15651);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15653);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9240" + width="4.8921967" + height="4.017745" + x="23.574509" + y="-39.622746" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15655);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9244" + width="4.8921962" + height="4.0177464" + x="16.050222" + y="-45.229042" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088732" + rx="1.2577788" /> + <rect + rx="1.2577786" + ry="2.0088739" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-45.793304" + x="24.032372" + height="4.0177479" + width="4.8921957" + id="rect9260" + style="opacity:1;fill:url(#linearGradient15657);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + </g> + <g + id="g15659" + transform="translate(0.896282,6.585141)"> + <rect + inkscape:transform-center-y="-2.9147578" + style="opacity:1;fill:url(#linearGradient15691);fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.95430326;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15661" + width="13.529572" + height="11.002351" + x="-16.330395" + y="27.665213" + transform="matrix(-0.736543,-0.676391,0,1,0,0)" /> + <rect + inkscape:transform-center-y="1.2727273" + inkscape:transform-center-x="7.3636364" + style="opacity:1;fill:#b45e3c;fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.88640648;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15663" + width="51.681412" + height="13.75526" + x="-23.410841" + y="-47.773937" + transform="matrix(0.965488,-0.260446,-0.725136,-0.688606,0,0)" /> + <rect + transform="matrix(0.965812,-0.259244,0,1,0,0)" + y="42.347282" + x="12.489389" + height="10.841806" + width="51.709148" + id="rect15665" + style="opacity:1;fill:url(#linearGradient15693);fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.83337253;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + rx="1.2577795" + ry="2.0088689" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-43.596188" + x="-15.943752" + height="4.0177379" + width="4.892199" + id="rect15667" + style="opacity:1;fill:url(#linearGradient15695);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600295;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15697);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600304;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15669" + width="4.8921981" + height="4.0177407" + x="-17.133751" + y="-37.82296" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088704" + rx="1.2577792" /> + <rect + rx="1.257779" + ry="2.0088718" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-44.165485" + x="-7.9492798" + height="4.0177436" + width="4.8921971" + id="rect15671" + style="opacity:1;fill:url(#linearGradient15699);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600319;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + rx="1.2577786" + ry="2.0088739" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-44.890163" + x="8.3283815" + height="4.0177479" + width="4.8921957" + id="rect15673" + style="opacity:1;fill:url(#linearGradient15701);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15703);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15675" + width="4.8921967" + height="4.017745" + x="-7.876812" + y="-38.092388" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-44.734779" + x="0.045193601" + height="4.017745" + width="4.8921967" + id="rect15677" + style="opacity:1;fill:url(#linearGradient15705);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15707);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15679" + width="4.8921967" + height="4.017745" + x="0.40642422" + y="-38.2477" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + rx="1.257779" + ry="2.0088718" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-38.816994" + x="8.400897" + height="4.0177436" + width="4.8921971" + id="rect15681" + style="opacity:1;fill:url(#linearGradient15709);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600319;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15711);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15683" + width="4.8921967" + height="4.017745" + x="16.39537" + y="-39.386284" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-39.622746" + x="23.574509" + height="4.017745" + width="4.8921967" + id="rect15685" + style="opacity:1;fill:url(#linearGradient15713);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + rx="1.2577788" + ry="2.0088732" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-45.229042" + x="16.050222" + height="4.0177464" + width="4.8921962" + id="rect15687" + style="opacity:1;fill:url(#linearGradient15715);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15717);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15689" + width="4.8921957" + height="4.0177479" + x="24.032372" + y="-45.793304" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088739" + rx="1.2577786" /> + </g> + </g> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/measure.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="measure.svg"> + <defs + id="defs1874" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.197802" + inkscape:cx="8" + inkscape:cy="8" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="588" + inkscape:window-x="53" + inkscape:window-y="400" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="opacity:0.98156684;fill:white;fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect1880" + width="14.999995" + height="7.4550009" + x="0.4999997" + y="8.0449991" /> + <path + sodipodi:type="star" + style="opacity:0.98156684;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.98248434;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="path6374" + sodipodi:sides="3" + sodipodi:cx="1.6217822" + sodipodi:cy="3.070792" + sodipodi:r1="2.3892968" + sodipodi:r2="0.56356913" + sodipodi:arg1="3.1227368" + sodipodi:arg2="4.1699343" + inkscape:flatsided="true" + inkscape:rounded="0" + inkscape:randomized="0" + d="M -0.76708985,3.1158415 L 2.7772041,0.97944331 L 2.8552323,5.117091 L -0.76708985,3.1158415 z " + transform="matrix(1.035974,0,0,1,1.88033,-0.135149)" /> + <path + transform="matrix(-1.035974,0,0,1,14.1558,-8.961075e-2)" + d="M -0.81057489,3.0707919 L 2.8379608,0.96430898 L 2.8379607,5.177275 L -0.81057489,3.0707919 z " + inkscape:randomized="0" + inkscape:rounded="0" + inkscape:flatsided="true" + sodipodi:arg2="-2.0943951" + sodipodi:arg1="-3.1415926" + sodipodi:r2="0.56356913" + sodipodi:r1="2.4323571" + sodipodi:cy="3.070792" + sodipodi:cx="1.6217822" + sodipodi:sides="3" + id="path6380" + style="opacity:0.98156684;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.98248434;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + sodipodi:type="star" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 3.1534679,2.909901 L 13.513201,2.909901" + id="path6382" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.99999928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 3.9999996,11.846375 L 3.9999996,8.0285077" + id="path6386" /> + <path + id="path6446" + d="M 7.9999996,12.071623 L 7.9999996,8.2537552" + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.99999928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.99999928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 12,12.071623 L 12,8.2537552" + id="path6448" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/menu.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="menu.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1874" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.197802" + inkscape:cx="8" + inkscape:cy="8" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1013" + inkscape:window-height="592" + inkscape:window-x="345" + inkscape:window-y="234"> + <sodipodi:guide + orientation="vertical" + position="24.957426" + id="guide3733" /> + <sodipodi:guide + orientation="vertical" + position="13.469802" + id="guide3735" /> + </sodipodi:namedview> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + sodipodi:type="star" + style="opacity:0.98156684;fill:#767676;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="path2162" + sodipodi:sides="3" + sodipodi:cx="7.9287128" + sodipodi:cy="7.8009901" + sodipodi:r1="3.5138614" + sodipodi:r2="1.7569307" + sodipodi:arg1="3.1415927" + sodipodi:arg2="4.1887902" + inkscape:flatsided="true" + inkscape:rounded="0" + inkscape:randomized="0" + d="M 4.4148514,7.8009899 L 9.6856437,4.7578969 L 9.6856434,10.844083 L 4.4148514,7.8009899 z " + transform="matrix(1.3280736,0,0,1.314452,-1.8632474,-2.2540272)" /> + <rect + style="opacity:0.98156684;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#767676;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect1958" + width="10.839109" + height="10.801485" + x="2.6608906" + y="2.5" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/normalline.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images" + sodipodi:docname="normalline.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1874" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.197802" + inkscape:cx="8" + inkscape:cy="8" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="593" + inkscape:window-x="53" + inkscape:window-y="373" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="opacity:0.98156684;fill:white;fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="rect1880" + width="14.999995" + height="7.4550009" + x="0.4999997" + y="8.0449991" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.99999928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 3.9999996,11.846375 L 3.9999996,8.0285077" + id="path6386" /> + <path + id="path6446" + d="M 7.9999996,12.071623 L 7.9999996,8.2537552" + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.99999928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:0.99999928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 12,12.071623 L 12,8.2537552" + id="path6448" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/parcialline.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,274 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images" + sodipodi:docname="parcialline.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1874"> + <linearGradient + inkscape:collect="always" + id="linearGradient17756"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop17758" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop17760" /> + </linearGradient> + <linearGradient + id="linearGradient14825"> + <stop + style="stop-color:#767676;stop-opacity:1;" + offset="0" + id="stop14827" /> + <stop + style="stop-color:#767676;stop-opacity:0;" + offset="1" + id="stop14829" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient12879"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop12881" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop12883" /> + </linearGradient> + <linearGradient + id="linearGradient11894"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop11896" /> + <stop + id="stop12873" + offset="0.5" + style="stop-color:#000000;stop-opacity:0.49803922;" /> + <stop + style="stop-color:#000000;stop-opacity:0.24705882;" + offset="0.75" + id="stop12875" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop11898" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient12879" + id="linearGradient12885" + x1="27.034161" + y1="12.910394" + x2="17.256927" + y2="3.1346524" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.066667,0,0,1.0666666,-43.235618,-4.6997925)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient14825" + id="linearGradient16775" + x1="13.375" + y1="12.875" + x2="6.5" + y2="5.75" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-24.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17764" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-24.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17768" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-21.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17772" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-18.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17776" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-15.25,-0.5625)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17786" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-24.25,1.9375)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17788" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-21.25,1.9375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17790" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-18.25,1.9375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17792" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-15.25,1.9375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17802" + gradientUnits="userSpaceOnUse" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" + gradientTransform="translate(-24.25,4.4375)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17804" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-21.25,4.4375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17806" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-18.25,4.4375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient17756" + id="linearGradient17808" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-15.25,4.4375)" + x1="2.734375" + y1="7.234375" + x2="4.5" + y2="9" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="16" + inkscape:cx="0.18483036" + inkscape:cy="2.0462504" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1280" + inkscape:window-height="946" + inkscape:window-x="0" + inkscape:window-y="26" /> + <metadata + id="metadata1877"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <text + xml:space="preserve" + style="font-size:17.83880806px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans" + x="-0.72295946" + y="12.991862" + id="text17828" + transform="scale(0.812785,1.2303376)"><tspan + sodipodi:role="line" + x="-0.72295946" + y="12.991862" + id="tspan17832" + style="font-family:DejaVu Serif">Σ</tspan></text> + <text + xml:space="preserve" + style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans" + x="8.6478977" + y="13.546875" + id="text17836"><tspan + sodipodi:role="line" + id="tspan17838" + x="8.6478977" + y="13.546875" + style="font-size:12px">p</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/pyArq-Presupuestos.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,1323 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg2440" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="material16.svg"> + <defs + id="defs2442"> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.20759,4.280484)" + gradientUnits="userSpaceOnUse" + id="linearGradient15717" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.22545,4.844725)" + gradientUnits="userSpaceOnUse" + id="linearGradient15715" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.74975,10.45101)" + gradientUnits="userSpaceOnUse" + id="linearGradient15713" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.57061,10.68746)" + gradientUnits="userSpaceOnUse" + id="linearGradient15711" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.57613,11.25672)" + gradientUnits="userSpaceOnUse" + id="linearGradient15709" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.58166,11.82604)" + gradientUnits="userSpaceOnUse" + id="linearGradient15707" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.22043,5.338963)" + gradientUnits="userSpaceOnUse" + id="linearGradient15705" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.29843,11.98136)" + gradientUnits="userSpaceOnUse" + id="linearGradient15703" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.5036,5.183623)" + gradientUnits="userSpaceOnUse" + id="linearGradient15701" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.22596,5.908238)" + gradientUnits="userSpaceOnUse" + id="linearGradient15699" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(39.04149,12.25073)" + gradientUnits="userSpaceOnUse" + id="linearGradient15697" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(40.2315,6.477456)" + gradientUnits="userSpaceOnUse" + id="linearGradient15695" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="47.768186" + x2="64.261038" + y1="47.768186" + x1="12.426889" + gradientUnits="userSpaceOnUse" + id="linearGradient15693" + xlink:href="#linearGradient14721" + inkscape:collect="always" /> + <linearGradient + y2="37.731945" + x2="-3.6983578" + y1="30.163103" + x1="-14.005769" + gradientUnits="userSpaceOnUse" + id="linearGradient15691" + xlink:href="#linearGradient13828" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.20759,4.280484)" + gradientUnits="userSpaceOnUse" + id="linearGradient15657" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.22545,4.844725)" + gradientUnits="userSpaceOnUse" + id="linearGradient15655" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.74975,10.45101)" + gradientUnits="userSpaceOnUse" + id="linearGradient15653" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.57061,10.68746)" + gradientUnits="userSpaceOnUse" + id="linearGradient15651" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.57613,11.25672)" + gradientUnits="userSpaceOnUse" + id="linearGradient15649" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.58166,11.82604)" + gradientUnits="userSpaceOnUse" + id="linearGradient15647" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.22043,5.338963)" + gradientUnits="userSpaceOnUse" + id="linearGradient15645" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.29843,11.98136)" + gradientUnits="userSpaceOnUse" + id="linearGradient15643" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.5036,5.183623)" + gradientUnits="userSpaceOnUse" + id="linearGradient15641" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.22596,5.908238)" + gradientUnits="userSpaceOnUse" + id="linearGradient15639" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(39.04149,12.25073)" + gradientUnits="userSpaceOnUse" + id="linearGradient15637" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(40.2315,6.477456)" + gradientUnits="userSpaceOnUse" + id="linearGradient15635" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="47.768186" + x2="64.261038" + y1="47.768186" + x1="12.426889" + gradientUnits="userSpaceOnUse" + id="linearGradient15633" + xlink:href="#linearGradient14721" + inkscape:collect="always" /> + <linearGradient + y2="37.731945" + x2="-3.6983578" + y1="30.163103" + x1="-14.005769" + gradientUnits="userSpaceOnUse" + id="linearGradient15631" + xlink:href="#linearGradient13828" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="47.768186" + x2="64.261038" + y1="47.768186" + x1="12.426889" + id="linearGradient14727" + xlink:href="#linearGradient14721" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="37.731945" + x2="-3.6983578" + y1="30.163103" + x1="-14.005769" + id="linearGradient13834" + xlink:href="#linearGradient13828" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(81.61876,5.646799)" + gradientUnits="userSpaceOnUse" + id="linearGradient9332" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9328" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9326" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9324" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9322" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9320" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9318" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.25221,5.265743)" + gradientUnits="userSpaceOnUse" + id="linearGradient9316" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.59843,5.124412)" + gradientUnits="userSpaceOnUse" + id="linearGradient9300" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.06755,4.932912)" + gradientUnits="userSpaceOnUse" + id="linearGradient9298" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.88288,4.600081)" + gradientUnits="userSpaceOnUse" + id="linearGradient9296" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.88288,4.600081)" + gradientUnits="userSpaceOnUse" + id="linearGradient9294" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.06755,4.932912)" + gradientUnits="userSpaceOnUse" + id="linearGradient9292" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.38853,3.963864)" + gradientUnits="userSpaceOnUse" + id="linearGradient9290" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(80.20759,4.280484)" + gradientUnits="userSpaceOnUse" + id="linearGradient9288" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.22545,4.844725)" + gradientUnits="userSpaceOnUse" + id="linearGradient9258" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(78.93443,10.78375)" + gradientUnits="userSpaceOnUse" + id="linearGradient9256" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(79.74975,10.45101)" + gradientUnits="userSpaceOnUse" + id="linearGradient9254" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(72.57061,10.68746)" + gradientUnits="userSpaceOnUse" + id="linearGradient9252" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.57613,11.25672)" + gradientUnits="userSpaceOnUse" + id="linearGradient9250" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.58166,11.82604)" + gradientUnits="userSpaceOnUse" + id="linearGradient9248" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(56.22043,5.338963)" + gradientUnits="userSpaceOnUse" + id="linearGradient9246" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.29843,11.98136)" + gradientUnits="userSpaceOnUse" + id="linearGradient9230" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(64.5036,5.183623)" + gradientUnits="userSpaceOnUse" + id="linearGradient9228" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9226" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9224" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9222" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9220" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(58.4507,7.021745)" + gradientUnits="userSpaceOnUse" + id="linearGradient9218" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(48.22596,5.908238)" + gradientUnits="userSpaceOnUse" + id="linearGradient9202" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9200" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9198" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9196" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9194" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9192" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(52.08691,6.925356)" + gradientUnits="userSpaceOnUse" + id="linearGradient9190" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(39.04149,12.25073)" + gradientUnits="userSpaceOnUse" + id="linearGradient9174" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(40.2315,6.477456)" + gradientUnits="userSpaceOnUse" + id="linearGradient9172" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9170" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9168" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9166" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9164" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(45.72311,6.828969)" + gradientUnits="userSpaceOnUse" + id="linearGradient9162" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9146" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9144" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9142" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9140" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9138" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9136" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + spreadMethod="pad" + gradientTransform="translate(38.99899,6.879667)" + gradientUnits="userSpaceOnUse" + id="linearGradient9134" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + gradientTransform="translate(50.87266,29.07501)" + spreadMethod="pad" + gradientUnits="userSpaceOnUse" + y2="-48.064571" + x2="-51.220619" + y1="-48.064571" + x1="-56.237823" + id="linearGradient8942" + xlink:href="#linearGradient8944" + inkscape:collect="always" /> + <linearGradient + id="linearGradient8944"> + <stop + style="stop-color:black;stop-opacity:1;" + offset="0" + id="stop8946" /> + <stop + style="stop-color:#643205;stop-opacity:1;" + offset="1" + id="stop8948" /> + </linearGradient> + <linearGradient + id="linearGradient13828"> + <stop + id="stop13830" + offset="0" + style="stop-color:#b45f3c;stop-opacity:1;" /> + <stop + id="stop13832" + offset="1" + style="stop-color:black;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient14721"> + <stop + id="stop14723" + offset="0" + style="stop-color:#b45f3c;stop-opacity:1;" /> + <stop + id="stop14725" + offset="1" + style="stop-color:#b45a32;stop-opacity:1;" /> + </linearGradient> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.696216" + inkscape:cx="10.235446" + inkscape:cy="4.0291613" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="588" + inkscape:window-x="133" + inkscape:window-y="218" /> + <metadata + id="metadata2445"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <g + inkscape:label="Layer 1" + id="g2825" + transform="matrix(0.244199,0,0,0.244199,0.370708,0.585652)"> + <g + transform="translate(-1.103718,-14.41486)" + id="g15614"> + <rect + transform="matrix(-0.736543,-0.676391,0,1,0,0)" + y="27.665213" + x="-16.330395" + height="11.002351" + width="13.529572" + id="rect3730" + style="opacity:1;fill:url(#linearGradient15631);fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.95430326;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-y="-2.9147578" /> + <rect + transform="matrix(0.965488,-0.260446,-0.725136,-0.688606,0,0)" + y="-47.773937" + x="-23.410841" + height="13.75526" + width="51.681412" + id="rect7060" + style="opacity:1;fill:#b45e3c;fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.88640648;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="7.3636364" + inkscape:transform-center-y="1.2727273" /> + <rect + style="opacity:1;fill:url(#linearGradient15633);fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.83337253;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect1956" + width="51.709148" + height="10.841806" + x="12.489389" + y="42.347282" + transform="matrix(0.965812,-0.259244,0,1,0,0)" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15635);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600295;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9158" + width="4.892199" + height="4.0177379" + x="-15.943752" + y="-43.596188" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088689" + rx="1.2577795" /> + <rect + rx="1.2577792" + ry="2.0088704" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-37.82296" + x="-17.133751" + height="4.0177407" + width="4.8921981" + id="rect9160" + style="opacity:1;fill:url(#linearGradient15637);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600304;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15639);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600319;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9188" + width="4.8921971" + height="4.0177436" + x="-7.9492798" + y="-44.165485" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088718" + rx="1.257779" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15641);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9214" + width="4.8921957" + height="4.0177479" + x="8.3283815" + y="-44.890163" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088739" + rx="1.2577786" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-38.092388" + x="-7.876812" + height="4.017745" + width="4.8921967" + id="rect9216" + style="opacity:1;fill:url(#linearGradient15643);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15645);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9232" + width="4.8921967" + height="4.017745" + x="0.045193601" + y="-44.734779" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-38.2477" + x="0.40642422" + height="4.017745" + width="4.8921967" + id="rect9234" + style="opacity:1;fill:url(#linearGradient15647);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15649);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600319;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9236" + width="4.8921971" + height="4.0177436" + x="8.400897" + y="-38.816994" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088718" + rx="1.257779" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-39.386284" + x="16.39537" + height="4.017745" + width="4.8921967" + id="rect9238" + style="opacity:1;fill:url(#linearGradient15651);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15653);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9240" + width="4.8921967" + height="4.017745" + x="23.574509" + y="-39.622746" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15655);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect9244" + width="4.8921962" + height="4.0177464" + x="16.050222" + y="-45.229042" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088732" + rx="1.2577788" /> + <rect + rx="1.2577786" + ry="2.0088739" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-45.793304" + x="24.032372" + height="4.0177479" + width="4.8921957" + id="rect9260" + style="opacity:1;fill:url(#linearGradient15657);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + </g> + <g + id="g15659" + transform="translate(0.896282,6.585141)"> + <rect + inkscape:transform-center-y="-2.9147578" + style="opacity:1;fill:url(#linearGradient15691);fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.95430326;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15661" + width="13.529572" + height="11.002351" + x="-16.330395" + y="27.665213" + transform="matrix(-0.736543,-0.676391,0,1,0,0)" /> + <rect + inkscape:transform-center-y="1.2727273" + inkscape:transform-center-x="7.3636364" + style="opacity:1;fill:#b45e3c;fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.88640648;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15663" + width="51.681412" + height="13.75526" + x="-23.410841" + y="-47.773937" + transform="matrix(0.965488,-0.260446,-0.725136,-0.688606,0,0)" /> + <rect + transform="matrix(0.965812,-0.259244,0,1,0,0)" + y="42.347282" + x="12.489389" + height="10.841806" + width="51.709148" + id="rect15665" + style="opacity:1;fill:url(#linearGradient15693);fill-opacity:1;fill-rule:nonzero;stroke:#5a2d2d;stroke-width:0.83337253;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <rect + rx="1.2577795" + ry="2.0088689" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-43.596188" + x="-15.943752" + height="4.0177379" + width="4.892199" + id="rect15667" + style="opacity:1;fill:url(#linearGradient15695);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600295;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15697);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600304;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15669" + width="4.8921981" + height="4.0177407" + x="-17.133751" + y="-37.82296" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088704" + rx="1.2577792" /> + <rect + rx="1.257779" + ry="2.0088718" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-44.165485" + x="-7.9492798" + height="4.0177436" + width="4.8921971" + id="rect15671" + style="opacity:1;fill:url(#linearGradient15699);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600319;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + rx="1.2577786" + ry="2.0088739" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-44.890163" + x="8.3283815" + height="4.0177479" + width="4.8921957" + id="rect15673" + style="opacity:1;fill:url(#linearGradient15701);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15703);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15675" + width="4.8921967" + height="4.017745" + x="-7.876812" + y="-38.092388" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-44.734779" + x="0.045193601" + height="4.017745" + width="4.8921967" + id="rect15677" + style="opacity:1;fill:url(#linearGradient15705);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15707);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15679" + width="4.8921967" + height="4.017745" + x="0.40642422" + y="-38.2477" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + rx="1.257779" + ry="2.0088718" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-38.816994" + x="8.400897" + height="4.0177436" + width="4.8921971" + id="rect15681" + style="opacity:1;fill:url(#linearGradient15709);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600319;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15711);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15683" + width="4.8921967" + height="4.017745" + x="16.39537" + y="-39.386284" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088725" + rx="1.2577789" /> + <rect + rx="1.2577789" + ry="2.0088725" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-39.622746" + x="23.574509" + height="4.017745" + width="4.8921967" + id="rect15685" + style="opacity:1;fill:url(#linearGradient15713);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600328;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + rx="1.2577788" + ry="2.0088732" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + y="-45.229042" + x="16.050222" + height="4.0177464" + width="4.8921962" + id="rect15687" + style="opacity:1;fill:url(#linearGradient15715);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + inkscape:transform-center-x="0.79120403" + inkscape:transform-center-y="0.026301068" /> + <rect + inkscape:transform-center-y="0.026301068" + inkscape:transform-center-x="0.79120403" + style="opacity:1;fill:url(#linearGradient15717);fill-opacity:1;fill-rule:nonzero;stroke:black;stroke-width:0.42600334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect15689" + width="4.8921957" + height="4.0177479" + x="24.032372" + y="-45.793304" + transform="matrix(0.952979,-0.303036,-0.670014,-0.742349,0,0)" + ry="2.0088739" + rx="1.2577786" /> + </g> + </g> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/pyArqPresupuestos.xpm Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,1439 @@ +/* XPM */ +static char * arquimeter_xpm[] = { +"128 128 1308 2", +" c None", +". c #592D2D", +"+ c #5D2E2C", +"@ c #5A2D2D", +"# c #5B2D2D", +"$ c #5B2E2E", +"% c #5A2E2D", +"& c #5E2E2D", +"* c #743C32", +"= c #8D4835", +"- c #A55639", +"; c #B45E3C", +"> c #A5563A", +", c #61322F", +"' c #5C2E2E", +") c #5A2C2C", +"! c #6D3730", +"~ c #864534", +"{ c #9E5238", +"] c #B25D3C", +"^ c #A7573A", +"/ c #64332F", +"( c #5A2E2E", +"_ c #653430", +": c #7E4133", +"< c #974E37", +"[ c #AF5B3B", +"} c #984F33", +"| c #7D412A", +"1 c #8A482E", +"2 c #B25D3B", +"3 c #AA583A", +"4 c #66342F", +"5 c #5C2D2D", +"6 c #5B2C2C", +"7 c #60312F", +"8 c #773D32", +"9 c #904A36", +"0 c #A9583A", +"a c #B35E3C", +"b c #8F4A30", +"c c #4C2818", +"d c #1B0E07", +"e c #221106", +"f c #301803", +"g c #351A05", +"h c #2B1609", +"i c #693721", +"j c #B35D3C", +"k c #AC5A3B", +"l c #693630", +"m c #5C2E2D", +"n c #713931", +"o c #894735", +"p c #A25339", +"q c #88482E", +"r c #150B06", +"s c #190D05", +"t c #1E0F01", +"u c #301802", +"v c #391C02", +"w c #422103", +"x c #4A2503", +"y c #522904", +"z c #3D1F04", +"A c #30190D", +"B c #AC5A39", +"C c #AD5A3B", +"D c #6C362F", +"E c #683530", +"F c #824334", +"G c #9A5038", +"H c #B15C3C", +"I c #391E13", +"J c #0B0500", +"K c #190C01", +"L c #211001", +"M c #2A1502", +"N c #321902", +"O c #3A1D02", +"P c #432103", +"Q c #4B2503", +"R c #532904", +"S c #432104", +"T c #30190E", +"U c #B05B3B", +"V c #703931", +"W c #62322F", +"X c #7B3F33", +"Y c #934C36", +"Z c #AB593A", +"` c #985033", +" . c #6C3923", +".. c #6D3924", +"+. c #9D5234", +"@. c #592F1E", +"#. c #080401", +"$. c #110800", +"%. c #1A0D01", +"&. c #221101", +"*. c #331902", +"=. c #3B1D02", +"-. c #4C2603", +";. c #542A04", +">. c #2B1605", +",. c #793F28", +"'. c #723A31", +"). c #733B31", +"!. c #8C4835", +"~. c #A45539", +"{. c #904B30", +"]. c #4F291A", +"^. c #1C0F08", +"/. c #201006", +"(. c #2F1803", +"_. c #331A07", +":. c #3B1E10", +"<. c #9B5134", +"[. c #A55637", +"}. c #110906", +"|. c #090500", +"1. c #120900", +"2. c #231101", +"3. c #2B1502", +"4. c #3C1E03", +"5. c #442203", +"6. c #3B1D03", +"7. c #422215", +"8. c #773C31", +"9. c #6C3730", +"0. c #844534", +"a. c #9D5138", +"b. c #190D08", +"c. c #180C05", +"d. c #1B0D01", +"e. c #2D1602", +"f. c #361B02", +"g. c #3E1F03", +"h. c #472303", +"i. c #4F2703", +"j. c #4F2704", +"k. c #221107", +"l. c #85452C", +"m. c #89472D", +"n. c #120A06", +"o. c #0A0500", +"p. c #130900", +"q. c #241201", +"r. c #2C1602", +"s. c #341A02", +"t. c #3B1E03", +"u. c #1A0D04", +"v. c #673522", +"w. c #7A3F33", +"x. c #65332F", +"y. c #7D4033", +"z. c #964E37", +"A. c #7C4129", +"B. c #0F0704", +"C. c #150A01", +"D. c #261301", +"E. c #2E1702", +"F. c #371B02", +"G. c #3F1F03", +"H. c #502804", +"I. c #1B0E05", +"J. c #964F32", +"K. c #26140D", +"L. c #100803", +"M. c #130901", +"N. c #1D0E06", +"O. c #4B2718", +"P. c #804133", +"Q. c #592E2E", +"R. c #5B2E2D", +"S. c #5F2F2E", +"T. c #763D32", +"U. c #8F4A36", +"V. c #A8573A", +"W. c #653521", +"X. c #512A19", +"Y. c #773E27", +"Z. c #9F5335", +"`. c #0F0804", +" + c #0E0700", +".+ c #160B01", +"++ c #1F0F01", +"@+ c #271301", +"#+ c #2F1702", +"$+ c #381C02", +"%+ c #402003", +"&+ c #482403", +"*+ c #512804", +"=+ c #462303", +"-+ c #321A0F", +";+ c #82442B", +">+ c #3B1F13", +",+ c #2F180F", +"'+ c #542B1C", +")+ c #944D31", +"!+ c #834334", +"~+ c #6F3830", +"{+ c #884635", +"]+ c #A05339", +"^+ c #954E32", +"/+ c #542C1B", +"(+ c #1E1009", +"_+ c #1E0F06", +":+ c #2D1603", +"<+ c #3B1E04", +"[+ c #2D1709", +"}+ c #653520", +"|+ c #3D2014", +"1+ c #090401", +"2+ c #0F0700", +"3+ c #170B01", +"4+ c #201001", +"5+ c #281402", +"6+ c #412003", +"7+ c #492403", +"8+ c #512904", +"9+ c #0C0603", +"0+ c #914C30", +"a+ c #532B1A", +"b+ c #381D10", +"c+ c #4B2716", +"d+ c #884735", +"e+ c #673430", +"f+ c #814234", +"g+ c #995038", +"h+ c #B05C3B", +"i+ c #391D13", +"j+ c #130A05", +"k+ c #180C01", +"l+ c #291402", +"m+ c #3A1D05", +"n+ c #3B1F11", +"o+ c #AD5A3A", +"p+ c #2A160E", +"q+ c #0B0502", +"r+ c #100800", +"s+ c #311802", +"t+ c #231205", +"u+ c #361C11", +"v+ c #472517", +"w+ c #190D07", +"x+ c #2E1602", +"y+ c #482404", +"z+ c #361B06", +"A+ c #A05435", +"B+ c #8D4936", +"C+ c #61312E", +"D+ c #7A3E32", +"E+ c #924B36", +"F+ c #AA593A", +"G+ c #090503", +"H+ c #381C05", +"I+ c #B15D3B", +"J+ c #512A1B", +"K+ c #0D0700", +"L+ c #180B01", +"M+ c #1A0E07", +"N+ c #482617", +"O+ c #552C1C", +"P+ c #100804", +"Q+ c #4C2503", +"R+ c #221108", +"S+ c #914B36", +"T+ c #5A2D2C", +"U+ c #5D2E2D", +"V+ c #723B31", +"W+ c #8A4835", +"X+ c #A25539", +"Y+ c #663521", +"Z+ c #412213", +"`+ c #4E2817", +" @ c #8C492F", +".@ c #25130C", +"+@ c #080400", +"@@ c #452203", +"#@ c #4D2603", +"$@ c #552A04", +"%@ c #1A0D05", +"&@ c #A25436", +"*@ c #A65737", +"=@ c #653421", +"-@ c #3F2114", +";@ c #562C1C", +">@ c #924C31", +",@ c #0C0600", +"'@ c #4D2703", +")@ c #1E1008", +"!@ c #944D37", +"~@ c #5B2D2C", +"{@ c #6A3630", +"]@ c #9C5138", +"^@ c #B15C3B", +"/@ c #5A2F1D", +"(@ c #20110A", +"_@ c #1C0F06", +":@ c #291503", +"<@ c #361C0E", +"[@ c #0E0705", +"}@ c #1C0E01", +"|@ c #351A02", +"1@ c #3D1E03", +"2@ c #4E2703", +"3@ c #261305", +"4@ c #592F1D", +"5@ c #2F180D", +"6@ c #321A0E", +"7@ c #5D301D", +"8@ c #A75738", +"9@ c #613320", +"0@ c #0A0502", +"a@ c #301804", +"b@ c #703B25", +"c@ c #64322F", +"d@ c #7C4033", +"e@ c #954E37", +"f@ c #773E28", +"g@ c #0E0704", +"h@ c #150B01", +"i@ c #211107", +"j@ c #8C492E", +"k@ c #783E28", +"l@ c #110905", +"m@ c #0B0600", +"n@ c #140A01", +"o@ c #251201", +"p@ c #271405", +"q@ c #180C07", +"r@ c #A35536", +"s@ c #974F32", +"t@ c #4D2819", +"u@ c #1B0E08", +"v@ c #2A1508", +"w@ c #6A3822", +"x@ c #1B0E09", +"y@ c #070300", +"z@ c #512A1A", +"A@ c #5A2E2C", +"B@ c #5D302E", +"C@ c #753B31", +"D@ c #8E4936", +"E@ c #A6563A", +"F@ c #462417", +"G@ c #1A0D06", +"H@ c #934C31", +"I@ c #26140C", +"J@ c #110904", +"K@ c #0F0701", +"L@ c #432315", +"M@ c #85462C", +"N@ c #964E32", +"O@ c #331905", +"P@ c #4D2818", +"Q@ c #A45637", +"R@ c #1F100A", +"S@ c #321802", +"T@ c #2B1501", +"U@ c #241206", +"V@ c #B45D3C", +"W@ c #834434", +"X@ c #68352F", +"Y@ c #6E3730", +"Z@ c #874535", +"`@ c #9F5339", +" # c #B25E3C", +".# c #0D0704", +"+# c #381C03", +"@# c #582E1C", +"## c #934D31", +"$# c #5B301E", +"%# c #5D301E", +"&# c #80432B", +"*# c #291505", +"=# c #753E26", +"-# c #AF5B3A", +";# c #110902", +"># c #120901", +",# c #190D06", +"'# c #1C0E08", +")# c #502A1A", +"!# c #6E3831", +"~# c #5C2F2D", +"{# c #60302D", +"]# c #66332F", +"^# c #984F37", +"/# c #AE5B3B", +"(# c #AE5B3A", +"_# c #7C412A", +":# c #3A1E12", +"<# c #231209", +"[# c #2A1509", +"}# c #391D0F", +"|# c #27140D", +"1# c #070301", +"2# c #341B0F", +"3# c #AB5939", +"4# c #3F2113", +"5# c #62331F", +"6# c #0F0805", +"7# c #1F1008", +"8# c #7B4029", +"9# c #995033", +"0# c #974E38", +"a# c #753C31", +"b# c #602F2E", +"c# c #71392F", +"d# c #894530", +"e# c #A25031", +"f# c #B35A32", +"g# c #69352E", +"h# c #5F312F", +"i# c #793E32", +"j# c #904B36", +"k# c #A8583A", +"l# c #81432B", +"m# c #170C06", +"n# c #1F1004", +"o# c #381C06", +"p# c #391E10", +"q# c #AA5939", +"r# c #7C4029", +"s# c #A95838", +"t# c #6C3924", +"u# c #2A160D", +"v# c #241203", +"w# c #422003", +"x# c #2D1708", +"y# c #5F311E", +"z# c #6F3A25", +"A# c #1D0E01", +"B# c #4A2403", +"C# c #9F5238", +"D# c #7F4033", +"E# c #82412F", +"F# c #9A4E31", +"G# c #B15832", +"H# c #B45A32", +"I# c #723930", +"J# c #8A4635", +"K# c #A15439", +"L# c #9E5335", +"M# c #0A0503", +"N# c #452204", +"O# c #27140A", +"P# c #592E1E", +"Q# c #1A0E08", +"R# c #110903", +"S# c #3E2013", +"T# c #130A02", +"U# c #391C05", +"V# c #3D2012", +"W# c #663522", +"X# c #2D1702", +"Y# c #241205", +"Z# c #683722", +"`# c #A6573A", +" $ c #874735", +".$ c #62312D", +"+$ c #7C3E2F", +"@$ c #944A31", +"#$ c #AB5632", +"$$ c #9A5033", +"%$ c #492617", +"&$ c #7F422B", +"*$ c #A05335", +"=$ c #321905", +"-$ c #5C301D", +";$ c #2C170E", +">$ c #180D07", +",$ c #150A03", +"'$ c #8B492E", +")$ c #AD5B3B", +"!$ c #934B37", +"~$ c #733A31", +"{$ c #5E2F2D", +"]$ c #753A2E", +"^$ c #8D4630", +"/$ c #A55332", +"($ c #B45A33", +"_$ c #7B3F32", +":$ c #1E100A", +"<$ c #140A05", +"[$ c #150B07", +"}$ c #542904", +"|$ c #88472D", +"1$ c #9A5138", +"2$ c #7B3E32", +"3$ c #62312E", +"4$ c #6E372F", +"5$ c #874330", +"6$ c #9F5032", +"7$ c #B25A33", +"8$ c #5E2F2E", +"9$ c #743B31", +"0$ c #693723", +"a$ c #2B160C", +"b$ c #2B160B", +"c$ c #361C0F", +"d$ c #6F3B23", +"e$ c #120906", +"f$ c #090502", +"g$ c #1D0F08", +"h$ c #261308", +"i$ c #2F180B", +"j$ c #512A18", +"k$ c #87462D", +"l$ c #130A04", +"m$ c #844434", +"n$ c #67332E", +"o$ c #804130", +"p$ c #984D32", +"q$ c #AE5934", +"r$ c #B45B34", +"s$ c #6C3830", +"t$ c #5F321F", +"u$ c #22110A", +"v$ c #231202", +"w$ c #391C03", +"x$ c #3E1F05", +"y$ c #2D170B", +"z$ c #944E32", +"A$ c #1A0D09", +"B$ c #0B0501", +"C$ c #1D0F06", +"D$ c #25130A", +"E$ c #170C07", +"F$ c #271408", +"G$ c #7C4028", +"H$ c #753D27", +"I$ c #281303", +"J$ c #1B0E06", +"K$ c #3D2013", +"L$ c #AB593B", +"M$ c #5C2F2E", +"N$ c #61302D", +"O$ c #7A3D2F", +"P$ c #924931", +"Q$ c #AA5633", +"R$ c #582C2C", +"S$ c #341B11", +"T$ c #0D0701", +"U$ c #211106", +"V$ c #8C482F", +"W$ c #532C1C", +"X$ c #21110A", +"Y$ c #1A0D07", +"Z$ c #160C06", +"`$ c #27150C", +" % c #2E180F", +".% c #261405", +"+% c #753D26", +"@% c #9A5134", +"#% c #0E0701", +"$% c #170C04", +"%% c #2D180E", +"&% c #703A25", +"*% c #A85838", +"=% c #763C31", +"-% c #5F302D", +";% c #723A30", +">% c #8A4632", +",% c #A35232", +"'% c #B35B34", +")% c #592C2C", +"!% c #532A24", +"~% c #944C37", +"{% c #20110B", +"]% c #502704", +"^% c #A25536", +"/% c #7A4029", +"(% c #A05439", +"_% c #6B362E", +":% c #854331", +"<% c #9D4F33", +"[% c #B15934", +"}% c #B45B35", +"|% c #502822", +"1% c #5A2D2B", +"2% c #0B0603", +"3% c #743C27", +"4% c #231207", +"5% c #2B1608", +"6% c #331A0D", +"7% c #7F4229", +"8% c #321903", +"9% c #874635", +"0% c #6B3730", +"a% c #64322D", +"b% c #7D3F30", +"c% c #954B32", +"d% c #AE5734", +"e% c #4E2822", +"f% c #4B2819", +"g% c #572E1D", +"h% c #5C2E2C", +"i% c #23120B", +"j% c #271404", +"k% c #643521", +"l% c #4E2819", +"m% c #1C0E06", +"n% c #241101", +"o% c #381B02", +"p% c #391C06", +"q% c #371D10", +"r% c #3B1F14", +"s% c #482303", +"t% c #211103", +"u% c #643421", +"v% c #914C37", +"w% c #773D30", +"x% c #904832", +"y% c #A85534", +"z% c #4C2721", +"A% c #522B1B", +"B% c #5E3220", +"C% c #5D302C", +"D% c #874534", +"E% c #291502", +"F% c #231204", +"G% c #391E12", +"H% c #0D0603", +"I% c #29150B", +"J% c #492618", +"K% c #120905", +"L% c #271302", +"M% c #542B1B", +"N% c #9C5037", +"O% c #70382F", +"P% c #884632", +"Q% c #A05234", +"R% c #B35C36", +"S% c #B45C36", +"T% c #582C2B", +"U% c #4A2620", +"V% c #422316", +"W% c #4E291A", +"X% c #5A2F1E", +"Y% c #663622", +"Z% c #60302B", +"`% c #733C26", +" & c #22120B", +".& c #180C06", +"+& c #160B06", +"@& c #7F422A", +"#& c #0E0703", +"$& c #341B04", +"%& c #5D311D", +"&& c #321A10", +"*& c #1D0F09", +"=& c #562D1C", +"-& c #A5553A", +";& c #834435", +">& c #69352F", +",& c #824231", +"'& c #9A4E33", +")& c #B05A36", +"!& c #482520", +"~& c #3E2114", +"{& c #4A2718", +"]& c #623320", +"^& c #63332B", +"/& c #7F4133", +"(& c #201009", +"_& c #301806", +":& c #2E1809", +"<& c #462514", +"[& c #090400", +"}& c #1C0E07", +"|& c #8E4836", +"1& c #6E3830", +"2& c #7B3E30", +"3& c #934B33", +"4& c #AB5736", +"5& c #B45C37", +"6& c #46231F", +"7& c #3A1E13", +"8& c #462517", +"9& c #5E311F", +"0& c #69362C", +"a& c #7A3F32", +"b& c #6C3824", +"c& c #241207", +"d& c #82432A", +"e& c #8E4B30", +"f& c #974F38", +"g& c #753C32", +"h& c #60302E", +"i& c #753B30", +"j& c #8D4833", +"k& c #A55436", +"l& c #44221F", +"m& c #361C12", +"n& c #422216", +"o& c #713B25", +"p& c #7D4229", +"q& c #70392D", +"r& c #763C32", +"s& c #070402", +"t& c #140901", +"u& c #88462D", +"v& c #1C0E09", +"w& c #0C0601", +"x& c #231201", +"y& c #1F1006", +"z& c #A15339", +"A& c #6E382F", +"B& c #864532", +"C& c #9E5135", +"D& c #B25B37", +"E& c #582B2B", +"F& c #41211E", +"G& c #311A10", +"H& c #552D1C", +"I& c #783F28", +"J& c #84462C", +"K& c #763D2E", +"L& c #4F2804", +"M& c #613321", +"N& c #27150D", +"O& c #874634", +"P& c #804131", +"Q& c #984E34", +"R& c #AE5B38", +"S& c #B45D38", +"T& c #40201D", +"U& c #2D180F", +"V& c #452417", +"W& c #5C301E", +"X& c #743D26", +"Y& c #80432A", +"Z& c #7D4130", +"`& c #221105", +" * c #924C36", +".* c #783E31", +"+* c #914A33", +"@* c #A95736", +"#* c #3E1F1C", +"$* c #29150D", +"%* c #351C11", +"&* c #412215", +"** c #4C2819", +"=* c #582E1D", +"-* c #87472D", +";* c #874632", +">* c #AE5A3B", +",* c #0F0803", +"'* c #9C5134", +")* c #9C5038", +"!* c #8B4734", +"~* c #A25437", +"{* c #B45C39", +"]* c #572B2B", +"^* c #3C1E1C", +"/* c #311910", +"(* c #482618", +"_* c #542C1C", +":* c #603220", +"<* c #773F27", +"[* c #83452B", +"}* c #8F4B2F", +"|* c #9B5233", +"1* c #904B34", +"2* c #68342F", +"3* c #140A06", +"4* c #1F1001", +"5* c #1E1005", +"6* c #A5573A", +"7* c #6A362F", +"8* c #834332", +"9* c #9C5036", +"0* c #B15B38", +"a* c #B45D39", +"b* c #B25932", +"c* c #9F4F31", +"d* c #864330", +"e* c #3A1D1B", +"f* c #21110B", +"g* c #2D170F", +"h* c #381D12", +"i* c #442316", +"j* c #683622", +"k* c #7F432A", +"l* c #A35636", +"m* c #995037", +"n* c #402115", +"o* c #25130B", +"p* c #8D4A2F", +"q* c #8E4835", +"r* c #7E4032", +"s* c #964C35", +"t* c #AC5938", +"u* c #AB5532", +"v* c #934A31", +"w* c #7E3F2F", +"x* c #8C4630", +"y* c #AE5733", +"z* c #A55231", +"A* c #8D4730", +"B* c #753B2F", +"C* c #381C1A", +"D* c #1C0F09", +"E* c #28150D", +"F* c #3F2115", +"G* c #633421", +"H* c #924D30", +"I* c #9E5334", +"J* c #AA5938", +"K* c #A35539", +"L* c #63322F", +"M* c #5F2F2D", +"N* c #763D31", +"O* c #8E4A35", +"P* c #A75739", +"Q* c #B45E3A", +"R* c #B05934", +"S* c #9A4E32", +"T* c #824130", +"U* c #AC5632", +"V* c #7B3E2F", +"W* c #63302D", +"X* c #5C2D2C", +"Y* c #361B1A", +"Z* c #180C08", +"`* c #24130C", +" = c #2F190F", +".= c #532C1B", +"+= c #5E321F", +"@= c #6A3823", +"#= c #763E27", +"$= c #82452B", +"%= c #8E4B2F", +"&= c #995133", +"*= c #A55737", +"== c #A55739", +"-= c #5F302E", +";= c #A15238", +">= c #7D4133", +",= c #6F3930", +"'= c #884634", +")= c #A05337", +"!= c #B35E3A", +"~= c #A25132", +"{= c #894531", +"]= c #70392F", +"^= c #64322E", +"/= c #7E3F30", +"(= c #6A342E", +"_= c #341A19", +":= c #2B170E", +"<= c #371D12", +"[= c #432316", +"}= c #723C26", +"|= c #7E422A", +"1= c #8A492E", +"2= c #954F31", +"3= c #A15535", +"4= c #AD5B39", +"5= c #B45F3C", +"6= c #A7583A", +"7= c #974F37", +"8= c #69342F", +"9= c #814233", +"0= c #994F37", +"a= c #B05C39", +"b= c #8F4831", +"c= c #783C2F", +"d= c #61302E", +"e= c #592D2C", +"f= c #321918", +"g= c #100805", +"h= c #331B11", +"i= c #4B2719", +"j= c #6E3A24", +"k= c #7A4028", +"l= c #9D5334", +"m= c #A95938", +"n= c #AA5A3A", +"o= c #5D2F2D", +"p= c #B45E3B", +"q= c #AE5834", +"r= c #964C33", +"s= c #7E4031", +"t= c #301818", +"u= c #81442B", +"v= c #7C3F33", +"w= c #7C4032", +"x= c #B25A35", +"y= c #9E5033", +"z= c #864331", +"A= c #8E4A2F", +"B= c #4C2718", +"C= c #311804", +"D= c #341A06", +"E= c #2D180A", +"F= c #773E26", +"G= c #63332F", +"H= c #713C25", +"I= c #89482D", +"J= c #954E31", +"K= c #A15435", +"L= c #A55434", +"M= c #8D4832", +"N= c #703A31", +"O= c #140B06", +"P= c #311902", +"Q= c #371C05", +"R= c #020100", +"S= c #904C30", +"T= c #9C5234", +"U= c #AC5835", +"V= c #944B33", +"W= c #7C3F30", +"X= c #63322E", +"Y= c #0D0600", +"Z= c #3A1D04", +"`= c #422214", +" - c #391D1D", +".- c #0C0604", +"+- c #160B07", +"@- c #512B1B", +"#- c #5D311F", +"$- c #8C4A2E", +"%- c #985032", +"&- c #AF5C3A", +"*- c #B15A37", +"=- c #9C4F33", +"-- c #231105", +";- c #6C3731", +">- c #422121", +",- c #150B08", +"'- c #1E0F0A", +")- c #9F5435", +"!- c #AB5A39", +"~- c #B45B37", +"{- c #A35335", +"]- c #5D2F2E", +"^- c #201106", +"/- c #381B03", +"(- c #2F1808", +"_- c #452414", +":- c #341902", +"<- c #572D1C", +"[- c #6F3730", +"}- c #492524", +"|- c #84452C", +"1- c #A75837", +"2- c #B35E3B", +"3- c #AA5636", +"4- c #914933", +"5- c #783D31", +"6- c #3D1F03", +"7- c #4E2827", +"8- c #27130E", +"9- c #381E12", +"0- c #442416", +"a- c #AF5A37", +"b- c #984E35", +"c- c #68342E", +"d- c #66332E", +"e- c #0B0602", +"f- c #0D0702", +"g- c #522A29", +"h- c #2F1811", +"i- c #402215", +"j- c #6F3B25", +"k- c #7B4129", +"l- c #AA5A38", +"m- c #B25D38", +"n- c #9F5235", +"o- c #874532", +"p- c #602F2D", +"q- c #592F1C", +"r- c #462416", +"s- c #562B2B", +"t- c #381C15", +"u- c #3C1F14", +"v- c #6B3823", +"w- c #9A5133", +"x- c #7B4033", +"y- c #A65636", +"z- c #8E4933", +"A- c #763C30", +"B- c #3C1E02", +"C- c #391D05", +"D- c #4B2504", +"E- c #562D1B", +"F- c #3F2119", +"G- c #673622", +"H- c #7D4032", +"I- c #2A1402", +"J- c #532A04", +"K- c #1F110B", +"L- c #391D02", +"M- c #201004", +"N- c #452416", +"O- c #331907", +"P- c #432313", +"Q- c #48251D", +"R- c #86462C", +"S- c #783F32", +"T- c #9D5136", +"U- c #844333", +"V- c #6B362F", +"W- c #311805", +"X- c #633320", +"Y- c #0E0600", +"Z- c #4A2617", +"`- c #110804", +" ; c #472304", +".; c #A15436", +"+; c #4E281F", +"@; c #A45436", +"#; c #8B4733", +"$; c #462415", +"%; c #572D1B", +"&; c #150B05", +"*; c #1A0D08", +"=; c #29150C", +"-; c #542A22", +";; c #753C30", +">; c #924C35", +",; c #844334", +"'; c #9B5138", +"); c #582F1D", +"!; c #1F1009", +"~; c #432203", +"{; c #341B07", +"]; c #3C1F11", +"^; c #1F1005", +"/; c #311A0E", +"(; c #351C0F", +"_; c #6A3722", +":; c #83452C", +"<; c #582D25", +"[; c #794028", +"}; c #733C30", +"|; c #994F36", +"1; c #814232", +"2; c #693530", +"3; c #221208", +"4; c #643422", +"5; c #412103", +"6; c #4B2603", +"7; c #401F04", +"8; c #793F27", +"9; c #080300", +"0; c #2C1603", +"a; c #5B2E28", +"b; c #693724", +"c; c #713B2F", +"d; c #A05438", +"e; c #703930", +"f; c #5E302E", +"g; c #86462D", +"h; c #110803", +"i; c #1C0E05", +"j; c #442315", +"k; c #89482E", +"l; c #0D0604", +"m; c #2B1606", +"n; c #62341F", +"o; c #170C08", +"p; c #2C1502", +"q; c #5D2F29", +"r; c #703A2F", +"s; c #904A35", +"t; c #88472E", +"u; c #50291A", +"v; c #5B2F1E", +"w; c #572B04", +"x; c #201005", +"y; c #100801", +"z; c #5E302B", +"A; c #763E28", +"B; c #6F392F", +"C; c #67342F", +"D; c #2C170A", +"E; c #402112", +"F; c #190D09", +"G; c #060300", +"H; c #361B03", +"I; c #462516", +"J; c #753E27", +"K; c #412214", +"L; c #6D3823", +"M; c #5E312D", +"N; c #733C2B", +"O; c #60312E", +"P; c #2E180E", +"Q; c #4E2704", +"R; c #271305", +"S; c #170C05", +"T; c #2A150D", +"U; c #251203", +"V; c #3F2004", +"W; c #6F3A24", +"X; c #A05239", +"Y; c #65322F", +"Z; c #160A01", +"`; c #402005", +" > c #4A2719", +".> c #0E0805", +"+> c #130902", +"@> c #200F01", +"#> c #311905", +"$> c #502A19", +"%> c #2F1802", +"&> c #2A1501", +"*> c #723B25", +"=> c #6B3630", +"-> c #331A05", +";> c #8F4B30", +">> c #562B04", +",> c #2A1505", +"'> c #723C25", +")> c #140A03", +"!> c #140A07", +"~> c #5B2E2C", +"{> c #2D170D", +"]> c #2C160B", +"^> c #1E0F08", +"/> c #281509", +"(> c #31190C", +"_> c #5C2F1D", +":> c #713B26", +"<> c #9E5138", +"[> c #5D301F", +"}> c #241202", +"|> c #3A1C03", +"1> c #4D2704", +"2> c #3B1E06", +"3> c #321A0D", +"4> c #231102", +"5> c #1D0F05", +"6> c #271409", +"7> c #5F3220", +"8> c #281404", +"9> c #4A2717", +"0> c #9F5338", +"a> c #0F0802", +"b> c #472518", +"c> c #28150C", +"d> c #6A3723", +"e> c #87472C", +"f> c #25140C", +"g> c #160B05", +"h> c #100701", +"i> c #170C03", +"j> c #532A23", +"k> c #4E2821", +"l> c #512A1C", +"m> c #090402", +"n> c #381D0F", +"o> c #623321", +"p> c #2C1604", +"q> c #4B271F", +"r> c #582E1E", +"s> c #180D08", +"t> c #221104", +"u> c #743D27", +"v> c #452415", +"w> c #1E0F04", +"x> c #48251F", +"y> c #603222", +"z> c #241204", +"A> c #1B0D06", +"B> c #3E1E04", +"C> c #46241E", +"D> c #5E2F2C", +"E> c #0A0602", +"F> c #2C1605", +"G> c #44231D", +"H> c #6E3A25", +"I> c #61312C", +"J> c #2E1707", +"K> c #2E170A", +"L> c #2C170C", +"M> c #41221C", +"N> c #64332D", +"O> c #211101", +"P> c #231208", +"Q> c #452303", +"R> c #30190F", +"S> c #3E211B", +"T> c #68362D", +"U> c #080402", +"V> c #3C1F1B", +"W> c #70392E", +"X> c #522A1B", +"Y> c #3A1E19", +"Z> c #783D2F", +"`> c #432317", +" , c #371C19", +"., c #7F4131", +"+, c #090501", +"@, c #341B18", +"#, c #884633", +"$, c #B25A32", +"%, c #321917", +"&, c #975032", +"*, c #914B35", +"=, c #8D462F", +"-, c #301817", +";, c #984E37", +">, c #2D1715", +",, c #9E5339", +"', c #B15833", +"), c #9A4D31", +"!, c #2A1615", +"~, c #A05539", +"{, c #9D5238", +"], c #B35A33", +"^, c #A15132", +"/, c #281414", +"(, c #A75533", +"_, c #904831", +":, c #261313", +"<, c #301910", +"[, c #AD5833", +"}, c #964C32", +"|, c #65322D", +"1, c #582D2D", +"2, c #251313", +"3, c #844331", +"4, c #6C362E", +"5, c #4D2727", +"6, c #040201", +"7, c #B35B35", +"8, c #A45233", +"9, c #8B4631", +"0, c #73392F", +"a, c #AA5634", +"b, c #924932", +"c, c #7A3D30", +"d, c #3A1E1D", +"e, c #140B07", +"f, c #AC5B39", +"g, c #AF5935", +"h, c #994E33", +"i, c #432221", +"j, c #1B0F09", +"k, c #A85938", +"l, c #B25C36", +"m, c #9F5134", +"n, c #A45636", +"o, c #A65535", +"p, c #4F2827", +"q, c #2E1811", +"r, c #944E31", +"s, c #AC5836", +"t, c #944C34", +"u, c #7C3F31", +"v, c #63312D", +"w, c #542A29", +"x, c #361C14", +"y, c #9B4F35", +"z, c #824232", +"A, c #6A352F", +"B, c #552B2A", +"C, c #3E2117", +"D, c #B45C38", +"E, c #A25335", +"F, c #8A4532", +"G, c #46241A", +"H, c #A85737", +"I, c #904A34", +"J, c #4D281E", +"K, c #6D3830", +"L, c #AD5937", +"M, c #964E35", +"N, c #7F4132", +"O, c #532B21", +"P, c #B25C39", +"Q, c #9D5035", +"R, c #854332", +"S, c #6C372F", +"T, c #582D24", +"U, c #6B372F", +"V, c #B35D39", +"W, c #A45437", +"X, c #8C4734", +"Y, c #743A30", +"Z, c #5C3026", +"`, c #AB5838", +" ' c #924B35", +".' c #7A3E31", +"+' c #5E3128", +"@' c #713C26", +"#' c #69362E", +"$' c #995036", +"%' c #814333", +"&' c #61312A", +"*' c #68352E", +"=' c #B25E3A", +"-' c #9F5337", +";' c #874633", +">' c #6F382F", +",' c #7F432B", +"'' c #67342D", +")' c #A65739", +"!' c #8E4934", +"~' c #61322D", +"{' c #AC5A3A", +"]' c #944D36", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" . + ", +" @ # @ @ @ @ $ ", +" # % @ & * = - ; > , ' ", +" ) $ @ # ! ~ { ] ; ; ; ; ; ^ / $ ", +" ( $ @ @ _ : < [ ; ; ; } | 1 2 ; ; ; 3 4 $ ", +" @ 5 6 @ 7 8 9 0 ; ; ; a b c d e f g h i j ; ; k l # ", +" 5 ' @ m n o p a ; ; ; ; ; q r s t u v w x y z A B ; ; C D % ", +" @ # @ @ E F G H ; ; ; ; ; ; ; ; ; I J K L M N O P Q R S T a ; ; U V # ", +" ( $ @ @ W X Y Z ; ; ; ; ` ...+.; ; ; ; ; @.#.$.%.&.M *.=.P -.;.>.,.; ; ; H '.. ", +" % % @ m ).!.~.; ; ; ; ; {.].^./.(.v _.:.<.; ; ; [.}.|.1.%.2.3.*.4.5.-.6.7.; ; ; ; ] 8.@ ", +" ( # @ % 9.0.a.] ; ; ; ; ; ; [.b.c.d.e.f.g.h.i.j.k.l.; ; ; m.n.o.p.d.q.r.s.t.*.u.v.; ; ; ; ; a w.@ # ", +" @ # @ @ x.y.z.C ; ; ; ; ; ; ; ; ; ; A.B.C.t D.E.F.G.h.H.;.I.` ; ; ; J.K.L.M.d.d.N.d O.b ; ; ; ; ; ; ; a P.@ Q. ", +" ( R.# @ S.T.U.V.; ; ; +.W.X.Y.B ; ; ; ; ; ; Z.`. +.+++@+#+$+%+&+*+=+-+; ; ; ; ; ;+>+,+'+)+; ; ; ; ; ; ; ; ; ; ; a !+@ @ ", +" . $ @ # ~+{+]+a ; ; ; ^+/+(+_+:+G.<+[+}+a ; ; ; ; ; |+1+2+3+4+5+u v 6+7+8+9+; ; ; ; ; ; ; ; ; ; ; ; ; ; 0+a+b+c+b ; ; ; ; d+@ @ ", +" ( ( @ @ e+f+g+h+; ; ; ; ; ; i+j+k+l+N O P Q R m+n+h+; ; ; ; o+p+q+r+k+4+l+s+$+N t+u+; ; ; ; ; ; ; ; ; ; ; 1 v+w+/.x+5.y+z+:.A+; ; ; B+@ # ", +" @ # . @ C+D+E+F+; ; ; ; ; ; ; ; ; ; G+1.%.&.3.*.=.P -.;.H+c ; ; ; ; ; I+J+b.K+3+L+I.M+N+1 a ; ; ; ; ; ; ; ; ; ; O+P+L+@+#+$+%+&+H.Q+R+J.; ; ; S+T+% ", +" @ # @ U+V+W+X+a ; A+Y+Z+`+ @; ; ; ; ; ; ; .@+@p.d.2.r.s.4.@@#@$@%@&@; ; ; ; ; ; *@=@-@;@>@; ; ; ; ; ; ; ; ; ; ; ; ; ; p+,@3+4+5+u v 6+7+*+'@)@o+; ; ; !@# ~@ ", +" @ $ @ % {@!+]@^@; ; <./@(@_@:@G.@@z+<@<.; ; ; ; ; >@[@J p.}@q.r.|@1@@@2@3@| ; ; ; ; ; ; ; ; ; ; ; ; ; ` 4@5@6@7@8@; ; ; ; ; ; 9@0@r+k+4+l+s+v w x y a@b@; ; ; ; g+m $ ", +" ) $ @ @ c@d@e@k ; ; ; ; ; f@g@h@q.E.F.G.h.H.j.i@j@; ; ; ; ; k@l@m@n@}@o@e.|@u p@q@r@; ; ; ; ; ; ; ; ; ; s@t@u@_+5+%+-.5.v@w@; ; ; ; ; h+x@y@r+K L l+N O w Q u z@; ; ; ; ; ]@% % ", +" A@% @ B@C@D@E@; ; ; ; ; ; ; ; ; F@|..+++@+#+F.%+&+H.*+G@[.; ; ; ; ; H@I@J@K@n@I.q@L@M@I+; ; ; ; ; ; ; ; ; ; N@9+M.&.3.*.4.5.-.$@O@P@; ; ; ; ; Q@R@1+$.%.&.M S@T@U@d 0+; ; V@X+W@X@@ @ # ", +" ) # @ # Y@Z@`@ #; ; ; ; ; ; ; ; ; ; ; ; | .#2+3+4+5+u v 6+7+*++#@#; ; ; ; ; ; ; ##$#%#b a ; ; ; ; ; ; ; ; ; ; ; ; ; &#B.p.d.q.r.s.1@@@#@$@*#=#; ; ; ; ; -#J+u@;#>#,#'#)#0+; 3 B+!#~#% @ @ {#@ # ", +" # $ @ @ ]#P.^#/#; ; ; (#_#:#<#[#}#M@; ; ; ; ; ; a |#1#r+k+4+l+s+v w x 4.2#; ; ; ; ; ; ; ; ; ; ; ; ; ; 3#Y.4#2#5#8@; ; ; ; ; B 6#m@n@}@o@e.|@g.=+2@j.7#; ; ; ; ; ; ; (#l.8#9#U 0#a#b## @ @ m c#d#e#f#g## ", +" ) $ 6 @ h#i#j#k#; ; ; ; ; l#,+m#n##+6+7+H.o#p#B ; ; ; ; ; q#.@q+r+K L l+N #+3@m#r#; ; ; ; ; ; ; ; ; ; ; s#t#u#,#v#+#x w#x#y#a ; ; ; ; z#.#,@C.A#o@E.f.g.h.B#9+; ; ; ; ; ; ; #C#D#/ # % @ # g#E#F#G#H#H#H#H#g## ", +" # $ @ U+I#J#K#V@; ; ; ; ; ; ; L#M#C.L l+s+O w x y N#O#o+; ; ; ; ; I+P#Q#R#>#%@m#S#&#h+; ; ; ; ; ; ; ; ; ; ; -#6#T#++M *.=.P -.;.U#V#2 ; ; ; ; W#l@,@C.t D.X#l+Y#,#Z#; ; ; ; `# ${@R.# @ @ .$+$@$#$H#H#H#H#H#H#H#H#g## ", +" ) $ @ @ E F G H ; ; ; ; ; ; ; ; ; ; ; $$6#$.K L M N O P Q R <+%$; ; ; ; ; ; ; (#&$z#1 j ; ; ; ; ; ; ; ; ; ; ; ; ; ; *$g@1.%.2.3.*.4.5.-.$@=$-$; ; ; ; ; J.;$>$,$s w+N+'$j ; )$!$~${$# @ @ {$]$^$/$($($($($H#H#H#H#H#H#H#H#g## ", +" @ # @ @ , _$Y Z ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; :$y@$.%.&.M *.=.P -.;.<$h+; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; [$o.p.d.2.r.s.4.@@#@}$<$h+; ; ; ; ; ; *@|$` ; ^@1$2$3$@ @ @ # 4$5$6$7$($($($($($($($H#H#H#H#H#H#H#H#g## ", +" Q.# R.@ 8$9$B+> ; ; ; ; ; r@0$a$b$c$d$j ; ; ; ; ; ; ; ; } e$|.1.d.2.3.*.4.5.@@f$-#; ; ; ; ; ; ; ; ; ; ; ; j @O.g$h$i$j$s#; ; ; ; ; ; k$[@,@n@}@o@e.|@1@=+2@l$*$; ; ; ; ; ; a ~.m$X@@ # @ @ n$o$p$q$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" @ @ s${ ] ; ; ; ; ; s#t$u$G@v$w$h.2@x$y$##; ; ; ; ; ; ; ; z$A$B$p.}@q.5+v$C$D$,.; ; ; ; ; ; ; ; ; ; ; A+7.E$C$@+4.@@2@7+F$G$; ; ; ; ; ; H$l@m@C.A#o@E.u I$J$K$; ; ; ; L$D@~+M$$ @ @ N$O$P$Q$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" R$# m ^#; ; ; ; ; ; S$T$}@D.E.F.G.h.H.H.U$V$; ; ; ; ; ; ; ; (#W$X$Y$Z$`$0$Q@; ; ; ; ; ; ; ; ; ; ; ; ; %T$}@o@e.|@g.=+2@$@.%+%; ; ; ; ; ; @% %m##%$%m#%%&%*%; h+< =%-%@ @ @ m ;%>%,%'%r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" )%!%T+# ~%; ; ; ; ; {%,@.+++@+#+$+%+&+H.]%d 3#; ; ; ; ; ; ; ; ; ; s#j ; ; ; ; ; ; o+o+; ; ; ; ; ; ; ; ;$J C.A#o@E.f.g.h.i.R %@^%; ; ; ; ; ; ; r@/%M@o+a (%: x.@ # @ % _%:%<%[%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" )%|%J+1%% 9 ; ; ; ; W.2%2+3+4+5+u v 6+7+*+a@3%; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 0+z@)@4%5%6%7%; ; ; ; ; ; ,..# +.+t @+#+F.G.&+H.8%W.; ; ; ; ; ; ; ; V.9%0%R.@ @ @ a%b%c%d%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" )%e%f%g%h%# !.; ; ; 2 i%#.r+k+4+l+s+v w x j%k%; ; ; ; ; ; ; ; ; ; ; ; h+l%q@m%n%o%w x *+p%q%B ; ; ; ; ; r%9+ +3+++@+u $+%+s%t%u%; ; ; ; /#v%'.{$# @ @ -%w%x%y%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" R$z%v+A%B%C%@ D%; ; ; B ;$9+r+K L l+E%F%J$G%[.; ; ; ; ; ; ; ; ; ; ; ; f@H%K L l+N O w Q R N#I%I+; ; ; ; a J%K% +3+4+L%&./.g$M%o+] N%D+3$@ @ @ m O%P%Q%R%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" T%U%V%W%X%Y%Z%@ F a ; ; ; `% &.&,#+&G%| (#; ; ; ; Q@` h+; ; ; ; ; ; ; @&#&$.%.&.M N =.P Q ;.$&%&; ; ; ; ; ; N@&&'#>$*&=&J.-&;&E # # @ @ >&,&'&)&S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" T%!&~&{&=&]&..^&@ /&V@; ; ; ; Q@+.2 ; ; ; ; ^+=&(&U$_&:&<&*@; ; ; ; ; -#[$[&1.%.2.3.*.4.5.-.j.}&; ; ; ; ; ; ; ; ; Z |&1&m # @ @ .$2&3&4&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" T%6&7&8&A%9&0$H$0&@ a& #; ; ; ; ; ; ; ; b&>$G@4+*.g.=+2@Q c&d&; ; ; ; ; e&}.|.p.d.2.r.s.4.5.S@X$; ; ; ; ; H f&g&h&# @ @ {$i&j&k&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" T%l&m&n&W%X%W.o&p&q&@ r&] ; ; ; ; ; ; I+s&t&A#o@E.f.g.h.i.}$U$u&; ; ; ; ; ##v&w&p.}@x&4+y&d %$Z.; V@z&: x.# # @ # A&B&C&D&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" E&F&G&|+J%H&9@t#I&J&K&@ V+H ; ; ; ; ; ; 6# +.+t D.#+F.G.&+H.L&d j ; ; ; ; ; I+M&N&(+*&)#0+; 0 O&0%R.# @ @ n$P&Q&R&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" E&T&U&I V&)#W&Z#X&Y&'$Z&@ ~+[ ; ; ; ; ; @.2% +3+++@+u $+%+7+*+`&b ; ; ; ; ; ; ; ; ; /# *'.{$# @ @ N$.*+*@*S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" E&#*$*%*&***=*k%b@A.-*##;*R.9.>*; ; ; ; 2 %2%2+3+4+5+u v 6+$+,*'*; ; ; ; ; #)*w.3$# @ @ M$;%!*~*{*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#g## ", +" ]*^*.@/*|+(*_*:*t#<*[*}*|*1*R.2*Z ; ; ; ; 2 (*3* +k+4*t 5*Y$L@b ; ; ; 6*;&E ( # @ % 7*8*9*0*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#b*c*d*@ . ", +" ]*e*f*g*h*i*)#W&j*`%k*'$s@l*m*U+]#0 ; ; ; ; ; @%n*o*X$O.p*a ; k q*~+U+# @ @ / r*s*t*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$u*v*w*x*y*($($($($($H#H#z*A*B*{$@ @ % ", +" ]*C*D*E*S$F*f%g%G*z#8#-*H*I*J*K*& L*`#; ; ; ; ; ; ; ; ^@< g&h&# @ @ M*N*O*P*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$R*S*T*g#@ @ @ @ 7*U*($($#$v*V*W*@ @ X*( ", +" ]*Y*Z*`* =>+v+.=+=@=#=$=%=&=*=I+==-=3$~.; ; ; a ;=>=4 R.@ @ m ,='=)=!=Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$'%~={=]=m @ 8$g&= - ; { -=^=/=(=# @ % @ ", +" ]*_=3*R@:=<=[=].X%Y%}=|=1=2=3=4=5=6=C+h&7='=D R.@ @ @ 8=9=0=a=Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%y%b=c=d=@ # 1&~ { ] ; ; ; ; ; K#h&# e=. ", +" ]*f=g=x@|#h=F*i==&]&j=k=M@0+l=m=5=5=n=o=# @ @ 3$X Y 3#p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%q=r=s=n$@ @ 4 : < [ ; ; ; J.;+)+; ; ; ; ~.W $ ", +" ]*t=2%E$i%,+>+8&A%9&@=#=u=p*9#*=I+5=5=v=@ w=- p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%x=y=z=4$# @ C+8 9 0 ; ; ; a A=B='#e C=D=E=F=; ; ; ^ G=# ", +" R$t=s&n.:$p+m&n&W%X%W.H=p&I=J=K=B 5=5=d@@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%L=M=i&8$@ m N=o p a ; ; ; ; ; |=O=s ++P=O P Q y Q=S#h+; ; 0 ]## ", +" ]*@ R=g@Q#I@&&|+J%H&9@t#I&J&S=T=*%5=5=d@@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%U=V=W=X=@ @ >&F G h+; ; ; ; ; ; ; ; ; K.Y=%.&.M *.=.P -.;.Z=`=; ; ; Z E $ ", +" @ -.-+- & %I V&@-#-Z#X&Y&$-%-l*&-5=d@@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&*-=-8*7*# @ L*X Y Z ; ; ; ; } }=`%[.; ; ; ; ; [=y@1.d.2.3.s.4.5.-.$@-- @; ; ; >*;-R. ", +" . >-,-'-$*%*&*t@4@k%b@A.|$##)-!-5=d@@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&~-{->%c#]-@ o=9$!.~.; ; ; ; a {.t@^.^-(./-(-_-*@; ; ; <.6#J p.}@q.r.|@1@@@#@:-<-; ; ; ; [ [-% ", +" . }-'-.@/*|+J%O+:*t#I&|-}*|*1-2-d@@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&3-4-5-3$@ % s$0.a.] ; ; ; ; ; ; Z.E$c.}@E.F.G.&+H.x i@##; ; ; f@g=m@n@}@o@e.|@6-s.$%#=; ; ; ; ; H '.6 ", +" )%7-8-g*9-0-)#W&j*X&k*'$s@l*&-d@@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&a-b-P&c-@ @ d-y.z.C ; ; ; ; ; ; ; ; ; ; b&e-3+++@+u $+%+7+*+*+J$Q@; ; ; 1=(@f-n@}@%.C$d P@{.; ; ; ; ; ; ; ] r&@ ", +" )%g-h-S$i-f%g%G*j-k--*H*I*l-d@@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&m-n-o-,=5 @ p-T.U.V.; ; ; '*Y+q-u=h+; ; ; ; ; ; p*`.2+3+4+5+u v 6+7+y g.r-; ; ; ; 2 H$h=;$O+^+; ; ; ; ; ; ; ; ; ; ; #a&@ ", +" R$s-t-u-v+.=t$v-#=$=%=w-*@x-@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&y-z-A--=@ 5 ~+{+]+a ; ; ; )+/+(+_+:+B-C-[#F=; ; ; ; ; a p+1#r+k+4+l+s+v w x D-m#; ; ; ; ; ; ; ; ; ; ; ; ; ; 0+/+V#E-9#; ; ; V@/&@ . ", +" R$R$F-[=].$#G-}=|=1=J.^%a&@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*t*s*H-/ @ @ X@f+g+h+; ; ; ; ; ; U&<$K I-*.4.5.-.J-=$c a ; ; ; ; *@K-1+$.K L M N L-N M-L@; ; ; ; ; ; ; ; ; ; ; 1 N-w+/.#+5.@@O-P-s#; ; a F @ ( ", +" R$e=Q-i=g%G*j=k=R-H*l=S-@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*0*T-U-V-% @ 3$D+E+F+; ; ; ; ; ; ; ; ; (#G+p.d.2.r.s.4.@@#@$@W-X-; ; ; ; ; B i*+&Y-k+K m%w+Z-'$; ; ; ; ; ; ; ; ; ; ; 0-`-k+5+u v 6+7+y ;D$.;; ; ; D%@ ( ", +" . )%+;A%9&@=#=;+A=9#8 @ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*!=@;#;V+o=@ ]-~$W+X+a ; A+W.$;%;J.; ; ; ; ; ; ; E$o.p.}@q.r.|@1@@@2@;.&;(#; ; ; ; ; ; Z.=*h*;@)+; ; ; ; ; ; ; ; ; ; ; ; ; ; *; +k+4+l+s+v w x y s%=;2 ; ; ; !.@ @ ", +" ( @ -;X%W.H=p&I=J=;;@ ~.p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*3#>;a&3$@ % D ,;';^@; ; 9#);!;C$:@G.~;{;];Q@; ; ; ; ; l#.#,@n@A#o@e.f.g.=+2@^;A=; ; ; ; ; ; ; ; ; ; ; ; ; s@4@/;(;_;(#; ; ; ; ; ; i=#.$.K L M N O w Q R *#:;; ; ; ; 9 @ A@ ", +" @ <;9@..[;J&S=};@ ~.p=p=p=p=p=p=p=p=Q*Q*a=|;1;2;@ @ / d@e@k ; ; ; ; ; Y%`..+o@u $+%+&+*+Q 3;9#; ; ; ; ; 4;g=Y=C.t D.E.F.s+p@Y$3#; ; ; ; ; ; ; ; ; ; ^+**u@_+M 5;6;7;h 8;; ; ; ; ; s#.#9;$.%.&.M *.=.P -.0;u%; ; ; ; ; ~%@ ~@ ", +" ) a;b;H$Y&$-c;@ ~.p=p=p=p=p=p=2-d;'=e;m @ f;a#D@E@; ; ; ; ; ; ; ; ; G&J 3+4+5+u v 6+7+y #@7#(#; ; ; ; ; g;f*h;>#.+i;w+j;g;2 ; ; ; ; ; ; ; ; ; ; k;l;n@x&r.|@1@@@2@$@m;n;; ; ; ; ; <.o;|.1.%.2.3.S@p;U@^.9#; ; V@X+W@X@@ @ . ", +" @ q;&%A.|$r;@ ~.p=p=p=P*s;5-h&@ 5 1&Z@`@ #; ; ; ; ; ; ; ; ; ; ; ; G-0@r+k+4+l+s+v w x y C=t#; ; ; ; ; ; a t;u;v;b a ; ; ; ; ; ; ; ; ; ; ; ; ; b@e-n@}@o@e.|@g.=+2@w;x;u&; ; ; ; ; s#i*>$y;>#,#'#z@0+; 3 B+!#~#% @ @ {#@ ) ", +" % z;A;|-B;@ { z./&4 @ @ C;P.^#/#; ; ; (#r#G%<#D;E;H@; ; ; ; ; ; h+F;G;$.K L M N O w Q H;I;; ; ; ; ; ; ; ; ; ; ; ; ; ; 3#J;K;];L;B ; ; ; ; ; *$6#,@C.A#o@E.f.g.h.i.s%T ; ; ; ; ; ; ; s#I&I&$$U 0#a#b## @ @ m c#d#e#f#M*@ ", +" ( M;N;a%# # @ O;i#j#k#; ; ; ; ; A.P;m#M-u w Q Q;O-$;h+; ; ; ; ; ^%x@1+$.%.&.M *.#+R;S;M@; ; ; ; ; ; ; ; ; ; ; *%v-T;G@U;w$7+V;[+W;; ; ; ; ; g%2%Y=.+t D.#+F.G.h.=+m#; ; ; ; ; ; ; #X;/&Y;# % @ # g#E#F#G#H#H#H#H#M*@ ", +" # @ @ ' n J#K#V@; ; ; ; ; ; ; {.9+Z;L M N O P Q R `;6@2 ; ; ; ; ; B >b.y;>#%@.&S#;+h+; ; ; ; ; ; ; ; ; ; ; *@.>+>@>3.*.4.5.-.$@#>$>; ; ; ; ; ].`. +3+++@+%>&>Y#,#*>; ; ; ; `# $=>R.# @ @ .$+$@$#$H#H#H#H#H#H#H#H#M*@ ", +" ) $ @ @ E F G H ; ; ; ; ; ; ; ; ; ; ; |$B.1.%.&.M *.=.P -.;.->%&; ; ; ; ; ; ; s##=G-'$j ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;>`.p.}@q.r.s.1@@@#@>>,>'>; ; ; ; ; k;.@m#)>s w+Z-'$j ; )$!$~$o=# @ @ {$]$^$/$($($($($H#H#H#H#H#H#H#H#M*@ ", +" @ # @ @ , _$Y Z ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; I+!>[&p.d.2.r.s.4.5.#@y .&; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; h+6#m@n@}@o@e.|@g.=+2@y ,#; ; ; ; ; ; ; L#|-` ; ^@1$2$3$@ @ @ # 4$5$6$7$($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" ( ~>R.@ U+9$!.> ; ; ; ; ; r@j*{>]>:.G$; ; ; ; ; ; ; ; ; q 6#o.p.}@q.r.|@1@@@5.9+; ; ; ; ; ; ; ; ; ; ; ; ; j @O.^>/>(>_>(#; ; ; ; ; ; :>.-,@C.A#o@E.f.g.h.2@9+(#; ; ; ; ; ; a ~.m$X@@ # @ @ n$o$p$q$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" % @ 9$<>] ; ; ; ; ; *%[>(@J$}>|>h.1>2>3>Z.; ; ; ; ; ; ; ; l.+-m@n@}@o@l+4>C$o*&#; ; ; ; ; ; ; ; ; ; ; +.-@E$5>@+6-=+2@N#6>'$; ; ; ; ; ; 7>g=Y=C.t D.E.s+8>%@9>; ; ; ; L$D@~+M$$ @ @ N$O$P$Q$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" @ # 8$0>; ; ; ; ; ; i%a>A#@+u $+%+7+*+-.i@9#; ; ; ; ; ; ; ; s#b>(+Y$Z$c>d>Q@; ; ; ; ; ; ; ; ; ; ; ; ; R@#%t D.E.f.G.h.i.y U$e>; ; ; ; ; ; 1=f>g>h>i>m#%%:>*%; h+< =%-%@ @ @ m ;%>%,%'%r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" ) j>~@o=]@; ; ; ; ; e$ +3+4+5+u v 6+7+y x <#I+; ; ; ; ; ; ; ; ; a 8@-#; ; ; ; ; ; I+-#; ; ; ; ; ; ; ; x@Y=.+t @+#+F.%+&+H.*+J$B ; ; ; ; ; ; ; $$f@l#o+a (%: x.@ # @ % _%:%<%[%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" ) k>l>R.M$g+; ; ; ; **m>r+k+4+l+s+v w x y *#g;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; {.u;^>4%h n>j@; ; ; ; ; ; o>2% +3+++@+u $+%+7+*+p>,.; ; ; ; ; ; ; ; V.9%0%R.@ @ @ a%b%c%d%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" ) q>**r>X*R.!@; ; ; o+s>y@$.K L M N O w Q t>u>; ; ; ; ; ; ; ; ; ; ; ; o+{&E$m%q.v w Q H.D=v>I+; ; ; ; j $*0@2+k+4+5+u v 6+s%w>`%; ; ; ; /#v%'.{$# @ @ -%w%x%y%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" ) x>(*_*y>~## S+; ; ; [.f*q+$.%.&.M I-z>A>K$q#; ; ; ; ; ; ; ; ; ; ; ; W#q+%.&.M *.=.P -.;.B>q%; ; ; ; ; h+m&`-r+K L L%&./.g$<-h+] N%a&3$@ @ @ m O%P%Q%R%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" ) C>i*)#W&Y%D># B+; ; ; j 7>R@S;,#+&G%|=(#; ; ; ; *@+.j ; ; ; ; ; ; ; ..E>1.%.2.3.*.4.5.-.$@F>b@; ; ; ; ; ; l.:=u@m#*&=*s@-&;&E # # @ @ >&,&'&)&S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" ) G>F*f%g%G*H>I>@ d+; ; ; ; ; <.<.2 ; ; ; ; ^+/+(&e J>K>j$B ; ; ; ; ; 8@}.|.p.d.2.r.s.4.@@#@h.L>; ; ; ; ; ; ; ; h+Z |&1&m # @ @ .$2&3&4&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" )%M>>+v+.=+=@=A;N>@ !+a ; ; ; ; ; ; ; ; u%q@I.O>s.G.h.i. ;P>S=; ; ; ; ; | 6#m@n@}@q.e.|@1@Q>E.R>; ; ; ; ; H f&g&h&# @ @ {$i&j&k&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" )%S><=[=].X%Y%}=|=T>@ P.a ; ; ; ; ; ; 8@U>h@t @+#+F.%+&+H.y i;J.; ; ; ; ; |-s>w&C.A#q.L ^;d O..;; V@z&: x.# # @ # A&B&C&D&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" )%V>h=F*{&=&]&j=k=M@W>@ w.a ; ; ; ; ; (#.# +3+++@+u $+%+7+*+B#D$; ; ; ; ; ; B X>i%u@(+z@>@; 0 O&0%R.# @ @ n$P&Q&R&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" )%Y>,+>+8&A%9&@=#=u=p*Z># 8.] ; ; ; ; ; `>m>2+3+4+5+u v 6+7+y %@*$; ; ; ; ; ; ; ; ; /# *'.{$# @ @ N$.*+*@*S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" )% ,p+m&n&W%X%W.o&p&I=J=.,% ).H ; ; ; ; (# &+,r+k+L l+s+O w v 9+*%; ; ; ; ; #)*w.3$# @ @ M$;%!*~*{*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#H#H#H#M*@ ", +" )%@,I@G&|+J%H&9@t#I&J&S=T=#,# V U ; ; ; ; (#I K%r+K 4+++^;w+j;>@; ; ; 6*;&E ( # @ % 7*8*9*0*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#H#H#H#$,c*5$@ . ", +" )%%, &U&I V&@-#-Z#X&Y&$-&,l**,R.D C ; ; ; ; ; A=<=X$(@O.b a ; k q*~+U+# @ @ / r*s*t*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($($($H#H#z*=,B*{$@ @ % ", +" )%-,'-$*%*&*t@=*k%b@A.|$##)-!-0=R.l k ; ; ; ; ; ; ; ; ^@;,r&h&# @ @ M*N*O*P*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($($($($($#$@$V*.$@ @ X*( ", +" )%>,b..@/*|+J%_*:*t#I&|-}*|*1-2-,,M$4 3 ; ; ; a ;=>=4 R.@ @ m ,='=)=!=Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$($($($($',),T*(=# @ % @ ", +" )%!,[$f*g*9-0-)#W&j*X&k*'$s@l*&-5=~,]-^={,'=D R.@ @ @ 8=9=0=a=Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$r$r$r$],^,{=O%R.@ . ~@. ", +" )%/,g=D*E*S$F*f%g%G*j-8#-*H*I*l-5=5=6*@ # @ @ 3$X Y 3#p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$r$r$r$r$(,_,c={#@ @ R.( ", +" )%:,.-Z*`*<,>+v+.=t$v-#=$=%=w-*=I+5=5=n @ O&- p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%}%r$r$r$[,},/=|,@ @ ~@@ ", +" 1,2,U>3*(@;$<=[=].$#Y%}=|=1=J.3=4=5=5=V @ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%}%}%}%}%[%=-3,4,% @ @ . ", +" ) 5,6,g=v&E*h=F*i=g%]&j=k=R-H*l=m=5=5=V @ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%}%}%}%7,8,9,0,U+@ @ ~@) ", +" @ t=2%E$i%,+>+v+A%9&@=#=;+p*9#*=I+5=V @ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%S%S%}%}%a,b,c,N$@ @ m # ", +" . d,e,:$p+m&V%W%X%W.H=p&I=J=K=f,5=V @ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%S%S%S%S%g,h,o$c-@ @ % @ ", +" . i,j,I@&&~&J%H&9@..[;J&S=T=k,5=V @ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&S%S%S%l,m,o-A&# @ 6 6 6 ", +" )%}-.@ %7&V&@-#-0$H$Y&$-%-n,&-V @ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&5&5&5&5&o,M=i&{$@ @ R.( ", +" 1,p,q,m&&*t@4@W.b@A.|$r,A+!-V @ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&5&5&5&5&s,t,u,v,@ @ R.# ", +" R$w,x,|+J%O+9@t#I&|-S=T=1-e;@ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&S&S&5&5&*-y,z,A,# @ % . ", +" )%B,C,0-)#W&j*X&k*'$s@l*e;@ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&S&S&S&D,E,F,c#m @ @ % 6 ", +" . R$G,**g%G*j-k--*H*I*1&@ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&S&S&S&S&H,I,w%{#@ @ m . ", +" )%. J,.=t$v-<*[*%=w-K,@ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*a*a*a*S&L,M,N,d-@ @ X*@ ", +" R$) O,$#G-`%|=1=J.9.@ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*a*a*a*a*P,Q,R,S,~@@ # ) ", +" @ @ T,G*z#k=R-H*U,@ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*a*a*a*V,W,X,Y,U+@ @ R.( ", +" 6 @ Z,@=#=;+A=7*@ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*`, '.'3$@ @ ' @ ", +" @ +'@'p&I=#'@ /#p=p=p=p=p=p=p=p=Q*Q*Q*Q*Q*Q*a=$'%'8=@ @ T+# ", +" @ &'I&M@*'@ /#p=p=p=p=p=p=p=p=Q*Q*='-';'>'# @ 6 @ ) ", +" e=I>,'''@ /#p=p=p=p=p=p=p=)'!'=%M*@ @ ' # ", +" # ~'N>@ /#p=p=p={']'d@^=@ @ m . ", +" ( @ @ 3#N%U-=># @ # ) ", +" @ @ @ @ @ % Q. ", +" % @ ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/sheet.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1899" + sodipodi:version="0.32" + inkscape:version="0.45.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="sheet.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs1901" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.627417" + inkscape:cx="18.120705" + inkscape:cy="8.0546018" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1013" + inkscape:window-height="592" + inkscape:window-x="0" + inkscape:window-y="26" /> + <metadata + id="metadata1904"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Bookman L" + x="0.92097086" + y="15.1" + id="text1907" + sodipodi:linespacing="100%"><tspan + sodipodi:role="line" + id="tspan1909" + x="0.92097086" + y="15.1">T</tspan></text> + <text + xml:space="preserve" + style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="10.057447" + y="15.097196" + id="text1911" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan1913" + x="10.057447" + y="15.097196" + style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">2</tspan></text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/throbber.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,256 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg2816" + version="1.1" + inkscape:version="0.47 r22583" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + sodipodi:docname="throbber.svg"> + <defs + id="defs2818"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 8 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="16 : 8 : 1" + inkscape:persp3d-origin="8 : 5.3333333 : 1" + id="perspective2824" /> + <inkscape:perspective + id="perspective3618" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4392" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4392-7" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4392-6" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4392-73" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective4392-2" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="10.859375" + inkscape:cx="3.0797409" + inkscape:cy="6.1241029" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1280" + inkscape:window-height="950" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="1"> + <inkscape:grid + type="xygrid" + id="grid4380" /> + </sodipodi:namedview> + <metadata + id="metadata2821"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + sodipodi:type="arc" + style="fill:#000000;stroke-width:0.99599999;stroke-miterlimit:4;stroke-dasharray:none" + id="path3606" + sodipodi:cx="7.5572038" + sodipodi:cy="1.7252818" + sodipodi:rx="1.016466" + sodipodi:ry="1.5467961" + d="m 8.5736698,1.7252818 a 1.016466,1.5467961 0 1 1 -2.0329321,0 1.016466,1.5467961 0 1 1 2.0329321,0 z" + transform="matrix(1.9676014,0,0,1.9394929,-6.8695653,-0.34617159)" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber5.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + style="fill:none;stroke:none" + id="rect4382" + width="16" + height="16" + x="-2.8393347e-07" + y="-2.3374795e-07" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber3.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + sodipodi:type="arc" + style="fill:#4d4d4d;stroke-width:0.99599999;stroke-miterlimit:4;stroke-dasharray:none" + id="path3606-0" + sodipodi:cx="7.5572038" + sodipodi:cy="1.7252818" + sodipodi:rx="1.016466" + sodipodi:ry="1.5467961" + d="m 8.5736698,1.7252818 a 1.016466,1.5467961 0 1 1 -2.0329321,0 1.016466,1.5467961 0 1 1 2.0329321,0 z" + transform="matrix(0.9838007,-1.7039928,1.6796501,0.96974643,-6.6627793,16.704335)" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber5.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + style="fill:none;stroke:none" + id="rect4382-8" + width="16" + height="16" + x="-18.928202" + y="-5.0717974" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber5.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + transform="matrix(-0.5,-0.8660254,0.8660254,-0.5,0,0)" /> + <path + sodipodi:type="arc" + style="fill:#808080;stroke-width:0.99599999;stroke-miterlimit:4;stroke-dasharray:none" + id="path3606-9" + sodipodi:cx="7.5572038" + sodipodi:cy="1.7252818" + sodipodi:rx="1.016466" + sodipodi:ry="1.5467961" + d="m 8.5736698,1.7252818 a 1.016466,1.5467961 0 1 1 -2.0329321,0 1.016466,1.5467961 0 1 1 2.0329321,0 z" + transform="matrix(-0.9838007,-1.7039928,1.6796501,-0.96974644,8.2067862,25.050507)" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber5.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + style="fill:none;stroke:none" + id="rect4382-86" + width="16" + height="16" + x="-18.928204" + y="-5.0717978" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber4.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + transform="matrix(-0.5,-0.8660254,0.8660254,-0.5,0,0)" /> + <path + sodipodi:type="arc" + style="fill:#b3b3b3;stroke-width:0.99599999;stroke-miterlimit:4;stroke-dasharray:none" + id="path3606-3" + sodipodi:cx="7.5572038" + sodipodi:cy="1.7252818" + sodipodi:rx="1.016466" + sodipodi:ry="1.5467961" + d="m 8.5736698,1.7252818 a 1.016466,1.5467961 0 1 1 -2.0329321,0 1.016466,1.5467961 0 1 1 2.0329321,0 z" + transform="matrix(-1.9676014,0,0,-1.9394929,22.869564,16.346171)" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber5.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + style="fill:none;stroke:none" + id="rect4382-9" + width="16" + height="16" + x="-16" + y="-16" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber3.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + transform="scale(-1,-1)" /> + <path + sodipodi:type="arc" + style="fill:#cccccc;stroke-width:0.99599999;stroke-miterlimit:4;stroke-dasharray:none" + id="path3606-07" + sodipodi:cx="7.5572038" + sodipodi:cy="1.7252818" + sodipodi:rx="1.016466" + sodipodi:ry="1.5467961" + d="m 8.5736698,1.7252818 a 1.016466,1.5467961 0 1 1 -2.0329321,0 1.016466,1.5467961 0 1 1 2.0329321,0 z" + transform="matrix(-0.9838007,1.7039928,-1.6796501,-0.96974643,22.662777,-0.7043353)" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber5.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + style="fill:none;stroke:none" + id="rect4382-4" + width="16" + height="16" + x="2.9282029" + y="-10.928203" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber5.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + transform="matrix(0.5,0.8660254,-0.8660254,0.5,0,0)" /> + <path + sodipodi:type="arc" + style="fill:#e6e6e6;stroke-width:0.99599999;stroke-miterlimit:4;stroke-dasharray:none" + id="path3606-5" + sodipodi:cx="7.5572038" + sodipodi:cy="1.7252818" + sodipodi:rx="1.016466" + sodipodi:ry="1.5467961" + d="m 8.5736698,1.7252818 a 1.016466,1.5467961 0 1 1 -2.0329321,0 1.016466,1.5467961 0 1 1 2.0329321,0 z" + transform="matrix(0.9838007,1.7039928,-1.6796501,0.96974644,7.7932129,-9.0505065)" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber5.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + style="fill:none;stroke:none" + id="rect4382-5" + width="16" + height="16" + x="2.9282029" + y="-10.928203" + inkscape:export-filename="/home/io/Desarrollo/FIEBDC-3/pyArq-Presupuestos/images/throbber4.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + transform="matrix(0.5,0.8660254,-0.8660254,0.5,0,0)" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/unit.svg Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16px" + height="16px" + id="svg1884" + sodipodi:version="0.32" + inkscape:version="0.44.1" + sodipodi:docbase="/home/io/Desarrollo/FIEBDC-3/Arquimeter/images" + sodipodi:docname="unit.svg"> + <defs + id="defs1886"> + <linearGradient + y2="26.363961" + x2="49.032393" + y1="26.363961" + x1="29.513063" + gradientUnits="userSpaceOnUse" + id="linearGradient8369" + xlink:href="#linearGradient6546" + inkscape:collect="always" /> + <linearGradient + y2="26.36396" + x2="49.184048" + y1="26.36396" + x1="29.361408" + gradientUnits="userSpaceOnUse" + id="linearGradient7461" + xlink:href="#linearGradient7447" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="26.36396" + x2="49.184048" + y1="26.36396" + x1="29.361408" + id="linearGradient7457" + xlink:href="#linearGradient7447" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="26.363961" + x2="49.032393" + y1="26.363961" + x1="29.513063" + id="linearGradient6552" + xlink:href="#linearGradient6546" + inkscape:collect="always" /> + <linearGradient + id="linearGradient6546"> + <stop + id="stop6548" + offset="0" + style="stop-color:black;stop-opacity:1;" /> + <stop + id="stop6550" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient7447" + inkscape:collect="always"> + <stop + id="stop7449" + offset="0" + style="stop-color:black;stop-opacity:1;" /> + <stop + id="stop7451" + offset="1" + style="stop-color:black;stop-opacity:0;" /> + </linearGradient> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="22.197802" + inkscape:cx="20.098773" + inkscape:cy="5.5896024" + inkscape:current-layer="g1993" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1280" + inkscape:window-height="946" + inkscape:window-x="0" + inkscape:window-y="51" /> + <metadata + id="metadata1889"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <g + inkscape:label="Layer 1" + id="g1993" + transform="matrix(0.212243,0,0,0.212243,0.952256,1.020614)"> + <path + transform="matrix(1.004353,0,0,1.214516,14.60583,-22.01946)" + sodipodi:open="true" + sodipodi:end="8.0512033" + sodipodi:start="1.8036959" + d="M 37.090621,33.970737 A 9.454545,7.818182 0 1 1 37.420151,34.030261" + sodipodi:ry="7.818182" + sodipodi:rx="9.454545" + sodipodi:cy="26.363636" + sodipodi:cx="39.272728" + id="path5613" + style="opacity:1;fill:black;fill-opacity:0.55251142;stroke:url(#linearGradient7457);stroke-width:4.28722906;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99541285" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:navy;fill-opacity:1;stroke:url(#linearGradient8369);stroke-width:2.85815334;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path5615" + sodipodi:cx="39.272728" + sodipodi:cy="26.363636" + sodipodi:rx="9.454545" + sodipodi:ry="7.818182" + d="M 37.090621,33.970737 A 9.454545,7.818182 0 1 1 37.420151,34.030261" + sodipodi:start="1.8036959" + sodipodi:end="8.0512033" + sodipodi:open="true" + transform="matrix(1.532193,0,0,1.852807,-45.17338,-16.84733)" /> + <path + sodipodi:type="arc" + style="opacity:1;fill:black;fill-opacity:0.55251142;stroke:url(#linearGradient7461);stroke-width:4.28722906;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.99541285" + id="path7459" + sodipodi:cx="39.272728" + sodipodi:cy="26.363636" + sodipodi:rx="9.454545" + sodipodi:ry="7.818182" + d="M 37.090621,33.970737 A 9.454545,7.818182 0 1 1 37.420151,34.030261" + sodipodi:start="1.8036959" + sodipodi:end="8.0512033" + sodipodi:open="true" + transform="matrix(1.004352,0,0,1.214515,14.55633,21.98056)" /> + <path + id="path8377" + d="M 27.296321,24.453679 L 45.203679,13.296321" + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:4.71158059;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:4.24042253;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 27.046321,39.046321 L 44.953679,50.203679" + id="path8379" /> + </g> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mo/pyArq-Presupuestos.es.po Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,1117 @@ +# pyArq-Presupuestos translatión to Spanish. +# Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +# This file is distributed under the same license as the pyArq-Presupuestos +# package. +# Changes: +# - Initial translation: +# Miguel Ángel Bárcena Rodríguez <miguelangel@obraencurso.es>, 2010 +# +# +msgid "" +msgstr "" +"Project-Id-Version: pyArq-Presupuestos 0.0.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-10-31 20:01+0100\n" +"PO-Revision-Date: 2010-01-11 12:24+0100\n" +"Last-Translator: Miguel Ángel Bárcena Rodríguez <miguelangel@obraencurso." +"es>\n" +"Language-Team: Spanish\n" +"Language: Spannish\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../Generic/base.py:358 +msgid "Invalid code: $1" +msgstr "Código no válido: $1" + +#: ../Generic/base.py:373 +msgid "Synonyms ($1) must be a list, code: $2" +msgstr "Sinónimos ($1) debe ser una lista, código: $2" + +#: ../Generic/base.py:377 +msgid "Invalid Code in synomyms list ($1) code: $2" +msgstr "Código no válido es la lista de sinónimos ($1) código: $2" + +#: ../Generic/base.py:408 +msgid "Unit ($1) must be a string: $2" +msgstr "Unidad ($1) debe ser una cadena: $2" + +#: ../Generic/base.py:422 +msgid "Summary ($1) must be a string: $1" +msgstr "Resumen ($1) debe ser una cadena: $1" + +#: ../Generic/base.py:439 +msgid "Prices ($1) must be a list: $2" +msgstr "«Prices» ($1) debe ser una lista: $2" + +#: ../Generic/base.py:460 +msgid "Price ($1) must be a list with two items: $2" +msgstr "«Prece» ($1) debe ser una lista con dos elementos: $2" + +#: ../Generic/base.py:465 +msgid "Price must be a float number: $1" +msgstr "Precio debe ser un número de coma flotante: $1" + +#: ../Generic/base.py:475 +#, python-format +msgid "The record do not have this Price. Code: %s" +msgstr "El registro no tiene ese precio. Código: %s" + +#: ../Generic/base.py:481 +msgid "The record do not have this Price" +msgstr "El registro no tiene ese precio" + +#: ../Generic/base.py:496 +msgid "Parents ($1) must be a list: $2" +msgstr "Padres ($1) debe ser una lista: $2" + +#: ../Generic/base.py:500 ../Generic/base.py:512 +msgid "Invalid parent code ($1) in the record: $2" +msgstr "Código padre no válido ($1) en el registro: $2" + +#: ../Generic/base.py:528 +msgid "children ($1) must be a list, record: $2" +msgstr "Hijos ($1) debe ser una lista, registro: $2" + +#: ../Generic/base.py:532 +msgid "child ($1) must be a Decomposition object, record: $2" +msgstr "«child» ($1) debe ser una objeto «Decomposition», registro $2" + +#: ../Generic/base.py:580 +msgid "Text ($1) must be a string, record: $2" +msgstr "Texto ($1) debe ser una cadena, registro: $2" + +#: ../Generic/base.py:593 +msgid "sheet must be a Sheet instance" +msgstr "sheet debe ser una instancia de Sheet" + +#: ../Generic/base.py:606 +msgid "files must be a list: $1" +msgstr "«files» debe ser una lista: $1" + +#: ../Generic/base.py:617 ../Generic/base.py:632 +msgid "Incorrect path" +msgstr "Ruta incorrecta" + +#: ../Generic/base.py:622 +msgid "file must be a list or a File object: $1" +msgstr "«file» debe ser una lista o un objeto «File: $1" + +#: ../Generic/base.py:651 +msgid "labels must be a list" +msgstr "«labels» debe ser una lista" + +#: ../Generic/base.py:657 +msgid "label must be a string" +msgstr "«label» debe ser una cadena de texto." + +#: ../Generic/base.py:666 +msgid "Label must be a string" +msgstr "Label debe ser una cadena de texto." + +#: ../Generic/base.py:894 +msgid "Position must be a integer" +msgstr "«Position» debe ser un número entero" + +#: ../Generic/base.py:904 +msgid "BudgetMeasures atribute must be a list" +msgstr "El atributo «BudgetMeasures» debe ser una lista" + +#: ../Generic/base.py:907 +msgid "BudgetMeasures item must be a Measure " +msgstr "El atributo «BudgetMeasures» debe ser un objeto «Measure»" + +#: ../Generic/base.py:914 +msgid "Certification atribute must be a list or None" +msgstr "El atributo «Certification» debe ser una lista o «None»" + +#: ../Generic/base.py:920 +msgid "Real cost atribute must be a list or None" +msgstr "El atributo «Real cost» debe ser listo o «None»" + +#: ../Generic/base.py:926 +msgid "Cost goals atribute must be a list or None" +msgstr "El atributo «Cost goals» debe ser una lista o «None»" + +#: ../Generic/base.py:932 +msgid "Cost Planned atribute must be a list or None" +msgstr "El atributo «Cost Planned» debe ser una lista o «None»" + +#: ../Generic/base.py:1023 +msgid "Measure must be a float number. Type: $1" +msgstr "«Measure» debe ser un número de coma flotante. Tipo: $1" + +#: ../Generic/base.py:1034 +msgid "Lines must be a list" +msgstr "«Lines» debe ser una lista" + +#: ../Generic/base.py:1037 +msgid "Line must be a MeasureLine objetc" +msgstr "«Line» debe ser un objeto «MeasureLine»" + +#: ../Generic/base.py:1045 +msgid "Factor must be a float number |$1|" +msgstr "«Factor» debe ser un número de coma flotante |$1|" + +#: ../Generic/base.py:1057 +msgid "Yield must be a float number" +msgstr "«Yield» debe ser un número de coma flotante" + +#: ../Generic/base.py:1068 +msgid "Fixed must be boolean object" +msgstr "«Fixed» debe ser un objeto booleano" + +#: ../Generic/base.py:1137 +msgid "Type must be M or A. Type: $1" +msgstr "«Type» debe ser M o A. Type: $1" + +#: ../Generic/base.py:1269 +msgid " Parcial Subtotal must be a float number. Parcial: $1" +msgstr "«Parcial Subtotal» debe ser un número de coma flotante. Parcial: $1" + +#: ../Generic/base.py:1276 +msgid " Acumulated Subtotal must be a float number. Parcial: $1" +msgstr " «Acumulate Subtotal» debe ser un número de coma flotante. Parcial: $1" + +#: ../Generic/base.py:1311 +msgid "Invalid measure line type ($1)" +msgstr "Tipo de línea de medición no válido ($1)" + +#: ../Generic/base.py:1316 +msgid "Measure Comment must be a string ($1)" +msgstr "El comentario de la medición debe ser una cadena ($1)" + +#: ../Generic/base.py:1322 +msgid "Invalid Measure Units ($1)" +msgstr "Unidades de medición no vacías ($1)" + +#: ../Generic/base.py:1334 +msgid "Invalid Measure length ($1)" +msgstr "Longitud de medición no válida ($1)" + +#: ../Generic/base.py:1346 +msgid "Invalid Measure Width ($1)" +msgstr "Anchura de medición no válida ($1)" + +#: ../Generic/base.py:1358 +msgid "Invalid Measure Height ($1)" +msgstr "Altura de medición no válida ($1)" + +#: ../Generic/base.py:1369 +msgid "Formula must be a string ($1)" +msgstr "«Formula» debe ser una cadena de texto ($1)" + +#: ../Generic/base.py:1372 +msgid "There is invalid charactersin formula ($1)" +msgstr "Hay caracteres inválidos en la fórmula ($1)" + +#: ../Generic/base.py:1437 ../Generic/base.py:2406 +msgid "'a' value must be a float number" +msgstr "El valor «a» debe ser un número de coma flotante" + +#: ../Generic/base.py:1441 ../Generic/base.py:2410 +msgid "'b' value must be a float number" +msgstr "El valor «b» debe ser un número de coma flotante" + +#: ../Generic/base.py:1445 ../Generic/base.py:2414 +msgid "'c' value must be a float number" +msgstr "El valor «c» debe ser un número de coma flotante" + +#: ../Generic/base.py:1449 ../Generic/base.py:2418 +msgid "'d' value must be a float number" +msgstr "El valor «d» debe ser un número de coma flotante" + +#: ../Generic/base.py:1477 ../Generic/base.py:2446 +msgid "Invalid formula" +msgstr "Fórmula no válida" + +#: ../Generic/base.py:1727 +msgid "sheet_dict must be a dictionay" +msgstr "sheet_dict debe ser un diccionario." + +#: ../Generic/base.py:1744 ../Generic/base.py:1750 +msgid "sheet field must be a string" +msgstr "El ambito del pliego debe ser una cadena de texto" + +#: ../Generic/base.py:1746 +msgid "section_dict must be a dictionary" +msgstr "section_dict debe ser un dicionario" + +#: ../Generic/base.py:1752 +msgid "sheet section must be a string" +msgstr "La seccion del pliego debe ser una cadena de texto" + +#: ../Generic/base.py:1754 +msgid "sheet paragraph must be a string" +msgstr "El parrafo del pliego debe ser una cadena de texto" + +#: ../Generic/base.py:1992 +msgid "Owner must be a string" +msgstr "«Owner» debe ser una cadena de texto." + +#: ../Generic/base.py:2008 +#, python-format +msgid "Invalid Date: %s" +msgstr "Fecha inválida: %s" + +#: ../Generic/base.py:2019 +msgid "Comment must be a string" +msgstr "El comentario debe ser una cadena" + +#: ../Generic/base.py:2035 +msgid "Budget type must be 1, 2, 3 or 4." +msgstr "El tipo de presupuesto debe ser 1, 2, 3 o 4" + +#: ../Generic/base.py:2047 +msgid "Certificate order must be a integer." +msgstr "«Certificate order» debe ser un número entero" + +#: ../Generic/base.py:2062 +msgid "Budget certificate Date must be a valid Date." +msgstr "«Budget certificate Date» debe ser una fecha válida" + +#: ../Generic/base.py:2076 +msgid "Invalid title list format" +msgstr "Formato de lista de rótulos no válida" + +#: ../Generic/base.py:2105 +msgid "Invalid Index Title" +msgstr "Índice de rótulo no válido" + +#: ../Generic/base.py:2140 +msgid "Decimal Key error" +msgstr "Clave de decimales errónea" + +#: ../Generic/base.py:2176 +msgid "Invalid Percentage key" +msgstr "Clave de porcentajes no válida" + +#: ../Generic/base.py:2291 +msgid "Invalid parent code: $1" +msgstr "Código del padre inválido: $1" + +#: ../Generic/base.py:2294 +msgid "Invalid child code: $1" +msgstr "Código de hijo inválido: $1" + +#: ../Generic/base.py:2297 +msgid "Invalid position in measure $1, in code $2" +msgstr "Posición no válida en medición $1, en código $2" + +#: ../Generic/base.py:2305 +msgid "" +"Circular Decomposition, parent code: $1, child code: $2, repeated code: $3" +msgstr "" +"Descomposición circular, código padre: $1, código hijo: $2, código repetido: " +"$3" + +#: ../Generic/base.py:2360 ../Generic/base.py:2372 +msgid "" +"Error: Invalid child position in decomposition. Parent code: $1 Child code: " +"$2 Position: $3" +msgstr "" +"Error: Posición del hijo no válida en descomposición. Código padre: $1 " +"Código hijo: $2 Posición: $3" + +#: ../Generic/base.py:2366 +msgid "Error: Empty child code. Parent code: $1 Position: $2" +msgstr "Error: Código hijo vacío. Código padre: $1 Posición: $2" + +#: ../Generic/base.py:2457 +msgid "Invalid code" +msgstr "Código no válido" + +#: ../Generic/base.py:2467 +msgid "Invalid record: $1" +msgstr "Registro no válido: $1" + +#: ../Generic/base.py:2530 +msgid "Only can be one root record" +msgstr "Sólo puede haber un registro raíz" + +#: ../Generic/base.py:2624 ../Generic/base.py:2630 +msgid "This record does not exits" +msgstr "Este registro no existe" + +#: ../Generic/base.py:2627 +msgid "Path item must be a integer" +msgstr "El elemento del camino debe ser un número entero" + +#: ../Generic/base.py:2632 +msgid "Path must be a not empty tuple: $1" +msgstr "El camino debe ser una tupla no vacía: $1" + +#: ../Generic/base.py:2683 +msgid "The sheet code must be a string" +msgstr "El código del pliego debe ser una cadena de texto" + +#: ../Generic/base.py:2685 +msgid "The sheet title must be a string" +msgstr "El título del pliego debe ser una cadena de texto." + +#: ../Generic/base.py:2693 +msgid "The sheet sections must be a dictionary" +msgstr "La sección del pliego debe ser un dicionario" + +#: ../Generic/base.py:2698 +msgid "The field code must be a string" +msgstr "El código del ámbito debe ser una cadena de texto" + +#: ../Generic/base.py:2700 +msgid "The field title must be a string" +msgstr "El título del ámbito debe ser una cadena de texto." + +#: ../Generic/base.py:2708 +msgid "The sheet field must be a dictionary" +msgstr "El ámbito del pliego debe ser un dicionario." + +#: ../Generic/base.py:2713 +msgid "The paragraph code must be a string" +msgstr "El código del parrafo debe ser una cadena de texto." + +#: ../Generic/base.py:2715 +msgid "The paragraph text must be a string" +msgstr "El texto del parrafo debe ser una cadena de texto" + +#: ../Generic/base.py:2723 +msgid "The paragraph dict must be a dictionary" +msgstr "El dicionario del parrafo debe ser un diccionario" + +#: ../Generic/base.py:2728 ../Generic/base.py:2752 ../Generic/base.py:2882 +#: ../Generic/base.py:2906 ../Generic/base.py:2928 +msgid "The record_code code must be a string" +msgstr "record_code debe ser una cadena de texto" + +#: ../Generic/base.py:2730 +msgid "The field must be a string" +msgstr "El ámbito debe ser una cadena de texto." + +#: ../Generic/base.py:2732 +msgid "The section dict must be a dictionary" +msgstr "El dicionario de la seccion debe ser un dicionario." + +#: ../Generic/base.py:2736 +msgid "" +"Error: The budget do not have this record code and can not be added the " +"sheet text in the field $1. Record Code: $2" +msgstr "" +"Error: El presupuesto no tiene ese codigo de registro y no puede añadirse el " +"texto del pliego en el ambito $1. Código del registro: $2" + +#: ../Generic/base.py:2754 +msgid "The filename must be a string" +msgstr "El nombre del fichero debe ser una cadena de texto." + +#: ../Generic/base.py:2758 +msgid "" +"Error: The budget do not have the record code $1 and can not be added the " +"file: $2" +msgstr "" +"Error: El presupuesto no tiene el código de registro $1 y no puede añadirse " +"el fichero: $2" + +#: ../Generic/base.py:2768 +msgid "The company code must be a string" +msgstr "El código de la entidad debe ser una cadena de texto." + +#: ../Generic/base.py:2770 +msgid "The summary must be a string" +msgstr "El resumen debe ser una cadena de texto" + +#: ../Generic/base.py:2772 ../Generic/base.py:2800 +msgid "The name must be a string" +msgstr "El nombre debe ser una cadena de texto." + +#: ../Generic/base.py:2774 +msgid "The name must be a list" +msgstr "El nombre debe ser una lista" + +#: ../Generic/base.py:2778 +msgid "The office must be a list" +msgstr "«The office» debe ser una lista" + +#: ../Generic/base.py:2780 +msgid "The office must be a 10 items list" +msgstr "«The office» debe ser una lista de 10 elementos" + +#: ../Generic/base.py:2783 +msgid "This office item must be a string" +msgstr "El elemento de la oficina debe ser una cadena de texto." + +#: ../Generic/base.py:2787 +msgid "This office item must be a list" +msgstr "Este elemento de la oficina debe ser una lista" + +#: ../Generic/base.py:2802 +msgid "The web must be a string" +msgstr "La web debe ser una cadena de texto." + +#: ../Generic/base.py:2804 +msgid "The email must be a string" +msgstr "El email debe ser una cadena de texto." + +#: ../Generic/base.py:2814 +msgid "The tecnical info code must be a string" +msgstr "La información técnica debe ser una cadena de texto." + +#: ../Generic/base.py:2816 +msgid "The tecnical info description must be a string" +msgstr "La descripción de la información técnica debe ser una cadena de texto" + +#: ../Generic/base.py:2819 +msgid "The tecnical info unit must be a string" +msgstr "La unidad de la información técnica debe ser una cadena de texto." + +#: ../Generic/base.py:2866 +msgid "The label must be a string" +msgstr "La etiqueta debe ser una cadena de texto." + +#: ../Generic/base.py:2884 +msgid "The parametric select comment must be a string" +msgstr "El comentario de selección paramétrico debe ser una cadena de texto" + +#: ../Generic/base.py:2887 +msgid "" +"Error: The budget do not have the record code $1 and can not be added the " +"Parametric select comment: $2" +msgstr "" +"Error: El presupuesto no tiene el código de registro $1 y no puede añadirse " +"el comentario de selección paramétrico: $2" + +#: ../Generic/base.py:2894 +msgid "" +"Error: The Record $1 is not a Parametric Record and can not have Parametric " +"comment" +msgstr "" +"Error: El registro $1 no es un registro paramétrico y no puede tener " +"comentario paramétrico." + +#: ../Generic/base.py:2908 +msgid "The summary record must be a string" +msgstr "El resumen del registro debe ser una cadena de texto" + +#: ../Generic/base.py:2910 +msgid "" +"Error: The budget do not have the record code $1 and can not be seted the " +"summary: $2" +msgstr "" +"Error: El presupuesto no tiene el codigo de registro $1 y no puede fijarse " +"el resumen: $2" + +#: ../Generic/base.py:2916 +msgid "" +"Error: The Record $1 is not a Parametric Record and can not have Parametric " +"summary" +msgstr "" +"Error: El registro $1 no es un registro paramétrico y no puede tener resumen " +"paramétrico." + +#: ../Generic/base.py:2930 +msgid "The text record must be a string" +msgstr "El texto del registro debe ser una cadena de texto" + +#: ../Generic/base.py:2932 +msgid "" +"Error: The budget do not have the record code $1 and can not be seted the " +"text: $2" +msgstr "" +"Error: El presupuesto no tiene el codigo de registro $1 y no puede fijarse " +"el texto: $2" + +#: ../Generic/base.py:2938 +msgid "" +"Error: The Record $1 is not a Parametric Record and can not have Parametric " +"text" +msgstr "" +"Error: El registro $1 no es un registro paramétrico y no puede tener texto " +"paramétrico." + +#: ../Generic/base.py:3396 +msgid "Invalid Hierarchy ($1) The hierarchy must be -1, 0, 1 or 2" +msgstr "Categoría no válida ($1) La categoria debe ser -1, 0, 1 or 2" + +#: ../Generic/base.py:3403 +msgid "Invalid type ($1),the type must be (empty string,0,1,2,3)" +msgstr "Tipo inválido ($1), el tipo debe ser (cadena vacía, 0, 1, 2, 3)" + +#: ../Generic/base.py:3412 +msgid "" +"Invalid subtype ($1), The subtype must one in (empty string, EA, EU, EC, EF, " +"OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)" +msgstr "" +"Subtipo inválido ($1), el subtipo debe ser uno de (cadena vacía, EA, EU, EC, " +"EF, OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)" + +#: ../Generic/fiebdc.py:151 +msgid "Invalid code, it must be a string" +msgstr "Código no válido, debe ser una cadena" + +#: ../Generic/fiebdc.py:157 +msgid "The code '$1' have invalid characters." +msgstr "El código «$1» tiene caracteres inválidos." + +#: ../Generic/fiebdc.py:170 +msgid "The code '$1' contains special characters repeated." +msgstr "El código «$1» contiene caractectes especiales repetidos." + +#: ../Generic/fiebdc.py:391 +msgid "" +"The 'V' record (Property and Version) must be the first record in the file " +"but it is the number: $1" +msgstr "" +"El registro «V» (Propiedad y versión) debe ser el primer registro en el " +"archivo pero es el número: $1" + +#: ../Generic/fiebdc.py:394 +msgid "The default values were taken and this V record is ignored" +msgstr "El valor por amisión ha sido tomado y el registro V es ignorado" + +#: ../Generic/fiebdc.py:428 +#, python-format +msgid "FIEBDC format: %s" +msgstr "Formato FIEBDC: %s" + +#: ../Generic/fiebdc.py:437 +#, python-format +msgid "FIEBDC file generated by %s" +msgstr "Fichero FIEBDC generado por %s" + +#: ../Generic/fiebdc.py:776 +msgid "Record C without a valid code" +msgstr "Registro C sin un código válido" + +#: ../Generic/fiebdc.py:852 ../Generic/fiebdc.py:864 ../Generic/fiebdc.py:892 +msgid "Incorrect type ($1) in the code $2" +msgstr "Tipo incorrecto ($1) en el código $2" + +#: ../Generic/fiebdc.py:943 +msgid "" +"ValueError loadig the descomposition of the record $1, the factor of the " +"child $2 must be a float number and can not be $3, seted default value 1.0" +msgstr "" +"Error de valor al cargar la descomposición del registro $1, el factor del " +"hijo $2 debe ser un número de coma flotante y no puede ser $3, fijado el " +"valor por omisión 1.0" + +#: ../Generic/fiebdc.py:954 +msgid "" +"ValueError loading the descomposition of the record $1, the yield of the " +"child $2, must be a float number and cannot be $3, seted default value 1.0" +msgstr "" +"Error de valor cargando la descomposición del registro $1, el rendimiento " +"del hijo $2, debe ser un número de coma flotante y no puede ser $3, fijado " +"el valor por omisión 1.0" + +#: ../Generic/fiebdc.py:1041 +msgid "Invalid codes in $1 record, codes $2" +msgstr "Códigos no válidos en registro $1, códigos $2" + +#: ../Generic/fiebdc.py:1045 +msgid "Empty child code in $1 record, codes: $2" +msgstr "Código de hijo vacío en el registro $1, códigos: $2" + +#: ../Generic/fiebdc.py:1058 +msgid "Invalid path in $1 record, codes $2" +msgstr "Camino no válido en el registro $1, códigos $2" + +#: ../Generic/fiebdc.py:1069 +msgid "Invalid Total Measure value in $1 record, codes $2" +msgstr "Total de medición no válido en el registro $1, códigos $2" + +#: ../Generic/fiebdc.py:1089 +msgid "" +"The comment is not a formula or its have invalid characters, in the $1 " +"record, codes $2" +msgstr "" +"El comentario no es una fórmula o tiene caracteres inválidos, en el registro " +"$1, códigos $2" + +#: ../Generic/fiebdc.py:1403 ../Generic/fiebdc.py:1657 +msgid "The file $1 do not exist" +msgstr "El archivo $1 no existe" + +#: ../Generic/fiebdc.py:1763 ../Generic/fiebdc.py:1770 +msgid "PyArq hates parametric DLLs" +msgstr "PyArq odia las DLLs paramétricas" + +#: ../Generic/fiebdc.py:1980 +msgid "Loading file $1" +msgstr "Cargando archivo $1" + +#: ../Generic/fiebdc.py:2000 +msgid "This codepage do not exist in FIEBDC3! Default codepage: $1" +msgstr "¡Esta codificación no existe en FIEBDC3! Codificación por omisión: $1" + +#: ../Generic/fiebdc.py:2004 +msgid "This V record dot have a codepage! Default codepage: $1" +msgstr "¡Este registro V no define codificación! Codificación por omisión: $1" + +#: ../Generic/fiebdc.py:2008 +msgid "Not 'V' record in File! Default codepage: $1" +msgstr "¡No hay registro «V» en el archivo! Codificación por omisión: $1" + +#: ../Generic/fiebdc.py:2049 +msgid "Cancelled process" +msgstr "Proceso cancelado" + +#: ../Generic/fiebdc.py:2052 +msgid "Time to load: $1 seconds" +msgstr "Tiempo de carga: $1 segundos" + +#: ../Generic/fiebdc.py:2054 +msgid "Records/Valid Records: $1/$2" +msgstr "Registro/Registros válidos: $1/$2" + +#: ../Generic/fiebdc.py:2057 +msgid "$1 unsuported record type O: Comercial Relationship" +msgstr "" + +#: ../Generic/fiebdc.py:2060 +msgid "This file is not a valid FIBDC3 file" +msgstr "El archivo no es un archivo FIEBDC3 válido" + +#: ../Generic/fiebdc.py:2097 +msgid "Testing budget ..." +msgstr "Comprobando presupuesto ..." + +#: ../Generic/fiebdc.py:2115 +msgid "End Test" +msgstr "Comprobación finalizada" + +#: ../Gtk/gui.py:69 +msgid "The icon file does not exist. '$1'" +msgstr "El archivo de icono no existe. «$1»" + +#: ../Gtk/gui.py:75 +msgid "pyArq-Presupuestos running on $1" +msgstr "pyArq-Presupuestos ejecutandose en $1" + +#: ../Gtk/gui.py:164 +msgid "_File" +msgstr "_Archivo" + +#: ../Gtk/gui.py:165 +msgid "_Import Fiebdc" +msgstr "_Importar Fiebdc" + +#: ../Gtk/gui.py:167 +msgid "_Close" +msgstr "_Cerrar" + +#: ../Gtk/gui.py:169 +msgid "_View" +msgstr "_Ver" + +#: ../Gtk/gui.py:170 +msgid "_Text" +msgstr "_Texto" + +#: ../Gtk/gui.py:172 +msgid "_Test" +msgstr "_Pruebas" + +#: ../Gtk/gui.py:174 +msgid "Import Fiebdc _price database" +msgstr "Importar base de _precios Fiebdc" + +#: ../Gtk/gui.py:176 +msgid "_Open price database" +msgstr "_Abrir base de precios" + +#: ../Gtk/gui.py:248 +msgid "Saving file: $1" +msgstr "Guardando archivo: $1" + +#: ../Gtk/gui.py:253 +msgid "Saving time: $1 seconds" +msgstr "Tiempo de guardado: $1 segundos" + +#: ../Gtk/gui.py:321 +msgid "Loading file: $1:" +msgstr "Cargando archivo: $1" + +#: ../Gtk/gui.py:468 ../Gtk/importFiebdc.py:224 +msgid "Time: 0s" +msgstr "Tiempo: 0s" + +#: ../Gtk/gui.py:532 ../Gtk/importFiebdc.py:303 +msgid "Time: $1" +msgstr "Tiempo: $1" + +#: ../Gtk/gui.py:809 +msgid "The value must be a list" +msgstr "El valor debe ser una lista" + +#: ../Gtk/gui.py:812 +msgid "Incorrect len" +msgstr "Longuitud incorrecta" + +#: ../Gtk/gui.py:840 +msgid "Incorrect item $1" +msgstr "Elemento incorrecto $1" + +#: ../Gtk/gui.py:854 +msgid "The budget does not have the path record: $1" +msgstr "El presupuesto no tiene el registro con camino: $1" + +#: ../Gtk/gui.py:989 +msgid "Decomposition" +msgstr "Descomposición" + +#: ../Gtk/gui.py:990 ../Gtk/gui.py:2006 +msgid "Description" +msgstr "Descripción" + +#: ../Gtk/gui.py:991 ../Gtk/gui.py:2008 +msgid "Measure" +msgstr "Medición" + +#: ../Gtk/gui.py:992 +msgid "Sheet of Conditions" +msgstr "Pliego de condicones" + +#: ../Gtk/gui.py:993 +msgid "Files" +msgstr "Archivos" + +#: ../Gtk/gui.py:994 +msgid "Companies" +msgstr "Entidades" + +#: ../Gtk/gui.py:1355 +msgid "The item must be a widget object." +msgstr "El elemento debe ser un objeto «widget»." + +#: ../Gtk/gui.py:1361 +msgid "Invalid orientation." +msgstr "Orientación no válida" + +#: ../Gtk/gui.py:1736 ../Gtk/gui.py:2370 ../Gtk/gui.py:3780 +msgid "Argument must be a Budget object" +msgstr "El argumento debe ser un objeto «Budget»" + +#: ../Gtk/gui.py:1745 +msgid "DecompositionList.__init__: Record path can not be None" +msgstr "«DecompositionList.__init__:» La ruta del registro no puede ser «None»" + +#: ../Gtk/gui.py:1776 +msgid "a" +msgstr "a" + +#: ../Gtk/gui.py:2003 ../Gtk/gui.py:3840 +msgid "Code" +msgstr "Código" + +#: ../Gtk/gui.py:2004 +msgid "Unit" +msgstr "Unidad" + +#: ../Gtk/gui.py:2010 +msgid "Price" +msgstr "Precio" + +#: ../Gtk/gui.py:2012 +msgid "Amount" +msgstr "Importe" + +#: ../Gtk/gui.py:2024 ../Gtk/gui.py:2502 +msgid "Invalid path" +msgstr "Camino no válido" + +#: ../Gtk/gui.py:2375 +msgid "Record path must be a tuple" +msgstr "La posición del registro debe ser una tupla" + +#: ../Gtk/gui.py:2519 +msgid "measure must be a Measure object. Type: $1" +msgstr "«measure» debe ser un objeto «Measure». Tipo: $1" + +#: ../Gtk/gui.py:2530 ../Gtk/gui.py:3855 ../Gtk/gui.py:4182 +msgid "Type" +msgstr "Tipo" + +#: ../Gtk/gui.py:2531 +msgid "Comment" +msgstr "Comentario" + +#: ../Gtk/gui.py:2532 +msgid "" +"N\n" +"(a)" +msgstr "" +"N\n" +"(a)" + +#: ../Gtk/gui.py:2533 +msgid "" +"Length\n" +"(b)" +msgstr "" +"Longitud\n" +"(b)" + +#: ../Gtk/gui.py:2534 +msgid "" +"Width\n" +"(c)" +msgstr "" +"Anchura\n" +"(c)" + +#: ../Gtk/gui.py:2535 +msgid "" +"Height\n" +"(d)" +msgstr "" +"Altura\n" +"(d)" + +#: ../Gtk/gui.py:2536 +msgid "Formula" +msgstr "Fórmula" + +#: ../Gtk/gui.py:2537 +#, python-format +msgid "" +"Parcial\n" +"[%s]" +msgstr "" +"Parcial\n" +"[%s]" + +#: ../Gtk/gui.py:2538 +msgid "Subtotal" +msgstr "Subtotal" + +#: ../Gtk/gui.py:2946 ../Gtk/gui.py:2968 +msgid "Description text of the record $1" +msgstr "Texto descriptivo del registro $1" + +#: ../Gtk/gui.py:3125 +msgid "Sheet of Conditions of the record $1" +msgstr "Pliego de condiciones del registro $1" + +#: ../Gtk/gui.py:3145 +msgid "Field" +msgstr "Ámbito" + +#: ../Gtk/gui.py:3167 +msgid "Section" +msgstr "Sección" + +#: ../Gtk/gui.py:3320 +msgid "Sheet2 of Conditions of the record $1" +msgstr "Pliego2 de condiciones del registro $1" + +#: ../Gtk/gui.py:3696 +msgid "$1 text" +msgstr "Texto de $1" + +#: ../Gtk/gui.py:3841 +msgid "Code that define the company" +msgstr "Código que define la entidad" + +#: ../Gtk/gui.py:3842 +msgid "Summary" +msgstr "Resumen" + +#: ../Gtk/gui.py:3843 +msgid "Summary of the company name" +msgstr "Resumen del nombre de la entidad" + +#: ../Gtk/gui.py:3844 ../Gtk/gui.py:3860 +msgid "Name" +msgstr "Nombre" + +#: ../Gtk/gui.py:3845 +msgid "Complete name" +msgstr "Nombre completo" + +#: ../Gtk/gui.py:3846 +msgid "CIF" +msgstr "CIF" + +#: ../Gtk/gui.py:3847 +msgid "Fiscal identifier number" +msgstr "Número de identificación fiscal" + +#: ../Gtk/gui.py:3848 +msgid "Web" +msgstr "Web" + +#: ../Gtk/gui.py:3849 +msgid "Company web page" +msgstr "Página web de la entidad" + +#: ../Gtk/gui.py:3850 +msgid "Email" +msgstr "Email" + +#: ../Gtk/gui.py:3851 +msgid "Company email" +msgstr "Correo electrónico de la entidad" + +#: ../Gtk/gui.py:3856 +msgid "" +"Type of Office:\n" +" C: Central office\n" +" D: Local office\n" +" R: Performer" +msgstr "" +"Type of Office:\n" +" C: Oficina central\n" +" D: Delegación\n" +" R: Representante" + +#: ../Gtk/gui.py:3861 +msgid "Office name" +msgstr "Nombre de la oficina" + +#: ../Gtk/gui.py:3862 +msgid "Address" +msgstr "Dirección" + +#: ../Gtk/gui.py:3863 +msgid "Postal code" +msgstr "Código postal" + +#: ../Gtk/gui.py:3864 +msgid "Town" +msgstr "Ciudad" + +#: ../Gtk/gui.py:3865 +msgid "Province" +msgstr "Provincia" + +#: ../Gtk/gui.py:3866 +msgid "Country" +msgstr "Ciudad" + +#: ../Gtk/gui.py:3867 +msgid "Phone" +msgstr "Teléfono" + +#: ../Gtk/gui.py:3868 +msgid "Phone numbers of the office" +msgstr "Teléfono de la officina" + +#: ../Gtk/gui.py:3869 +msgid "Fax" +msgstr "Fax" + +#: ../Gtk/gui.py:3870 +msgid "Fax numbers of the office" +msgstr "Fax de la oficina" + +#: ../Gtk/gui.py:3871 +msgid "Contact person" +msgstr "Persona de contacto" + +#: ../Gtk/gui.py:3872 +msgid "Contact persons in the office" +msgstr "Persona de contacto en la oficina" + +#: ../Gtk/gui.py:3876 +msgid "Unknow Option Type" +msgstr "Tipo de opcion desconocida" + +#: ../Gtk/gui.py:4120 +msgid "Boolean" +msgstr "Booleano" + +#: ../Gtk/gui.py:4121 +msgid "Integer" +msgstr "Entero" + +#: ../Gtk/gui.py:4122 +msgid "Text" +msgstr "Texto" + +#: ../Gtk/gui.py:4123 +msgid "Color" +msgstr "Color" + +#: ../Gtk/gui.py:4124 +msgid "List" +msgstr "Lista" + +#: ../Gtk/gui.py:4156 +msgid "Option name" +msgstr "Nombre de Opción" + +#: ../Gtk/gui.py:4169 +msgid "Value" +msgstr "Valor" + +#: ../Gtk/gui.py:4207 +msgid "Description:" +msgstr "Descripción:" + +#: ../Gtk/gui.py:4369 +msgid "Option values must be strings" +msgstr "Los valores de la opción deben ser cadenas" + +#: ../Gtk/gui.py:4371 +msgid "Option must be a tuple with 4 items" +msgstr "La opcion debe ser una tupla de 4 elementos" + +#: ../Gtk/gui.py:4373 +msgid "Option list must be a list" +msgstr "La lista de opciones debe ser una lista lista" + +#: ../Gtk/gui.py:4393 +msgid "Icorrect type, must be boolean" +msgstr "Tipo erroneo, debe ser booleano" + +#: ../Gtk/gui.py:4398 +msgid "Icorrect type, must be integer" +msgstr "Tipo erroneo, debe ser un número entero" + +#: ../Gtk/gui.py:4411 +msgid "Icorrect type, must be string" +msgstr "Tipo erroneo, debe ser una cadena de texto" + +#: ../Gtk/gui.py:4424 +msgid "Icorrect type, must be list" +msgstr "Tipo erroneo, debe ser una lista" + +#: ../Gtk/gui.py:4430 +msgid "Icorrect type, must be a parseable color" +msgstr "Tipo erroneo, debe ser un color parseable" + +#: ../Gtk/gui.py:4438 +msgid "Type must be boolean, integer, string or color" +msgstr "El tipo debe ser booleano, entero, cadena de texto o color" + +#: ../Gtk/gui.py:4441 +msgid "Value must be in the option dict" +msgstr "El valor debe estar en el diccionario de opciones" + +#: ../Gtk/gui.py:4443 +msgid "Values must be a dict" +msgstr "El valor debe ser un dicionario" + +#: ../Gtk/gui.py:4501 +msgid "No file selected" +msgstr "Ningún fichero seleccionado" + +#: ../Gtk/gui.py:4503 +msgid "The filename must have durus extension" +msgstr "El nombre del archivo debe tener extensión «durus»" + +#: ../Gtk/importFiebdc.py:89 +msgid "Open File" +msgstr "Abrir archivo" + +#: ../Gtk/importFiebdc.py:139 +msgid "The file must have 'bc3' extension" +msgstr "El archivo debe tener extensión «bc3»" + +#: ../Gtk/importFiebdc.py:212 +msgid "Loading file ..." +msgstr "Cargando archivo ..." + +#: ../Gtk/importFiebdc.py:236 +msgid "Cancel" +msgstr "Cancelar"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mo/pyArq-Presupuestos.pot Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,1067 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-10-31 20:01+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../Generic/base.py:358 +msgid "Invalid code: $1" +msgstr "" + +#: ../Generic/base.py:373 +msgid "Synonyms ($1) must be a list, code: $2" +msgstr "" + +#: ../Generic/base.py:377 +msgid "Invalid Code in synomyms list ($1) code: $2" +msgstr "" + +#: ../Generic/base.py:408 +msgid "Unit ($1) must be a string: $2" +msgstr "" + +#: ../Generic/base.py:422 +msgid "Summary ($1) must be a string: $1" +msgstr "" + +#: ../Generic/base.py:439 +msgid "Prices ($1) must be a list: $2" +msgstr "" + +#: ../Generic/base.py:460 +msgid "Price ($1) must be a list with two items: $2" +msgstr "" + +#: ../Generic/base.py:465 +msgid "Price must be a float number: $1" +msgstr "" + +#: ../Generic/base.py:475 +#, python-format +msgid "The record do not have this Price. Code: %s" +msgstr "" + +#: ../Generic/base.py:481 +msgid "The record do not have this Price" +msgstr "" + +#: ../Generic/base.py:496 +msgid "Parents ($1) must be a list: $2" +msgstr "" + +#: ../Generic/base.py:500 ../Generic/base.py:512 +msgid "Invalid parent code ($1) in the record: $2" +msgstr "" + +#: ../Generic/base.py:528 +msgid "children ($1) must be a list, record: $2" +msgstr "" + +#: ../Generic/base.py:532 +msgid "child ($1) must be a Decomposition object, record: $2" +msgstr "" + +#: ../Generic/base.py:580 +msgid "Text ($1) must be a string, record: $2" +msgstr "" + +#: ../Generic/base.py:593 +msgid "sheet must be a Sheet instance" +msgstr "" + +#: ../Generic/base.py:606 +msgid "files must be a list: $1" +msgstr "" + +#: ../Generic/base.py:617 ../Generic/base.py:632 +msgid "Incorrect path" +msgstr "" + +#: ../Generic/base.py:622 +msgid "file must be a list or a File object: $1" +msgstr "" + +#: ../Generic/base.py:651 +msgid "labels must be a list" +msgstr "" + +#: ../Generic/base.py:657 +msgid "label must be a string" +msgstr "" + +#: ../Generic/base.py:666 +msgid "Label must be a string" +msgstr "" + +#: ../Generic/base.py:894 +msgid "Position must be a integer" +msgstr "" + +#: ../Generic/base.py:904 +msgid "BudgetMeasures atribute must be a list" +msgstr "" + +#: ../Generic/base.py:907 +msgid "BudgetMeasures item must be a Measure " +msgstr "" + +#: ../Generic/base.py:914 +msgid "Certification atribute must be a list or None" +msgstr "" + +#: ../Generic/base.py:920 +msgid "Real cost atribute must be a list or None" +msgstr "" + +#: ../Generic/base.py:926 +msgid "Cost goals atribute must be a list or None" +msgstr "" + +#: ../Generic/base.py:932 +msgid "Cost Planned atribute must be a list or None" +msgstr "" + +#: ../Generic/base.py:1023 +msgid "Measure must be a float number. Type: $1" +msgstr "" + +#: ../Generic/base.py:1034 +msgid "Lines must be a list" +msgstr "" + +#: ../Generic/base.py:1037 +msgid "Line must be a MeasureLine objetc" +msgstr "" + +#: ../Generic/base.py:1045 +msgid "Factor must be a float number |$1|" +msgstr "" + +#: ../Generic/base.py:1057 +msgid "Yield must be a float number" +msgstr "" + +#: ../Generic/base.py:1068 +msgid "Fixed must be boolean object" +msgstr "" + +#: ../Generic/base.py:1137 +msgid "Type must be M or A. Type: $1" +msgstr "" + +#: ../Generic/base.py:1269 +msgid " Parcial Subtotal must be a float number. Parcial: $1" +msgstr "" + +#: ../Generic/base.py:1276 +msgid " Acumulated Subtotal must be a float number. Parcial: $1" +msgstr "" + +#: ../Generic/base.py:1311 +msgid "Invalid measure line type ($1)" +msgstr "" + +#: ../Generic/base.py:1316 +msgid "Measure Comment must be a string ($1)" +msgstr "" + +#: ../Generic/base.py:1322 +msgid "Invalid Measure Units ($1)" +msgstr "" + +#: ../Generic/base.py:1334 +msgid "Invalid Measure length ($1)" +msgstr "" + +#: ../Generic/base.py:1346 +msgid "Invalid Measure Width ($1)" +msgstr "" + +#: ../Generic/base.py:1358 +msgid "Invalid Measure Height ($1)" +msgstr "" + +#: ../Generic/base.py:1369 +msgid "Formula must be a string ($1)" +msgstr "" + +#: ../Generic/base.py:1372 +msgid "There is invalid charactersin formula ($1)" +msgstr "" + +#: ../Generic/base.py:1437 ../Generic/base.py:2406 +msgid "'a' value must be a float number" +msgstr "" + +#: ../Generic/base.py:1441 ../Generic/base.py:2410 +msgid "'b' value must be a float number" +msgstr "" + +#: ../Generic/base.py:1445 ../Generic/base.py:2414 +msgid "'c' value must be a float number" +msgstr "" + +#: ../Generic/base.py:1449 ../Generic/base.py:2418 +msgid "'d' value must be a float number" +msgstr "" + +#: ../Generic/base.py:1477 ../Generic/base.py:2446 +msgid "Invalid formula" +msgstr "" + +#: ../Generic/base.py:1727 +msgid "sheet_dict must be a dictionay" +msgstr "" + +#: ../Generic/base.py:1744 ../Generic/base.py:1750 +msgid "sheet field must be a string" +msgstr "" + +#: ../Generic/base.py:1746 +msgid "section_dict must be a dictionary" +msgstr "" + +#: ../Generic/base.py:1752 +msgid "sheet section must be a string" +msgstr "" + +#: ../Generic/base.py:1754 +msgid "sheet paragraph must be a string" +msgstr "" + +#: ../Generic/base.py:1992 +msgid "Owner must be a string" +msgstr "" + +#: ../Generic/base.py:2008 +#, python-format +msgid "Invalid Date: %s" +msgstr "" + +#: ../Generic/base.py:2019 +msgid "Comment must be a string" +msgstr "" + +#: ../Generic/base.py:2035 +msgid "Budget type must be 1, 2, 3 or 4." +msgstr "" + +#: ../Generic/base.py:2047 +msgid "Certificate order must be a integer." +msgstr "" + +#: ../Generic/base.py:2062 +msgid "Budget certificate Date must be a valid Date." +msgstr "" + +#: ../Generic/base.py:2076 +msgid "Invalid title list format" +msgstr "" + +#: ../Generic/base.py:2105 +msgid "Invalid Index Title" +msgstr "" + +#: ../Generic/base.py:2140 +msgid "Decimal Key error" +msgstr "" + +#: ../Generic/base.py:2176 +msgid "Invalid Percentage key" +msgstr "" + +#: ../Generic/base.py:2291 +msgid "Invalid parent code: $1" +msgstr "" + +#: ../Generic/base.py:2294 +msgid "Invalid child code: $1" +msgstr "" + +#: ../Generic/base.py:2297 +msgid "Invalid position in measure $1, in code $2" +msgstr "" + +#: ../Generic/base.py:2305 +msgid "" +"Circular Decomposition, parent code: $1, child code: $2, repeated code: $3" +msgstr "" + +#: ../Generic/base.py:2360 ../Generic/base.py:2372 +msgid "" +"Error: Invalid child position in decomposition. Parent code: $1 Child code: " +"$2 Position: $3" +msgstr "" + +#: ../Generic/base.py:2366 +msgid "Error: Empty child code. Parent code: $1 Position: $2" +msgstr "" + +#: ../Generic/base.py:2457 +msgid "Invalid code" +msgstr "" + +#: ../Generic/base.py:2467 +msgid "Invalid record: $1" +msgstr "" + +#: ../Generic/base.py:2530 +msgid "Only can be one root record" +msgstr "" + +#: ../Generic/base.py:2624 ../Generic/base.py:2630 +msgid "This record does not exits" +msgstr "" + +#: ../Generic/base.py:2627 +msgid "Path item must be a integer" +msgstr "" + +#: ../Generic/base.py:2632 +msgid "Path must be a not empty tuple: $1" +msgstr "" + +#: ../Generic/base.py:2683 +msgid "The sheet code must be a string" +msgstr "" + +#: ../Generic/base.py:2685 +msgid "The sheet title must be a string" +msgstr "" + +#: ../Generic/base.py:2693 +msgid "The sheet sections must be a dictionary" +msgstr "" + +#: ../Generic/base.py:2698 +msgid "The field code must be a string" +msgstr "" + +#: ../Generic/base.py:2700 +msgid "The field title must be a string" +msgstr "" + +#: ../Generic/base.py:2708 +msgid "The sheet field must be a dictionary" +msgstr "" + +#: ../Generic/base.py:2713 +msgid "The paragraph code must be a string" +msgstr "" + +#: ../Generic/base.py:2715 +msgid "The paragraph text must be a string" +msgstr "" + +#: ../Generic/base.py:2723 +msgid "The paragraph dict must be a dictionary" +msgstr "" + +#: ../Generic/base.py:2728 ../Generic/base.py:2752 ../Generic/base.py:2882 +#: ../Generic/base.py:2906 ../Generic/base.py:2928 +msgid "The record_code code must be a string" +msgstr "" + +#: ../Generic/base.py:2730 +msgid "The field must be a string" +msgstr "" + +#: ../Generic/base.py:2732 +msgid "The section dict must be a dictionary" +msgstr "" + +#: ../Generic/base.py:2736 +msgid "" +"Error: The budget do not have this record code and can not be added the " +"sheet text in the field $1. Record Code: $2" +msgstr "" + +#: ../Generic/base.py:2754 +msgid "The filename must be a string" +msgstr "" + +#: ../Generic/base.py:2758 +msgid "" +"Error: The budget do not have the record code $1 and can not be added the " +"file: $2" +msgstr "" + +#: ../Generic/base.py:2768 +msgid "The company code must be a string" +msgstr "" + +#: ../Generic/base.py:2770 +msgid "The summary must be a string" +msgstr "" + +#: ../Generic/base.py:2772 ../Generic/base.py:2800 +msgid "The name must be a string" +msgstr "" + +#: ../Generic/base.py:2774 +msgid "The name must be a list" +msgstr "" + +#: ../Generic/base.py:2778 +msgid "The office must be a list" +msgstr "" + +#: ../Generic/base.py:2780 +msgid "The office must be a 10 items list" +msgstr "" + +#: ../Generic/base.py:2783 +msgid "This office item must be a string" +msgstr "" + +#: ../Generic/base.py:2787 +msgid "This office item must be a list" +msgstr "" + +#: ../Generic/base.py:2802 +msgid "The web must be a string" +msgstr "" + +#: ../Generic/base.py:2804 +msgid "The email must be a string" +msgstr "" + +#: ../Generic/base.py:2814 +msgid "The tecnical info code must be a string" +msgstr "" + +#: ../Generic/base.py:2816 +msgid "The tecnical info description must be a string" +msgstr "" + +#: ../Generic/base.py:2819 +msgid "The tecnical info unit must be a string" +msgstr "" + +#: ../Generic/base.py:2866 +msgid "The label must be a string" +msgstr "" + +#: ../Generic/base.py:2884 +msgid "The parametric select comment must be a string" +msgstr "" + +#: ../Generic/base.py:2887 +msgid "" +"Error: The budget do not have the record code $1 and can not be added the " +"Parametric select comment: $2" +msgstr "" + +#: ../Generic/base.py:2894 +msgid "" +"Error: The Record $1 is not a Parametric Record and can not have Parametric " +"comment" +msgstr "" + +#: ../Generic/base.py:2908 +msgid "The summary record must be a string" +msgstr "" + +#: ../Generic/base.py:2910 +msgid "" +"Error: The budget do not have the record code $1 and can not be seted the " +"summary: $2" +msgstr "" + +#: ../Generic/base.py:2916 +msgid "" +"Error: The Record $1 is not a Parametric Record and can not have Parametric " +"summary" +msgstr "" + +#: ../Generic/base.py:2930 +msgid "The text record must be a string" +msgstr "" + +#: ../Generic/base.py:2932 +msgid "" +"Error: The budget do not have the record code $1 and can not be seted the " +"text: $2" +msgstr "" + +#: ../Generic/base.py:2938 +msgid "" +"Error: The Record $1 is not a Parametric Record and can not have Parametric " +"text" +msgstr "" + +#: ../Generic/base.py:3396 +msgid "Invalid Hierarchy ($1) The hierarchy must be -1, 0, 1 or 2" +msgstr "" + +#: ../Generic/base.py:3403 +msgid "Invalid type ($1),the type must be (empty string,0,1,2,3)" +msgstr "" + +#: ../Generic/base.py:3412 +msgid "" +"Invalid subtype ($1), The subtype must one in (empty string, EA, EU, EC, EF, " +"OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)" +msgstr "" + +#: ../Generic/fiebdc.py:151 +msgid "Invalid code, it must be a string" +msgstr "" + +#: ../Generic/fiebdc.py:157 +msgid "The code '$1' have invalid characters." +msgstr "" + +#: ../Generic/fiebdc.py:170 +msgid "The code '$1' contains special characters repeated." +msgstr "" + +#: ../Generic/fiebdc.py:391 +msgid "" +"The 'V' record (Property and Version) must be the first record in the file " +"but it is the number: $1" +msgstr "" + +#: ../Generic/fiebdc.py:394 +msgid "The default values were taken and this V record is ignored" +msgstr "" + +#: ../Generic/fiebdc.py:428 +#, python-format +msgid "FIEBDC format: %s" +msgstr "" + +#: ../Generic/fiebdc.py:437 +#, python-format +msgid "FIEBDC file generated by %s" +msgstr "" + +#: ../Generic/fiebdc.py:776 +msgid "Record C without a valid code" +msgstr "" + +#: ../Generic/fiebdc.py:852 ../Generic/fiebdc.py:864 ../Generic/fiebdc.py:892 +msgid "Incorrect type ($1) in the code $2" +msgstr "" + +#: ../Generic/fiebdc.py:943 +msgid "" +"ValueError loadig the descomposition of the record $1, the factor of the " +"child $2 must be a float number and can not be $3, seted default value 1.0" +msgstr "" + +#: ../Generic/fiebdc.py:954 +msgid "" +"ValueError loading the descomposition of the record $1, the yield of the " +"child $2, must be a float number and cannot be $3, seted default value 1.0" +msgstr "" + +#: ../Generic/fiebdc.py:1041 +msgid "Invalid codes in $1 record, codes $2" +msgstr "" + +#: ../Generic/fiebdc.py:1045 +msgid "Empty child code in $1 record, codes: $2" +msgstr "" + +#: ../Generic/fiebdc.py:1058 +msgid "Invalid path in $1 record, codes $2" +msgstr "" + +#: ../Generic/fiebdc.py:1069 +msgid "Invalid Total Measure value in $1 record, codes $2" +msgstr "" + +#: ../Generic/fiebdc.py:1089 +msgid "" +"The comment is not a formula or its have invalid characters, in the $1 " +"record, codes $2" +msgstr "" + +#: ../Generic/fiebdc.py:1403 ../Generic/fiebdc.py:1657 +msgid "The file $1 do not exist" +msgstr "" + +#: ../Generic/fiebdc.py:1763 ../Generic/fiebdc.py:1770 +msgid "PyArq hates parametric DLLs" +msgstr "" + +#: ../Generic/fiebdc.py:1980 +msgid "Loading file $1" +msgstr "" + +#: ../Generic/fiebdc.py:2000 +msgid "This codepage do not exist in FIEBDC3! Default codepage: $1" +msgstr "" + +#: ../Generic/fiebdc.py:2004 +msgid "This V record dot have a codepage! Default codepage: $1" +msgstr "" + +#: ../Generic/fiebdc.py:2008 +msgid "Not 'V' record in File! Default codepage: $1" +msgstr "" + +#: ../Generic/fiebdc.py:2049 +msgid "Cancelled process" +msgstr "" + +#: ../Generic/fiebdc.py:2052 +msgid "Time to load: $1 seconds" +msgstr "" + +#: ../Generic/fiebdc.py:2054 +msgid "Records/Valid Records: $1/$2" +msgstr "" + +#: ../Generic/fiebdc.py:2057 +msgid "$1 unsuported record type O: Comercial Relationship" +msgstr "" + +#: ../Generic/fiebdc.py:2060 +msgid "This file is not a valid FIBDC3 file" +msgstr "" + +#: ../Generic/fiebdc.py:2097 +msgid "Testing budget ..." +msgstr "" + +#: ../Generic/fiebdc.py:2115 +msgid "End Test" +msgstr "" + +#: ../Gtk/gui.py:69 +msgid "The icon file does not exist. '$1'" +msgstr "" + +#: ../Gtk/gui.py:75 +msgid "pyArq-Presupuestos running on $1" +msgstr "" + +#: ../Gtk/gui.py:164 +msgid "_File" +msgstr "" + +#: ../Gtk/gui.py:165 +msgid "_Import Fiebdc" +msgstr "" + +#: ../Gtk/gui.py:167 +msgid "_Close" +msgstr "" + +#: ../Gtk/gui.py:169 +msgid "_View" +msgstr "" + +#: ../Gtk/gui.py:170 +msgid "_Text" +msgstr "" + +#: ../Gtk/gui.py:172 +msgid "_Test" +msgstr "" + +#: ../Gtk/gui.py:174 +msgid "Import Fiebdc _price database" +msgstr "" + +#: ../Gtk/gui.py:176 +msgid "_Open price database" +msgstr "" + +#: ../Gtk/gui.py:248 +msgid "Saving file: $1" +msgstr "" + +#: ../Gtk/gui.py:253 +msgid "Saving time: $1 seconds" +msgstr "" + +#: ../Gtk/gui.py:321 +msgid "Loading file: $1:" +msgstr "" + +#: ../Gtk/gui.py:468 ../Gtk/importFiebdc.py:224 +msgid "Time: 0s" +msgstr "" + +#: ../Gtk/gui.py:532 ../Gtk/importFiebdc.py:303 +msgid "Time: $1" +msgstr "" + +#: ../Gtk/gui.py:809 +msgid "The value must be a list" +msgstr "" + +#: ../Gtk/gui.py:812 +msgid "Incorrect len" +msgstr "" + +#: ../Gtk/gui.py:840 +msgid "Incorrect item $1" +msgstr "" + +#: ../Gtk/gui.py:854 +msgid "The budget does not have the path record: $1" +msgstr "" + +#: ../Gtk/gui.py:989 +msgid "Decomposition" +msgstr "" + +#: ../Gtk/gui.py:990 ../Gtk/gui.py:2006 +msgid "Description" +msgstr "" + +#: ../Gtk/gui.py:991 ../Gtk/gui.py:2008 +msgid "Measure" +msgstr "" + +#: ../Gtk/gui.py:992 +msgid "Sheet of Conditions" +msgstr "" + +#: ../Gtk/gui.py:993 +msgid "Files" +msgstr "" + +#: ../Gtk/gui.py:994 +msgid "Companies" +msgstr "" + +#: ../Gtk/gui.py:1355 +msgid "The item must be a widget object." +msgstr "" + +#: ../Gtk/gui.py:1361 +msgid "Invalid orientation." +msgstr "" + +#: ../Gtk/gui.py:1736 ../Gtk/gui.py:2370 ../Gtk/gui.py:3780 +msgid "Argument must be a Budget object" +msgstr "" + +#: ../Gtk/gui.py:1745 +msgid "DecompositionList.__init__: Record path can not be None" +msgstr "" + +#: ../Gtk/gui.py:1776 +msgid "a" +msgstr "" + +#: ../Gtk/gui.py:2003 ../Gtk/gui.py:3840 +msgid "Code" +msgstr "" + +#: ../Gtk/gui.py:2004 +msgid "Unit" +msgstr "" + +#: ../Gtk/gui.py:2010 +msgid "Price" +msgstr "" + +#: ../Gtk/gui.py:2012 +msgid "Amount" +msgstr "" + +#: ../Gtk/gui.py:2024 ../Gtk/gui.py:2502 +msgid "Invalid path" +msgstr "" + +#: ../Gtk/gui.py:2375 +msgid "Record path must be a tuple" +msgstr "" + +#: ../Gtk/gui.py:2519 +msgid "measure must be a Measure object. Type: $1" +msgstr "" + +#: ../Gtk/gui.py:2530 ../Gtk/gui.py:3855 ../Gtk/gui.py:4182 +msgid "Type" +msgstr "" + +#: ../Gtk/gui.py:2531 +msgid "Comment" +msgstr "" + +#: ../Gtk/gui.py:2532 +msgid "" +"N\n" +"(a)" +msgstr "" + +#: ../Gtk/gui.py:2533 +msgid "" +"Length\n" +"(b)" +msgstr "" + +#: ../Gtk/gui.py:2534 +msgid "" +"Width\n" +"(c)" +msgstr "" + +#: ../Gtk/gui.py:2535 +msgid "" +"Height\n" +"(d)" +msgstr "" + +#: ../Gtk/gui.py:2536 +msgid "Formula" +msgstr "" + +#: ../Gtk/gui.py:2537 +#, python-format +msgid "" +"Parcial\n" +"[%s]" +msgstr "" + +#: ../Gtk/gui.py:2538 +msgid "Subtotal" +msgstr "" + +#: ../Gtk/gui.py:2946 ../Gtk/gui.py:2968 +msgid "Description text of the record $1" +msgstr "" + +#: ../Gtk/gui.py:3125 +msgid "Sheet of Conditions of the record $1" +msgstr "" + +#: ../Gtk/gui.py:3145 +msgid "Field" +msgstr "" + +#: ../Gtk/gui.py:3167 +msgid "Section" +msgstr "" + +#: ../Gtk/gui.py:3320 +msgid "Sheet2 of Conditions of the record $1" +msgstr "" + +#: ../Gtk/gui.py:3696 +msgid "$1 text" +msgstr "" + +#: ../Gtk/gui.py:3841 +msgid "Code that define the company" +msgstr "" + +#: ../Gtk/gui.py:3842 +msgid "Summary" +msgstr "" + +#: ../Gtk/gui.py:3843 +msgid "Summary of the company name" +msgstr "" + +#: ../Gtk/gui.py:3844 ../Gtk/gui.py:3860 +msgid "Name" +msgstr "" + +#: ../Gtk/gui.py:3845 +msgid "Complete name" +msgstr "" + +#: ../Gtk/gui.py:3846 +msgid "CIF" +msgstr "" + +#: ../Gtk/gui.py:3847 +msgid "Fiscal identifier number" +msgstr "" + +#: ../Gtk/gui.py:3848 +msgid "Web" +msgstr "" + +#: ../Gtk/gui.py:3849 +msgid "Company web page" +msgstr "" + +#: ../Gtk/gui.py:3850 +msgid "Email" +msgstr "" + +#: ../Gtk/gui.py:3851 +msgid "Company email" +msgstr "" + +#: ../Gtk/gui.py:3856 +msgid "" +"Type of Office:\n" +" C: Central office\n" +" D: Local office\n" +" R: Performer" +msgstr "" + +#: ../Gtk/gui.py:3861 +msgid "Office name" +msgstr "" + +#: ../Gtk/gui.py:3862 +msgid "Address" +msgstr "" + +#: ../Gtk/gui.py:3863 +msgid "Postal code" +msgstr "" + +#: ../Gtk/gui.py:3864 +msgid "Town" +msgstr "" + +#: ../Gtk/gui.py:3865 +msgid "Province" +msgstr "" + +#: ../Gtk/gui.py:3866 +msgid "Country" +msgstr "" + +#: ../Gtk/gui.py:3867 +msgid "Phone" +msgstr "" + +#: ../Gtk/gui.py:3868 +msgid "Phone numbers of the office" +msgstr "" + +#: ../Gtk/gui.py:3869 +msgid "Fax" +msgstr "" + +#: ../Gtk/gui.py:3870 +msgid "Fax numbers of the office" +msgstr "" + +#: ../Gtk/gui.py:3871 +msgid "Contact person" +msgstr "" + +#: ../Gtk/gui.py:3872 +msgid "Contact persons in the office" +msgstr "" + +#: ../Gtk/gui.py:3876 +msgid "Unknow Option Type" +msgstr "" + +#: ../Gtk/gui.py:4120 +msgid "Boolean" +msgstr "" + +#: ../Gtk/gui.py:4121 +msgid "Integer" +msgstr "" + +#: ../Gtk/gui.py:4122 +msgid "Text" +msgstr "" + +#: ../Gtk/gui.py:4123 +msgid "Color" +msgstr "" + +#: ../Gtk/gui.py:4124 +msgid "List" +msgstr "" + +#: ../Gtk/gui.py:4156 +msgid "Option name" +msgstr "" + +#: ../Gtk/gui.py:4169 +msgid "Value" +msgstr "" + +#: ../Gtk/gui.py:4207 +msgid "Description:" +msgstr "" + +#: ../Gtk/gui.py:4369 +msgid "Option values must be strings" +msgstr "" + +#: ../Gtk/gui.py:4371 +msgid "Option must be a tuple with 4 items" +msgstr "" + +#: ../Gtk/gui.py:4373 +msgid "Option list must be a list" +msgstr "" + +#: ../Gtk/gui.py:4393 +msgid "Icorrect type, must be boolean" +msgstr "" + +#: ../Gtk/gui.py:4398 +msgid "Icorrect type, must be integer" +msgstr "" + +#: ../Gtk/gui.py:4411 +msgid "Icorrect type, must be string" +msgstr "" + +#: ../Gtk/gui.py:4424 +msgid "Icorrect type, must be list" +msgstr "" + +#: ../Gtk/gui.py:4430 +msgid "Icorrect type, must be a parseable color" +msgstr "" + +#: ../Gtk/gui.py:4438 +msgid "Type must be boolean, integer, string or color" +msgstr "" + +#: ../Gtk/gui.py:4441 +msgid "Value must be in the option dict" +msgstr "" + +#: ../Gtk/gui.py:4443 +msgid "Values must be a dict" +msgstr "" + +#: ../Gtk/gui.py:4501 +msgid "No file selected" +msgstr "" + +#: ../Gtk/gui.py:4503 +msgid "The filename must have durus extension" +msgstr "" + +#: ../Gtk/importFiebdc.py:89 +msgid "Open File" +msgstr "" + +#: ../Gtk/importFiebdc.py:139 +msgid "The file must have 'bc3' extension" +msgstr "" + +#: ../Gtk/importFiebdc.py:212 +msgid "Loading file ..." +msgstr "" + +#: ../Gtk/importFiebdc.py:236 +msgid "Cancel" +msgstr ""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyArq-Presupuestos Sun Oct 31 20:07:33 2010 +0100 @@ -0,0 +1,50 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## File presupuestos.py +## This file is part of pyArq-Presupuestos. +## +## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## <miguelangel@obraencurso.es> +## +## pyArq-Presupuestos 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. +## +## pyArq-Presupuestos 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 <http://www.gnu.org/licenses/>. + +def _translate(): + """def translate() + + Translates the program using gettext module + """ + _app = "pyArq-Presupuestos" + _dir = globals.path["APPDATA"] + "/mo/" + print _dir + gettext.install(_app, _dir, unicode=1) + +def _run_gui(): + """def _run_gui + + Shows main window and starts the GTK+ event processing loop. + """ + _window = gui.MainWindow() + +# Run pyArq-Presupuestos +if __name__ == "__main__": + # Modules + import gettext + import sys + from Generic import globals + # take path to find mo file + _path = sys.path[0] + globals.path["APPDATA"]= _path + _translate() + from Gtk import gui + _run_gui()