diff options
author | Cristian Garcia <cristian99garcia@gmail.com> | 2013-05-06 17:33:31 (GMT) |
---|---|---|
committer | Cristian Garcia <cristian99garcia@gmail.com> | 2013-05-06 17:33:31 (GMT) |
commit | ac174acfe7afe947c0f48ed11132159723358001 (patch) | |
tree | 573e5701664216f12a070338f45b030f4396722b |
Agregando archivos
-rw-r--r-- | CristianEdit.py | 92 | ||||
-rw-r--r-- | CristianEdit/Creditos.py | 746 | ||||
-rw-r--r-- | CristianEdit/Creditos.pyc | bin | 0 -> 37510 bytes | |||
-rw-r--r-- | CristianEdit/CristianEdit.py | 694 | ||||
-rw-r--r-- | CristianEdit/CristianEdit.pyc | bin | 0 -> 20622 bytes | |||
-rw-r--r-- | CristianEdit/Run.py | 45 | ||||
-rw-r--r-- | CristianEdit/Run.pyc | bin | 0 -> 853 bytes | |||
-rw-r--r-- | CristianEdit/Terminal.py | 129 | ||||
-rw-r--r-- | CristianEdit/Terminal.pyc | bin | 0 -> 3661 bytes | |||
-rw-r--r-- | CristianEdit/__init__.py | 1 | ||||
-rw-r--r-- | CristianEdit/__init__.pyc | bin | 0 -> 140 bytes | |||
-rw-r--r-- | CristianEdit/objetos.py | 1476 | ||||
-rw-r--r-- | CristianEdit/objetos.pyc | bin | 0 -> 46349 bytes | |||
-rw-r--r-- | CristianEdit/objetos.py~ | 1474 | ||||
-rw-r--r-- | Iconos/CristianEdit.png | bin | 0 -> 86183 bytes | |||
-rw-r--r-- | Iconos/CristianEdit.svg | 180 |
16 files changed, 4837 insertions, 0 deletions
diff --git a/CristianEdit.py b/CristianEdit.py new file mode 100644 index 0000000..704341a --- /dev/null +++ b/CristianEdit.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# CristianEdit.py por: +# Cristian García <cristian99garcia@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import sys +import os + +import gi +from gi.repository import Gtk + +import CristianEdit +from CristianEdit.CristianEdit import CristianEdit +from CristianEdit import objetos + + +class Ventana(Gtk.Window): + + def __init__(self, direcciones): + + super(Ventana, self).__init__() + + self.set_title('CristianEdit') + self.set_icon_from_file(os.path.join(os.path.dirname(__file__), + 'Iconos/CristianEdit.svg')) + + self.set_size_request(640, 480) + self.set_position(Gtk.WindowPosition.CENTER) + + self.socket = Gtk.Socket() + self.add(self.socket) + self.cristianedit = CristianEdit() + self.socket.add_id(self.cristianedit.get_id()) + + self.show_all() + self.realize() + self.cristianedit.setup_init(direcciones) + + self.connect('destroy', self.salir) + self.connect('key-press-event', self.cristianedit.tecla) + + def salir(self, widget): + """Consultar al plug CristianEdit sí se puede salir, + en ese caso le pasa Gtk.main_quit(), de lo + contrario consulta al usuario sí guardar o no + antes de cerrar""" + + buffers, direcciones, views = self.cristianedit.get_if_exit() + for buffer in buffers: + if buffer.get_modified(): + + numero = buffers.index(buffer) + view = views[numero] + direccion = direcciones[numero] + dialogo = objetos.dialogo_cerrar(direccion, buffer, + self.cristianedit, 'cerrar') + numero = 0 + + self.cristianedit.guardar_configuracion() + Gtk.main_quit() + +if __name__ == '__main__': + if len(sys.argv) >= 2: + lista = list(sys.argv)[1:] + + else: + lista = None + + direcciones = [] + + if lista: + for lugar in lista: + if os.path.exists(lugar): + direcciones.append(lugar) + + Ventana(direcciones) + Gtk.main() diff --git a/CristianEdit/Creditos.py b/CristianEdit/Creditos.py new file mode 100644 index 0000000..da16e23 --- /dev/null +++ b/CristianEdit/Creditos.py @@ -0,0 +1,746 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +from gi.repository import Gtk +from gi.repository import Pango + +licencia = '''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>.''' + + +class Creditos(Gtk.Dialog): + + def __init__(self, padre): + + Gtk.Dialog.__init__(self, title='Créditos', parent=padre) + + label = Gtk.Label('CristianEdit 2') + label.modify_font(Pango.FontDescription('Ubuntu bold 40')) + + notebook = Gtk.Notebook() + + label1 = Gtk.Label('Créditos') + label2 = Gtk.Label('Licencia') + + vbox1 = Gtk.VBox() + vbox2 = Gtk.VBox() + + self.vbox.add(label) + self.vbox.pack_start(notebook, True, True, 10) + + creador = Gtk.Label('CristianEdit creado por:\n\t Cristian García') + datos = Gtk.Label( + 'Mis datos:\n\t Correo electrónico: <cristian99garcia@gmial.com>') + + imagen = Gtk.Image() + imagen.set_from_pixbuf(padre.get_icon()) + + gracias = Gtk.Label('¡Gracias por utlizar CristianEdit2!') + v_licencia = Gtk.TextView() + scroll1 = Gtk.ScrolledWindow() + scroll1.add_with_viewport(imagen) + + v_licencia.set_editable(False) + v_licencia.get_buffer().set_text(licencia) + + scroll = Gtk.ScrolledWindow() + scroll.add(v_licencia) + + vbox1.pack_start(creador, False, False, 10) + vbox1.pack_start(datos, False, False, 0) + vbox1.pack_start(scroll1, True, True, 0) + vbox1.pack_end(gracias, False, False, 0) + + vbox2.pack_start(scroll, True, True, 0) + + notebook.append_page(vbox1, label1) + notebook.append_page(vbox2, label2) + + labels = [label, creador, datos, gracias] + + for x in labels: + x.set_selectable(True) + + boton_cerrar = Gtk.Button(None, Gtk.STOCK_CLOSE) + boton_cerrar.connect('clicked', self.cerrar) + self.action_area.add(boton_cerrar) + + self.show_all() + + def cerrar(self, widget): + + self.destroy() diff --git a/CristianEdit/Creditos.pyc b/CristianEdit/Creditos.pyc Binary files differnew file mode 100644 index 0000000..28b5008 --- /dev/null +++ b/CristianEdit/Creditos.pyc diff --git a/CristianEdit/CristianEdit.py b/CristianEdit/CristianEdit.py new file mode 100644 index 0000000..2835c13 --- /dev/null +++ b/CristianEdit/CristianEdit.py @@ -0,0 +1,694 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 -*- + +# CristianEdit.py por: +# Cristian García <cristian99garcia@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import objetos +import os +import ConfigParser +import time +import datetime +import Run +import thread + +from gi.repository import Gtk +from gi.repository import GObject +from gi.repository import Pango +from gi.repository import Gdk + +datos = os.path.expanduser('~/.cristianedit') +if not os.path.exists(datos): + os.mkdir(datos) + +configuracion = os.path.join(datos, 'configuracion.cfg') + +if not os.path.exists(configuracion): + + f = open(configuracion, 'w') + f.write('''[datos] +enumeracion = True +fuente = Monospace +margen = 80 +is_margen = +ajuste = True +ajuste_palabras = +tabulador = 8 +insertar_espacios = +sangria = +recientes = +tema = classic''') + + f.close() + + +class CristianEdit(Gtk.Plug): + """Clase principal""" + + def __init__(self): + """Inicia la clase""" + + Gtk.Plug.__init__(self) + + self.buffers = None + self.views = None + self.lugares = None + self.etiquetas = None + self.barras_de_abajo = None + self.funciones = None + + self.fuente = None + self.enumeracion = False + self.margen = None + self.is_margen = None + self.ajuste = None + self.ajuste_palabras = None + self.tabulador = None + self.insertar_espacios = False + self.sangria = None + self.tema = None + + self.vbox = None + self.menu = None + self.toolbar = None + self.notebook = None + + self.show_all() + self.connect('embedded', self.embed_event) + + def tecla(self, widget, event): + """Saber sí elusuario presionó una tecla""" + + tecla = Gdk.keyval_name(event.keyval) + + if tecla == 'F5': + self.ejecutar(None) + + if tecla == 'Escape': + self.get_parent().get_parent().salir(None) + + def embed_event(self, widget): + + print 'CristianEdit 2 embebido' + + def setup_init(self, direcciones): + """Se crea la interfaz grafica, + se setea y empaqueta todo.""" + + #****** Listas >>> ****** + self.buffers = [] + self.views = [] + self.lugares = ['Sin dirección'] + self.etiquetas = [] + self.barras_de_abajo = [] + self.funciones = [self.guardar, # Guarda archivo + self.pagina_nueva, # Crea una página nueva + self.deshacer, # Deshacer cambios + self.rehacer, # Rahacer cambios + self.ejecutar, # Ejecuta el archivo + self.seleccionar_fuente, # Seleccionar fuente + self.configuraciones, # Configuraciones + self.buscar_changed, + self.buscar_enter] + + #****** <<< Listas ****** + + #****** Configuraciones >>> ****** + self.abrir_configuracion() + + #****** <<< Configuraciones ****** + + abrir = Gtk.ToolButton(Gtk.STOCK_OPEN) + + self.vbox = Gtk.VBox() + self.menu = objetos.Menu(self) + hbox_toolbar = Gtk.HBox() + self.toolbar = objetos.Barra(self.funciones, abrir) + self.notebook = objetos.Notebook(self) + + abrir.connect('clicked', self.abrir) + self.notebook.connect('boton-cerrar-clicked', self.cerrar_desde_boton) + + self.vbox.pack_start(self.menu, False, False, 0) + self.vbox.pack_start(hbox_toolbar, False, False, 0) + hbox_toolbar.add(self.toolbar) + self.vbox.pack_start(self.notebook, True, True, 0) + + self.notebook.set_show_tabs(False) + self.pagina_nueva() + self.menu.actualizar_recientes(self.recientes) + + numero = 0 + + if direcciones: + for direccion in direcciones: + if os.path.exists(direccion): + self.abrir(None, direccion) + self.lugares[numero] = direccion + numero += 1 + + self.lugares.remove(self.lugares[-1]) + + self.add(self.vbox) + self.show_all() + + def mostrar_teclado(self, mostrar): + """Muestra un teclado en pantalla""" + + if mostrar: + self.teclado = objetos.Teclado(self) + self.teclado.show_all() + + else: + self.teclado.destroy() + + def cerrar_desde_boton(self, widget, objeto): + """Cierra la pestaña desde el botón de cerrado""" + + numero = self.notebook.page_num(objeto) + + label = self.etiquetas[numero] + view = self.views[numero] + buffer = self.buffers[numero] + barra = self.barras_de_abajo[numero] + lugar = self.lugares[numero] + + if buffer.get_modified(): + objetos.dialogo_cerrar(lugar, buffer, self, None) + + self.etiquetas.remove(label) + self.views.remove(view) + self.buffers.remove(buffer) + self.barras_de_abajo.remove(barra) + + label.destroy() + view.destroy() + barra.destroy() + + self.notebook.borrar_pagina(numero) + + def abrir(self, widget, direccion=None): + """Abrir archivo/s para ver o editar""" + + pagina = self.notebook.get_current_page() + + if not direccion: + navegador = objetos.Navegador('Abrir archivo de Texto', + self, Gtk.FileChooserAction(0), (Gtk.STOCK_OPEN, 1)) + + respuesta = navegador.run() + + if respuesta: + for lugar in navegador.get_filenames(): + if os.path.exists(lugar) and not lugar in self.lugares: + dir, mod, cuen = self.get_sirve(self.lugares[pagina]) + + if not dir or not mod: + self.pagina_nueva() + self.desplazar_al_final() + pagina = self.notebook.get_current_page() + + self.lugares[pagina] = lugar + buffer = self.buffers[pagina] + view = self.views[pagina] + texto = open(lugar, 'r').read() + barra = self.barras_de_abajo[pagina] + combo = barra.get_combo() + escritura = self.get_escritura(lugar) + + self.agregar_a_recientes(lugar) + self.menu.actualizar_recientes(self.recientes) + + buffer.set_text(texto) + buffer.set_modified(False) + buffer.buscar_lenguaje(lugar, combo) + buffer.begin_not_undoable_action() + buffer.end_not_undoable_action() + view.set_editable(escritura) + + nombre = self.lugares[pagina].split('/')[-1] + label = self.etiquetas[pagina] + label.set_text(nombre) + + elif lugar in self.lugares: + numero = self.lugares.index(lugar) + self.notebook.set_current_page(numero) + + navegador.destroy() + + else: + if os.path.exists(direccion) and os.path.isfile(direccion): + texto = open(direccion).read() + dir, mod, cue = self.get_sirve(self.lugares[pagina]) + + if not dir or not mod or not cue: + self.pagina_nueva() + self.desplazar_al_final() + + pagina = self.notebook.get_current_page() + buffer = self.get_buffer() + barra = self.barras_de_abajo[pagina] + combo = barra.get_combo() + view = self.get_view() + escritura = self.get_escritura(direccion) + + self.agregar_a_recientes(direccion) + self.menu.actualizar_recientes(self.recientes) + + buffer.set_text(texto) + buffer.set_modified(False) + buffer.buscar_lenguaje(direccion, combo) + buffer.begin_not_undoable_action() + buffer.end_not_undoable_action() + view.set_editable(escritura) + + self.lugares[pagina] = direccion + nombre = self.lugares[pagina].split('/')[-1] + label = self.etiquetas[pagina] + + label.set_text(nombre) + + def guardar(self, widget, direccion=None): + """Guardar los cambios o por primera vez el + archivo que se está mostrando en el GtkNotebook(). + Sí se guarda por primera vez, se llamará a la + función 'guardar_como()'""" + + pagina = self.notebook.get_current_page() + label = self.etiquetas[pagina] + + if self.lugares[pagina] == 'Sin dirección' and not direccion: + self.guardar_como(None) + + else: + if not direccion: + archivo = open(self.lugares[pagina], 'w') + + else: + archivo = open(direccion, 'w') + self.lugares[pagina] = direccion + label.set_text(direccion.split('/')[-1]) + + self.buffers[pagina].set_modified(False) + + texto = self.get_texto() + archivo.write(texto) + archivo.close() + + def guardar_como(self, widget): + """Guardar copia o por primera vez""" + + pagina = self.notebook.get_current_page() + buffer = self.buffers[pagina] + + self.navegador = objetos.Navegador('Guardar archivo', self, + Gtk.FileChooserAction(1), (Gtk.STOCK_SAVE, 1)) + + respuesta = self.navegador.run() + direccion = self.navegador.get_filename() + + if respuesta == 1: + if not os.path.exists(direccion): + self.lugares[pagina] = direccion + + self.guardar(None, direccion=self.lugares[pagina]) + self.agregar_a_recientes(direccion) + + else: + objetos.dialogo_reemplazar(direccion, buffer, self) + + self.navegador.destroy() + + def estado(self, *args): + """Mantiene informado al usuario sobre el + estado actual del archivo actual""" + + dialogo = objetos.DialogoEstado(self, self.notebook) + dialogo.show_all() + + def get_escritura(self, direccion): + """Devuelve sí se puede editar el archivo""" + + escritura = os.access(direccion, os.W_OK) + return escritura + + def actualizar_b_estado(self, buffer, new_location, mark): + """Actualiza la barra de estado, + con la posisión actual""" + + pagina = self.notebook.get_current_page() + b_estado = self.barras_de_abajo[pagina].get_statusbar() + + b_estado.pop(0) + + buffer = self.buffers[pagina] + iter = buffer.get_iter_at_mark(buffer.get_insert()) + + row = iter.get_line() + col = iter.get_line_offset() + + mensage = 'Línea:%d, Columna:%d' % (row, col) + + b_estado.push(0, mensage) + + def pagina_nueva(self, *args): + """Crea algunos Widgets y llama a la función + 'agregar' de la objetos.Notebook()""" + + barra_inferior = objetos.Barra_Inferior() + combo = barra_inferior.get_combo() + buffer = objetos.Buffer(combo) + view = objetos.View(buffer) + label = Gtk.Label('Sin título') + + combo.connect('changed', self.combo_changed) + buffer.connect('mark-set', self.actualizar_b_estado) + buffer.connect('modified-changed', self.changed_modificado) + label.modify_font(Pango.FontDescription('Arial')) + + self.notebook.agregar(view, label, barra_inferior) + self.buffers.append(buffer) + self.views.append(view) + self.lugares.append('Sin dirección') + self.etiquetas.append(label) + self.barras_de_abajo.append(barra_inferior) + + view.configurar(self.enumeracion, + self.fuente, self.margen, + self.is_margen, self.ajuste, + self.ajuste_palabras, + self.tabulador, self.insertar_espacios, + self.sangria, self.tema) + + self.desplazar_al_final() + self.notebook.set_show_tabs(self.notebook.get_n_pages() > 1) + + self.show_all() + + def combo_changed(self, widget): + """Usa el lenguaje seleccionado""" + + pagina = self.notebook.get_current_page() + buffer = self.buffers[pagina] + nombre = widget.get_active() + lenguajes = widget.get_lenguajes() + lenguaje_manager = widget.get_lenguaje_manager() + + if nombre != 0: + nombre_lenguaje = lenguajes[nombre - 1] + lenguaje = lenguaje_manager.get_language(nombre_lenguaje) + + buffer.set_highlight_syntax(True) + buffer.set_language(lenguaje) + + elif nombre == 0: + buffer.set_highlight_syntax(False) + + def changed_modificado(self, widget): + """Hace una acción para llamar la antensión + del usuario, y así sabrá cuando un archivo + se ha modificado y todaía no se han guardado + los cambios""" + + pagina = self.notebook.get_current_page() + label = self.etiquetas[pagina] + + if widget.get_modified(): + label.modify_font(Pango.FontDescription('bold')) + + else: + label.modify_font(Pango.FontDescription('Arial')) + + def agregar_a_recientes(self, direccion): + """Agrega una dirección a archivos recientes""" + + self.recientes = direccion + ', ' + self.recientes + self.menu.actualizar_recientes(self.recientes) + + def desplazar_al_final(self): + """Selecciona la última página + del Cuderno de Fichas""" + + for x in range(0, len(self.etiquetas)): + self.notebook.next_page() + + def ejecutar(self, widget): + """Ejecuta el archivo actual""" + + buffer = self.get_buffer() + lugar = self.get_direccion() + inicio, fin = buffer.get_bounds() + + thread.start_new_thread(Run.ejecutar, (lugar,)) + time.sleep(0.1) + buffer.select_range(inicio, fin) + + def deshacer(self, widget): + """Deshacer cambios""" + + view = self.get_view() + view.deshacer() + + def rehacer(self, widget): + """Rehacer cambios""" + + view = self.get_view() + view.rehacer() + + def text_hora(self, *args): + """Inserta la fecha y la hora actual, + en el buffer actual""" + + pagina = self.notebook.get_current_page() + buffer = self.buffers[pagina] + dia = datetime.date.today() + fecha = dia.strftime('%d/%m/%y') + hora = time.strftime('%H:%M:%S') + + insertar = buffer.insert_at_cursor(str(fecha + ' ' + hora)) + + def seleccionar_fuente(self, widget): + """Selecciona la fuente de texto""" + + selector = objetos.Selector_de_Fuente(self.fuente) + selector.connect('font-changed', self.set_fuente) + + def set_fuente(self, widget, fuente): + """Establece la información de la variable + 'self.fuente' y establece la fuene de texto + de todos los views""" + + self.fuente = fuente + for view in self.views: + view.modify_font(Pango.FontDescription(self.fuente)) + + def configuraciones(self, widget): + """Abre un díalogo con configuraciones""" + + configurador = objetos.Configuraciones(self, self.enumeracion, + self.margen, self.is_margen, + self.ajuste, + self.ajuste_palabras, + self.tabulador, + self.insertar_espacios, + self.sangria, + self.tema) + + configurador.show_all() + + def get_view(self): + """Devuelve el view actual""" + + pagina = self.notebook.get_current_page() + view = self.views[pagina] + return view + + def get_buffer(self): + """Devuelve el buffer actual""" + + pagina = self.notebook.get_current_page() + buffer = self.buffers[pagina] + return buffer + + def get_direccion(self): + """Devuelve, la dirección acutal""" + + pagina = self.notebook.get_current_page() + lugar = self.lugares[pagina] + return lugar + + def get_direccion(self): + """Devuelve la dirección del buffer actual""" + + pagina = self.notebook.get_current_page() + direccion = self.lugares[pagina] + return direccion + + def get_fuente(self): + + return self.fuente + + def get_sirve(self, direccion): + """Devuelve si el GtkSourceView() actual + sirve para abrir un archivo o si se necesita + crear una página nueva en el cuaderno de fichas""" + + pagina = self.notebook.get_current_page() + + if direccion == 'Sin dirección': + sirve1 = True + + else: + sirve1 = False + + if not self.buffers[pagina].get_modified(): + sirve2 = True + + else: + sirve2 = False + + if self.buffers[pagina].get_char_count() == 0: + sirve3 = True + + else: + sirve3 = False + + return sirve1, sirve2, sirve3 + + def get_texto(self): + """Obtiene el texto del buffer en la + pestaña actual del cuaderno de fichas""" + + pagina = self.notebook.get_current_page() + start, end = self.buffers[pagina].get_bounds() + return self.buffers[pagina].get_text(start, end, False) + + def set_configuracion(self, lista): + """Establece la configuración según datos de una lista""" + + self.enumeracion = lista[0] + self.margen = lista[1] + self.is_margen = lista[2] + self.ajuste = lista[3] + self.ajuste_palabras = lista[4] + self.tabulador = lista[5] + self.insertar_espacios = lista[6] + self.sangria = lista[7] + self.tema = lista[8] + for view in self.views: + view.configurar(self.enumeracion, + self.fuente, self.margen, + self.is_margen, self.ajuste, + self.ajuste_palabras, + self.tabulador, + self.insertar_espacios, + self.sangria, self.tema) + + self.guardar_configuracion() + + def get_if_exit(self): + """Obtiene el estado de modificación de cada + buffer de la lista de buffers, sí están modificados + para consultar al usuario se desea guardar antes + de cerrarlos o no""" + + return self.buffers, self.lugares, self.views + + def buscar_changed(self, widget): + """Busca texto en el buffer actual por + cada cambio que se haga en la entrada de texto""" + + buffer = self.get_buffer() + view = self.get_view() + texto = widget.get_text() + + view.buscar_texto(texto) + + def buscar_enter(self, widget, icon_position=None, event=None): + """Busca texto en el buffer actual y + selecciona la siguiente coincidecia""" + + buffer = self.get_buffer() + view = self.get_view() + texto = widget.get_text() + + view.buscar_texto(texto, enter=True) + + def guardar_configuracion(self, *args): + """Guarda la configuración en el archivo 'configuracion.cfg'""" + + cfg = ConfigParser.ConfigParser() + + cfg.add_section('datos') + + self.guardar_dato('enumeracion', self.enumeracion, cfg) + cfg.set('datos', 'fuente', self.fuente) + cfg.set('datos', 'margen', self.margen) + self.guardar_dato('is_margen', self.is_margen, cfg) + self.guardar_dato('ajuste', self.ajuste, cfg) + self.guardar_dato('ajuste_palabras', self.ajuste_palabras, cfg) + cfg.set('datos', 'tabulador', self.tabulador) + self.guardar_dato('insertar_espacios', self.insertar_espacios, cfg) + self.guardar_dato('sangria', self.sangria, cfg) + cfg.set('datos', 'recientes', self.recientes) + cfg.set('datos', 'tema', self.tema) + + f = open(configuracion, 'w') + cfg.write(f) + f.close() + + def guardar_dato(self, cadena, dato, archivo): + + if dato: + archivo.set('datos', cadena, dato) + + else: + archivo.set('datos', cadena, '') + + def abrir_configuracion(self, *args): + """Abre la configuración desde el archivo configuraciones.cfg""" + + cfg = ConfigParser.ConfigParser() + cfg.read([configuracion]) + + try: + self.enumeracion = bool(cfg.get('datos', 'enumeracion')) + self.fuente = cfg.get('datos', 'fuente') + self.margen = int(float(cfg.get('datos', 'margen'))) + self.is_margen = bool(cfg.get('datos', 'is_margen')) + self.ajuste = bool(cfg.get('datos', 'ajuste')) + self.ajuste_palabras = bool(cfg.get('datos', 'ajuste_palabras')) + self.tabulador = int(float(cfg.get('datos', 'tabulador'))) + self.insertar_espacios = bool(cfg.get('datos', 'insertar_espacios')) + self.sangria = bool(cfg.get('datos', 'sangria')) + self.recientes = str(cfg.get('datos', 'recientes')) + self.tema = str(cfg.get('datos', 'tema')) + + except ConfigParser.NoOptionError: + self.enumeracion = True + self.fuente = 'Monospace' + self.margen = 80 + self.is_maegen = False + self.ajuste = False + self.ajuste_palabras = False + self.tabulador = 8 + self.insertar_espacios = False + self.sangria = False + self.recientes = '' + self.tema = 'classic' + + self.guardar_configuracion() diff --git a/CristianEdit/CristianEdit.pyc b/CristianEdit/CristianEdit.pyc Binary files differnew file mode 100644 index 0000000..f4ae452 --- /dev/null +++ b/CristianEdit/CristianEdit.pyc diff --git a/CristianEdit/Run.py b/CristianEdit/Run.py new file mode 100644 index 0000000..f214401 --- /dev/null +++ b/CristianEdit/Run.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# objetos.py por: +# Cristian García <cristian99garcia@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os + +from threading import Thread +from Terminal import Terminal + + +def ejecutar(direccion): + + if direccion != 'Sin dirección': + + bash = os.path.expanduser('~/.cristianedit/bash.sh') + texto = 'chmod +x %s \nexec %s' % (direccion, direccion) + + comando = open(bash, 'w') + comando.write(texto) + comando.close() + + os.system('chmod +x %s' % bash) + + string = '' + + for x in direccion.split('/')[:-1]: + string = string + x + '/' + + terminal = Terminal(string) diff --git a/CristianEdit/Run.pyc b/CristianEdit/Run.pyc Binary files differnew file mode 100644 index 0000000..aac70df --- /dev/null +++ b/CristianEdit/Run.pyc diff --git a/CristianEdit/Terminal.py b/CristianEdit/Terminal.py new file mode 100644 index 0000000..af4163c --- /dev/null +++ b/CristianEdit/Terminal.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Terminal.py por: +# Cristian García <cristian99garcia@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import objetos + +from gi.repository import Gtk +from gi.repository import Vte + + +class Terminal(Gtk.Window): + + def __init__(self, direccion): + + Gtk.Window.__init__(self) + + self.connect('destroy', self.salir) + + self.set_size_request(700, 500) + self.set_title('Terminal') + + self.terminales = [] + self.etiquetas = [] + self.direccion = direccion + self.primera_vez = True + + self.toolbar = objetos.Terminal_Toolbar(self) + self.notebook = objetos.Terminal_Notebook() + self.vbox = Gtk.VBox() + + self.notebook.set_show_tabs(False) + + self.vbox.pack_start(self.toolbar, False, False, 5) + self.vbox.pack_start(self.notebook, True, True, 0) + + self.crear_pagina() + + self.connect('destroy', self.salir) + self.notebook.connect('boton-cerrar-clicked', self.cerrar_desde_boton) + + self.add(self.vbox) + self.show_all() + + def salir(self, *args): + + #self.destroy() + Gtk.main_quit() + + def crear_pagina(self, *args): + """Crea una página en el cuaderno de fichas, + y selecciona un emulador a utilizar(bash, + o un archivo que ejecuta otro archivo)""" + + if self.primera_vez: + emulacion = (os.path.expanduser('~/.cristianedit/bash.sh'),) + self.primera_vez = False + + else: + emulacion = ('/bin/bash',) + + terminal = objetos.Terminal(self.direccion, emulacion) + label = Gtk.Label('Terminal') + + self.notebook.nueva_pagina(terminal, label) + self.terminales.append(terminal) + self.etiquetas.append(label) + + terminal.connect('window-title-changed', self.title_changed) + terminal.connect('child-exited', self.cerrar_terminal) + + self.notebook.set_show_tabs(self.notebook.get_n_pages() > 1) + + self.show_all() + + def title_changed(self, widget): + """Establece el texto a la etiqueta + de la etiqueta de la ficha actual""" + + numero = self.notebook.get_n_pages() - 1 + label = self.etiquetas[numero] + + label.set_text(widget.get_window_title()) + + def cerrar_terminal(self, widget): + """Cierra una página desde el + comando 'exit' de una terminal""" + + vbox = widget.get_parent() + numero = self.notebook.get_n_pages() - 2 + + if numero > -1: + self.cerrar_desde_boton(None, vbox) + + else: + self.salir() + + def cerrar_desde_boton(self, widget, objeto): + """Cierra una página desde el botón + de cerrado en la ficha del cuaderno""" + + numero = self.notebook.page_num(objeto) + terminal = self.terminales[numero] + label = self.etiquetas[numero] + + self.terminales.remove(terminal) + self.etiquetas.remove(label) + + terminal.destroy() + label.destroy() + + self.notebook.borrar_pagina(numero) + self.notebook.set_show_tabs(self.notebook.get_n_pages() > 1) diff --git a/CristianEdit/Terminal.pyc b/CristianEdit/Terminal.pyc Binary files differnew file mode 100644 index 0000000..e432fbe --- /dev/null +++ b/CristianEdit/Terminal.pyc diff --git a/CristianEdit/__init__.py b/CristianEdit/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/CristianEdit/__init__.py @@ -0,0 +1 @@ + diff --git a/CristianEdit/__init__.pyc b/CristianEdit/__init__.pyc Binary files differnew file mode 100644 index 0000000..35d5e72 --- /dev/null +++ b/CristianEdit/__init__.pyc diff --git a/CristianEdit/objetos.py b/CristianEdit/objetos.py new file mode 100644 index 0000000..e9730e4 --- /dev/null +++ b/CristianEdit/objetos.py @@ -0,0 +1,1476 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 -*- + +# objetos.py por: +# Cristian García <cristian99garcia@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import mimetypes +import os + +from gi.repository import Pango +from gi.repository import Gtk +from gi.repository import GObject +from gi.repository import GtkSource +from gi.repository import Gdk +from gi.repository import Vte +from gi.repository import GLib + +from Creditos import Creditos + +lenguaje_manager = GtkSource.LanguageManager() +lenguajes = lenguaje_manager.get_language_ids() + +lenguajes.sort() +lenguajes.remove(lenguajes[0]) +lenguajes.insert(0, 'Texto Plano') + +estilo_manager = GtkSource.StyleSchemeManager() +estilos = estilo_manager.get_scheme_ids() + +BIENVENIDA = '''\n\nTerminal creada en python, +por Cristian García <cristian99garcia@gmail.com>''' + + +def get_clasico(): + """Devuelve la posisión de classic en el combo""" + + cuenta = 0 + clasico = 0 + + for estilo in estilos: + if estilo == 'classic': + clasico = cuenta + + cuenta += 1 + + return clasico + + +def dialogo_cerrar(direccion, buffer, cristianedit, accion): + """Diálogo que cierra el programa o guarda según el usuario""" + + dialog = Gtk.MessageDialog(type=Gtk.MessageType(1)) + dialog.add_buttons(Gtk.STOCK_NO, 0, Gtk.STOCK_YES, 1) + + archivo = direccion.split('/')[-1] + dialog.set_markup('<b>%s</b>' % \ + 'El archivo %s tiene cambios sin guardar' % archivo) + + dialog.format_secondary_text('¿Guardar antes de salir?') + + respuesta = dialog.run() + dialog.destroy() + + if respuesta == 1: + cristianedit.guardar(None, direccion=direccion) + + if accion == 'cerrar': + Gtk.main_quit() + + +def dialogo_reemplazar(direccion, buffer, cristianedit): + """Preguntar si reemplazar o no, cuando la dirección ya existe""" + + dialog = Gtk.MessageDialog(type=Gtk.MessageType(2)) + + dialog.add_buttons(Gtk.STOCK_NO, 0, Gtk.STOCK_YES, 1) + dialog.set_markup('<b>%s</b>' % 'La dirección especificada ya existe...') + dialog.format_secondary_text( + 'Sí sobrescribe el archivo, se reemplazará su contenido.') + + respuesta = dialog.run() + dialog.destroy() + + if respuesta == 1: + escritura = open(direccion, 'w') + + escritura.write(cristianedit.get_texto()) + buffer.set_modified(False) + + escritura.close() + + else: + dialog.destroy() + + +class Menu(Gtk.MenuBar): + """Barra de Menú""" + + def __init__(self, padre): + + Gtk.MenuBar.__init__(self) + + items = [] + self.padre = padre + self.grupo = Gtk.AccelGroup() + self.recientes = [] + + self.ventana = self.padre.get_parent().get_parent() + self.ventana.add_accel_group(self.grupo) + + menu_archivo = Gtk.MenuItem('_Archivo') + menu_recientes = Gtk.MenuItem('_Recientes') + menu_editar = Gtk.MenuItem('_Editar') + menu_ayuda = Gtk.MenuItem('Ay_uda') + + menu_archivo.set_use_underline(True) + menu_recientes.set_use_underline(True) + menu_editar.set_use_underline(True) + menu_ayuda.set_use_underline(True) + + self.add(menu_archivo) + self.add(menu_editar) + self.add(menu_ayuda) + + archivo = Gtk.Menu() + self.menu_recientes = Gtk.Menu() + editar = Gtk.Menu() + ayuda = Gtk.Menu() + + menu_archivo.set_submenu(archivo) + menu_editar.set_submenu(editar) + menu_recientes.set_submenu(self.menu_recientes) + menu_ayuda.set_submenu(ayuda) + + self.menu_item('_Nuevo', self.padre.pagina_nueva, archivo, 'N') + + archivo.append(Gtk.SeparatorMenuItem()) + self.menu_item('_Abrir', self.padre.abrir, archivo, 'O') + self.menu_item('_Guardar', self.padre.guardar, archivo, 'S') + self.menu_item('Guardar _como', self.padre.guardar_como, archivo) + + archivo.append(Gtk.SeparatorMenuItem()) + archivo.append(menu_recientes) + + self.menu_item('_Deshacer', self.deshacer, editar, 'Z') + self.menu_item('_Rehacer', self.rehacer, editar, 'R') + + editar.append(Gtk.SeparatorMenuItem()) + self.menu_item('In_sertar fecha y hora', self.padre.text_hora, editar) + + editar.append(Gtk.SeparatorMenuItem()) + self.menu_item('_Estado del archivo', self.padre.estado, editar, 'E') + + editar.append(Gtk.SeparatorMenuItem()) + self.menu_item('Mostrar _teclado...', self.teclado, editar, 'T') + + self.menu_item('Acerca _de', self.creditos, ayuda) + + def teclado(self, widget): + + texto = widget.get_label() + + if texto == 'Mostrar _teclado...': + self.padre.mostrar_teclado(True) + widget.set_label('Ocultar _teclado') + + else: + self.padre.mostrar_teclado(False) + widget.set_label('Mostrar _teclado...') + + def creditos(self, widget): + """Muestra el diálogo con los créditos""" + + Creditos(self.padre.get_parent().get_parent()) + + def deshacer(self, widget): + """Obtiene el view actual y le pasa deshacer""" + + view = self.padre.get_view() + view.deshacer() + + def rehacer(self, widget): + """Obtiene el view actual y le pasa rehacer""" + + view = self.padre.get_view() + view.rehacer() + + def menu_item(self, etiqueta, callback, menu, letra=None, devolver=None): + """Creando los item para los menús""" + item = Gtk.MenuItem(etiqueta) + item.connect('activate', callback) + menu.append(item) + item.set_use_underline(True) + + if letra: + item.add_accelerator('activate', self.grupo, ord(letra), + Gdk.ModifierType(4), Gtk.AccelFlags(1)) + + if devolver: + return item + + def abrir_reciente(self, widget): + """Abre un archivo desde un menuitem""" + + direccion = widget.get_label().split(' ')[-1] + self.padre.abrir(None, direccion) + + def actualizar_recientes(self, recientes): + """Agregar menuitems por cada archivo reciente""" + + self.borrar_recientes() + numero = 1 + + if ', ' in recientes: + lista = recientes.split(', ') + + for archivo in lista: + if os.path.exists(archivo) and not archivo in self.recientes: + asbpath = os.path.abspath(archivo) + + if os.path.exists(asbpath): + direccion = asbpath + + else: + direccion = archivo + + texto = '_' + str(numero) + ' - ' + direccion + + self.menu_item(texto, self.abrir_reciente, + self.menu_recientes) + + self.recientes.append(archivo) + numero += 1 + + else: + #self.menu_recientes.get_parent().get_parent().set_sensitive(False) + + pass + + self.show_all() + + def borrar_recientes(self): + + for item in self.menu_recientes: + self.menu_recientes.remove(item) + + while len(self.recientes) != 0: + for x in self.recientes: + self.recientes.remove(x) + + +class Buffer(GtkSource.Buffer): + """Buffer de Texto""" + + def __init__(self, combo): + + GtkSource.Buffer.__init__(self) + + self.combo = combo + self.lenguaje = None + + def buscar_lenguaje(self, lugar, combo): + """Busca el lenguaje de programación en un archivo + al guardarlo o abrirlo, sí es que tiene uno""" + + tipo = list(mimetypes.guess_type(lugar))[0] + encontrado = False + + for id in lenguajes: + lenguaje = lenguaje_manager.get_language(id) + + if lenguaje and len(lenguaje.get_mime_types()): + mime = lenguaje.get_mime_types()[0] + + if tipo == mime: + self.set_highlight_syntax(True) + self.set_language(lenguaje) + + list_num = lenguajes.index(id) + 1 + self.lenguaje = lenguaje + encontrado = True + + combo.set_active(list_num) + + if not encontrado: + self.set_highlight_syntax(False) + + self.lenguaje = None + combo.set_active(0) + + def get_lenguaje(self): + """Devuelve el lenguaje seleccionado""" + + return self.lenguaje + + +class View(GtkSource.View): + """Visor de Texto""" + + def __init__(self, buffer=None): + + GtkSource.View.__init__(self) + + self.set_buffer(buffer) + self.set_size_request(400, 500) + + def deshacer(self): + """Deshace cambios""" + + if self.get_buffer().can_undo(): + self.get_buffer().undo() + + def rehacer(self): + """Rehace cambios""" + + if self.get_buffer().can_redo(): + self.get_buffer().redo() + + def configurar(self, enumeracion, + fuente, margen, + is_margen, ajuste, + ajuste_palabras, + tabulador, insertar_espacios, + sangria, tema): + + """Establecer configuración + según los argumentos""" + + self.set_property('show-line-numbers', enumeracion) + self.modify_font(Pango.font_description_from_string(fuente)) + self.set_property('right-margin-position', margen) + self.set_property('show-right-margin', is_margen) + self.set_property('insert-spaces-instead-of-tabs', insertar_espacios) + self.set_tab_width(tabulador) + self.set_property('auto-indent', sangria) + self.get_buffer().set_style_scheme(estilo_manager.get_scheme(tema)) + + if ajuste: + self.set_wrap_mode(Gtk.WrapMode(1)) + + if ajuste and ajuste_palabras: + self.set_wrap_mode(Gtk.WrapMode(2)) + + def buscar_texto(self, texto, enter=None): + """Buscar Texto""" + + buffer = self.get_buffer() + + cursor_mark = buffer.get_insert() + start = buffer.get_iter_at_mark(cursor_mark) + if start.get_offset() == buffer.get_char_count(): + start = buffer.get_start_iter() + + self.seleccionar_texto(texto, start, enter) + + def seleccionar_texto(self, text, start, enter): + """Selecciona el texto solicitado, + y mueve el scrolled sí es necesario""" + + buffer = self.get_buffer() + end = buffer.get_end_iter() + match = start.forward_search(text, 0, end) + + if match: + match_start, match_end = match + + if not enter: + buffer.select_range(match_start, match_end) + + else: + buffer.select_range(match_end, match_start) + + self.scroll_to_iter(match_end, 0.1, 1, 1, 1) + + else: + start = buffer.get_start_iter() + try: + self.seleccionar_texto(text, start, None) + + except RuntimeError: + pass + + +class Notebook(Gtk.Notebook): + """Cuaderno de Fichas""" + + __gsignals__ = { + 'boton-cerrar-clicked': (GObject.SIGNAL_RUN_FIRST, + GObject.TYPE_NONE, (GObject.TYPE_OBJECT,)) + } + + def __init__(self, padre=None): + + Gtk.Notebook.__init__(self) + + self.numero = 0 + self.botones = [] + self.labels = [] + self.padre = padre + + self.set_scrollable(True) + + def agregar(self, objeto, label, barra): + """Agrega una página al Widget clase""" + + hbox = Gtk.HBox() + imagen = Gtk.Image() + imagen.set_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize(4)) + boton = Gtk.Button(None, image=imagen) + + hbox.pack_start(label, False, False, 0) + hbox.pack_start(boton, False, False, 0) + + self.botones.append(boton) + self.labels.append(label) + + vbox = Gtk.VBox() + scrolled = self.crear_scrolled() + + vbox.pack_start(scrolled, True, True, 0) + vbox.pack_start(barra, False, False, 0) + scrolled.add(objeto) + self.append_page(vbox, hbox) + + hbox.show() + boton.show() + label.show() + + self.show_all() + + numero = 0 + for x in self.botones: + x.numero = numero + numero += 1 + + boton.connect('clicked', self.borrar_pagina_desde_boton, vbox) + + def crear_scrolled(self): + """Crea y devuelve un GtkScrolledWindow()""" + + scrolled = Gtk.ScrolledWindow() + scrolled.set_policy(Gtk.PolicyType(1), Gtk.PolicyType(1)) + scrolled.set_shadow_type(Gtk.ShadowType(1)) + + return scrolled + + def borrar_pagina(self, numero=None): + """Borra la página actual""" + + if numero == None: + self.remove_page(self.get_current_page()) + + else: + self.remove_page(numero) + + self.set_show_tabs(self.get_n_pages() > 1) + + def borrar_pagina_desde_boton(self, widget, objeto): + """Borrar página desde el botón de cerrado""" + + self.emit('boton-cerrar-clicked', objeto) + + +class Barra(Gtk.HBox): + """GtkHBox() que simula una GtkToolBar()""" + + def __init__(self, funciones, abrir): + + Gtk.HBox.__init__(self) + + self.funciones = funciones + + self.pack_start(abrir, False, False, 4) + + guardar = self.funciones[0] + nuevo = self.funciones[1] + deshacer = self.funciones[2] + rehacer = self.funciones[3] + ejecutar = self.funciones[4] + seleccionar_fuente = self.funciones[5] + preferencias = self.funciones[6] + buscar = self.funciones[7] + buscar_enter = self.funciones[8] + + self.toolbutton(Gtk.STOCK_SAVE, guardar, 'Guardar archivo') + + self.separador() + self.toolbutton(Gtk.STOCK_NEW, nuevo, 'Nuevo archivo') + + self.separador() + self.toolbutton(Gtk.STOCK_UNDO, deshacer, 'Deshacer cambios') + self.toolbutton(Gtk.STOCK_REDO, rehacer, 'Rehacer cambios') + self.toolbutton(Gtk.STOCK_EXECUTE, ejecutar, 'Ejecutar archivo') + + self.separador() + self.toolbutton(Gtk.STOCK_SELECT_FONT, seleccionar_fuente, + 'Seleccionar fuente de texto') + self.toolbutton(Gtk.STOCK_PREFERENCES, preferencias) + + self.separador() + entry = Gtk.Entry() + entry.props.secondary_icon_stock = 'gtk-find' + entry.connect('changed', buscar) + entry.connect('activate', buscar_enter) + entry.connect('icon-release', buscar_enter) + self.pack_start(entry, False, False, 4) + + self.show_all() + + def separador(self): + """Crea y empaqueta un separador""" + + separador = Gtk.SeparatorToolItem() + separador.set_size_request(10, 10) + self.pack_start(separador, False, False, 0) + + def toolbutton(self, stock, callback, tooltip=None): + """Crea un boton para el Widget clase""" + + toolbutton = Gtk.ToolButton(stock) + toolbutton.connect('clicked', callback) + self.pack_start(toolbutton, False, False, 0) + if tooltip != None: + toolbutton.set_tooltip_text(tooltip) + + +class Navegador(Gtk.FileChooserDialog): + """Navegador de archivos""" + + def __init__(self, titulo, padre, accion, botones): + + Gtk.FileChooserDialog.__init__(self, titulo, None, accion, botones) + + self.set_focus_visible(False) + + if accion == Gtk.FileChooserAction(0): + self.set_select_multiple(True) + + self.set_default_response(1) + + filter = Gtk.FileFilter() + boton = Gtk.Button(None, Gtk.STOCK_CANCEL) + + filter.set_name('Archivos de Texto') + filter.add_mime_type('text/*') + + boton_ok = list(self.action_area)[0] + self.action_area.remove(boton_ok) + self.action_area.add(boton) + self.action_area.add(boton_ok) + self.add_filter(filter) + + boton.connect('clicked', self.cerrar) + boton.show() + + def cerrar(self, widget): + """Destruye al Widget clase""" + + self.destroy() + + +class Barra_Inferior(Gtk.HBox): + """Un GtkHBox() que contiene los + Widgets de la parte inferior de la ventana""" + + def __init__(self): + + Gtk.HBox.__init__(self) + + self.combo = Combo_Lenguajes() + self.b_estado = Gtk.Statusbar() + + self.b_estado.push(0, 'Línea:0, Columna:0') + + self.pack_end(self.b_estado, False, False, 20) + self.pack_end(self.combo, False, False, 0) + + def get_combo(self): + """Devuelve el GtkComboBoxText() + con los lenguajes de programación""" + + return self.combo + + def get_statusbar(self): + """Devuelve la barra de estado""" + + return self.b_estado + + +class Combo_Estilos(Gtk.ComboBoxText): + """Un GtkComboBoxText para mostrar y utilizar + los temas instalados en el sistema""" + + def __init__(self, estilo_principal=0): + + Gtk.ComboBoxText.__init__(self) + + for estilo in estilos: + self.append_text(estilo) + + self.set_active(estilo_principal) + + +class Combo_Lenguajes(Gtk.ComboBoxText): + """Un GtkComboBoxText para mostrar los + lenguajes de programación instalados en el sistema""" + + def __init__(self): + + Gtk.ComboBoxText.__init__(self) + + self.primera_vez = True + + for lenguaje in lenguajes: + self.append_text(lenguaje) + + self.set_active(0) + + def update(self, view, direccion, buffer): + """Muestra el lenguaje del View actual, + esta función sire para cuando se cambia + de página""" + + if direccion != 'Sin dirección': + tipo = list(mimetypes.guess_type(direccion))[0] + + else: + tipo = 'text/plain' + + if not self.primera_vez: + self.buscar_lenguaje(tipo, buffer) + + else: + self.primera_vez = False + + def buscar_lenguaje(self, filename, buffer): + """Busca un lenguaje especifico, + y lo activa en el Widget clase""" + + manager = lenguaje_manager + extension = filename.split('.')[-1] + + if extension != filename and extension in lenguajes: + lenguaje = manager.get_language() + numero = self.index(extension) + + self.set_active(numero) + buffer.set_language(lenguaje) + + else: + language = manager.guess_language(filename, 'algo') + + if language: + buffer.set_highlight_syntax(True) + buffer.set_language(language) + + else: + buffer.set_highlight_syntax(False) + + buffer.buscar_lenguaje(filename) + + def get_lenguajes(self): + """Devuelve la lista con lenguajes ya ordenados por orden alfabetico""" + + return lenguajes + + def get_lenguaje_manager(self): + """Devuelve la variable 'lenguaje_manager'""" + + return lenguaje_manager + + +class DialogoCerrar(Gtk.MessageDialog): + """El díalogo que le pregunta al usuario sí en + realidad quiere borrar la página del GtkNotebook()""" + + def __init__(self, direccion, pagina, notebook, lugares, etiquetas, padre): + + Gtk.MessageDialog.__init__(self, type=Gtk.MessageType(2), + title='Hay cambios sin guardar') + + self.direccion = direccion + self.pagina = pagina + self.notebook = notebook + self.lugares = lugares + self.etiquetas = etiquetas + self.padre = padre + + self.set_markup('<b>%s</b>' % 'Sí cierra, se perderán los cambios') + + boton_cerrar = Gtk.Button(None, Gtk.STOCK_CANCEL) + boton_cerrar.connect('clicked', self.cerrar) + self.action_area.add(boton_cerrar) + + boton_no = Gtk.Button('_No guardar') + boton_no.connect('clicked', self.borrar) + self.action_area.add(boton_no) + + boton_si = Gtk.Button(None, Gtk.STOCK_SAVE) + boton_si.connect('clicked', self.guardar) + self.action_area.add(boton_si) + + self.show_all() + + def cerrar(self, widget): + """Cierra la clase destrullendola""" + + self.destroy() + + def borrar(self, widget): + """Borra la pestaña""" + + self.etiquetas.remove(self.etiquetas[self.pagina]) + self.lugares.remove(self.lugares[self.pagina]) + self.notebook.borrar_pagina() + self.cerrar(None) + self.change_page(self, None, None) + + def guardar(self, widget): + """Guarda el archivo antes de cerrar la pestaña""" + + if not self.direccion == 'Sin dirección': + self.padre.guardar(None, direccion=self.direccion) + + else: + self.padre.guardar_como(None) + + self.borrar(None) + + +class DialogoEstado(Gtk.Dialog): + + def __init__(self, padre, notebook): + + Gtk.Dialog.__init__(self) + + self.padre = padre + self.notebook = notebook + + self.label_caracteres = Gtk.Label() + self.label_lineas = Gtk.Label() + self.label_modificado = Gtk.Label() + self.label_fuente = Gtk.Label() + self.label_lugar = Gtk.Label() + self.label_pestania = Gtk.Label() + + self.actualizar_estado() + + self.tabla = Gtk.Table(7, 2, False) + + label_caracteres = Gtk.Label('Cantidad de caractéres:') + label_lineas = Gtk.Label('Cantidad de líneas:') + label_lugar = Gtk.Label('Ubicación de archivo:') + label_modificado = Gtk.Label('Estado de modificación:') + label_fuente = Gtk.Label('Fuente de Texto:') + label_pestania = Gtk.Label('Pestaña actual:') + + lista = [self.label_caracteres, self.label_lineas, self.label_lugar, + self.label_modificado, self.label_pestania] + + for label in lista: + label.modify_font(Pango.FontDescription('bold')) + + fuente = self.padre.get_fuente() + fuente = Pango.FontDescription(fuente) + fuente.set_size(14000) + self.label_fuente.modify_font(fuente) + + self.tabla.attach(label_caracteres, 0, 1, 0, 1) + self.tabla.attach(label_lineas, 0, 1, 1, 2) + self.tabla.attach(label_lugar, 0, 1, 2, 3) + self.tabla.attach(label_modificado, 0, 1, 3, 4) + self.tabla.attach(label_fuente, 0, 1, 4, 5) + self.tabla.attach(label_pestania, 0, 1, 5, 6) + + self.tabla.attach(self.label_caracteres, 1, 2, 0, 1) + self.tabla.attach(self.label_lineas, 1, 2, 1, 2) + self.tabla.attach(self.label_lugar, 1, 2, 2, 3) + self.tabla.attach(self.label_modificado, 1, 2, 3, 4) + self.tabla.attach(self.label_fuente, 1, 2, 4, 5) + self.tabla.attach(self.label_pestania, 1, 2, 5, 6) + + self.vbox.pack_start(self.tabla, True, True, 0) + + boton_cerrar = Gtk.Button(None, Gtk.STOCK_CLOSE) + boton_cerrar.connect('clicked', self.cerrar) + self.action_area.add(boton_cerrar) + + boton_actualizar = Gtk.Button('_Actualizar estado') + boton_actualizar.set_use_underline(True) + boton_actualizar.connect('clicked', self.actualizar_estado) + self.action_area.add(boton_actualizar) + + def actualizar_estado(self, *args): + """Actualiza la información que se + guarda y muestran en las etiquetas""" + + buffer = self.padre.get_buffer() + direccion = self.padre.get_direccion() + fuente = self.padre.get_fuente() + pagina = self.notebook.get_current_page() + 1 + paginas = self.notebook.get_n_pages() + + self.label_caracteres.set_text(str(buffer.get_char_count())) + self.label_lineas.set_text(str(buffer.get_line_count())) + self.label_fuente.set_text(fuente) + self.label_lugar.set_text(direccion) + self.label_pestania.set_text(str(pagina) + '/' + str(paginas)) + + if buffer.get_modified(): + self.label_modificado.set_text('Modificado') + + else: + self.label_modificado.set_text('Sin modificar') + + def cerrar(self, widget): + """Destruye al Widget clase""" + + self.destroy() + + +class Selector_de_Fuente(Gtk.FontSelectionDialog): + + __gsignals__ = { + 'font-changed': (GObject.SIGNAL_RUN_FIRST, + GObject.TYPE_NONE, (GObject.TYPE_STRING,)) + } + + def __init__(self, fuente): + + Gtk.FontSelectionDialog.__init__(self, title='Fuente de texto...') + + self.fuente = fuente + + close_button = Gtk.Button(None, Gtk.STOCK_CLOSE) + ok_button = Gtk.Button(None, Gtk.STOCK_OK) + + for x in list(self.action_area): + x.destroy() + + self.set_font_name(self.fuente) + + self.action_area.add(close_button) + self.action_area.add(ok_button) + + ok_button.connect('clicked', self.aplicar_fuente) + close_button.connect('clicked', self.cerrar) + + self.show_all() + + def aplicar_fuente(self, widget): + """Emite la señal 'font-changed'""" + + self.emit('font-changed', self.get_font_name()) + + def cerrar(self, widget): + """Destruye al Widget clase""" + + self.destroy() + + +class Configuraciones(Gtk.Dialog): + + def __init__(self, padre, + enumeracion, + margen, is_margen, + ajuste, ajuste_palabras, + tabulador, insertar_espacios, + sangria, tema): + + ventana = padre.get_parent().get_parent() + + Gtk.Dialog.__init__(self, 'Configurar CristianEdit 2', ventana) + + self.padre = padre + self.enumeracion = enumeracion + self.margen = margen + self.is_margen = is_margen + self.ajuste = ajuste + self.ajuste_palabras = ajuste_palabras + self.tabulador = tabulador + self.insertar_espacios = insertar_espacios + self.sangria = sangria + self.tema = tema + self.lista = [self.enumeracion, + self.margen, self.is_margen, + self.ajuste, self.ajuste_palabras, + self.tabulador, + self.insertar_espacios, + self.sangria, self.tema] + + self.set_resizable(False) + + notebook = Gtk.Notebook() + vbox1 = Gtk.VBox() + vbox2 = Gtk.VBox() + vbox1.a = Gtk.HBox() + vbox1.b = Gtk.HBox() + + self.vbox.pack_start(notebook, True, True, 0) + + boton_enumeracion = Gtk.CheckButton('Mostrar los números de líneas') + boton_margen = Gtk.CheckButton('Mostrar margen derecho en la columna:') + boton_ajuste1 = Gtk.CheckButton('Ajuste de Texto') + boton_ajuste2 = Gtk.CheckButton('No dividir palabras en dos líneas') + boton_insertar = Gtk.CheckButton( + 'Insertar espacios en lugar de tabulaciones') + boton_sangria = Gtk.CheckButton('Sangría automatica') + + ajuste1 = Gtk.Adjustment(self.margen, 1, 1000, 1, 10) + ajuste2 = Gtk.Adjustment(self.tabulador, 1, 30, 1, 10) + spin1 = Gtk.SpinButton() + spin2 = Gtk.SpinButton() + + label1 = Gtk.Label('Editor') + label2 = Gtk.Label('Taulador') + label3 = Gtk.Label('Sangría') + label4 = Gtk.Label('Tema de colores') + + l = [label1, label2, label3, label4] + for x in l: + x.modify_font(Pango.FontDescription('bold')) + + boton_margen.set_active(self.is_margen) + boton_enumeracion.set_active(self.enumeracion) + spin1.set_adjustment(ajuste1) + spin2.set_adjustment(ajuste2) + boton_ajuste1.set_active(self.ajuste) + boton_ajuste2.set_active(self.ajuste_palabras) + boton_insertar.set_active(self.insertar_espacios) + boton_sangria.set_active(self.sangria) + + spin1.set_sensitive(boton_margen.get_active()) + boton_ajuste2.set_sensitive(boton_ajuste1.get_active()) + + boton_enumeracion.connect('clicked', self.change_enumeracion) + spin1.connect('value-changed', self.margen_changed) + spin2.connect('value-changed', self.tabulador_changed) + boton_margen.connect('clicked', self.is_margen_changed, spin1) + boton_ajuste1.connect('clicked', self.change_ajuste, boton_ajuste2) + boton_ajuste2.connect('clicked', self.change_ajuste_palabras) + boton_insertar.connect('clicked', self.insertar_espacios_changed) + boton_sangria.connect('clicked', self.sangria_changed) + + vbox1.pack_start(label1, False, False, 10) + vbox1.pack_start(boton_enumeracion, False, False, 0) + vbox1.pack_start(vbox1.a, False, False, 0) + vbox1.pack_start(label2, False, False, 10) + vbox1.pack_start(vbox1.b, False, False, 0) + vbox1.pack_start(boton_sangria, False, False, 0) + vbox1.pack_start(boton_insertar, False, False, 0) + vbox1.a.pack_start(boton_margen, False, False, 0) + vbox1.a.pack_start(spin1, False, False, 0) + vbox1.b.pack_start(Gtk.Label('Ancho del tabulador:'), False, False, 0) + vbox1.b.pack_start(spin2, False, False, 0) + vbox1.pack_start(label3, False, False, 10) + vbox1.pack_start(boton_ajuste1, False, False, 0) + vbox1.pack_start(boton_ajuste2, False, False, 0) + + combo_estilos = Combo_Estilos(estilos.index(self.tema)) + + combo_estilos.connect('changed', self.estilo_changed) + + vbox2.pack_start(label4, False, False, 10) + vbox2.pack_start(combo_estilos, False, False, 0) + + notebook.append_page(vbox1, Gtk.Label('Editor')) + notebook.append_page(vbox2, Gtk.Label('Temas de colores')) + + boton = Gtk.Button(None, Gtk.STOCK_OK) + boton.connect('clicked', self.cerrar) + self.action_area.add(boton) + + def estilo_changed(self, widget): + """Establece en tema de colores""" + + self.tema = estilos[widget.get_active()] + self.lista[8] = self.tema + self.padre.set_configuracion(self.lista) + + def sangria_changed(self, widget): + """Establece o desabilita la sangría automatica""" + + self.sangria = widget.get_active() + self.lista[7] = self.sangria + + self.padre.set_configuracion(self.lista) + + def insertar_espacios_changed(self, widget): + """Establece sí resaltar la línea actual o no""" + + self.insertar_espacios = widget.get_active() + self.lista[6] = self.insertar_espacios + + self.padre.set_configuracion(self.lista) + + def tabulador_changed(self, widget): + """Establece el ancho del tabulador""" + + view = self.padre.get_view() + self.tabulador = widget.get_value() + + self.lista[5] = self.tabulador + self.padre.set_configuracion(self.lista) + + def change_ajuste(self, widget, boton): + """Activa/Desactiva ajuste de texto""" + + view = self.padre.get_view() + estado = widget.get_active() + + boton.set_sensitive(estado) + + if estado: + view.set_wrap_mode(Gtk.WrapMode(1)) + self.ajuste_palabras = False + + else: + view.set_wrap_mode(Gtk.WrapMode(0)) + + if estado and boton.get_active() and boton.get_sensitive: + view.set_wrap_mode(Gtk.WrapMode(2)) + self.ajuste_palabras = True + + self.ajuste = estado + self.lista[3] = self.ajuste + self.lista[4] = self.ajuste_palabras + + self.padre.set_configuracion(self.lista) + + def change_ajuste_palabras(self, widget): + """Ajuste por palabras, no divide las palabras en dos líneas""" + + view = self.padre.get_view() + + if widget.get_active(): + view.set_wrap_mode(Gtk.WrapMode(2)) + + else: + view.set_wrap_mode(Gtk.WrapMode(1)) + + self.ajuste_palabras = widget.get_active() + + self.lista[3] = self.ajuste + self.lista[4] = self.ajuste_palabras + self.padre.set_configuracion(self.lista) + + def change_enumeracion(self, widget): + """Hace que la enumeración sea igual al + estado de activación del botón""" + + self.enumeracion = widget.get_active() + self.lista[0] = self.enumeracion + + self.padre.set_configuracion(self.lista) + + def margen_changed(self, widget): + """Establece en la columna en la + que se muestra el margen derecho""" + + self.margen = widget.get_value() + self.lista[1] = self.margen + + self.padre.set_configuracion(self.lista) + + def is_margen_changed(self, widget, spin): + """Establece sí el usuario quiere o no margen derecho""" + + self.is_margen = widget.get_active() + spin.set_sensitive(self.is_margen) + + self.lista[2] = self.is_margen + self.padre.set_configuracion(self.lista) + + def cerrar(self, widget): + """Destruir al Widget clase""" + + self.destroy() + + +class DialogoAdvertencia(Gtk.Dialog): + + def __init__(self, padre, direccion, cristianedit): + + Gtk.Dialog.__init__(self, 'Hay cambios sin guardar', + padre, Gtk.DialogFlags.MODAL, + buttons=(Gtk.STOCK_CANCEL, 0, + Gtk.STOCK_OK, 1)) + + self.direccion = direccion + self.cristianedit = cristianedit + + if direccion == 'Sin dirección': + nombre = 'Sin título' + + else: + nombre = direccion.split('/')[-1] + + label = Gtk.Label('El archivo %s se ha modificado y no se han guardado\ + los cambios, ¿Desdea guardar antes de salir?' % nombre) + label.modify_font(Pango.FontDescription('bold')) + + respuesta = self.run() + + if respuesta == 0: + Gtk.main_quit() + + elif respuesta == 1: + self.cristianedit.guardar(None, self.direccion) + + +class Teclado(Gtk.Dialog): + + def __init__(self, padre): + + Gtk.Dialog.__init__(self) + + self.estado = 'minusculas' + self.padre = padre + + self.set_title('Teclado de CristianEdit 2') + self.set_resizable(False) + + vbox = Gtk.VBox() + self.vbox.hbox = Gtk.HBox() + self.vbox.vbox = Gtk.VBox() + self.vbox.hbox0 = Gtk.HBox() + self.vbox.hbox1 = Gtk.HBox() + self.vbox.hbox2 = Gtk.HBox() + self.vbox.hbox3 = Gtk.HBox() + self.vbox.hbox4 = Gtk.HBox() + self.vbox.hbox5 = Gtk.HBox() + self.vbox.hbox6 = Gtk.HBox() + + self.vbox.pack_start(self.vbox.hbox, False, False, 0) + self.vbox.hbox.pack_start(self.vbox.vbox, True, True, 0) + self.vbox.hbox.pack_start(vbox, True, True, 0) + self.vbox.vbox.pack_start(self.vbox.hbox0, False, False, 10) + self.vbox.vbox.pack_start(self.vbox.hbox1, False, False, 0) + self.vbox.vbox.pack_start(self.vbox.hbox2, False, False, 0) + self.vbox.vbox.pack_start(self.vbox.hbox3, False, False, 0) + self.vbox.vbox.pack_start(self.vbox.hbox4, False, False, 10) + self.vbox.vbox.pack_start(self.vbox.hbox5, False, False, 0) + self.vbox.vbox.pack_start(self.vbox.hbox6, False, False, 10) + + borrar = Gtk.Button('Borrar') + borrar.connect('pressed', self.borrar) + vbox.pack_start(borrar, False, False, 4) + + enter = Gtk.Button('Enter') + enter.connect('pressed', self.clic, '\n') + vbox.pack_start(enter, True, True, 10) + + espacio = Gtk.Button('Espacio') + espacio.connect('pressed', self.clic, ' ') + self.vbox.hbox6.pack_start(espacio, True, True, 10) + + self.lista0 = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'] + self.lista1 = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'] + self.lista2 = ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ñ'] + self.lista3 = ['z', 'x', 'c', 'v', 'b', 'n', 'm'] + self.lista4 = ['á', 'é', 'í', 'ó', 'ú'] + self.lista5 = ['¿', '?', '¡', '+', '*', '-', '{', '}', '[', ']', "'"] + + for x in self.lista5: + boton = Gtk.Button(x) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox5.pack_start(boton, False, False, 0) + + self.recargar() + + boton_cambio = Gtk.Button('_Mostrar Mayúsculas') + boton_cambio.set_use_underline(True) + boton_cambio.connect('clicked', self.cambio) + self.action_area.add(boton_cambio) + + boton_cerrar = Gtk.Button(None, Gtk.STOCK_CLOSE) + boton_cerrar.connect('clicked', self.cerrar) + self.action_area.add(boton_cerrar) + + self.action_area.show() + boton_cerrar.show() + + def cerrar(self, widget): + """Destruye al Widget clase""" + + self.destroy() + + def recargar(self): + """Borra y crea los botones nuevamente""" + + for x in self.vbox.hbox0: + x.destroy() + + for x in self.vbox.hbox1: + x.destroy() + + for x in self.vbox.hbox2: + x.destroy() + + for x in self.vbox.hbox3: + x.destroy() + + for x in self.vbox.hbox4: + x.destroy() + + for letra0 in self.lista0: + boton = Gtk.Button(letra0) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox0.pack_start(boton, False, False, 0) + + for letra1 in self.lista1: + boton = Gtk.Button(letra1) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox1.pack_start(boton, False, False, 0) + + for letra2 in self.lista2: + boton = Gtk.Button(letra2) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox2.pack_start(boton, False, False, 0) + + for letra3 in self.lista3: + boton = Gtk.Button(letra3) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox3.pack_start(boton, False, False, 0) + + for letra4 in self.lista4: + boton = Gtk.Button(letra4) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox4.pack_start(boton, False, False, 0) + + self.show_all() + + def cambio(self, widget): + """Cambia las letras por mayúsculas a minúsculas y viceversa""" + + if self.estado != 'minusculas': + self.lista0 = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'] + self.lista1 = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'] + self.lista2 = ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ñ'] + self.lista3 = ['z', 'x', 'c', 'v', 'b', 'n', 'm'] + self.lista4 = ['á', 'é', 'í', 'ó', 'ú'] + self.estado = 'minusculas' + widget.set_label('_Mostrar Mayúsculas') + + else: + self.lista0 = ['!', '"', '#', '$', '%', '&', '/', '(', ')', '='] + self.lista1 = ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'] + self.lista2 = ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ñ'] + self.lista3 = ['Z', 'X', 'C', 'V', 'B', 'N', 'M'] + self.lista4 = ['Á', 'É', 'Í', 'Ó', 'Ú'] + self.estado = 'mayusculas' + widget.set_label('_Mostrar Minúsculas') + + self.recargar() + + def clic(self, widget, especial=None): + """Escribe el texto""" + + buffer = self.padre.get_buffer() + + if not especial: + texto = widget.get_label() + + else: + texto = especial + + buffer.insert_at_cursor(texto) + + def borrar(self, widget): + """Borrar el carácter actual""" + + buffer = self.padre.get_buffer() + + if buffer.get_selection_bounds(): + start, end = buffer.get_bounds() + inicio, fin = buffer.get_selection_bounds() + + texto_start = list(buffer.get_text(start, inicio, 0)) + texto_end = list(buffer.get_text(fin, end, 0)) + + string1 = '' + string2 = '' + + for x1 in texto_start: + string1 = string1 + x1 + + for x2 in texto_end: + string1 = string1 + x2 + + else: + start, fin = buffer.get_bounds() + actual = buffer.get_iter_at_mark(buffer.get_insert()) + numero = actual.get_offset() + + texto_start = list(buffer.get_text(start, actual, 0))[:numero - 1] + texto_end = list(buffer.get_text(actual, fin, 0))#[numero:] + string1 = '' + string2 = '' + + for x1 in texto_start: + string1 = string1 + x1 + + for x2 in texto_end: + string2 = string2 + x2 + + buffer.set_text(string1 + string2) + + +class Terminal_Toolbar(Gtk.Toolbar): + + def __init__(self, padre): + + Gtk.Toolbar.__init__(self) + + self.padre = padre + + self.toolbutton(Gtk.STOCK_NEW, 'Nueva terminal', self.crear_pagina) + + def crear_pagina(self, widget): + """Llama a la función de + CristianEdit con el mismo nombre""" + + self.padre.crear_pagina() + + def toolbutton(self, stock, tooltip=None, callback=None): + """Crea un boton para el Widget clase""" + + toolbutton = Gtk.ToolButton(stock) + self.add(toolbutton) + + if callback: + toolbutton.connect('clicked', callback) + + if tooltip != None: + toolbutton.set_tooltip_text(tooltip) + + +class Terminal(Vte.Terminal): + + def configurar(self): + """Configura al Widget clase""" + + #shape: 0: Normal - Block + # 1: Barra simple - Ibeam + # 2: Guión bajo - Underline + + shape = Vte.TerminalCursorShape(2) + fg_color = '#00FF00' + bg_color = '#000000' + lineas = 1000 + fuente = 'Monospace' + transparente = True + nivel = 0.50 + + self.set_cursor_shape(shape) + self.set_colors(Gdk.color_parse(fg_color), + Gdk.color_parse(bg_color), []) + + self.set_scrollback_lines(lineas) + self.set_font(Pango.FontDescription(fuente)) + self.set_background_transparent(transparente) + self.set_background_saturation(nivel) + + def __init__(self, direccion, emulacion): + + Vte.Terminal.__init__(self) + + vteflags = Vte.PtyFlags(1) + lista = ['algo'] + glibflags = GLib.SpawnFlags(1) + algo = 'algo' + + self.configurar() + + #banderas de vte, dirección, emulación, lista, banderas de glib, función + + self.fork_command_full(vteflags, + direccion, + emulacion, + lista, + glibflags, + self.benvienida, + algo) + + def benvienida(self, widget): + """Imprime un texto cuando + recién se crea el Widget clase""" + + print BIENVENIDA + + def tecla(self, widget, event): + """Obtiene el evento de teclado y + llama a la función evento""" + + tecla = Gdk.keyval_name(event.keyval) + self.evento(event) + + def evento(self, event): + """Reacciona a los eventos de teclado""" + + pass + + +class Terminal_Notebook(Gtk.Notebook): + + __gsignals__ = { + 'boton-cerrar-clicked': (GObject.SIGNAL_RUN_FIRST, + GObject.TYPE_NONE, (GObject.TYPE_OBJECT,)) + } + + def __init__(self): + + Gtk.Notebook.__init__(self) + + self.set_scrollable(True) + + def nueva_pagina(self, objeto, label): + """Crea una página al Widget clase""" + + vbox = Gtk.VBox() + scrolled = Gtk.ScrolledWindow() + hbox = Gtk.HBox() + boton = Gtk.ToolButton(Gtk.STOCK_CLOSE) + + hbox.pack_start(label, False, False, 0) + hbox.pack_start(boton, False, False, 0) + + vbox.add(scrolled) + scrolled.add(objeto) + + self.append_page(vbox, hbox) + + hbox.show_all() + + boton.connect('clicked', self.cerrar, vbox) + + def borrar_pagina(self, numero=None): + """Borra una página según un número, o la actual""" + + if not numero: + numero = self.get_current_page() + + self.remove_page(numero) + + def desplazar_al_final(self): + """Activa la última pestaña""" + + numero = self.get_n_pages() + for x in range(0, numero): + self.next_page() + + def cerrar(self, widget, objeto): + """Emite la señal 'boton-cerrar-clicked'""" + + self.emit('boton-cerrar-clicked', objeto) diff --git a/CristianEdit/objetos.pyc b/CristianEdit/objetos.pyc Binary files differnew file mode 100644 index 0000000..47bf98c --- /dev/null +++ b/CristianEdit/objetos.pyc diff --git a/CristianEdit/objetos.py~ b/CristianEdit/objetos.py~ new file mode 100644 index 0000000..69884de --- /dev/null +++ b/CristianEdit/objetos.py~ @@ -0,0 +1,1474 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 -*- + +# objetos.py por: +# Cristian García <cristian99garcia@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import mimetypes +import os + +from gi.repository import Pango +from gi.repository import Gtk +from gi.repository import GObject +from gi.repository import GtkSource +from gi.repository import Gdk +from gi.repository import Vte +from gi.repository import GLib + +from Creditos import Creditos + +lenguaje_manager = GtkSource.LanguageManager() +lenguajes = lenguaje_manager.get_language_ids() + +lenguajes.sort() +lenguajes.remove(lenguajes[0]) +lenguajes.insert(0, 'Texto Plano') + +estilo_manager = GtkSource.StyleSchemeManager() +estilos = estilo_manager.get_scheme_ids() + +BIENVENIDA = '''\n\nTerminal creada en python, +por Cristian García <cristian99garcia@gmail.com>''' + + +def get_clasico(): + """Devuelve la posisión de classic en el combo""" + + cuenta = 0 + clasico = 0 + + for estilo in estilos: + if estilo == 'classic': + clasico = cuenta + + cuenta += 1 + + return clasico + + +def dialogo_cerrar(direccion, buffer, cristianedit, accion): + """Diálogo que cierra el programa o guarda según el usuario""" + + dialog = Gtk.MessageDialog(type=Gtk.MessageType(1)) + dialog.add_buttons(Gtk.STOCK_NO, 0, Gtk.STOCK_YES, 1) + + archivo = direccion.split('/')[-1] + dialog.set_markup('<b>%s</b>' % \ + 'El archivo %s tiene cambios sin guardar' % archivo) + + dialog.format_secondary_text('¿Guardar antes de salir?') + + respuesta = dialog.run() + dialog.destroy() + + if respuesta == 1: + cristianedit.guardar(None, direccion=direccion) + + if accion == 'cerrar': + Gtk.main_quit() + + +def dialogo_reemplazar(direccion, buffer, cristianedit): + """Preguntar si reemplazar o no, cuando la dirección ya existe""" + + dialog = Gtk.MessageDialog(type=Gtk.MessageType(2)) + + dialog.add_buttons(Gtk.STOCK_NO, 0, Gtk.STOCK_YES, 1) + dialog.set_markup('<b>%s</b>' % 'La dirección especificada ya existe...') + dialog.format_secondary_text( + 'Sí sobrescribe el archivo, se reemplazará su contenido.') + + respuesta = dialog.run() + dialog.destroy() + + if respuesta == 1: + escritura = open(direccion, 'w') + + escritura.write(cristianedit.get_texto()) + buffer.set_modified(False) + + escritura.close() + + else: + dialog.destroy() + + +class Menu(Gtk.MenuBar): + """Barra de Menú""" + + def __init__(self, padre): + + Gtk.Menu.__init__(self) + + items = [] + self.padre = padre + self.grupo = Gtk.AccelGroup() + self.recientes = [] + + self.ventana = self.padre.get_parent().get_parent() + self.ventana.add_accel_group(self.grupo) + + menu_archivo = Gtk.MenuItem('_Archivo') + menu_recientes = Gtk.MenuItem('_Recientes') + menu_editar = Gtk.MenuItem('_Editar') + menu_ayuda = Gtk.MenuItem('Ay_uda') + + menu_archivo.set_use_underline(True) + menu_recientes.set_use_underline(True) + menu_editar.set_use_underline(True) + menu_ayuda.set_use_underline(True) + + self.add(menu_archivo) + self.add(menu_editar) + self.add(menu_ayuda) + + archivo = Gtk.Menu() + self.menu_recientes = Gtk.Menu() + editar = Gtk.Menu() + ayuda = Gtk.Menu() + + menu_archivo.set_submenu(archivo) + menu_editar.set_submenu(editar) + menu_recientes.set_submenu(self.menu_recientes) + menu_ayuda.set_submenu(ayuda) + + self.menu_item('_Nuevo', self.padre.pagina_nueva, archivo, 'N') + + archivo.append(Gtk.SeparatorMenuItem()) + self.menu_item('_Abrir', self.padre.abrir, archivo, 'O') + self.menu_item('_Guardar', self.padre.guardar, archivo, 'S') + self.menu_item('Guardar _como', self.padre.guardar_como, archivo) + + archivo.append(Gtk.SeparatorMenuItem()) + archivo.append(menu_recientes) + + self.menu_item('_Deshacer', self.deshacer, editar, 'Z') + self.menu_item('_Rehacer', self.rehacer, editar, 'R') + + editar.append(Gtk.SeparatorMenuItem()) + self.menu_item('In_sertar fecha y hora', self.padre.text_hora, editar) + + editar.append(Gtk.SeparatorMenuItem()) + self.menu_item('_Estado del archivo', self.padre.estado, editar, 'E') + + editar.append(Gtk.SeparatorMenuItem()) + self.menu_item('Mostrar _teclado...', self.teclado, editar, 'T') + + self.menu_item('Acerca _de', self.creditos, ayuda) + + def teclado(self, widget): + + texto = widget.get_label() + + if texto == 'Mostrar _teclado...': + self.padre.mostrar_teclado(True) + widget.set_label('Ocultar _teclado') + + else: + self.padre.mostrar_teclado(False) + widget.set_label('Mostrar _teclado...') + + def creditos(self, widget): + """Muestra el diálogo con los créditos""" + + Creditos(self.padre.get_parent().get_parent()) + + def deshacer(self, widget): + """Obtiene el view actual y le pasa deshacer""" + + view = self.padre.get_view() + view.deshacer() + + def rehacer(self, widget): + """Obtiene el view actual y le pasa rehacer""" + + view = self.padre.get_view() + view.rehacer() + + def menu_item(self, etiqueta, callback, menu, letra=None, devolver=None): + """Creando los item para los menús""" + item = Gtk.MenuItem(etiqueta) + item.connect('activate', callback) + menu.append(item) + item.set_use_underline(True) + + if letra: + item.add_accelerator('activate', self.grupo, ord(letra), + Gdk.ModifierType(4), Gtk.AccelFlags(1)) + + if devolver: + return item + + def abrir_reciente(self, widget): + """Abre un archivo desde un menuitem""" + + direccion = widget.get_label().split(' ')[-1] + self.padre.abrir(None, direccion) + + def actualizar_recientes(self, recientes): + """Agregar menuitems por cada archivo reciente""" + + self.borrar_recientes() + numero = 1 + + if ', ' in recientes: + lista = recientes.split(', ') + + for archivo in lista: + if os.path.exists(archivo) and not archivo in self.recientes: + asbpath = os.path.abspath(archivo) + + if os.path.exists(asbpath): + direccion = asbpath + + else: + direccion = archivo + + texto = '_' + str(numero) + ' - ' + direccion + + self.menu_item(texto, self.abrir_reciente, + self.menu_recientes) + + self.recientes.append(archivo) + numero += 1 + + else: + self.menu_recientes.get_parent().get_parent().set_sensitive(False) + + self.show_all() + + def borrar_recientes(self): + + for item in self.menu_recientes: + self.menu_recientes.remove(item) + + while len(self.recientes) != 0: + for x in self.recientes: + self.recientes.remove(x) + + +class Buffer(GtkSource.Buffer): + """Buffer de Texto""" + + def __init__(self, combo): + + GtkSource.Buffer.__init__(self) + + self.combo = combo + self.lenguaje = None + + def buscar_lenguaje(self, lugar, combo): + """Busca el lenguaje de programación en un archivo + al guardarlo o abrirlo, sí es que tiene uno""" + + tipo = list(mimetypes.guess_type(lugar))[0] + encontrado = False + + for id in lenguajes: + lenguaje = lenguaje_manager.get_language(id) + + if lenguaje and len(lenguaje.get_mime_types()): + mime = lenguaje.get_mime_types()[0] + + if tipo == mime: + self.set_highlight_syntax(True) + self.set_language(lenguaje) + + list_num = lenguajes.index(id) + 1 + self.lenguaje = lenguaje + encontrado = True + + combo.set_active(list_num) + + if not encontrado: + self.set_highlight_syntax(False) + + self.lenguaje = None + combo.set_active(0) + + def get_lenguaje(self): + """Devuelve el lenguaje seleccionado""" + + return self.lenguaje + + +class View(GtkSource.View): + """Visor de Texto""" + + def __init__(self, buffer=None): + + GtkSource.View.__init__(self) + + self.set_buffer(buffer) + self.set_size_request(400, 500) + + def deshacer(self): + """Deshace cambios""" + + if self.get_buffer().can_undo(): + self.get_buffer().undo() + + def rehacer(self): + """Rehace cambios""" + + if self.get_buffer().can_redo(): + self.get_buffer().redo() + + def configurar(self, enumeracion, + fuente, margen, + is_margen, ajuste, + ajuste_palabras, + tabulador, insertar_espacios, + sangria, tema): + + """Establecer configuración + según los argumentos""" + + self.set_property('show-line-numbers', enumeracion) + self.modify_font(Pango.font_description_from_string(fuente)) + self.set_property('right-margin-position', margen) + self.set_property('show-right-margin', is_margen) + self.set_property('insert-spaces-instead-of-tabs', insertar_espacios) + self.set_tab_width(tabulador) + self.set_property('auto-indent', sangria) + self.get_buffer().set_style_scheme(estilo_manager.get_scheme(tema)) + + if ajuste: + self.set_wrap_mode(Gtk.WrapMode(1)) + + if ajuste and ajuste_palabras: + self.set_wrap_mode(Gtk.WrapMode(2)) + + def buscar_texto(self, texto, enter=None): + """Buscar Texto""" + + buffer = self.get_buffer() + + cursor_mark = buffer.get_insert() + start = buffer.get_iter_at_mark(cursor_mark) + if start.get_offset() == buffer.get_char_count(): + start = buffer.get_start_iter() + + self.seleccionar_texto(texto, start, enter) + + def seleccionar_texto(self, text, start, enter): + """Selecciona el texto solicitado, + y mueve el scrolled sí es necesario""" + + buffer = self.get_buffer() + end = buffer.get_end_iter() + match = start.forward_search(text, 0, end) + + if match: + match_start, match_end = match + + if not enter: + buffer.select_range(match_start, match_end) + + else: + buffer.select_range(match_end, match_start) + + self.scroll_to_iter(match_end, 0.1, 1, 1, 1) + + else: + start = buffer.get_start_iter() + try: + self.seleccionar_texto(text, start, None) + + except RuntimeError: + pass + + +class Notebook(Gtk.Notebook): + """Cuaderno de Fichas""" + + __gsignals__ = { + 'boton-cerrar-clicked': (GObject.SIGNAL_RUN_FIRST, + GObject.TYPE_NONE, (GObject.TYPE_OBJECT,)) + } + + def __init__(self, padre=None): + + Gtk.Notebook.__init__(self) + + self.numero = 0 + self.botones = [] + self.labels = [] + self.padre = padre + + self.set_scrollable(True) + + def agregar(self, objeto, label, barra): + """Agrega una página al Widget clase""" + + hbox = Gtk.HBox() + imagen = Gtk.Image() + imagen.set_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize(4)) + boton = Gtk.Button(None, image=imagen) + + hbox.pack_start(label, False, False, 0) + hbox.pack_start(boton, False, False, 0) + + self.botones.append(boton) + self.labels.append(label) + + vbox = Gtk.VBox() + scrolled = self.crear_scrolled() + + vbox.pack_start(scrolled, True, True, 0) + vbox.pack_start(barra, False, False, 0) + scrolled.add(objeto) + self.append_page(vbox, hbox) + + hbox.show() + boton.show() + label.show() + + self.show_all() + + numero = 0 + for x in self.botones: + x.numero = numero + numero += 1 + + boton.connect('clicked', self.borrar_pagina_desde_boton, vbox) + + def crear_scrolled(self): + """Crea y devuelve un GtkScrolledWindow()""" + + scrolled = Gtk.ScrolledWindow() + scrolled.set_policy(Gtk.PolicyType(1), Gtk.PolicyType(1)) + scrolled.set_shadow_type(Gtk.ShadowType(1)) + + return scrolled + + def borrar_pagina(self, numero=None): + """Borra la página actual""" + + if numero == None: + self.remove_page(self.get_current_page()) + + else: + self.remove_page(numero) + + self.set_show_tabs(self.get_n_pages() > 1) + + def borrar_pagina_desde_boton(self, widget, objeto): + """Borrar página desde el botón de cerrado""" + + self.emit('boton-cerrar-clicked', objeto) + + +class Barra(Gtk.HBox): + """GtkHBox() que simula una GtkToolBar()""" + + def __init__(self, funciones, abrir): + + Gtk.HBox.__init__(self) + + self.funciones = funciones + + self.pack_start(abrir, False, False, 4) + + guardar = self.funciones[0] + nuevo = self.funciones[1] + deshacer = self.funciones[2] + rehacer = self.funciones[3] + ejecutar = self.funciones[4] + seleccionar_fuente = self.funciones[5] + preferencias = self.funciones[6] + buscar = self.funciones[7] + buscar_enter = self.funciones[8] + + self.toolbutton(Gtk.STOCK_SAVE, guardar, 'Guardar archivo') + + self.separador() + self.toolbutton(Gtk.STOCK_NEW, nuevo, 'Nuevo archivo') + + self.separador() + self.toolbutton(Gtk.STOCK_UNDO, deshacer, 'Deshacer cambios') + self.toolbutton(Gtk.STOCK_REDO, rehacer, 'Rehacer cambios') + self.toolbutton(Gtk.STOCK_EXECUTE, ejecutar, 'Ejecutar archivo') + + self.separador() + self.toolbutton(Gtk.STOCK_SELECT_FONT, seleccionar_fuente, + 'Seleccionar fuente de texto') + self.toolbutton(Gtk.STOCK_PREFERENCES, preferencias) + + self.separador() + entry = Gtk.Entry() + entry.props.secondary_icon_stock = 'gtk-find' + entry.connect('changed', buscar) + entry.connect('activate', buscar_enter) + entry.connect('icon-release', buscar_enter) + self.pack_start(entry, False, False, 4) + + self.show_all() + + def separador(self): + """Crea y empaqueta un separador""" + + separador = Gtk.SeparatorToolItem() + separador.set_size_request(10, 10) + self.pack_start(separador, False, False, 0) + + def toolbutton(self, stock, callback, tooltip=None): + """Crea un boton para el Widget clase""" + + toolbutton = Gtk.ToolButton(stock) + toolbutton.connect('clicked', callback) + self.pack_start(toolbutton, False, False, 0) + if tooltip != None: + toolbutton.set_tooltip_text(tooltip) + + +class Navegador(Gtk.FileChooserDialog): + """Navegador de archivos""" + + def __init__(self, titulo, padre, accion, botones): + + Gtk.FileChooserDialog.__init__(self, titulo, None, accion, botones) + + self.set_focus_visible(False) + + if accion == Gtk.FileChooserAction(0): + self.set_select_multiple(True) + + self.set_default_response(1) + + filter = Gtk.FileFilter() + boton = Gtk.Button(None, Gtk.STOCK_CANCEL) + + filter.set_name('Archivos de Texto') + filter.add_mime_type('text/*') + + boton_ok = list(self.action_area)[0] + self.action_area.remove(boton_ok) + self.action_area.add(boton) + self.action_area.add(boton_ok) + self.add_filter(filter) + + boton.connect('clicked', self.cerrar) + boton.show() + + def cerrar(self, widget): + """Destruye al Widget clase""" + + self.destroy() + + +class Barra_Inferior(Gtk.HBox): + """Un GtkHBox() que contiene los + Widgets de la parte inferior de la ventana""" + + def __init__(self): + + Gtk.HBox.__init__(self) + + self.combo = Combo_Lenguajes() + self.b_estado = Gtk.Statusbar() + + self.b_estado.push(0, 'Línea:0, Columna:0') + + self.pack_end(self.b_estado, False, False, 20) + self.pack_end(self.combo, False, False, 0) + + def get_combo(self): + """Devuelve el GtkComboBoxText() + con los lenguajes de programación""" + + return self.combo + + def get_statusbar(self): + """Devuelve la barra de estado""" + + return self.b_estado + + +class Combo_Estilos(Gtk.ComboBoxText): + """Un GtkComboBoxText para mostrar y utilizar + los temas instalados en el sistema""" + + def __init__(self, estilo_principal=0): + + Gtk.ComboBoxText.__init__(self) + + for estilo in estilos: + self.append_text(estilo) + + self.set_active(estilo_principal) + + +class Combo_Lenguajes(Gtk.ComboBoxText): + """Un GtkComboBoxText para mostrar los + lenguajes de programación instalados en el sistema""" + + def __init__(self): + + Gtk.ComboBoxText.__init__(self) + + self.primera_vez = True + + for lenguaje in lenguajes: + self.append_text(lenguaje) + + self.set_active(0) + + def update(self, view, direccion, buffer): + """Muestra el lenguaje del View actual, + esta función sire para cuando se cambia + de página""" + + if direccion != 'Sin dirección': + tipo = list(mimetypes.guess_type(direccion))[0] + + else: + tipo = 'text/plain' + + if not self.primera_vez: + self.buscar_lenguaje(tipo, buffer) + + else: + self.primera_vez = False + + def buscar_lenguaje(self, filename, buffer): + """Busca un lenguaje especifico, + y lo activa en el Widget clase""" + + manager = lenguaje_manager + extension = filename.split('.')[-1] + + if extension != filename and extension in lenguajes: + lenguaje = manager.get_language() + numero = self.index(extension) + + self.set_active(numero) + buffer.set_language(lenguaje) + + else: + language = manager.guess_language(filename, 'algo') + + if language: + buffer.set_highlight_syntax(True) + buffer.set_language(language) + + else: + buffer.set_highlight_syntax(False) + + buffer.buscar_lenguaje(filename) + + def get_lenguajes(self): + """Devuelve la lista con lenguajes ya ordenados por orden alfabetico""" + + return lenguajes + + def get_lenguaje_manager(self): + """Devuelve la variable 'lenguaje_manager'""" + + return lenguaje_manager + + +class DialogoCerrar(Gtk.MessageDialog): + """El díalogo que le pregunta al usuario sí en + realidad quiere borrar la página del GtkNotebook()""" + + def __init__(self, direccion, pagina, notebook, lugares, etiquetas, padre): + + Gtk.MessageDialog.__init__(self, type=Gtk.MessageType(2), + title='Hay cambios sin guardar') + + self.direccion = direccion + self.pagina = pagina + self.notebook = notebook + self.lugares = lugares + self.etiquetas = etiquetas + self.padre = padre + + self.set_markup('<b>%s</b>' % 'Sí cierra, se perderán los cambios') + + boton_cerrar = Gtk.Button(None, Gtk.STOCK_CANCEL) + boton_cerrar.connect('clicked', self.cerrar) + self.action_area.add(boton_cerrar) + + boton_no = Gtk.Button('_No guardar') + boton_no.connect('clicked', self.borrar) + self.action_area.add(boton_no) + + boton_si = Gtk.Button(None, Gtk.STOCK_SAVE) + boton_si.connect('clicked', self.guardar) + self.action_area.add(boton_si) + + self.show_all() + + def cerrar(self, widget): + """Cierra la clase destrullendola""" + + self.destroy() + + def borrar(self, widget): + """Borra la pestaña""" + + self.etiquetas.remove(self.etiquetas[self.pagina]) + self.lugares.remove(self.lugares[self.pagina]) + self.notebook.borrar_pagina() + self.cerrar(None) + self.change_page(self, None, None) + + def guardar(self, widget): + """Guarda el archivo antes de cerrar la pestaña""" + + if not self.direccion == 'Sin dirección': + self.padre.guardar(None, direccion=self.direccion) + + else: + self.padre.guardar_como(None) + + self.borrar(None) + + +class DialogoEstado(Gtk.Dialog): + + def __init__(self, padre, notebook): + + Gtk.Dialog.__init__(self) + + self.padre = padre + self.notebook = notebook + + self.label_caracteres = Gtk.Label() + self.label_lineas = Gtk.Label() + self.label_modificado = Gtk.Label() + self.label_fuente = Gtk.Label() + self.label_lugar = Gtk.Label() + self.label_pestania = Gtk.Label() + + self.actualizar_estado() + + self.tabla = Gtk.Table(7, 2, False) + + label_caracteres = Gtk.Label('Cantidad de caractéres:') + label_lineas = Gtk.Label('Cantidad de líneas:') + label_lugar = Gtk.Label('Ubicación de archivo:') + label_modificado = Gtk.Label('Estado de modificación:') + label_fuente = Gtk.Label('Fuente de Texto:') + label_pestania = Gtk.Label('Pestaña actual:') + + lista = [self.label_caracteres, self.label_lineas, self.label_lugar, + self.label_modificado, self.label_pestania] + + for label in lista: + label.modify_font(Pango.FontDescription('bold')) + + fuente = self.padre.get_fuente() + fuente = Pango.FontDescription(fuente) + fuente.set_size(14000) + self.label_fuente.modify_font(fuente) + + self.tabla.attach(label_caracteres, 0, 1, 0, 1) + self.tabla.attach(label_lineas, 0, 1, 1, 2) + self.tabla.attach(label_lugar, 0, 1, 2, 3) + self.tabla.attach(label_modificado, 0, 1, 3, 4) + self.tabla.attach(label_fuente, 0, 1, 4, 5) + self.tabla.attach(label_pestania, 0, 1, 5, 6) + + self.tabla.attach(self.label_caracteres, 1, 2, 0, 1) + self.tabla.attach(self.label_lineas, 1, 2, 1, 2) + self.tabla.attach(self.label_lugar, 1, 2, 2, 3) + self.tabla.attach(self.label_modificado, 1, 2, 3, 4) + self.tabla.attach(self.label_fuente, 1, 2, 4, 5) + self.tabla.attach(self.label_pestania, 1, 2, 5, 6) + + self.vbox.pack_start(self.tabla, True, True, 0) + + boton_cerrar = Gtk.Button(None, Gtk.STOCK_CLOSE) + boton_cerrar.connect('clicked', self.cerrar) + self.action_area.add(boton_cerrar) + + boton_actualizar = Gtk.Button('_Actualizar estado') + boton_actualizar.set_use_underline(True) + boton_actualizar.connect('clicked', self.actualizar_estado) + self.action_area.add(boton_actualizar) + + def actualizar_estado(self, *args): + """Actualiza la información que se + guarda y muestran en las etiquetas""" + + buffer = self.padre.get_buffer() + direccion = self.padre.get_direccion() + fuente = self.padre.get_fuente() + pagina = self.notebook.get_current_page() + 1 + paginas = self.notebook.get_n_pages() + + self.label_caracteres.set_text(str(buffer.get_char_count())) + self.label_lineas.set_text(str(buffer.get_line_count())) + self.label_fuente.set_text(fuente) + self.label_lugar.set_text(direccion) + self.label_pestania.set_text(str(pagina) + '/' + str(paginas)) + + if buffer.get_modified(): + self.label_modificado.set_text('Modificado') + + else: + self.label_modificado.set_text('Sin modificar') + + def cerrar(self, widget): + """Destruye al Widget clase""" + + self.destroy() + + +class Selector_de_Fuente(Gtk.FontSelectionDialog): + + __gsignals__ = { + 'font-changed': (GObject.SIGNAL_RUN_FIRST, + GObject.TYPE_NONE, (GObject.TYPE_STRING,)) + } + + def __init__(self, fuente): + + Gtk.FontSelectionDialog.__init__(self, title='Fuente de texto...') + + self.fuente = fuente + + close_button = Gtk.Button(None, Gtk.STOCK_CLOSE) + ok_button = Gtk.Button(None, Gtk.STOCK_OK) + + for x in list(self.action_area): + x.destroy() + + self.set_font_name(self.fuente) + + self.action_area.add(close_button) + self.action_area.add(ok_button) + + ok_button.connect('clicked', self.aplicar_fuente) + close_button.connect('clicked', self.cerrar) + + self.show_all() + + def aplicar_fuente(self, widget): + """Emite la señal 'font-changed'""" + + self.emit('font-changed', self.get_font_name()) + + def cerrar(self, widget): + """Destruye al Widget clase""" + + self.destroy() + + +class Configuraciones(Gtk.Dialog): + + def __init__(self, padre, + enumeracion, + margen, is_margen, + ajuste, ajuste_palabras, + tabulador, insertar_espacios, + sangria, tema): + + ventana = padre.get_parent().get_parent() + + Gtk.Dialog.__init__(self, 'Configurar CristianEdit 2', ventana) + + self.padre = padre + self.enumeracion = enumeracion + self.margen = margen + self.is_margen = is_margen + self.ajuste = ajuste + self.ajuste_palabras = ajuste_palabras + self.tabulador = tabulador + self.insertar_espacios = insertar_espacios + self.sangria = sangria + self.tema = tema + self.lista = [self.enumeracion, + self.margen, self.is_margen, + self.ajuste, self.ajuste_palabras, + self.tabulador, + self.insertar_espacios, + self.sangria, self.tema] + + self.set_resizable(False) + + notebook = Gtk.Notebook() + vbox1 = Gtk.VBox() + vbox2 = Gtk.VBox() + vbox1.a = Gtk.HBox() + vbox1.b = Gtk.HBox() + + self.vbox.pack_start(notebook, True, True, 0) + + boton_enumeracion = Gtk.CheckButton('Mostrar los números de líneas') + boton_margen = Gtk.CheckButton('Mostrar margen derecho en la columna:') + boton_ajuste1 = Gtk.CheckButton('Ajuste de Texto') + boton_ajuste2 = Gtk.CheckButton('No dividir palabras en dos líneas') + boton_insertar = Gtk.CheckButton( + 'Insertar espacios en lugar de tabulaciones') + boton_sangria = Gtk.CheckButton('Sangría automatica') + + ajuste1 = Gtk.Adjustment(self.margen, 1, 1000, 1, 10) + ajuste2 = Gtk.Adjustment(self.tabulador, 1, 30, 1, 10) + spin1 = Gtk.SpinButton() + spin2 = Gtk.SpinButton() + + label1 = Gtk.Label('Editor') + label2 = Gtk.Label('Taulador') + label3 = Gtk.Label('Sangría') + label4 = Gtk.Label('Tema de colores') + + l = [label1, label2, label3, label4] + for x in l: + x.modify_font(Pango.FontDescription('bold')) + + boton_margen.set_active(self.is_margen) + boton_enumeracion.set_active(self.enumeracion) + spin1.set_adjustment(ajuste1) + spin2.set_adjustment(ajuste2) + boton_ajuste1.set_active(self.ajuste) + boton_ajuste2.set_active(self.ajuste_palabras) + boton_insertar.set_active(self.insertar_espacios) + boton_sangria.set_active(self.sangria) + + spin1.set_sensitive(boton_margen.get_active()) + boton_ajuste2.set_sensitive(boton_ajuste1.get_active()) + + boton_enumeracion.connect('clicked', self.change_enumeracion) + spin1.connect('value-changed', self.margen_changed) + spin2.connect('value-changed', self.tabulador_changed) + boton_margen.connect('clicked', self.is_margen_changed, spin1) + boton_ajuste1.connect('clicked', self.change_ajuste, boton_ajuste2) + boton_ajuste2.connect('clicked', self.change_ajuste_palabras) + boton_insertar.connect('clicked', self.insertar_espacios_changed) + boton_sangria.connect('clicked', self.sangria_changed) + + vbox1.pack_start(label1, False, False, 10) + vbox1.pack_start(boton_enumeracion, False, False, 0) + vbox1.pack_start(vbox1.a, False, False, 0) + vbox1.pack_start(label2, False, False, 10) + vbox1.pack_start(vbox1.b, False, False, 0) + vbox1.pack_start(boton_sangria, False, False, 0) + vbox1.pack_start(boton_insertar, False, False, 0) + vbox1.a.pack_start(boton_margen, False, False, 0) + vbox1.a.pack_start(spin1, False, False, 0) + vbox1.b.pack_start(Gtk.Label('Ancho del tabulador:'), False, False, 0) + vbox1.b.pack_start(spin2, False, False, 0) + vbox1.pack_start(label3, False, False, 10) + vbox1.pack_start(boton_ajuste1, False, False, 0) + vbox1.pack_start(boton_ajuste2, False, False, 0) + + combo_estilos = Combo_Estilos(estilos.index(self.tema)) + + combo_estilos.connect('changed', self.estilo_changed) + + vbox2.pack_start(label4, False, False, 10) + vbox2.pack_start(combo_estilos, False, False, 0) + + notebook.append_page(vbox1, Gtk.Label('Editor')) + notebook.append_page(vbox2, Gtk.Label('Temas de colores')) + + boton = Gtk.Button(None, Gtk.STOCK_OK) + boton.connect('clicked', self.cerrar) + self.action_area.add(boton) + + def estilo_changed(self, widget): + """Establece en tema de colores""" + + self.tema = estilos[widget.get_active()] + self.lista[8] = self.tema + self.padre.set_configuracion(self.lista) + + def sangria_changed(self, widget): + """Establece o desabilita la sangría automatica""" + + self.sangria = widget.get_active() + self.lista[7] = self.sangria + + self.padre.set_configuracion(self.lista) + + def insertar_espacios_changed(self, widget): + """Establece sí resaltar la línea actual o no""" + + self.insertar_espacios = widget.get_active() + self.lista[6] = self.insertar_espacios + + self.padre.set_configuracion(self.lista) + + def tabulador_changed(self, widget): + """Establece el ancho del tabulador""" + + view = self.padre.get_view() + self.tabulador = widget.get_value() + + self.lista[5] = self.tabulador + self.padre.set_configuracion(self.lista) + + def change_ajuste(self, widget, boton): + """Activa/Desactiva ajuste de texto""" + + view = self.padre.get_view() + estado = widget.get_active() + + boton.set_sensitive(estado) + + if estado: + view.set_wrap_mode(Gtk.WrapMode(1)) + self.ajuste_palabras = False + + else: + view.set_wrap_mode(Gtk.WrapMode(0)) + + if estado and boton.get_active() and boton.get_sensitive: + view.set_wrap_mode(Gtk.WrapMode(2)) + self.ajuste_palabras = True + + self.ajuste = estado + self.lista[3] = self.ajuste + self.lista[4] = self.ajuste_palabras + + self.padre.set_configuracion(self.lista) + + def change_ajuste_palabras(self, widget): + """Ajuste por palabras, no divide las palabras en dos líneas""" + + view = self.padre.get_view() + + if widget.get_active(): + view.set_wrap_mode(Gtk.WrapMode(2)) + + else: + view.set_wrap_mode(Gtk.WrapMode(1)) + + self.ajuste_palabras = widget.get_active() + + self.lista[3] = self.ajuste + self.lista[4] = self.ajuste_palabras + self.padre.set_configuracion(self.lista) + + def change_enumeracion(self, widget): + """Hace que la enumeración sea igual al + estado de activación del botón""" + + self.enumeracion = widget.get_active() + self.lista[0] = self.enumeracion + + self.padre.set_configuracion(self.lista) + + def margen_changed(self, widget): + """Establece en la columna en la + que se muestra el margen derecho""" + + self.margen = widget.get_value() + self.lista[1] = self.margen + + self.padre.set_configuracion(self.lista) + + def is_margen_changed(self, widget, spin): + """Establece sí el usuario quiere o no margen derecho""" + + self.is_margen = widget.get_active() + spin.set_sensitive(self.is_margen) + + self.lista[2] = self.is_margen + self.padre.set_configuracion(self.lista) + + def cerrar(self, widget): + """Destruir al Widget clase""" + + self.destroy() + + +class DialogoAdvertencia(Gtk.Dialog): + + def __init__(self, padre, direccion, cristianedit): + + Gtk.Dialog.__init__(self, 'Hay cambios sin guardar', + padre, Gtk.DialogFlags.MODAL, + buttons=(Gtk.STOCK_CANCEL, 0, + Gtk.STOCK_OK, 1)) + + self.direccion = direccion + self.cristianedit = cristianedit + + if direccion == 'Sin dirección': + nombre = 'Sin título' + + else: + nombre = direccion.split('/')[-1] + + label = Gtk.Label('El archivo %s se ha modificado y no se han guardado\ + los cambios, ¿Desdea guardar antes de salir?' % nombre) + label.modify_font(Pango.FontDescription('bold')) + + respuesta = self.run() + + if respuesta == 0: + Gtk.main_quit() + + elif respuesta == 1: + self.cristianedit.guardar(None, self.direccion) + + +class Teclado(Gtk.Dialog): + + def __init__(self, padre): + + Gtk.Dialog.__init__(self) + + self.estado = 'minusculas' + self.padre = padre + + self.set_title('Teclado de CristianEdit 2') + self.set_resizable(False) + + vbox = Gtk.VBox() + self.vbox.hbox = Gtk.HBox() + self.vbox.vbox = Gtk.VBox() + self.vbox.hbox0 = Gtk.HBox() + self.vbox.hbox1 = Gtk.HBox() + self.vbox.hbox2 = Gtk.HBox() + self.vbox.hbox3 = Gtk.HBox() + self.vbox.hbox4 = Gtk.HBox() + self.vbox.hbox5 = Gtk.HBox() + self.vbox.hbox6 = Gtk.HBox() + + self.vbox.pack_start(self.vbox.hbox, False, False, 0) + self.vbox.hbox.pack_start(self.vbox.vbox, True, True, 0) + self.vbox.hbox.pack_start(vbox, True, True, 0) + self.vbox.vbox.pack_start(self.vbox.hbox0, False, False, 10) + self.vbox.vbox.pack_start(self.vbox.hbox1, False, False, 0) + self.vbox.vbox.pack_start(self.vbox.hbox2, False, False, 0) + self.vbox.vbox.pack_start(self.vbox.hbox3, False, False, 0) + self.vbox.vbox.pack_start(self.vbox.hbox4, False, False, 10) + self.vbox.vbox.pack_start(self.vbox.hbox5, False, False, 0) + self.vbox.vbox.pack_start(self.vbox.hbox6, False, False, 10) + + borrar = Gtk.Button('Borrar') + borrar.connect('pressed', self.borrar) + vbox.pack_start(borrar, False, False, 4) + + enter = Gtk.Button('Enter') + enter.connect('pressed', self.clic, '\n') + vbox.pack_start(enter, True, True, 10) + + espacio = Gtk.Button('Espacio') + espacio.connect('pressed', self.clic, ' ') + self.vbox.hbox6.pack_start(espacio, True, True, 10) + + self.lista0 = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'] + self.lista1 = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'] + self.lista2 = ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ñ'] + self.lista3 = ['z', 'x', 'c', 'v', 'b', 'n', 'm'] + self.lista4 = ['á', 'é', 'í', 'ó', 'ú'] + self.lista5 = ['¿', '?', '¡', '+', '*', '-', '{', '}', '[', ']', "'"] + + for x in self.lista5: + boton = Gtk.Button(x) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox5.pack_start(boton, False, False, 0) + + self.recargar() + + boton_cambio = Gtk.Button('_Mostrar Mayúsculas') + boton_cambio.set_use_underline(True) + boton_cambio.connect('clicked', self.cambio) + self.action_area.add(boton_cambio) + + boton_cerrar = Gtk.Button(None, Gtk.STOCK_CLOSE) + boton_cerrar.connect('clicked', self.cerrar) + self.action_area.add(boton_cerrar) + + self.action_area.show() + boton_cerrar.show() + + def cerrar(self, widget): + """Destruye al Widget clase""" + + self.destroy() + + def recargar(self): + """Borra y crea los botones nuevamente""" + + for x in self.vbox.hbox0: + x.destroy() + + for x in self.vbox.hbox1: + x.destroy() + + for x in self.vbox.hbox2: + x.destroy() + + for x in self.vbox.hbox3: + x.destroy() + + for x in self.vbox.hbox4: + x.destroy() + + for letra0 in self.lista0: + boton = Gtk.Button(letra0) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox0.pack_start(boton, False, False, 0) + + for letra1 in self.lista1: + boton = Gtk.Button(letra1) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox1.pack_start(boton, False, False, 0) + + for letra2 in self.lista2: + boton = Gtk.Button(letra2) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox2.pack_start(boton, False, False, 0) + + for letra3 in self.lista3: + boton = Gtk.Button(letra3) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox3.pack_start(boton, False, False, 0) + + for letra4 in self.lista4: + boton = Gtk.Button(letra4) + boton.modify_font(Pango.FontDescription('bold')) + boton.connect('pressed', self.clic) + self.vbox.hbox4.pack_start(boton, False, False, 0) + + self.show_all() + + def cambio(self, widget): + """Cambia las letras por mayúsculas a minúsculas y viceversa""" + + if self.estado != 'minusculas': + self.lista0 = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'] + self.lista1 = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'] + self.lista2 = ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ñ'] + self.lista3 = ['z', 'x', 'c', 'v', 'b', 'n', 'm'] + self.lista4 = ['á', 'é', 'í', 'ó', 'ú'] + self.estado = 'minusculas' + widget.set_label('_Mostrar Mayúsculas') + + else: + self.lista0 = ['!', '"', '#', '$', '%', '&', '/', '(', ')', '='] + self.lista1 = ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'] + self.lista2 = ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ñ'] + self.lista3 = ['Z', 'X', 'C', 'V', 'B', 'N', 'M'] + self.lista4 = ['Á', 'É', 'Í', 'Ó', 'Ú'] + self.estado = 'mayusculas' + widget.set_label('_Mostrar Minúsculas') + + self.recargar() + + def clic(self, widget, especial=None): + """Escribe el texto""" + + buffer = self.padre.get_buffer() + + if not especial: + texto = widget.get_label() + + else: + texto = especial + + buffer.insert_at_cursor(texto) + + def borrar(self, widget): + """Borrar el carácter actual""" + + buffer = self.padre.get_buffer() + + if buffer.get_selection_bounds(): + start, end = buffer.get_bounds() + inicio, fin = buffer.get_selection_bounds() + + texto_start = list(buffer.get_text(start, inicio, 0)) + texto_end = list(buffer.get_text(fin, end, 0)) + + string1 = '' + string2 = '' + + for x1 in texto_start: + string1 = string1 + x1 + + for x2 in texto_end: + string1 = string1 + x2 + + else: + start, fin = buffer.get_bounds() + actual = buffer.get_iter_at_mark(buffer.get_insert()) + numero = actual.get_offset() + + texto_start = list(buffer.get_text(start, actual, 0))[:numero - 1] + texto_end = list(buffer.get_text(actual, fin, 0))#[numero:] + string1 = '' + string2 = '' + + for x1 in texto_start: + string1 = string1 + x1 + + for x2 in texto_end: + string2 = string2 + x2 + + buffer.set_text(string1 + string2) + + +class Terminal_Toolbar(Gtk.Toolbar): + + def __init__(self, padre): + + Gtk.Toolbar.__init__(self) + + self.padre = padre + + self.toolbutton(Gtk.STOCK_NEW, 'Nueva terminal', self.crear_pagina) + + def crear_pagina(self, widget): + """Llama a la función de + CristianEdit con el mismo nombre""" + + self.padre.crear_pagina() + + def toolbutton(self, stock, tooltip=None, callback=None): + """Crea un boton para el Widget clase""" + + toolbutton = Gtk.ToolButton(stock) + self.add(toolbutton) + + if callback: + toolbutton.connect('clicked', callback) + + if tooltip != None: + toolbutton.set_tooltip_text(tooltip) + + +class Terminal(Vte.Terminal): + + def configurar(self): + """Configura al Widget clase""" + + #shape: 0: Normal - Block + # 1: Barra simple - Ibeam + # 2: Guión bajo - Underline + + shape = Vte.TerminalCursorShape(2) + fg_color = '#00FF00' + bg_color = '#000000' + lineas = 1000 + fuente = 'Monospace' + transparente = True + nivel = 0.50 + + self.set_cursor_shape(shape) + self.set_colors(Gdk.color_parse(fg_color), + Gdk.color_parse(bg_color), []) + + self.set_scrollback_lines(lineas) + self.set_font(Pango.FontDescription(fuente)) + self.set_background_transparent(transparente) + self.set_background_saturation(nivel) + + def __init__(self, direccion, emulacion): + + Vte.Terminal.__init__(self) + + vteflags = Vte.PtyFlags(1) + lista = ['algo'] + glibflags = GLib.SpawnFlags(1) + algo = 'algo' + + self.configurar() + + #banderas de vte, dirección, emulación, lista, banderas de glib, función + + self.fork_command_full(vteflags, + direccion, + emulacion, + lista, + glibflags, + self.benvienida, + algo) + + def benvienida(self, widget): + """Imprime un texto cuando + recién se crea el Widget clase""" + + print BIENVENIDA + + def tecla(self, widget, event): + """Obtiene el evento de teclado y + llama a la función evento""" + + tecla = Gdk.keyval_name(event.keyval) + self.evento(event) + + def evento(self, event): + """Reacciona a los eventos de teclado""" + + pass + + +class Terminal_Notebook(Gtk.Notebook): + + __gsignals__ = { + 'boton-cerrar-clicked': (GObject.SIGNAL_RUN_FIRST, + GObject.TYPE_NONE, (GObject.TYPE_OBJECT,)) + } + + def __init__(self): + + Gtk.Notebook.__init__(self) + + self.set_scrollable(True) + + def nueva_pagina(self, objeto, label): + """Crea una página al Widget clase""" + + vbox = Gtk.VBox() + scrolled = Gtk.ScrolledWindow() + hbox = Gtk.HBox() + boton = Gtk.ToolButton(Gtk.STOCK_CLOSE) + + hbox.pack_start(label, False, False, 0) + hbox.pack_start(boton, False, False, 0) + + vbox.add(scrolled) + scrolled.add(objeto) + + self.append_page(vbox, hbox) + + hbox.show_all() + + boton.connect('clicked', self.cerrar, vbox) + + def borrar_pagina(self, numero=None): + """Borra una página según un número, o la actual""" + + if not numero: + numero = self.get_current_page() + + self.remove_page(numero) + + def desplazar_al_final(self): + """Activa la última pestaña""" + + numero = self.get_n_pages() + for x in range(0, numero): + self.next_page() + + def cerrar(self, widget, objeto): + """Emite la señal 'boton-cerrar-clicked'""" + + self.emit('boton-cerrar-clicked', objeto) diff --git a/Iconos/CristianEdit.png b/Iconos/CristianEdit.png Binary files differnew file mode 100644 index 0000000..6e19686 --- /dev/null +++ b/Iconos/CristianEdit.png diff --git a/Iconos/CristianEdit.svg b/Iconos/CristianEdit.svg new file mode 100644 index 0000000..778d34e --- /dev/null +++ b/Iconos/CristianEdit.svg @@ -0,0 +1,180 @@ +<?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" + width="500" + height="500" + id="svg2" + version="1.1" + inkscape:version="0.48.3.1 r9886" + sodipodi:docname="CristianEdit.svg"> + <defs + id="defs4"> + <linearGradient + inkscape:collect="always" + id="linearGradient3790"> + <stop + style="stop-color:#ff0000;stop-opacity:1;" + offset="0" + id="stop3792" /> + <stop + style="stop-color:#ff0000;stop-opacity:0;" + offset="1" + id="stop3794" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient2844"> + <stop + style="stop-color:#0000ff;stop-opacity:1;" + offset="0" + id="stop2846" /> + <stop + style="stop-color:#0000ff;stop-opacity:0;" + offset="1" + id="stop2848" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient2832"> + <stop + style="stop-color:#ff0000;stop-opacity:1;" + offset="0" + id="stop2834" /> + <stop + style="stop-color:#ff0000;stop-opacity:0;" + offset="1" + id="stop2836" /> + </linearGradient> + <linearGradient + id="linearGradient2824"> + <stop + style="stop-color:#00ff00;stop-opacity:1;" + offset="0" + id="stop2826" /> + <stop + style="stop-color:#00ff00;stop-opacity:0;" + offset="1" + id="stop2828" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2824" + id="linearGradient2830" + x1="-45.377811" + y1="557.7807" + x2="142.61597" + y2="11.086151" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2832" + id="linearGradient2838" + x1="-109.91237" + y1="615.60419" + x2="391.86148" + y2="85.157555" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2844" + id="linearGradient2850" + x1="-125.67691" + y1="685.17145" + x2="411.30624" + y2="102.48757" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3790" + id="linearGradient3796" + x1="-27.142857" + y1="785.2193" + x2="597.14288" + y2="784.46094" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.91037028,0,0,0.91037028,-10.405283,70.27791)" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.0800781" + inkscape:cx="283.97885" + inkscape:cy="195.62613" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1024" + inkscape:window-height="545" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <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 + inkscape:label="Capa 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-552.36218)"> + <path + sodipodi:type="arc" + style="fill:url(#linearGradient2830);fill-opacity:1" + id="path2818" + sodipodi:cx="248.49753" + sodipodi:cy="259.58368" + sodipodi:rx="248.49753" + sodipodi:ry="248.49753" + d="m 496.99506,259.58368 a 248.49753,248.49753 0 1 1 -496.99506,0 248.49753,248.49753 0 1 1 496.99506,0 z" + transform="matrix(0.93495935,0,0,0.93495935,20.203051,559.14414)" /> + <path + sodipodi:type="arc" + style="fill:url(#linearGradient2850);fill-opacity:1" + id="path2840" + sodipodi:cx="248.49753" + sodipodi:cy="259.58368" + sodipodi:rx="248.49753" + sodipodi:ry="248.49753" + d="m 496.99506,259.58368 a 248.49753,248.49753 0 1 1 -496.99506,0 248.49753,248.49753 0 1 1 496.99506,0 z" + transform="matrix(0.79929845,0,0,0.79929845,53.91445,594.3595)" /> + <text + xml:space="preserve" + style="font-size:36.414814px;font-style:italic;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:url(#linearGradient3796);fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Comic Sans MS Bold Italic" + x="28.610582" + y="808.52777" + id="text3778"><tspan + sodipodi:role="line" + id="tspan3780" + x="28.610582" + y="808.52777" + style="font-size:65.54665375px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:url(#linearGradient3796);fill-opacity:1;font-family:Comic Sans MS;-inkscape-font-specification:Comic Sans MS Bold Italic">CristianEdit</tspan></text> + </g> +</svg> |