#!/usr/bin/env python # -*- coding:UTF-8 -*- # objetos.py por: # Cristian García # # 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 import commands 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 . import Globales as G class Menu(Gtk.MenuBar): """Barra de Menú""" __gtype_name__ = 'Menu' __gsignals__ = { 'accion': (GObject.SIGNAL_RUN_FIRST, None, (str,)), 'abrir': (GObject.SIGNAL_RUN_FIRST, None, (str,)) } def __init__(self, padre): Gtk.MenuBar.__init__(self) self.padre = padre self.grupo = Gtk.AccelGroup() self.recientes = [] self.ventana = self.get_toplevel() menu_archivo = Gtk.MenuItem('_Archivo') menu_recientes = Gtk.MenuItem('_Recientes') menu_editar = Gtk.MenuItem('_Editar') menu_buscar = Gtk.MenuItem('_Buscar') menu_ayuda = Gtk.MenuItem('Ay_uda') self.menus = [ menu_archivo, menu_recientes, menu_editar, menu_ayuda, menu_buscar] for menu in self.menus: menu.set_use_underline(True) self.add(menu_archivo) self.add(menu_editar) self.add(menu_buscar) self.add(menu_ayuda) archivo = Gtk.Menu() self.menu_recientes = Gtk.Menu() editar = Gtk.Menu() buscar = Gtk.Menu() ayuda = Gtk.Menu() menu_archivo.set_submenu(archivo) menu_editar.set_submenu(editar) menu_buscar.set_submenu(buscar) menu_recientes.set_submenu(self.menu_recientes) menu_ayuda.set_submenu(ayuda) self.menu_item('Nuevo', self.emit_accion, archivo, 'N') archivo.append(Gtk.SeparatorMenuItem()) self.menu_item('Abrir', self.emit_accion, archivo, 'O') self.menu_item('Guardar', self.emit_accion, archivo, 'S') self.menu_item('Guardar Como', self.emit_accion, archivo) archivo.append(Gtk.SeparatorMenuItem()) archivo.append(menu_recientes) self.menu_item('Deshacer', self.emit_accion, editar, 'Z') self.menu_item('Rehacer', self.emit_accion, editar, 'R') editar.append(Gtk.SeparatorMenuItem()) self.menu_item('Insertar fecha y hora', self.emit_accion, editar) editar.append(Gtk.SeparatorMenuItem()) self.menu_item('Estado del archivo', self.emit_accion, editar, 'E') editar.append(Gtk.SeparatorMenuItem()) self.menu_item('Mostrar teclado...', self.emit_accion, editar, 'T') self.menu_item('Reemplazar', self.emit_accion, buscar, 'H') #ajuste = Gtk.Adjustment(2, 0, 100, 1, 1, 0) #escala = Gtk.HScale() #escala.set_adjustment(ajuste) #item = Gtk.MenuItem() #item.add(escala) #editar.append(item) self.menu_item('Acerca de', self.emit_accion, ayuda) def menu_item(self, objeto, callback, menu, letra=None, devolver=None): """Crea los item para los menús""" item = Gtk.MenuItem() menu.append(item) if str(type(objeto)) == "": item.set_label(objeto) else: item.add(objeto) if callback: item.connect('activate', callback) 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.emit('abrir', direccion) def actualizar_recientes(self, lista): """Agregar menuitems por cada archivo reciente.""" self.borrar_recientes() numero = 1 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 self.show_all() def borrar_recientes(self): """Borra todo dato de archivos recientes.""" 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) def emit_accion(self, widget): """Emite la señal 'accion'""" texto = widget.get_label() if '.' in texto: texto = texto.replace('.', '') self.emit('accion', texto) def bloquear_menus(self): """Bloquea todos los menús""" for x in self.menus: x.set_sensitive(False) def desbloquear_menus(self): """Desbloquea todos los menús""" for x in self.menus: x.set_sensitive(True) class Buffer(GtkSource.Buffer): """Buffer de Texto""" def __init__(self): GtkSource.Buffer.__init__(self) self.lenguaje = None self.lenguaje_manager = G.lenguaje_manager self.lenguajes = G.lenguajes def buscar_lenguaje(self, filename, combo): """Busca el lenguaje de programación en un archivo al guardarlo o abrirlo, sí es que tiene uno""" lenguaje = self.lenguaje_manager.guess_language(filename, None) if not lenguaje: tipo = commands.getoutput( 'file %s --mime-type' % filename).split(' ')[1] if 'x-' in tipo: tipo = tipo.replace('x-', '') if 'text/' in tipo: tipo = tipo.replace('text/', '') lenguaje = self.lenguaje_manager.get_language(tipo) if not lenguaje: self.set_highlight_syntax(False) combo.set_active(0) if lenguaje: self.set_highlight_syntax(True) self.set_language(lenguaje) try: nombre = lenguaje.get_name().lower() if nombre == 'c++': nombre = 'cpp' if nombre == '.desktop': nombre = 'desktop' combo.set_active(self.lenguajes.index(nombre) + 1) except: pass def get_lenguaje(self): """Devuelve el lenguaje seleccionado""" return self.lenguaje class View(GtkSource.View): """Visor de Texto""" __gsignals__ = {'cambio-de-busqueda': (GObject.SIGNAL_RUN_FIRST, None, (str,))} def __init__(self, buffer=None): GtkSource.View.__init__(self) self.set_buffer(buffer) self.set_size_request(400, 500) self.lenguaje_manager = G.lenguaje_manager self.lenguajes = G.lenguajes self.estilo_manager = G.estilo_manager self.estilos = G.estilos 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, configuraciones): """Establecer configuración según los argumentos.""" buffer = self.get_buffer() enumeracion = configuraciones['enumeracion'] margen = configuraciones['margen'] is_margen = configuraciones['is_margen'] ajuste = configuraciones['ajuste'] ajuste_palabras = configuraciones['ajuste_palabras'] tabulador = configuraciones['tabulador'] insertar_espacios = configuraciones['insertar_espacios'] sangria = configuraciones['sangria'] tema = configuraciones['tema'] fuente = Pango.font_description_from_string(configuraciones['fuente']) self.set_property('show-line-numbers', enumeracion) self.set_property('right-margin-position', margen) self.set_property('show-right-margin', is_margen) if ajuste: self.set_wrap_mode(Gtk.WrapMode.CHAR) else: self.set_wrap_mode(False) if ajuste and ajuste_palabras: self.set_wrap_mode(Gtk.WrapMode.WORD) self.set_tab_width(tabulador) self.set_property('insert-spaces-instead-of-tabs', insertar_espacios) self.set_property('auto-indent', sangria) buffer.set_style_scheme(self.estilo_manager.get_scheme(tema)) self.modify_font(fuente) def buscar_texto(self, texto, enter=None): """Buscar texto. En lugar que no se encuentre, saca la selección, de método manual, ya que de la automática demora mucho y se cuelga.""" buffer = self.get_buffer() inicio, fin = buffer.get_bounds() texto_actual = buffer.get_text(inicio, fin, 0) posicion = buffer.get_iter_at_mark(buffer.get_insert()) if texto: if texto in texto_actual: 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) self.emit('cambio-de-busqueda', '#000000') else: buffer.select_range(posicion, posicion) self.emit('cambio-de-busqueda', '#FF0000') else: self.emit('cambio-de-busqueda', '#000000') 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""" __gtype_name__ = 'Notebook' __gsignals__ = { 'boton-cerrar-clicked': (GObject.SIGNAL_RUN_FIRST, None, (object,)), 'boton-nuevo-clicked': (GObject.SIGNAL_RUN_FIRST, None, []) } def __init__(self, padre=None): Gtk.Notebook.__init__(self) self.numero = 0 self.botones = [] self.labels = [] self.padre = padre boton = Gtk.ToolButton(Gtk.STOCK_ADD) boton.connect('clicked', self.emit_agregar) self.connect('button-press-event', self.click) self.set_scrollable(True) self.set_action_widget(boton, Gtk.PackType.END) boton.show() def agregar(self, objeto, label, barra): """Agrega una página al Widget clase""" hbox = Gtk.HBox() imagen = Gtk.Image.new_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize.MENU) boton = Gtk.Button() boton.set_relief(Gtk.ReliefStyle.NONE) boton.set_size_request(12, 12) boton.set_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) self.set_current_page(-1) 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 not numero: 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) def emit_agregar(self, widget): """Emita la señal 'boton-nuevo-clicked' para que se le agregue una página nueva""" self.emit('boton-nuevo-clicked') def click(self, widget, event): """Recibe el evento cuando se hace clic encima del widget clase.""" if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3: self.popup.popup(None, None, None, None, event.button, event.time) self.popup.show_all() return True # event has been handled def desplazar_al_final(self): """Se mueve a la última pestaña""" for x in range(0, self.get_n_pages()): self.next_page() class Toolbar(Gtk.Toolbar): """Barra de herramientas.""" __gtype_name__ = 'Toolbar' __gsignals__ = { 'accion': (GObject.SIGNAL_RUN_FIRST, None, (str,)), 'buscar': (GObject.SIGNAL_RUN_FIRST, None, (str, str)) } def __init__(self): Gtk.Toolbar.__init__(self) self.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR); self.toolbutton(Gtk.STOCK_NEW, 'Nuevo') self.separador() self.toolbutton(Gtk.STOCK_OPEN, 'Abrir') self.toolbutton(Gtk.STOCK_SAVE, 'Guardar') self.separador() self.toolbutton(Gtk.STOCK_UNDO, 'Deshacer') self.toolbutton(Gtk.STOCK_REDO, 'Rehacer') self.separador() self.toolbutton(Gtk.STOCK_PREFERENCES, 'Preferencias') self.separador() item = Gtk.ToolItem() self.add(item) self.entry = Gtk.SearchEntry() self.entry.connect('changed', self.emit_buscar, 'Buscar changed') self.entry.connect('activate', self.emit_buscar, 'Buscar activate') item.add(self.entry) self.show_all() def separador(self): """Crea y empaqueta un separador""" separador = Gtk.SeparatorToolItem() separador.set_size_request(10, 10) self.add(separador) def toolbutton(self, stock, tooltip): """Crea un boton para el Widget clase""" toolbutton = Gtk.ToolButton(stock) toolbutton.set_tooltip_text(tooltip) toolbutton.connect('clicked', self.emit_accion, tooltip) self.add(toolbutton) def emit_accion(self, widget, accion): """Emite la señan 'accion' con la acción que se le pasa a esta función.""" self.emit('accion', accion) def emit_buscar(self, widget, accion, *args): """Emite la señal que corresponde al argumento 'senial', con el texto como parámetro.""" texto = widget.get_text() self.emit('buscar', accion, texto) class Navegador(Gtk.FileChooserDialog): """Navegador de archivos""" __gtype_name__ = 'Navegador' def __init__(self, titulo, padre, accion, botones): Gtk.FileChooserDialog.__init__(self, title=titulo, parent=padre, flags=Gtk.DialogFlags.MODAL, buttons=botones) if accion == Gtk.FileChooserAction.OPEN: self.set_select_multiple(True) self.set_default_response(accion) 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 BarraInferior(Gtk.HBox): """Un GtkHBox() que contiene los Widgets de la parte inferior de la ventana""" __gtype_name__ = 'BarraInferior' def __init__(self): Gtk.HBox.__init__(self) self.combo = ComboLenguajes() 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 ComboEstilos(Gtk.ComboBoxText): """Un GtkComboBoxText para mostrar y utilizar los temas instalados en el sistema""" __gtype_name__ = 'ComboEstilos' def __init__(self, estilo_principal=0): Gtk.ComboBoxText.__init__(self) for estilo in G.estilos: self.append_text(estilo) self.set_active(G.estilos.index(estilo_principal)) class ComboLenguajes(Gtk.ComboBoxText): """Un GtkComboBoxText para mostrar los lenguajes de programación instalados en el sistema""" __gtype_name__ = 'ComboLenguajes' def __init__(self): Gtk.ComboBoxText.__init__(self) self.lenguaje_manager = G.lenguaje_manager self.lenguajes = G.lenguajes self.append_text('Texto Plano') for lenguaje in self.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""" print direccion if direccion != 'Sin dirección': tipo = G.get_mime_type(direccion, devolver=True) else: tipo = 'text/plain' self.buscar_lenguaje(tipo, buffer) def get_lenguajes(self): """Devuelve la lista con los lenguajes.""" return self.lenguajes def get_lenguaje_manager(self): """Devuelve la variable 'lenguaje_manager'.""" return self.lenguaje_manager class DialogoReemplazarTexto(Gtk.Dialog): __gsignals__ = { 'solicitar-buffer': (GObject.SIGNAL_RUN_FIRST, None, []) } def __init__(self, padre): Gtk.Dialog.__init__(self) self.set_title('Reemplazar') self.set_border_width(10) self.set_transient_for(padre) self.buffer = False self.mostrado = False self.entrada_buscar = Gtk.Entry() self.entrada_reemplazar = Gtk.Entry() tabla = Gtk.Table(2, 2, False) tabla.attach(Gtk.Label('Texto a buscar:'), 0, 1, 0, 1) tabla.attach(self.entrada_buscar, 1, 2, 0, 1) tabla.attach(Gtk.Label('Texto con el que se reemplazará:'), 0, 1, 1, 2) tabla.attach(self.entrada_reemplazar, 1, 2, 1, 2) hbox = Gtk.HBox() boton_ok = Gtk.Button('Reemplazar') boton_cerrar = Gtk.Button(None, Gtk.STOCK_CLOSE) boton_ok.connect('clicked', self.reemplazar_todo) boton_cerrar.connect('clicked', self.cerrar) hbox.pack_start(boton_ok, False, False, 2) hbox.pack_start(boton_cerrar, False, False, 2) self.vbox.add(tabla) self.vbox.pack_end(hbox, False, False, 10) self.vbox.remove(self.get_children()[0].get_children()[-1]) def reemplazar_todo(self, widget): """Reemplaza el texto.""" self.emit('solicitar-buffer') inicio, fin = self.buffer.get_bounds() texto_buscado = self.entrada_buscar.get_text() texto_solicitado = self.entrada_reemplazar.get_text() texto_existente = self.buffer.get_text(inicio, fin, 0) if texto_buscado and texto_buscado in texto_existente: texto = texto_existente.replace(texto_buscado, texto_solicitado) self.buffer.set_text(texto) def set_text(self, texto): """Setea el texto de la entrada de texto a buscar.""" self.entrada_buscar.set_text(texto) def cerrar(self, widget): """Oculta el widget del que ereda la clase.""" self.hide() self.mostrado = False class DialogoReemplazar(Gtk.MessageDialog): def __init__(self, direccion, buffer, padre, texto): Gtk.MessageDialog.__init__( self, parent=padre, type=Gtk.MessageType.QUESTION) self.set_transient_for(padre) self.set_modal(True) self.set_markup('%s' % 'La dirección especificada ya existe...') self.format_secondary_text( 'Sí sobrescribe el archivo, se reemplazará su contenido.') self.add_buttons( Gtk.STOCK_NO, Gtk.ResponseType.CANCEL, Gtk.STOCK_YES, Gtk.ResponseType.ACCEPT) respuesta = self.run() self.destroy() if respuesta == Gtk.ResponseType.ACCEPT: escritura = open(direccion, 'w') escritura.write(texto) buffer.set_modified(False) escritura.close() class DialogoCerrar(Gtk.Dialog): """El díalogo que le pregunta al usuario sí en realidad quiere borrar la página del GtkNotebook()""" __gtype_name__ = 'DialogoCerrar' def __init__( self, direccion, pagina, notebook, lugares, etiquetas, padre): Gtk.Dialog.__init__( self, title='Hay cambios sin guardar', parent=padre.get_toplevel(), flags=Gtk.DialogFlags.MODAL, buttons=[ Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, 'No guardar', Gtk.ResponseType.NO, Gtk.STOCK_SAVE, Gtk.ResponseType.YES]) self.direccion = direccion self.pagina = pagina self.notebook = notebook self.lugares = lugares self.etiquetas = etiquetas self.padre = padre def cerrar(self, widget): """Cierra el widget clase destrullendolo""" 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) def guardar(self, widget): """Guarda el archivo antes de cerrar la pestaña""" try: if not self.direccion == 'Sin dirección': self.padre.guardar(None, direccion=self.direccion) else: self.padre.guardar_como(None) except: if not self.direccion == 'Sin dirección': self.padre.cristianedit.guardar(None, direccion=self.direccion) else: self.padre.cristianedit.guardar_como(None) self.borrar(None) def add_label(self, string): """Crea un label con el texto y se le agrega""" label = Gtk.Label(string) self.vbox.add(label) label.show() class DialogoEstado(Gtk.Dialog): __gtype_name__ = 'DialogoEstado' __gsignals__ = { 'solicitar-objetos': (GObject.SIGNAL_RUN_FIRST, None, []) } def __init__(self, padre, dict): Gtk.Dialog.__init__(self, title='Estado del archivo.') self.padre = padre self.dict = dict self.label_caracteres = Gtk.Label() self.label_lineas = Gtk.Label() self.label_modificado = Gtk.Label() self.label_fuente = Gtk.Label() self.entry_lugar = Gtk.Entry() self.label_pestania = Gtk.Label() self.entry_lugar.set_editable(False) 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:') entry_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.entry_lugar, self.label_modificado, self.label_pestania] for label in lista: label.modify_font(Pango.FontDescription('bold')) self.tabla.attach(label_caracteres, 0, 1, 0, 1) self.tabla.attach(label_lineas, 0, 1, 1, 2) self.tabla.attach(entry_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.entry_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""" self.emit('solicitar-objetos') buffer = self.dict['buffer'] direccion = self.dict['direccion'] fuente = self.dict['fuente'] pagina = self.dict['pagina'] paginas = self.dict['paginas'] 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) fuente = Pango.FontDescription(self.dict['fuente']) fuente.set_size(14000) self.label_fuente.modify_font(fuente) self.entry_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 set_dict(self, dict): """Setea la variable 'dict' del widget que ejecuta esta función.""" self.dict = dict def cerrar(self, widget): """Destruye al Widget clase""" self.destroy() class Configuraciones(Gtk.Dialog): __gtype_name__ = 'Configuraciones' __gsignals__ = { 'configuration-changed': (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)) } def __init__(self, padre, configuraciones): Gtk.Dialog.__init__(self, 'Preferencias de CristianEdit') self.padre = padre self.configuraciones = configuraciones self.set_resizable(False) self.set_transient_for(padre) self.set_modal(True) notebook = Gtk.Notebook() vbox1 = Gtk.VBox() vbox2 = Gtk.VBox() vbox1.a = Gtk.HBox() vbox1.b = Gtk.HBox() for x in [vbox1, vbox2]: x.set_border_width(10) 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.configuraciones['margen'], 1, 1000, 1, 10) ajuste2 = Gtk.Adjustment( self.configuraciones['tabulador'], 1, 30, 1, 10) spin1 = Gtk.SpinButton() spin2 = Gtk.SpinButton() label1 = Gtk.Label('Editor') label2 = Gtk.Label('Tabulador') label3 = Gtk.Label('Sangría') label4 = Gtk.Label('Tipografías') label5 = Gtk.Label('Tema de colores') for x in [label1, label2, label3, label4, label5]: x.modify_font(Pango.FontDescription('bold')) boton_margen.set_active(self.configuraciones['is_margen']) boton_enumeracion.set_active(self.configuraciones['enumeracion']) spin1.set_adjustment(ajuste1) spin2.set_adjustment(ajuste2) boton_ajuste1.set_active(self.configuraciones['ajuste']) boton_ajuste2.set_active(self.configuraciones['ajuste_palabras']) boton_insertar.set_active(self.configuraciones['insertar_espacios']) boton_sangria.set_active(self.configuraciones['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) boton_fuente = Gtk.FontButton() combo_estilos = ComboEstilos(self.configuraciones['tema']) boton_fuente.set_font(self.configuraciones['fuente']) boton_fuente.connect('font-set', self.fuente_changed) combo_estilos.connect('changed', self.estilo_changed) vbox2.pack_start(label4, False, False, 10) vbox2.pack_start(boton_fuente, False, False, 0) vbox2.pack_start(label5, False, False, 10) vbox2.pack_start(combo_estilos, False, False, 0) notebook.append_page(vbox1, Gtk.Label('Editor')) notebook.append_page(vbox2, Gtk.Label('Tipografías y 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.configuraciones['tema'] = G.estilos[widget.get_active()] self.emit('configuration-changed', self.configuraciones) def fuente_changed(self, widget): """Establece la fuente de texto.""" self.configuraciones['fuente'] = widget.get_font() self.emit('configuration-changed', self.configuraciones) def sangria_changed(self, widget): """Establece o desabilita la sangría automatica""" self.configuraciones['sangria'] = widget.get_active() self.emit('configuration-changed', self.configuraciones) def insertar_espacios_changed(self, widget): """Establece sí resaltar la línea actual o no""" self.configuraciones['insertar_espacios'] = widget.get_active() self.emit('configuration-changed', self.configuraciones) def tabulador_changed(self, widget): """Establece el ancho del tabulador""" self.configuraciones['tabulador'] = widget.get_value() self.emit('configuration-changed', self.configuraciones) def change_ajuste(self, widget, boton): """Activa/Desactiva ajuste de texto""" self.configuraciones['ajuste'] = widget.get_active() boton.set_sensitive(self.configuraciones['ajuste']) if self.configuraciones['ajuste']: self.configuraciones['ajuste_palabras'] = False if boton.get_active() and boton.get_sensitive(): self.configuraciones['ajuste_palabras'] = True self.emit('configuration-changed', self.configuraciones) def change_ajuste_palabras(self, widget): """Ajuste por palabras, no divide las palabras en dos líneas""" self.configuraciones['ajuste_palabras'] = widget.get_active() self.emit('configuration-changed', self.configuraciones) def change_enumeracion(self, widget): """Hace que la enumeración sea igual al estado de activación del botón""" self.configuraciones['enumeracion'] = widget.get_active() self.emit('configuration-changed', self.configuraciones) def margen_changed(self, widget): """Establece en la columna en la que se muestra el margen derecho""" self.configuraciones['margen'] = widget.get_value_as_int() self.emit('configuration-changed', self.configuraciones) def is_margen_changed(self, widget, spin): """Establece sí el usuario quiere o no margen derecho""" self.configuraciones['is_margen'] = widget.get_active() spin.set_sensitive(self.configuraciones['is_margen']) self.emit('configuration-changed', self.configuraciones) def cerrar(self, widget): """Destruir al Widget clase""" self.destroy() class DialogoAdvertencia(Gtk.Dialog): __gtype_name__ = 'DialogoAdvertencia' 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): __gtype_name__ = 'Teclado' def __init__(self, padre, buffer): Gtk.Dialog.__init__(self) self.estado = 'minusculas' self.padre = padre self.buffer = buffer self.set_title('Teclado') self.set_resizable(False) self.set_transient_for(self.padre) self.set_modal(True) 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): """Destruye los botones y los crea 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""" if not especial: texto = widget.get_label() else: texto = especial self.buffer.insert_at_cursor(texto) def borrar(self, widget): """Borrar el carácter actual""" if self.buffer.get_selection_bounds(): start, end = self.buffer.get_bounds() inicio, fin = self.buffer.get_selection_bounds() texto_start = list(self.buffer.get_text(start, inicio, 0)) texto_end = list(self.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 = self.buffer.get_bounds() actual = self.buffer.get_iter_at_mark(self.buffer.get_insert()) numero = actual.get_offset() texto_start = list( self.buffer.get_text(start, actual, 0))[:numero - 1] texto_end = list(self.buffer.get_text(actual, fin, 0)) string1 = '' string2 = '' for x1 in texto_start: string1 = string1 + x1 for x2 in texto_end: string2 = string2 + x2 self.buffer.set_text(string1 + string2)