PyDay Rafaela 2010 - Introducción a wxPython

Para no ser menos que Juanjo y Fisa, ¡qué bueno estuvo el PyDay Rafaela 2010! Muchos (muchos) asistentes, muy buena onda, y una chorizeada + fernet a la noche inolvidables… En la sección de Charlas del blog están los slides de mi “Introducción a wxPython”, más los ejemplos de rigor. También [hice propaganda](http://marcelofernandez.info/charlas/Ubuntu Lightning Talk.pdf) de Ubuntu en las Lightning Talks. :-P Acá hay un par de fotos… con los días van a ir apareciendo más cosas en el sito del evento… incluso los videos de las charlas. :-) ...

May 10, 2010 · 1 min · mfernandez

Renderizando PDFs en Python con Poppler II

Hace unos días me llegó un mail de alguien preguntándome cómo, a partir de la parte I de este artículo, hacer un sencillo visor de PDFs con wxPython. Me encontré con algunas dificultades, principalmente que el ScrolledWindow de wxPython no permite actualizarse dinámicamente, o automáticamente según el contenido (esto sí es bastante sencillo en GTK); con lo cual se complicaba hacer zoom, modificar el tamaño de la ventana y adaptar los scrollbars, etc. Sin embargo, con alguna vuelta de más pude armar un ejemplo, que paso a dejar acá: ...

April 15, 2010 · 3 min · mfernandez

Reemplazando texto con expresiones regulares en Python

Hay veces en que uno necesita automatizar tareas, como reemplazar cierto texto por otro bajo ciertas condiciones, y el viejo “%s/cosa/otra/g” del vim nos queda corto. En mi caso en particular, estaba metiendo algunas pequeñas características en PyFpdf, y vi que había algunos archivos .py llenos de llamadas a la función chr(). Claro, PyFpdf es un port más o menos “haragán” ( lazy) de Fpdf para PHP, y el autor original evidentemente encontró más sencillo definir algunas fuentes (en binario) haciendo sucesivas llamadas a la función chr(), como esta: ...

April 2, 2010 · 3 min · mfernandez

Curso de Asterisk

Este es un quick-post como favor a un amigazo que participa de un emprendimiento involucrado en estos cursos de Asterisk… Bitsense empresa dedicada a la implementación de soluciones telefónicas, dará comienzo a su 3er curso de capacitación de Telefonía IP denominado Biac (Bitsense Initial Asterisk Course), el mismo es el primer curso en la Argentina dictado por dos instructores certificados dCAP (Digium-certified Asterisk Professional) junto con el apoyo de certificados Cisco y Juniper. ...

March 30, 2010 · 1 min · mfernandez

Cómo remover el módulo USB 2.0 en Ubuntu 9.10+

Este post va a intentar ser breve y me parece que es bastante técnico, pero puede serle útil a más de uno. Resulta que yo tengo una Impresora Multifunción Samsung SCX-4200, que tiene unos drivers (cerrados) para Linux [1]. Estos drivers sirven para imprimir y escanear, y si bien hoy en día Ubuntu se las arregla bárbaro para imprimir con los drivers libres de SpliX (¡instalación y configuración automágica!), queda pendiente aún el tema del escaneo. ...

March 19, 2010 · 5 min · mfernandez

Virtio - Paravirtualización de I/O

Hace un rato que estoy leyendo sobre virtualización, pero no de CPU, sino de I/O (otro más acá)… muy interesante, me aclaró algunas dudas que tenía, dado que últimamente al configurar este tipo de software se me confundían las cosas :-) Resulta que a nivel de I/O tenemos algo parecido a la virtualización al nivel de CPU: emulación, paravirtualización y ejecución “directa”, por llamarlo de alguna manera. Sugiero leer el artículo para más detalles, pero sólo quiero agregar que recién estamos en la etapa de paravirtualización, y que (en buena hora) Intel y AMD agregaron unidades IOMMU en sus últimos diseños para poder asignar dispositivos directamente a una (o más, según el caso) VM, evitando el Hypervisor y ahorrando ciclos de CPU. Pero esto parece estar verde aún. ...

February 27, 2010 · 2 min · mfernandez

PostgreSQL <strike>8.5</strike> 9.0 - Replicación mejorada

Para los que no están enterados, Streaming Replication es la nueva gran característica de PostgreSQL 9.0 (ex-8.5), todavía en desarrollo. Estoy muy contento por la noticia, realmente era algo pendiente ver integrado algo de esto en PostgreSQL mismo (ya que hay productos y/o versiones modificadas para hacer esto, pero no es lo mismo que “el original”, claro está :-) ) y lo hace cada vez más adecuado para evitar (o al menos dejar a uno la opción de) utilizar motores de bases de datos muy buenas pero caras y propietarias (Oracle) o lamentablemente en problemas políticos/de gestión (MySQL). ...

February 6, 2010 · 2 min · mfernandez

Navegador simple con Python + Webkit/GTK

Hoy me encontré con otro un hilo en la lista de PyAr que me deja un link más que interesante: ¡Existe un binding para usar Webkit sobre GTK desde Python, y lo mejor de todo es que ya está incluido en los repositorios de Ubuntu 9.10! Webkit es un motor de renderizado (“dibujado”) de páginas web, que es utilizado en el corazón en cada vez más navegadores, como Chrome, Safari, Konqueror, etc. Es super completo y veloz; y permite ejecutarse en muchísimas plataformas y sistemas diferentes. Si bien existen otros métodos para embeber un navegador en una aplicación PyGTK, como por ejemplo gtkmozembed (que embebe el motor de Firefox), éste no es muy poderoso, o por lo menos no deja meterle mucha “mano” para personalizarlo, y uno termina teniendo relativamente muy poco “poder”. En cambio con Webkit/GTK se pueden hacer muchas más cosas, tan sólo hace falta ver la documentación y un ejemplo (links al final, claro). :-) ...

November 19, 2009 · 3 min · mfernandez

Visor de Imágenes Simple con PyGTK

Dado que alguien me pidió vía twitter un ejemplo de cómo hacer un zoom de una imagen en PyGTK, hice este ejemplito sencillo que sólo carga una imagen en un widget Gtk.Image. Maneja el movimiento de la imagen con el mouse, las teclas del cursor y hace zoom con F1 (“0 o adaptar a ventana”), F2 (+25%), F3 (+50%), F4(+75%) y F5("%+100 o 1:1"). #!/usr/bin/env python # -*- coding: utf-8 -*- """ SimpleImageViewer - Visor simple de imágenes, de ejemplo, que utiliza PyGTK. Marcelo Fidel Fernández - http://www.marcelofernandez.info Licencia: BSD. Disponible en: http://www.freebsd.org/copyright/license.html TODO: * Dar la opción de usar el scroll del mouse para hacer zoom. * Mejorar el código y peformance (quizás). """ import os import sys import pygtk pygtk.require('2.0') import gtk # Variables globales para el ejemplo; podrían ir en un archivo de configuración, # como por ejemplo 'config.py' e importarlo. # Mapeo de teclas - Ver constantes en el modulo gtk.keysyms import gtk.keysyms as kb # Estructura: teclas (en mayúscula, contempla minúsculas también) # (offset_X_pixeles, offset_Y_pixeles) OFFSET_GRAL = 50 MOVE_KEYS = { kb.Up : (0, -OFFSET_GRAL), # Arriba kb.Down : (0, OFFSET_GRAL), # Abajo kb.Right : (OFFSET_GRAL, 0), # Derecha kb.Left : (-OFFSET_GRAL, 0), # Izquierda } # Estructura: tecla: nivel de zoom (zoom_ratio) ZOOM_KEYS = { kb.F1: 0.0, kb.F2: 25.0, kb.F3: 50.0, kb.F4: 75.0, kb.F5: 100.0, } DEFAULT_IMAGE = '/usr/share/backgrounds/Cherries.jpg' class SimpleImageViewer: def __init__(self, image_file): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.connect("delete_event", self.close_application) self.window.set_position(gtk.WIN_POS_CENTER_ALWAYS) self.window.set_default_size(800, 600) self.pixbuf = gtk.gdk.pixbuf_new_from_file(image_file) self.ancho_pixbuf = float(self.pixbuf.get_width()) self.alto_pixbuf = float(self.pixbuf.get_height()) self.image = gtk.Image() self.image.set_from_pixbuf(self.pixbuf) self.viewport = gtk.Viewport() # No están por defecto, los agrego self.viewport.add_events(gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.BUTTON1_MOTION_MASK) self.viewport.connect('button-press-event', self.on_button_pressed) self.viewport.connect('button-release-event', self.on_button_released) self.viewport.connect('motion-notify-event', self.on_mouse_moved) # Lo conecto a la ventana, ya que siempre tiene el foco self.window.connect('key-press-event', self.on_key_press) self.viewport.add(self.image) self.scrolled_wnd = gtk.ScrolledWindow() self.scrolled_wnd.add(self.viewport) self.window.add(self.scrolled_wnd) self.window.show_all() def _update_image(self, zoom_ratio): """ Updates the image in the widget according to the zoom_ratio Actualiza la imagen en el widget Image con el zoom_ratio de parámetro """ # TODO: Prioriza que encaje el ancho por sobre el alto de la imagen # al estar maximizado. Mejorar. # Obtengo las dimensiones actuales del viewport rect = self.viewport.get_allocation() # Resize de la imagen conservando las proporciones de la imagen if self.ancho_pixbuf > self.alto_pixbuf: base = self.ancho_pixbuf - rect.width ancho = int(rect.width + (base * (zoom_ratio/100))) relacion = (self.alto_pixbuf*100)/self.ancho_pixbuf alto = int(ancho * relacion/100) else: base = self.alto_pixbuf - rect.height alto = int(rect.height + (base * (zoom_ratio/100))) relacion = (self.ancho_pixbuf*100)/self.alto_pixbuf ancho = int(alto * (relacion/100)) scaled_buf = self.pixbuf.scale_simple(ancho, alto, gtk.gdk.INTERP_BILINEAR) self.image.set_from_pixbuf(scaled_buf) def _move_image(self, offset_x, offset_y): """ Moves the image inside the viewport to the specified offset (+ or - pixels) Mueve/Desplaza la imagen del viewport según el offset que se le especifique """ vport = self.viewport xadjust = vport.props.hadjustment newx = xadjust.value + offset_x yadjust = vport.props.vadjustment newy = yadjust.value + offset_y # Si las cosas están dentro de los bordes, seteo if (newx >= xadjust.lower) and \ (newx <= (xadjust.upper - xadjust.page_size)): xadjust.value = newx vport.set_hadjustment(xadjust) if (newy >= yadjust.lower) and \ (newy <= (yadjust.upper - yadjust.page_size)): yadjust.value = newy vport.set_vadjustment(yadjust) def on_key_press(self, widget, event): """ Callback to handle the keys pressed in the main window Callback que maneja las teclas que se presionan en la ventana """ keycode = gtk.gdk.keyval_to_upper(event.keyval) newx = newy = 0 if keycode in MOVE_KEYS.keys(): offset_x, offset_y = MOVE_KEYS[keycode] self._move_image(offset_x, offset_y) elif keycode in ZOOM_KEYS.keys(): self._update_image(ZOOM_KEYS[keycode]) else: return False return True # Con True cancelo el evento def on_mouse_moved(self, widget, event): """ Callback to the mouse movement inside the viewport Callback que es llamado cuando el mouse se mueve en el viewport """ # Ver: http://www.pygtk.org/pygtk2tutorial-es/sec-EventHandling.html if event.is_hint: x, y, state = event.window.get_pointer() else: state = event.state x, y = event.x_root, event.y_root if state & gtk.gdk.BUTTON1_MASK: offset_x = self.prevmousex - x offset_y = self.prevmousey - y self._move_image(offset_x, offset_y) self.prevmousex = x self.prevmousey = y def on_button_pressed(self, widget, event): """ When the user presses the left mouse button, save the x and y pixel positions, and change the cursor. Cuando el usuario presiona el botón izquierdo, guardo los puntos x, y de origen del evento y cambio el cursor a "moviéndose". """ if event.button == 1: self.change_vport_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR)) self.prevmousex = event.x_root self.prevmousey = event.y_root return True def on_button_released(self, widget, event): """ When the user releases the left mouse button, set the normal cursor. Cuando el usuario suelta el botón izquierdo, vuelvo el cursor al normal """ if event.button == 1: self.change_vport_cursor(None) return True def change_vport_cursor(self, type): self.viewport.window.set_cursor(type) def close_application(self, widget, event, data=None): gtk.main_quit() return False if __name__ == "__main__": if len(sys.argv) > 1 and os.path.exists(sys.argv[1]): image_file = sys.argv[1] else: image_file = DEFAULT_IMAGE SimpleImageViewer(image_file) gtk.main() Queda pendiente manejar el scroll del mouse para hacer zoom (ya que GTK mueve el gtk.Scrollwindow que contiene la imagen por defecto). Si bien funciona copiando y pegando esto en un archivo, también pueden descargar el ejemplo desde acá. ...

November 16, 2009 · 5 min · mfernandez

PyCon Argentina 2009, Cappuccino y LLVM

Me gustaría hacer un post bien largo acerca de todo lo que me dejó personalmente la última PyCon Argentina, pero lamentablemente estoy complicado con el tiempo, ya que no sólo quiero leer y escribir acerca de todo el “bombardeo” de información que te deja cada charla, sino que también quisiera investigar un poco cada cosa y dejar acá algo más que solamente los links. Pero bueno, vamos a hacer el intento de resaltar lo primero que me viene a la mente. ...

September 14, 2009 · 3 min · mfernandez