Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCristian Garcia <cristian99garcia@gmail.com>2013-05-06 17:33:31 (GMT)
committer Cristian Garcia <cristian99garcia@gmail.com>2013-05-06 17:33:31 (GMT)
commitac174acfe7afe947c0f48ed11132159723358001 (patch)
tree573e5701664216f12a070338f45b030f4396722b
Agregando archivos
-rw-r--r--CristianEdit.py92
-rw-r--r--CristianEdit/Creditos.py746
-rw-r--r--CristianEdit/Creditos.pycbin0 -> 37510 bytes
-rw-r--r--CristianEdit/CristianEdit.py694
-rw-r--r--CristianEdit/CristianEdit.pycbin0 -> 20622 bytes
-rw-r--r--CristianEdit/Run.py45
-rw-r--r--CristianEdit/Run.pycbin0 -> 853 bytes
-rw-r--r--CristianEdit/Terminal.py129
-rw-r--r--CristianEdit/Terminal.pycbin0 -> 3661 bytes
-rw-r--r--CristianEdit/__init__.py1
-rw-r--r--CristianEdit/__init__.pycbin0 -> 140 bytes
-rw-r--r--CristianEdit/objetos.py1476
-rw-r--r--CristianEdit/objetos.pycbin0 -> 46349 bytes
-rw-r--r--CristianEdit/objetos.py~1474
-rw-r--r--Iconos/CristianEdit.pngbin0 -> 86183 bytes
-rw-r--r--Iconos/CristianEdit.svg180
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
new file mode 100644
index 0000000..28b5008
--- /dev/null
+++ b/CristianEdit/Creditos.pyc
Binary files differ
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
new file mode 100644
index 0000000..f4ae452
--- /dev/null
+++ b/CristianEdit/CristianEdit.pyc
Binary files differ
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
new file mode 100644
index 0000000..aac70df
--- /dev/null
+++ b/CristianEdit/Run.pyc
Binary files differ
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
new file mode 100644
index 0000000..e432fbe
--- /dev/null
+++ b/CristianEdit/Terminal.pyc
Binary files differ
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
new file mode 100644
index 0000000..35d5e72
--- /dev/null
+++ b/CristianEdit/__init__.pyc
Binary files differ
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
new file mode 100644
index 0000000..47bf98c
--- /dev/null
+++ b/CristianEdit/objetos.pyc
Binary files differ
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
new file mode 100644
index 0000000..6e19686
--- /dev/null
+++ b/Iconos/CristianEdit.png
Binary files differ
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>