<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>El Blog de Marcelo! » programación</title>
	
	<link>http://blog.marcelofernandez.info</link>
	<description>Blog Informático sobre Programación, Software Libre y/o Open Source, Linux, Python y alguna que otra cosa más...</description>
	<lastBuildDate>Sat, 14 Aug 2010 07:14:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ElBlogDeMarcelo_programacion" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="elblogdemarcelo_programacion" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Free Pascal y Lazarus en Ubuntu</title>
		<link>http://blog.marcelofernandez.info/2010/06/free-pascal-y-lazarus-en-ubuntu/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=free-pascal-y-lazarus-en-ubuntu</link>
		<comments>http://blog.marcelofernandez.info/2010/06/free-pascal-y-lazarus-en-ubuntu/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 11:00:18 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=898</guid>
		<description><![CDATA[Creo que la gran mayoría de los programadores debemos recordar aquellos primeros momentos en que uno pasaba tardes y noches enteras escribiendo y escribiendo líneas de código en aquellas XT, AT, Commodores 64/128, etc., sólo por amor al arte y puro fanatismo. Supongo que diríamos lo mismo de los primeros años de facultad, cuando en [...]]]></description>
			<content:encoded><![CDATA[<p>Creo que la gran mayoría de los programadores debemos recordar aquellos primeros momentos en que uno pasaba tardes y noches enteras escribiendo y escribiendo líneas de código en aquellas XT, AT, Commodores 64/128, etc., sólo por amor al arte y puro fanatismo. Supongo que diríamos lo mismo de los primeros años de facultad, cuando en materias de título &#8220;Programación I&#8221; uno repasaba el paradigma de la <a href="http://es.wikipedia.org/wiki/Programaci%C3%B3n_estructurada" target="_blank">Programación Estructurada</a>, casi siempre en el lenguaje de aprendizaje facultativo por excelencia, al menos acá en Argentina: <strong><a href="http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_Pascal" target="_blank">Pascal</a></strong>, usando <a href="http://en.wikipedia.org/wiki/Turbo_pascal" target="_blank">Turbo Pascal</a>, su versión más popular.</p>
<p>Viniendo más acá en el tiempo, y buscando alguna herramienta donde aprovechar mis conocimientos de este lenguaje pero para desarrollar sobre Linux, supe de la existencia de <a href="http://freepascal.org/" target="_blank">Free Pascal</a>, un compilador Pascal libre, multiplataforma y con soporte a diferentes arquitecturas, que genera ejecutables binarios con dependencias mínimas. También estaba disponible <a href="http://www.lazarus.freepascal.org/" target="_blank">Lazarus</a>, su inseparable IDE, no casualmente muy parecido a <a href="http://en.wikipedia.org/wiki/CodeGear_Delphi" target="_blank">Delphi</a>.</p>
<p>El problema era que hasta Ubuntu 9.04 y por una cuestión de madurez, las bibliotecas gráficas de Lazarus aún dependían de GTK 1.2 ( completamente en desuso desde hace &#8220;siglos&#8221; en las distribuciones Linux), y se veía así:</p>
<p style="text-align: center;"><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Lazarus_IDE_GTK1_Linux.png"><img class="aligncenter size-medium wp-image-899" title="Lazarus IDE sobre GTK1" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Lazarus_IDE_GTK1_Linux-300x225.png" alt="" width="300" height="225" /></a></p>
<p>Se veía &#8220;duro&#8221;, anticuado y lejos de toda amigabilidad con el usuario programador, carente de características básicas hoy en día tales como <a href="http://es.wikipedia.org/wiki/Unicode" target="_blank">Unicode</a>, <a href="http://es.wikipedia.org/wiki/Antialiasing" target="_blank">antialiasing</a> y mucho más&#8230; por lo tanto, concluí en ese momento que uno no podía encarar ningún desarrollo nuevo para Linux/Unix usando GTK 1.2 (y por ende Free Pascal+Lazarus), sucedido por la versión 2.0 allá por el año 2002.</p>
<p>En estos días leí un mail en la lista de <a href="http://ubuntu-ar.org/" target="_blank">Ubuntu-Ar</a> sobre Lazarus y Free Pascal, y decidí a instalarlo para echarle un vistazo otra vez. Por suerte la situación cambió bastante, me encontré con un bonito e importante cambio:</p>
<p style="text-align: center;"><a href="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo1.png"><img class="aligncenter size-medium wp-image-900" title="Lazarus sobre GTK 2" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/06/Pantallazo1-300x187.png" alt="" width="300" height="187" /></a></p>
<p>Ahora, con Lazarus sobre GTK 2, ¡sí que está mucho más decente! Junto a <a href="http://es.wikipedia.org/wiki/Gambas" target="_blank">Gambas</a> es lo más parecido a un entorno <a href="http://es.wikipedia.org/wiki/Desarrollo_r%C3%A1pido_de_aplicaciones" target="_blank">RAD</a> &#8220;estilo Visual Basic&#8221; que hay dando vueltas para Linux. Y es aún mejor que éstos dos:</p>
<ul>
<li>Libre: <a href="http://freepascal.org/faq.var#general-license" target="_blank">Licencia LGPL</a> (salvo el compilador que es GPL). Permite desarrollar software con cualquier licencia, incluso comercial.</li>
<li>Gratuito: Viene con los fuentes de sí mismo ¡y se <a href="http://en.wikipedia.org/wiki/Self-hosting">compila a sí mismo</a>!</li>
<li>Multiplataforma: DOS, Linux, Windows, Mac OSX, FreeBSD, Solaris, y <a href="http://freepascal.org/docs-html/user/userse2.html#x5-40001.2" target="_blank">más</a>.</li>
<li>Soporte de diferentes arquitecturas: Intel, AMD64, ARM, PowerPC, Sparc&#8230;</li>
<li>Diferentes Toolkits GUI: Win32/Win64, GTK1/2, QT3/4, Carbon, Cocoa, (aunque en diferentes estados de madurez).</li>
<li>Compatibilidad en <a href="http://wiki.lazarus.freepascal.org/Lazarus_For_Delphi_Users/es">un alto porcentaje</a> con Object Pascal y Delphi.</li>
</ul>
<p>Por último, me hice un &#8220;Hola Mundo&#8221; muy muy sencillo y lo compilé. Luego, ejecuté el comando <a href="http://linux.about.com/library/cmd/blcmdl1_ldd.htm" target="_blank">ldd</a>, para saber de qué bibliotecas dependía. El binario, que ocupaba 14 MB (ojo, era todo info de debug, luego de pasarle un <a href="http://www.computerhope.com/unix/strip.htm" target="_blank">strip</a> ocupó 5.1 MB) dependía de esto:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">marcelo<span style="color: #000000; font-weight: bold;">@</span>marcelo-laptop:<span style="color: #000000; font-weight: bold;">/</span>tmp$ <span style="color: #c20cb9; font-weight: bold;">ldd</span> project1
	linux-vdso.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span>  <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007fff441ff000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libX11.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libX11.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6603e2f000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgdk_pixbuf-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgdk_pixbuf-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6603c13000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgtk-x11-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgtk-x11-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66035f0000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgdk-x11-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgdk-x11-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6603343000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgobject-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgobject-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66030fb000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libglib-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libglib-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6602e1c000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgthread-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgthread-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6602c17000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgmodule-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgmodule-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6602a13000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpango-1.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpango-1.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66027c8000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpthread.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpthread.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66025ab000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libatk-1.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libatk-1.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f660238a000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libcairo.so.2 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libcairo.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6602106000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libdl.so.2 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libdl.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601f02000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libc.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libc.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601b80000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libxcb.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libxcb.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601963000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libgio-2.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgio-2.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66016b0000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	librt.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>librt.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66014a8000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libm.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libm.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601224000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXext.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXext.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6601012000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXrender.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXrender.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6600e08000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXinerama.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXinerama.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6600c04000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXi.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXi.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66009f4000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXrandr.so.2 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXrandr.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66007eb000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXcursor.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXcursor.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66005e0000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpangocairo-1.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpangocairo-1.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66003d3000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXcomposite.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXcomposite.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f66001d0000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXdamage.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXdamage.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fffcc000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXfixes.so.3 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXfixes.so.3 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ffdc6000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpangoft2-1.0.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpangoft2-1.0.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ffb9c000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libfreetype.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libfreetype.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff915000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libz.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libz.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff6fe000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libfontconfig.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libfontconfig.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff4c9000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpcre.so.3 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpcre.so.3 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff29a000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">/</span>lib64<span style="color: #000000; font-weight: bold;">/</span>ld-linux-x86-64.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f6604184000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpixman-1.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpixman-1.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65ff041000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libdirectfb-1.2.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libdirectfb-1.2.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fedbd000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libfusion-1.2.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libfusion-1.2.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65febb3000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libdirect-1.2.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libdirect-1.2.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe99a000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libpng12.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libpng12.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe772000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libxcb-render-util.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libxcb-render-util.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe56e000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libxcb-render.so.0 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libxcb-render.so.0 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe365000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXau.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXau.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fe160000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libXdmcp.so.6 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libXdmcp.so.6 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fdf5a000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libresolv.so.2 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libresolv.so.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fdd41000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libselinux.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libselinux.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fdb22000<span style="color: #7a0874; font-weight: bold;">&#41;</span>
	libexpat.so.1 =<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libexpat.so.1 <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x00007f65fd8f9000<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Si bien 5 MB sigue siendo un poco mucho (y no incluye GTK ni nada, aunque no jugué con las opciones del compilador) para un simple binario, a partir de ahora FreePascal + Lazarus en mi ranking personal entran en la categoría de &#8220;interesantes&#8221; <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Es bastante tarde, es cierto, más cuando gracias a <a href="http://www.python.org" target="_blank">Python</a> disfruto y me divierto al programar; tengo todo lo que necesito y más que lo que podría tener con FreePascal + Lazarus (siempre lo digo, Python no sería Python si no fuera por <a href="http://www.python.com.ar/" target="_blank">PyAr</a>), pero&#8230; bueno, rescato y festejo que haya otra herramienta de desarrollo libre, potente y al alcance de cualquiera. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/06/free-pascal-y-lazarus-en-ubuntu/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PyDay Rafaela 2010 – Introducción a wxPython</title>
		<link>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pyday-rafaela-2010-introduccion-a-wxpython</link>
		<comments>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/#comments</comments>
		<pubDate>Mon, 10 May 2010 17:32:48 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=687</guid>
		<description><![CDATA[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&#8230; En la sección de Charlas del blog están los slides de mi &#8220;Introducción a wxPython&#8221;, más los ejemplos de rigor. También hice propaganda de Ubuntu [...]]]></description>
			<content:encoded><![CDATA[<p>Para no ser menos que <a href="http://www.juanjoconti.com.ar/2010/05/09/charla-entendiendo-decoradores-en-python/" target="_blank">Juanjo</a> y <a href="http://fisadev.blogspot.com/2010/05/pyday-rafaela-2010_09.html" target="_blank">Fisa</a>, ¡qué bueno estuvo el <a href="www.pyday.com.ar/rafaela2010/" target="_blank">PyDay Rafaela 2010</a>!</p>
<p>Muchos (muchos) asistentes, muy buena onda, y una chorizeada + fernet a la noche inolvidables&#8230; En la sección de <a href="http://blog.marcelofernandez.info/charlas/">Charlas</a> del blog están los <a href="http://marcelofernandez.info/charlas/Introduccion%20a%20wxPython.pdf">slides</a> de mi &#8220;Introducción a wxPython&#8221;, más los <a href="http://marcelofernandez.info/charlas/Introduccion%20a%20wxPython.zip">ejemplos</a> de rigor. También <a href="http://marcelofernandez.info/charlas/Ubuntu Lightning Talk.pdf">hice propaganda</a> de Ubuntu en las Lightning Talks. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </p>
<p>Acá hay un par de fotos&#8230; con los días van a ir apareciendo más cosas en el sito del evento&#8230; incluso los videos de las charlas. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<a href='http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/attachment/08052010022/' title='PyDay Rafaela 2010'><img width="150" height="150" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/05/08052010022-150x150.jpg" class="attachment-thumbnail" alt="PyDay Rafaela 2010" title="PyDay Rafaela 2010" /></a>
<a href='http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/attachment/023/' title='PyDay Rafaela 2010 - Grupo completo'><img width="150" height="150" src="http://blog.marcelofernandez.info/wp-content/uploads/2010/05/023-150x150.jpg" class="attachment-thumbnail" alt="PyDay Rafaela 2010 - Grupo completo" title="PyDay Rafaela 2010 - Grupo completo" /></a>

<p><strong>Actualización</strong>: <a href="http://pydayrafaela.blip.tv/" target="_blank">Acá</a> están los videos de las charlas.</p>
<p>Gracias a los chicos de PyRafaela por la organización, dedicación y aguante&#8230;. ¡espero que se repita!</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/05/pyday-rafaela-2010-introduccion-a-wxpython/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Renderizando PDFs en Python con Poppler II</title>
		<link>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=renderizando-pdfs-en-python-con-poppler-ii</link>
		<comments>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 18:04:29 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=663</guid>
		<description><![CDATA[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); [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días me llegó un mail de alguien preguntándome cómo, a partir de la <a href="http://blog.marcelofernandez.info/2009/05/renderizando-pdfs-en-python-con-poppler/" target="_self">parte I de este artículo</a>, hacer un sencillo visor de PDFs con <a href="http://www.wxpython.org" target="_blank">wxPython</a>. Me encontré con algunas dificultades, principalmente que el <a href="www.wxpython.org/docs/api/wx.ScrolledWindow-class.html" target="_blank">ScrolledWindow</a> de wxPython no permite actualizarse dinámicamente, o automáticamente según el contenido (esto <a href="http://www.pygtk.org/docs/pygtk/class-gtkadjustment.html" target="_blank">sí es bastante sencillo en GTK</a>); con lo cual se complicaba hacer zoom, modificar el tamaño de la ventana y adaptar los scrollbars, etc.</p>
<p>Sin embargo, con alguna vuelta de más pude armar un ejemplo, que paso a dejar <a href="http://code.activestate.com/recipes/577195-wxpython-pdf-viewer-using-poppler/" target="_blank">acá</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># coding: utf-8</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot; 
    wxPDFViewer - Simple PDF Viewer using Python-Poppler and wxPython 
    Marcelo Fidel Fernandez - MIT License
    http://www.marcelofernandez.info - marcelo.fidel.fernandez@gmail.com
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> wx
<span style="color: #ff7700;font-weight:bold;">import</span> wx.<span style="color: black;">lib</span>.<span style="color: black;">wxcairo</span> <span style="color: #ff7700;font-weight:bold;">as</span> wxcairo
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> poppler
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> PDFWindow<span style="color: black;">&#40;</span>wx.<span style="color: black;">ScrolledWindow</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; This example class implements a PDF Viewer Window, handling Zoom and Scrolling &quot;&quot;&quot;</span>
&nbsp;
    MAX_SCALE = <span style="color: #ff4500;">2</span>
    MIN_SCALE = <span style="color: #ff4500;">1</span>
    SCROLLBAR_UNITS = <span style="color: #ff4500;">20</span>  <span style="color: #808080; font-style: italic;"># pixels per scrollbar unit</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent<span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">ScrolledWindow</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, parent, wx.<span style="color: black;">ID_ANY</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Wrap a panel inside</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span> = wx.<span style="color: black;">Panel</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Initialize variables</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> = <span style="color: #ff4500;">0</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> = <span style="color: #ff4500;">1</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">document</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">width</span> = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">height</span> = <span style="color: #008000;">None</span>
        <span style="color: #808080; font-style: italic;"># Connect panel events</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_PAINT</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnPaint</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_KEY_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnKeyDown</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_LEFT_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnLeftDown</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">Bind</span><span style="color: black;">&#40;</span>wx.<span style="color: black;">EVT_RIGHT_DOWN</span>, <span style="color: #008000;">self</span>.<span style="color: black;">OnRightDown</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> LoadDocument<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">file</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">document</span> = poppler.<span style="color: black;">document_new_from_file</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;file://&quot;</span> + <span style="color: #008000;">file</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_n_pages</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_page</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">n_page</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">width</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span> = <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span>.<span style="color: black;">get_size</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
        <span style="color: #008000;">self</span>._UpdateSize<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnPaint<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        dc = wx.<span style="color: black;">PaintDC</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">panel</span><span style="color: black;">&#41;</span>
        cr = wxcairo.<span style="color: black;">ContextFromDC</span><span style="color: black;">&#40;</span>dc<span style="color: black;">&#41;</span>
        cr.<span style="color: black;">set_source_rgb</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># White background</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">1</span>:
            cr.<span style="color: black;">scale</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span>, <span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>
        cr.<span style="color: black;">rectangle</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, <span style="color: #008000;">self</span>.<span style="color: black;">width</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: black;">&#41;</span>
        cr.<span style="color: black;">fill</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span>.<span style="color: black;">render</span><span style="color: black;">&#40;</span>cr<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnLeftDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span> + <span style="color: #ff4500;">0.2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnRightDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span> - <span style="color: #ff4500;">0.2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _UpdateScale<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, new_scale<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> new_scale <span style="color: #66cc66;">&gt;</span>= PDFWindow.<span style="color: black;">MIN_SCALE</span> <span style="color: #ff7700;font-weight:bold;">and</span> new_scale <span style="color: #66cc66;">&lt;</span>= PDFWindow.<span style="color: black;">MAX_SCALE</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">scale</span> = new_scale
            <span style="color: #808080; font-style: italic;"># Obtain the current scroll position</span>
            prev_position = <span style="color: #008000;">self</span>.<span style="color: black;">GetViewStart</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Scroll to the beginning because I'm going to redraw all the panel</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Scroll</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Redraw (calls OnPaint and such)</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Refresh</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
            <span style="color: #808080; font-style: italic;"># Update panel Size and scrollbar config</span>
            <span style="color: #008000;">self</span>._UpdateSize<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># Get to the previous scroll position</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">Scroll</span><span style="color: black;">&#40;</span>prev_position<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, prev_position<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> 
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _UpdateSize<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        u = PDFWindow.<span style="color: black;">SCROLLBAR_UNITS</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">panel</span>.<span style="color: black;">SetSize</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">width</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SetScrollbars</span><span style="color: black;">&#40;</span>u, u, <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">width</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>/u, <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">height</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">scale</span><span style="color: black;">&#41;</span>/u<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> OnKeyDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, event<span style="color: black;">&#41;</span>:
        update = <span style="color: #008000;">True</span>
        <span style="color: #808080; font-style: italic;"># More keycodes in http://docs.wxwidgets.org/stable/wx_keycodes.html#keycodes</span>
        keycode = event.<span style="color: black;">GetKeyCode</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
        <span style="color: #ff7700;font-weight:bold;">if</span> keycode <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span>wx.<span style="color: black;">WXK_PAGEDOWN</span>, wx.<span style="color: black;">WXK_SPACE</span><span style="color: black;">&#41;</span>:
            next_page = <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> + <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> keycode == wx.<span style="color: black;">WXK_PAGEUP</span>:
            next_page = <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> - <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            update = <span style="color: #008000;">False</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> update <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#40;</span>next_page <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#40;</span>next_page <span style="color: #66cc66;">&lt;</span> <span style="color: #008000;">self</span>.<span style="color: black;">n_pages</span><span style="color: black;">&#41;</span>:
                <span style="color: #008000;">self</span>.<span style="color: black;">n_page</span> = next_page
                <span style="color: #008000;">self</span>.<span style="color: black;">current_page</span> = <span style="color: #008000;">self</span>.<span style="color: black;">document</span>.<span style="color: black;">get_page</span><span style="color: black;">&#40;</span>next_page<span style="color: black;">&#41;</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">Refresh</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MyFrame<span style="color: black;">&#40;</span>wx.<span style="color: black;">Frame</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        wx.<span style="color: black;">Frame</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">None</span>, -<span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;wxPdf Viewer&quot;</span>, size=<span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>,<span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span> = PDFWindow<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span>.<span style="color: black;">LoadDocument</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">pdfwindow</span>.<span style="color: black;">SetFocus</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># To capture keyboard events</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__==<span style="color: #483d8b;">&quot;__main__&quot;</span>:
    app = wx.<span style="color: black;">App</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    f = MyFrame<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    f.<span style="color: black;">Show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    app.<span style="color: black;">MainLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si bien tengo entendido que el scroll no es &#8220;óptimo&#8221;, ya que en cada OnPaint() se redibuja todo el PDF, anda bastante bien en mi instalación y no parece ser un problema. Lógicamente sí se puede redibujar un área en particular con Cairo (sería la que queda &#8220;invalidada&#8221; por el scroll), pero wxPython me explotó al intentar algunas cosas por un lado, y me parece que en realidad no sé hacerlo bien por el otro (si alguien puede tirar una soga en esto en particular, bienvenido sea).</p>
<p>Me entretuve mucho haciendo esto, y espero que a alguien le sea de utilidad; y aunque todavía Python-Poppler no está disponible para Windows en forma binaria (pero puede ser compilado, <a href="https://bugs.launchpad.net/poppler-python/+bug/499592" target="_blank">bug acá</a>), sí se puede usar en cualquier Linux, OSX, etc. Y nuevamente, hay una <a href="http://bazaar.launchpad.net/~poppler-python/poppler-python/trunk/annotate/head:/demo/demo-poppler.py">demo</a> para hacer esto mismo con PyGTK, y la <a href="http://cgit.freedesktop.org/poppler/poppler/tree/glib/demo" target="_blank">demo de Poppler en C</a> es mucho más completa, además de fácil de leer y traducir a Python.</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/04/renderizando-pdfs-en-python-con-poppler-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reemplazando texto con expresiones regulares en Python</title>
		<link>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=reemplazando-texto-con-expresiones-regulares-en-python</link>
		<comments>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 18:01:11 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=601</guid>
		<description><![CDATA[Hay veces en que uno necesita automatizar tareas, como reemplazar cierto texto por otro bajo ciertas condiciones, y el viejo &#8220;%s/cosa/otra/g&#8221; 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 [...]]]></description>
			<content:encoded><![CDATA[<p>Hay veces en que uno necesita automatizar tareas, como reemplazar cierto texto por otro bajo ciertas condiciones, y el viejo &#8220;%s/cosa/otra/g&#8221; <a href="http://www.linux.com/learn/tutorials/8255-vim-tips-the-basics-of-search-and-replace" target="_blank">del vim</a> nos queda corto. En mi caso en particular, estaba metiendo algunas pequeñas características en <a href="http://www.sistemasagiles.com.ar/trac/wiki/PyFpdf" target="_blank">PyFpdf</a>, y vi que había <a href="http://www.sistemasagiles.com.ar/trac/browser/pyfpdf/font/times.py?rev=103" target="_blank">algunos archivos .py</a> llenos de llamadas a la función <a href="http://docs.python.org/library/functions.html#chr" target="_blank">chr()</a>.</p>
<p>Claro, PyFpdf es un port más o menos &#8220;haragán&#8221; (<em>lazy</em>) de <a href="http://www.fpdf.org/" target="_blank">Fpdf para PHP</a>, y el autor original evidentemente encontró más sencillo definir algunas fuentes (en binario) haciendo sucesivas llamadas a la función chr(), como  esta:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">fpdf_charwidths<span style="color: black;">&#91;</span><span style="color: #483d8b;">'times'</span><span style="color: black;">&#93;</span>=<span style="color: black;">&#123;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>, <span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>:<span style="color: #ff4500;">250</span>,<span style="color: black;">&#125;</span> <span style="color: #808080; font-style: italic;"># Sigue...</span></pre></div></div>

<p>Enseguida pensé en mejorarlo, reemplazando esas sucesivas llamadas a chr() por la misma función pero ya evaluada y en forma de byte string; por ejemplo, la idea era convertir lo anterior en:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">fpdf_charwidths<span style="color: black;">&#91;</span><span style="color: #483d8b;">'times'</span><span style="color: black;">&#93;</span>=<span style="color: black;">&#123;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>01'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>02'</span>:<span style="color: #ff4500;">250</span>,<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>03'</span>:<span style="color: #ff4500;">250</span>,<span style="color: black;">&#125;</span> <span style="color: #808080; font-style: italic;"># Sigue...</span></pre></div></div>

<p>De esa manera, los archivos .py se simplificarían (se harían más legibles), no sufrirían modificaciones en su comportamiento y hasta serían más veloces en su interpretación y ejecución.</p>
<p>Primero se me ocurrió primero hacer algo más &#8220;a mano&#8221;, pero en cuanto se me complicó un poquito enseguida pensé que la mejor herramienta era usar <a href="http://es.wikipedia.org/wiki/Expresiones_regulares" target="_blank">expresiones regulares</a> para el matching del patrón &#8220;chr(x)&#8221; y, por consiguiente, el <a href="http://docs.python.org/library/re.html" target="_blank">módulo re</a> de la librería estándar de Python.</p>
<p>Leyendo <a href="http://www.amk.ca/python/howto/regex/" target="_blank">esta excelente página</a> y la documentación del módulo en cuestión, armé un script, y me quedó así:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># coding:utf-8</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># This script tries to identify all chr(XX) constant calls in python scripts</span>
<span style="color: #808080; font-style: italic;"># and replace them with '\xXX' strings.</span>
<span style="color: #808080; font-style: italic;"># Author: Marcelo Fernández - License: MIT</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> chrrepl<span style="color: black;">&#40;</span>match<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># See http://www.amk.ca/python/howto/regex/regex.html</span>
    <span style="color: #808080; font-style: italic;"># Use the captured group to get the hex string value.</span>
    char_number = match.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>char_number<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">3</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Usage: python chr_cleaner.py infile.py outfile.py'</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
    infile = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    outfile = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># Open file for reading</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        fin = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>infile, <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>
        fout = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>outfile, <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IOError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Error when reading %s or trying to write %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>infile, outfile<span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
    intext = fin.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    pattern = <span style="color: #483d8b;">'chr<span style="color: #000099; font-weight: bold;">\\</span>((<span style="color: #000099; font-weight: bold;">\\</span>d+)<span style="color: #000099; font-weight: bold;">\\</span>)'</span> <span style="color: #808080; font-style: italic;"># Group the chr() function parameter to capture it</span>
    p = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>pattern<span style="color: black;">&#41;</span>
    outtext = p.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>chrrepl, intext<span style="color: black;">&#41;</span>
    fout.<span style="color: black;">write</span><span style="color: black;">&#40;</span>outtext<span style="color: black;">&#41;</span>
    fout.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    fin.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    fout.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si bien creo que el <em>snippet</em> es bastante legible, lo interesante es que con el módulo re se puede:</p>
<ul>
<li><strong>Identificar un patrón en un texto</strong>: En este caso el patrón sería &#8220;chr(\d)&#8221; (\d porque busco un número allí).</li>
<li><strong>Marcar grupos en ese patrón utilizarlos luego</strong>; como sé que voy a utilizar el número en cuestión para convertirlo a su byte string, lo defino dentro de un grupo. El patrón queda entonces &#8220;chr((\d))&#8221;. También es posible usar <em>named groups</em>, identificables por nombre en vez de por posición, pero eso lo dejo de tarea al lector <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </li>
<li><strong>Reemplazar todo el texto que coincide con ese patrón, y en cada reemplazo, llamar a una función que especifique &#8220;lo que hay que poner&#8221; allí, devolviendo un string</strong>. Esta es la frutilla del postre&#8230; <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
Si bien puedo usar p.sub() para reemplazar lo que busco por un texto constante, también puedo hacer que en cada ocurrencia del patrón una función cualquiera sea llamada, y  se le pase la instancia de <a href="http://docs.python.org/library/re.html#re.MatchObject" target="_blank">MatchObject</a> para que decidamos qué hacer con lo encontrado y devolver un string. Esto hace la función chrrepl() del snippet. Allí tomo el primer grupo (el grupo 0 es el string completo, el 1 es el primer grupo definido posicionalmente, y así sucesivamente), lo convierto a entero, ejecuto la función chr() y devuelvo su representación en byte string.</li>
</ul>
<p>En fin, después de experimentar un buen rato, esto funcionó y <a href="http://www.sistemasagiles.com.ar/trac/changeset/104/pyfpdf/" target="_blank">acá se puede ver</a> el diff del commit correspondiente para que se aprecie un poco mejor&#8230;</p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2010/04/reemplazando-texto-con-expresiones-regulares-en-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Navegador simple con Python + Webkit/GTK</title>
		<link>http://blog.marcelofernandez.info/2009/11/navegador-simple-con-pywebkitgtk/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=navegador-simple-con-pywebkitgtk</link>
		<comments>http://blog.marcelofernandez.info/2009/11/navegador-simple-con-pywebkitgtk/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 21:56:12 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=501</guid>
		<description><![CDATA[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 (&#8220;dibujado&#8221;) de páginas [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy me encontré con otro <a href="http://mx.grulic.org.ar/lurker/message/20091118.001651.3f9b4974.es.html">un hilo en la lista de PyAr</a> que me deja un link más que interesante: ¡Existe un binding para usar <a href="http://code.google.com/p/pywebkitgtk/">Webkit sobre GTK desde Python</a>, y lo mejor de todo es que <a href="http://packages.ubuntu.com/karmic/python-webkit">ya está incluido en los repositorios</a> de Ubuntu 9.10!</p>
<p><a href="http://www.webkit.org">Webkit</a> es un motor de <a href="http://es.wikipedia.org/wiki/Renderización">renderizado</a> (&#8220;dibujado&#8221;) de páginas web, que es utilizado en el corazón en cada vez más navegadores, como <a href="http://www.google.com.ar/chrome">Chrome</a>, <a href="http://www.apple.com/es/safari/">Safari</a>, <a href="http://www.konqueror.org/">Konqueror</a>, 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 <a href="http://www.pygtk.org/pygtkmozembed/class-gtkmozembed.html">gtkmozembed</a> (que embebe el motor de <a href="http://www.mozilla-europe.org/es/firefox/">Firefox</a>), éste no es muy poderoso, o por lo menos no deja meterle mucha &#8220;mano&#8221; para personalizarlo, y uno termina teniendo relativamente muy poco &#8220;poder&#8221;. 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). <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>No podía dejar de probarlo. Entonces me puse manos a la obra, y salió esto, tratando de imitar lo que se posteó en la lista:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot; 
    SimpleBrowser - Navegador muy muy simple de internet, sólo de ejemplo,
                    que utiliza la biblioteca Webkit GTK desde Python (PyWebkitGTK).
&nbsp;
    Marcelo Fidel Fernández - http://www.marcelofernandez.info 
    Licencia: BSD. Disponible en: http://www.freebsd.org/copyright/license.html
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk
<span style="color: #ff7700;font-weight:bold;">import</span> webkit
&nbsp;
DEFAULT_URL = <span style="color: #483d8b;">'http://www.python.org'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SimpleBrowser:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span> = gtk.<span style="color: black;">Window</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WINDOW_TOPLEVEL</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_position</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WIN_POS_CENTER_ALWAYS</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'delete_event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">close_application</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_default_size</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>, <span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span>
&nbsp;
        vbox = gtk.<span style="color: black;">VBox</span><span style="color: black;">&#40;</span>spacing=<span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        vbox.<span style="color: black;">set_border_width</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">txt_url</span> = gtk.<span style="color: black;">Entry</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">txt_url</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'activate'</span>, <span style="color: #008000;">self</span>._txt_url_activate<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span> = gtk.<span style="color: black;">ScrolledWindow</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">webview</span> = webkit.<span style="color: black;">WebView</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">webview</span><span style="color: black;">&#41;</span>
&nbsp;
        vbox.<span style="color: black;">pack_start</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">txt_url</span>, fill=<span style="color: #008000;">False</span>, expand=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
        vbox.<span style="color: black;">pack_start</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scrolled_window</span>, fill=<span style="color: #008000;">True</span>, expand=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span>vbox<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _txt_url_activate<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, entry<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._load<span style="color: black;">&#40;</span>entry.<span style="color: black;">get_text</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _load<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">webview</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, url<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">txt_url</span>.<span style="color: black;">set_text</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_title</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'SimpleBrowser - %s'</span> <span style="color: #66cc66;">%</span> url<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>._load<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> show<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">show_all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> close_application<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event, data=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        gtk.<span style="color: black;">main_quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span>:
        url = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        url = DEFAULT_URL
&nbsp;
    <span style="color: #808080; font-style: italic;"># PyWebkitGTK necesita habilitar el soporte de los hilos en PyGTK</span>
    gtk.<span style="color: black;">gdk</span>.<span style="color: black;">threads_init</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    browser = SimpleBrowser<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    browser.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
    browser.<span style="color: black;">show</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    gtk.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p style="text-align: left;">¡Y Listo!</p>
<p><a href="http://blog.marcelofernandez.info/wp-content/uploads/2009/11/Pantallazo.png"><img class="size-medium wp-image-504 alignright" title="Pantallazo_PyWebkitGTK" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/11/Pantallazo-300x233.png" alt="Pantallazo_PyWebkitGTK" width="300" height="233" /></a></p>
<p>Todo lo que se necesita en Ubuntu 9.10 para poder correr esto es instalar el paquete &#8220;python-webkit&#8221;; sin embargo, esta versión es la 1.1.5, mientras que PyWebkitGTK va por la 1.1.7 y Webkit/GTK va por la 1.1.15, así que todavía hay lugar para mejoras.</p>
<p>Aquí dejo algunos links:</p>
<ul>
<li><a href="http://code.google.com/p/pywebkitgtk/">PyWebkitGTK</a> se llama el proyecto de llevar <a href="http://webkitgtk.org/">Webkit/GTK</a> (escrito naturalmente en C) a Python.</li>
<li><a href="http://code.google.com/p/pywebkitgtk/source/browse/trunk/demos/browser.py">Acá hay un ejemplo</a> muchísimo más completo de un navegador con múltiples pestañas y todo.</li>
<li>Lamentablemente, la documentación de la biblioteca en Python no existe aún (es un ticket del proyecto), así que por ahora habrá que conformarse con <a href="http://webkitgtk.org/reference/index.html">la documentación de Webkit/GTK</a>; sin embargo, yo lo encuentro bastante legible, ya que enseguida uno se adapta a &#8220;traducir&#8221; cómo se llamaría un método en C a uno en Python.</li>
</ul>
<p>Espero que les sirva. Me divertí mucho haciéndolo. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/11/navegador-simple-con-pywebkitgtk/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Visor de Imágenes Simple con PyGTK</title>
		<link>http://blog.marcelofernandez.info/2009/11/visor-de-imagenes-simple-con-pygtk/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=visor-de-imagenes-simple-con-pygtk</link>
		<comments>http://blog.marcelofernandez.info/2009/11/visor-de-imagenes-simple-con-pygtk/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 15:00:57 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=472</guid>
		<description><![CDATA[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 (&#8220;0 o adaptar a ventana&#8221;), [...]]]></description>
			<content:encoded><![CDATA[<p>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. </p>
<p>Maneja el movimiento de la imagen con el mouse, las teclas del cursor y hace zoom con F1 (&#8220;0 o adaptar a ventana&#8221;), F2 (+25%), F3 (+50%), F4(+75%) y F5(&#8220;%+100 o 1:1&#8243;).</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot; 
    SimpleImageViewer - Visor simple de imágenes, de ejemplo, que utiliza PyGTK.
    Marcelo Fidel Fernández - http://www.marcelofernandez.info
&nbsp;
    Licencia: BSD. Disponible en: http://www.freebsd.org/copyright/license.html
&nbsp;
    TODO: 
        * Dar la opción de usar el scroll del mouse para hacer zoom.
        * Mejorar el código y peformance (quizás).
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> pygtk
pygtk.<span style="color: black;">require</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'2.0'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Variables globales para el ejemplo; podrían ir en un archivo de configuración, </span>
<span style="color: #808080; font-style: italic;"># como por ejemplo 'config.py' e importarlo.</span>
<span style="color: #808080; font-style: italic;"># Mapeo de teclas - Ver constantes en el modulo gtk.keysyms</span>
<span style="color: #ff7700;font-weight:bold;">import</span> gtk.<span style="color: black;">keysyms</span> <span style="color: #ff7700;font-weight:bold;">as</span> kb
&nbsp;
<span style="color: #808080; font-style: italic;"># Estructura: teclas (en mayúscula, contempla minúsculas también)</span>
<span style="color: #808080; font-style: italic;"># (offset_X_pixeles, offset_Y_pixeles)</span>
OFFSET_GRAL = <span style="color: #ff4500;">50</span>
MOVE_KEYS = <span style="color: black;">&#123;</span> kb.<span style="color: black;">Up</span> : <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, -OFFSET_GRAL<span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;"># Arriba</span>
              kb.<span style="color: black;">Down</span> : <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,  OFFSET_GRAL<span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;"># Abajo</span>
              kb.<span style="color: black;">Right</span> : <span style="color: black;">&#40;</span>OFFSET_GRAL, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>,  <span style="color: #808080; font-style: italic;"># Derecha</span>
              kb.<span style="color: black;">Left</span> : <span style="color: black;">&#40;</span>-OFFSET_GRAL, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;"># Izquierda</span>
            <span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Estructura: tecla: nivel de zoom (zoom_ratio)</span>
ZOOM_KEYS = <span style="color: black;">&#123;</span> kb.<span style="color: black;">F1</span>: <span style="color: #ff4500;">0.0</span>,
              kb.<span style="color: black;">F2</span>: <span style="color: #ff4500;">25.0</span>,
              kb.<span style="color: black;">F3</span>: <span style="color: #ff4500;">50.0</span>,
              kb.<span style="color: black;">F4</span>: <span style="color: #ff4500;">75.0</span>,
              kb.<span style="color: black;">F5</span>: <span style="color: #ff4500;">100.0</span>,
            <span style="color: black;">&#125;</span>
&nbsp;
DEFAULT_IMAGE = <span style="color: #483d8b;">'/usr/share/backgrounds/Cherries.jpg'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SimpleImageViewer:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, image_file<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span> = gtk.<span style="color: black;">Window</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WINDOW_TOPLEVEL</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;delete_event&quot;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">close_application</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_position</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">WIN_POS_CENTER_ALWAYS</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">set_default_size</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">800</span>, <span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span> = gtk.<span style="color: black;">gdk</span>.<span style="color: black;">pixbuf_new_from_file</span><span style="color: black;">&#40;</span>image_file<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span> = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span>.<span style="color: black;">get_width</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span> = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span>.<span style="color: black;">get_height</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">image</span> = gtk.<span style="color: black;">Image</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">image</span>.<span style="color: black;">set_from_pixbuf</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span> = gtk.<span style="color: black;">Viewport</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># No están por defecto, los agrego</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">add_events</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">BUTTON_RELEASE_MASK</span> | gtk.<span style="color: black;">gdk</span>.<span style="color: black;">BUTTON1_MOTION_MASK</span><span style="color: black;">&#41;</span> 
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'button-press-event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">on_button_pressed</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'button-release-event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">on_button_released</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'motion-notify-event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">on_mouse_moved</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Lo conecto a la ventana, ya que siempre tiene el foco</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'key-press-event'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">on_key_press</span><span style="color: black;">&#41;</span> 
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">image</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_wnd</span> = gtk.<span style="color: black;">ScrolledWindow</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">scrolled_wnd</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">viewport</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scrolled_wnd</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">window</span>.<span style="color: black;">show_all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _update_image<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, zoom_ratio<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; 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 
        &quot;&quot;&quot;</span>
        <span style="color: #808080; font-style: italic;"># TODO: Prioriza que encaje el ancho por sobre el alto de la imagen </span>
        <span style="color: #808080; font-style: italic;"># al estar maximizado. Mejorar.</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Obtengo las dimensiones actuales del viewport</span>
        rect = <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">get_allocation</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Resize de la imagen conservando las proporciones de la imagen</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span>:
            base = <span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span> - rect.<span style="color: black;">width</span>
            ancho = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rect.<span style="color: black;">width</span> + <span style="color: black;">&#40;</span>base <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>zoom_ratio/<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            relacion = <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>/<span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span>
            alto = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>ancho <span style="color: #66cc66;">*</span> relacion/<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            base = <span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span> - rect.<span style="color: black;">height</span>
            alto = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rect.<span style="color: black;">height</span> + <span style="color: black;">&#40;</span>base <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>zoom_ratio/<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            relacion = <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">ancho_pixbuf</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>/<span style="color: #008000;">self</span>.<span style="color: black;">alto_pixbuf</span>
            ancho = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>alto <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>relacion/<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        scaled_buf = <span style="color: #008000;">self</span>.<span style="color: black;">pixbuf</span>.<span style="color: black;">scale_simple</span><span style="color: black;">&#40;</span>ancho, alto, gtk.<span style="color: black;">gdk</span>.<span style="color: black;">INTERP_BILINEAR</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">image</span>.<span style="color: black;">set_from_pixbuf</span><span style="color: black;">&#40;</span>scaled_buf<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _move_image<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, offset_x, offset_y<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; 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 
        &quot;&quot;&quot;</span>
        vport = <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>
        xadjust = vport.<span style="color: black;">props</span>.<span style="color: black;">hadjustment</span>
        newx = xadjust.<span style="color: black;">value</span> + offset_x
        yadjust = vport.<span style="color: black;">props</span>.<span style="color: black;">vadjustment</span>
        newy = yadjust.<span style="color: black;">value</span> + offset_y
        <span style="color: #808080; font-style: italic;"># Si las cosas están dentro de los bordes, seteo</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>newx <span style="color: #66cc66;">&gt;</span>= xadjust.<span style="color: black;">lower</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> \
               <span style="color: black;">&#40;</span>newx <span style="color: #66cc66;">&lt;</span>= <span style="color: black;">&#40;</span>xadjust.<span style="color: black;">upper</span> - xadjust.<span style="color: black;">page_size</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            xadjust.<span style="color: black;">value</span> = newx
            vport.<span style="color: black;">set_hadjustment</span><span style="color: black;">&#40;</span>xadjust<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>newy <span style="color: #66cc66;">&gt;</span>= yadjust.<span style="color: black;">lower</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> \
               <span style="color: black;">&#40;</span>newy <span style="color: #66cc66;">&lt;</span>= <span style="color: black;">&#40;</span>yadjust.<span style="color: black;">upper</span> - yadjust.<span style="color: black;">page_size</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            yadjust.<span style="color: black;">value</span> = newy
            vport.<span style="color: black;">set_vadjustment</span><span style="color: black;">&#40;</span>yadjust<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_key_press<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; Callback to handle the keys pressed in the main window
            Callback que maneja las teclas que se presionan en la ventana
        &quot;&quot;&quot;</span>
        keycode = gtk.<span style="color: black;">gdk</span>.<span style="color: black;">keyval_to_upper</span><span style="color: black;">&#40;</span>event.<span style="color: black;">keyval</span><span style="color: black;">&#41;</span>
        newx = newy = <span style="color: #ff4500;">0</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> keycode <span style="color: #ff7700;font-weight:bold;">in</span> MOVE_KEYS.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            offset_x, offset_y = MOVE_KEYS<span style="color: black;">&#91;</span>keycode<span style="color: black;">&#93;</span>
            <span style="color: #008000;">self</span>._move_image<span style="color: black;">&#40;</span>offset_x, offset_y<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> keycode <span style="color: #ff7700;font-weight:bold;">in</span> ZOOM_KEYS.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #008000;">self</span>._update_image<span style="color: black;">&#40;</span>ZOOM_KEYS<span style="color: black;">&#91;</span>keycode<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span> <span style="color: #808080; font-style: italic;"># Con True cancelo el evento</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_mouse_moved<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; Callback to the mouse movement inside the viewport
            Callback que es llamado cuando el mouse se mueve en el viewport 
        &quot;&quot;&quot;</span>
        <span style="color: #808080; font-style: italic;"># Ver: http://www.pygtk.org/pygtk2tutorial-es/sec-EventHandling.html</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">is_hint</span>:
            x, y, state = event.<span style="color: black;">window</span>.<span style="color: black;">get_pointer</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            state = event.<span style="color: black;">state</span>
        x, y = event.<span style="color: black;">x_root</span>, event.<span style="color: black;">y_root</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> state <span style="color: #66cc66;">&amp;</span> gtk.<span style="color: black;">gdk</span>.<span style="color: black;">BUTTON1_MASK</span>:
            offset_x = <span style="color: #008000;">self</span>.<span style="color: black;">prevmousex</span> - x
            offset_y = <span style="color: #008000;">self</span>.<span style="color: black;">prevmousey</span> - y
            <span style="color: #008000;">self</span>._move_image<span style="color: black;">&#40;</span>offset_x, offset_y<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">prevmousex</span> = x
        <span style="color: #008000;">self</span>.<span style="color: black;">prevmousey</span> = y
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_button_pressed<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; 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 &quot;moviéndose&quot;.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">button</span> == <span style="color: #ff4500;">1</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">change_vport_cursor</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">Cursor</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">FLEUR</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">prevmousex</span> = event.<span style="color: black;">x_root</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">prevmousey</span> = event.<span style="color: black;">y_root</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_button_released<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; 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 &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: black;">button</span> == <span style="color: #ff4500;">1</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">change_vport_cursor</span><span style="color: black;">&#40;</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> change_vport_cursor<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #008000;">type</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">viewport</span>.<span style="color: black;">window</span>.<span style="color: black;">set_cursor</span><span style="color: black;">&#40;</span><span style="color: #008000;">type</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> close_application<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event, data=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        gtk.<span style="color: black;">main_quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
        image_file = <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        image_file = DEFAULT_IMAGE
    SimpleImageViewer<span style="color: black;">&#40;</span>image_file<span style="color: black;">&#41;</span>
    gtk.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>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 <a href="http://www.marcelofernandez.info/files/image_viewer.py">desde acá</a>.</p>
<p>Espero que le sirva a alguien. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>Actualización</strong>: ¡Gracias StyXman por <a href="http://grulicueva.homelinux.net/~mdione/glob/posts/our-man-in-toulon/">la comparativa con PyQT</a>! Ahí agregué la licencia y sobre el código&#8230; bueno, sólo agregar que es un ejemplo, la idea era hacer el código verborrágico apropósito. Por otra parte, y como conclusión personal, veo que QT tiene una clase <a href="http://doc.trolltech.com/4.2/qgraphicsview.html">QGraphicsView</a> que maneja solito el tema del arrastrar y mover la imagen (eso lleva unas cuantas líneas en GTK). <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/11/visor-de-imagenes-simple-con-pygtk/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Desensamblando Python</title>
		<link>http://blog.marcelofernandez.info/2009/08/desensamblando-python/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=desensamblando-python</link>
		<comments>http://blog.marcelofernandez.info/2009/08/desensamblando-python/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 17:53:25 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=429</guid>
		<description><![CDATA[Mucho no me gusta hacer posts con casi nada de aporte propio, pero en este caso se lo merece. Este post sólo va a referenciar al excelente sitio de Doug Hellman, PyMOTW (Python Module of the Week). Básicamente el autor presenta una vez por semana un módulo de la biblioteca estándar de Python, realizando un [...]]]></description>
			<content:encoded><![CDATA[<p>Mucho no me gusta hacer posts con casi nada de aporte propio, pero en este caso se lo merece. Este post sólo va a referenciar al excelente sitio de <a href="http://www.doughellmann.com/about/" target="_blank">Doug Hellman</a>, <a href="http://www.doughellmann.com/PyMOTW/" target="_blank">PyMOTW</a> (Python Module of the Week). Básicamente el autor presenta una vez por semana un módulo de la biblioteca estándar de Python, realizando un análisis del mismo y mostrando ejemplos de uso.</p>
<p>En particular, <a href="http://www.doughellmann.com/PyMOTW/dis/" target="_blank">esta semana</a> hizo una introducción al módulo <a href="http://docs.python.org/library/dis.html" target="_blank">dis</a>, que desensambla código Python mostrando el bytecode respectivo. Lo bueno es que muestra varios usos para el mismo (nuevos para mí), como en el caso de un debug o en el de optimizar el funcionamiento ahorrando bytecodes.</p>
<p>En fin, preparándome para la inminente <a href="http://ar.pycon.org/2009/about/" target="_blank">PyCon Argentina</a>, me entusiasmé leyendo y probando los ejemplos de este post. No puede haber programador python que no esté subscripto a su feed. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Saludos!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/08/desensamblando-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Control de Versiones: Manejando las diferencias entre distribuido y centralizado</title>
		<link>http://blog.marcelofernandez.info/2009/07/control-de-versiones-manejando-las-diferencias-entre-distribuido-y-centralizado/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=control-de-versiones-manejando-las-diferencias-entre-distribuido-y-centralizado</link>
		<comments>http://blog.marcelofernandez.info/2009/07/control-de-versiones-manejando-las-diferencias-entre-distribuido-y-centralizado/#comments</comments>
		<pubDate>Sat, 25 Jul 2009 18:11:41 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=346</guid>
		<description><![CDATA[Dando vueltas por ahí, me entero que es muy sencillo utilizar localmente versionado de código fuente (gracias a los sistemas de control de versiones distribuidos, como por ejemplo Mercurial, GIT y Bazaar) para luego subir/actualizar los cambios a un repositorio Subversion principal. Es decir, en vez de usar los comandos svn como clientes de un [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-352" title="VCSs" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/VCSs.png" alt="VCSs" width="144" height="149" />Dando vueltas <a href="http://wxwidgets.blogspot.com/2009/07/playing-with-dvcs-for-wxwidgets.html" target="_blank">por ahí</a>, me entero que es muy sencillo utilizar localmente versionado de código fuente (gracias a los sistemas de control de versiones distribuidos, como por ejemplo <a href="http://mercurial.selenic.com/wiki/" target="_blank">Mercurial</a>, <a href="http://git-scm.com/" target="_blank">GIT</a> y <a href="http://bazaar-vcs.org/" target="_blank">Bazaar</a>) para luego subir/actualizar los cambios a un repositorio <a href="http://subversion.tigris.org/" target="_blank">Subversion</a> principal. Es decir, en vez de usar los comandos svn como clientes de un servidor Subversion, es posible utilizar alguno de estos sistemas distribuidos como clientes &#8220;consumidores&#8221; del repositorio principal, para luego aprovechar <a href="http://en.wikipedia.org/wiki/Distributed_revision_control#Advantages" target="_blank">sus importantes ventajas</a> en forma local.</p>
<p>En principio, admito que no conozco ningún <a href="http://en.wikipedia.org/wiki/Revision_control" target="_blank">VCS</a> distribuido, más que nada por vagancia (je), pero esto en particular sí lo necesito de vez en cuando, principalmente cuando no estoy conectado, y/o cuando los cambios que hago con respecto a <em>trunk</em> son profundos, llevan tiempo y quiero tener un control más &#8220;fino&#8221; en lo que hago.</p>
<p>A ver, habiendo nombrado primero los sistemas más conocidos (por mí), se desprende que tenemos:</p>
<ul>
<li><a href="http://mercurial.selenic.com/wiki/" target="_blank"><img class="size-full wp-image-354 alignright" title="Logo Mercurial" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/logo-droplets-200.png" alt="Logo Mercurial" width="98" height="118" /></a><a href="http://bitbucket.org/durin42/hgsubversion/wiki/Home" target="_blank">Mercurial-Svn</a>: Si bien el autor del artículo que me inspiró a escribir esto (<a href="http://www.linkedin.com/pub/vadim-zeitlin/6/145/445" target="_blank">Vadim Zeitlin</a>, desarrollador de <a href="http://www.wxwidgets.org/" target="_blank">wxWidgets</a>) comentaba que le gusta muchísimo Mercurial por su fácil uso, al momento de probar esta extensión para subir los cambios al servidor <a href="http://svn.wxwidgets.org" target="_blank">SVN de wxWidgets</a> tuvo problemas de performance, uso de memoria, etc. De todas maneras, el código fuente en el repositorio de wxWidgets <a href="http://trac.wxwidgets.org/browser" target="_blank">es bastante grandote</a> (~330MB), así que quizás funcione bien para proyectos chicos/medianos, y más si uno ya conoce Mercurial.</li>
</ul>
<ul>
<li><a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html" target="_blank">Git-Svn</a>: Bueno, citando nuevamente a Vadim, parece que critica un poco lo complicado de los comandos Git, sin embargo termina recomendándolo en forma rotunda por su velocidad y poca utilización de espacio extra en el disco*. <a href="http://flavio.castelli.name/howto_use_git_with_svn" target="_blank">Acá</a> parece haber un tutorial cortito para utilizarlo (Google me <a href="http://utsl.gen.nz/talks/git-svn/intro.html" target="_blank">devuelve</a> <a href="http://tsunanet.blogspot.com/2007/07/learning-git-svn-in-5min.html" target="_blank">muchísimos</a> <a href="http://git.or.cz/course/svn.html" target="_blank">enlaces</a> <a href="http://xmleye.wordpress.com/2008/10/13/recuperando-repo-svn-desde-clon-git-svn/" target="_blank">más</a> por si es poco).</li>
</ul>
<p style="text-align: center;"><a href="http://git-scm.com/"><img class="aligncenter size-full wp-image-362" title="Git Version Control" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/header.gif" alt="Git Version Control" width="442" height="59" /></a></p>
<ul>
<li><a href="http://bazaar-vcs.org/BzrForeignBranches/Subversion" target="_blank">Bazaar-Svn</a>: A <a href="http://bazaar-vcs.org/" target="_blank">Bazaar</a> lo conozco por su relación estrecha con <a href="http://launchpad.net" target="_blank">Launchpad</a> y <a href="http://www.ubuntu.com" target="_blank">Ubuntu</a>, por lo tanto yo probaría a este primero&#8230; ah, y ellos mismos elaboraron una comparativa (<span style="text-decoration: line-through;">imparcial</span>) entre <a href="http://bazaar-vcs.org/BzrVsGit" target="_blank">Bazaar y Git</a> por un lado, y entre <a href="http://bazaar-vcs.org/BzrVsHg" target="_blank">Bazaar y Mercurial</a> por el otro.</li>
</ul>
<p>En fin, recién me sumerjo en la lectura y experimentación de todo esto, pero para aquellos que trabajan contra un servidor SVN** y suben sus cambios con poca frecuencia al repositorio principal, &#8220;rompiendo todo&#8221; cada vez que lo hacen (guiño, guiño), me parece que esto les viene perfecto.</p>
<p><a href="http://bazaar-vcs.org"><img class="size-full wp-image-371 alignright" title="Bazaar" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/Bazaar1.png" alt="Bazaar" width="221" height="93" /></a>Además, tengo entendido que no es difícil usar Bazaar (por poner uno de ejemplo), y realmente está muy <em>cool</em> poder volver atrás en los cambios que uno hizo desde que hizo el <em>checkout</em>/<em>update</em> del SVN, mientras desarrolla, y sin tener que conectarse a Internet (VPN/SSH/etc.).</p>
<p>(*) Cuando el cliente de control de versiones distribuido hace un <em>checkout</em> del repositorio Subversion, no sólo descarga la última versión de <em>trunk</em>, sino que descarga <strong>todas las versiones pasadas de todas las ramas existentes</strong>, con lo cual el consumo de espacio en disco local pasa a ser un asunto importante. Git, según Vadim, parece tener poco <em>overhead</em> en este sentido comparado con la extensión de Mercurial.</p>
<p>(**) Una de las cuestiones que no le hacen perder valor e importancia a SVN es que, al ser centralizado, sigue siendo relevante en empresas que quieren tener un control más o menos estricto de su código; por lo tanto, la migración a sistemas distribuidos no siempre estará bajo su radar. Es por eso que hablo de &#8220;diferencias&#8221; en el título del post y no de una &#8220;futura migración&#8221;, es decir, <strong>que los distribuidos sean los &#8220;nuevos vecinos de la cuadra&#8221; no quiere decir que vengan a reemplazar a los viejos y conocidos</strong>. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>¡Saludos!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/07/control-de-versiones-manejando-las-diferencias-entre-distribuido-y-centralizado/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Applets Java en Ubuntu de 64 bits recargados</title>
		<link>http://blog.marcelofernandez.info/2009/07/applets-java-en-ubuntu-de-64-bits/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=applets-java-en-ubuntu-de-64-bits</link>
		<comments>http://blog.marcelofernandez.info/2009/07/applets-java-en-ubuntu-de-64-bits/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 23:55:44 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=259</guid>
		<description><![CDATA[Ayer actualicé mi Ubuntu 9.04 (64 bits) y vi que había una actualización de los paquetes &#8220;sun-java6&#8220;, que corresponden a la Máquina Virtual Java. Para mi sorpresa, se trata de una actualización bastante importante de todos los paquetes de la implementación distribuida por Sun de Java (que aún no es lo mismo que el proyecto [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.java.com"><img class="alignright size-full wp-image-311" title="java_logo" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/java_logo.png" alt="java_logo" width="78" height="111" /></a>Ayer actualicé mi Ubuntu 9.04 (64 bits) y vi que había una actualización de los paquetes &#8220;<a href="http://packages.ubuntu.com/search?keywords=sun-java6&amp;searchon=names&amp;suite=jaunty&amp;section=all" target="_blank">sun-java6</a>&#8220;, que corresponden a la <a href="http://es.wikipedia.org/wiki/M%C3%A1quina_virtual_Java" target="_blank">Máquina Virtual Java</a>. Para mi sorpresa, se trata de una actualización bastante importante de todos los paquetes de la <a href="http://java.sun.com/javase/" target="_blank">implementación</a> distribuida por <a href="http://www.sun.com" target="_blank">Sun</a> de Java (que aún no es lo mismo que el proyecto <a href="https://openjdk.dev.java.net/" target="_blank">OpenJDK</a>), y que incluye (después de <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4802695" target="_blank">¡6 años de espera!</a>) una implementación del <a href="http://packages.ubuntu.com/jaunty/sun-java6-plugin" target="_blank">Java Plugin de Sun</a> para 64 bits.</p>
<p>Lo bueno es que ya puedo probar la <a href="http://blogs.sun.com/javaone2008/entry/applets_reloaded" target="_blank">nueva versión del plugin Java</a> (incluida a partir de Java 6 Update 10) sobre Linux x86-84 en forma totalmente nativa.</p>
<p>Acá hay un video de un técnico de Sun, Kenneth Russell, donde describe todas las nuevas características del Java Plugin &#8220;recargado&#8221;:</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube-nocookie.com/v/4wi9Q1x8j7E&amp;hl=es&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube-nocookie.com/v/4wi9Q1x8j7E&amp;hl=es&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>La presentación del mismo en pdf está <a href="http://developers.sun.com/learning/javaoneonline/2008/pdf/TS-6290.pdf">acá</a>. Para información detallada y ejemplos para correr en el navegador, vayan a <a href="https://jdk6.dev.java.net/plugin2/" target="_blank">este link</a>. Las novedades son muchas e importantes, y aunque la gente de Sun debería haberle dado importancia a esto hace tiempo, mejor tarde que nunca; les sugiero pegarle una mirada.</p>
<p>Saludos!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/07/applets-java-en-ubuntu-de-64-bits/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PostgreSQL 8.5</title>
		<link>http://blog.marcelofernandez.info/2009/07/postgresql-8-5/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=postgresql-8-5</link>
		<comments>http://blog.marcelofernandez.info/2009/07/postgresql-8-5/#comments</comments>
		<pubDate>Sat, 04 Jul 2009 16:16:56 +0000</pubDate>
		<dc:creator>Marcelo</dc:creator>
				<category><![CDATA[codear]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[ubuntu-ar]]></category>

		<guid isPermaLink="false">http://blog.marcelofernandez.info/?p=247</guid>
		<description><![CDATA[No, no me equivoqué de número de versión. Si bien PostgreSQL 8.4 ya salió y tiene unas cuantas novedades, quisiera hacerme eco de lo que está en la cola de parches a aprobar para integrar la nueva rama de desarrollo de PostgreSQL 8.5. Esta lista está compuesta por cosas como: GRANT ON ALL IN schema: [...]]]></description>
			<content:encoded><![CDATA[<p>No, no me equivoqué de número de versión. <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> <a href="http://www.postgresql.org"><img class="size-full wp-image-251 alignright" src="http://blog.marcelofernandez.info/wp-content/uploads/2009/07/pgsql_logo.png" alt="pgsql_logo" width="206" height="80" /></a></p>
<p>Si bien <a href="http://www.postgresql.org/about/news.1108" target="_blank">PostgreSQL 8.4 ya salió</a> y tiene <a href="http://www.postgresql.org/about/press/features84">unas cuantas novedades</a>, quisiera <a href="http://www.depesz.com/index.php/2009/07/03/waiting-for-8-5-lets-start/" target="_blank">hacerme eco</a> de lo que está en la cola de parches a aprobar para integrar la nueva rama de desarrollo de PostgreSQL 8.5. <a href="http://commitfest.postgresql.org/action/commitfest_view?id=2" target="_blank">Esta lista</a> está compuesta por cosas como:</p>
<ul>
<li><a href="http://archives.postgresql.org/message-id/4A4DE104.8090605@pjmodos.net" target="_blank"><strong>GRANT ON ALL IN schema</strong></a>: Una manera de otorgar permisos a todos los objetos de un esquema.</li>
<li><a href="http://archives.postgresql.org/message-id/603c8f070906172043w6dba5b18x60e1cea76c44dba0@mail.gmail.com" target="_blank"><strong>Machine-readable explain output v2</strong></a>: Salidas del comando <a href="http://www.postgresql.org/docs/8.3/interactive/using-explain.html" target="_blank">EXPLAIN</a> fácilemente legibles por otro software, es decir, fácilmente parseables para su procesamiento. El comando explain aceptaría como segundo parámetro el formato (además de los actuales) la keyword FORMAT, quedando así: EXPLAIN FORMAT [TEXT | JSON | XML]. Está bueno porque abre la puerta del desarrollo de herramientas de auto-tunning, basado en reglas estilo Sistema Experto.</li>
<li><a href="http://wiki.postgresql.org/wiki/SEPostgreSQL" target="_blank"><strong>SE-PostgreSQL</strong></a>: Security-Enhanced PostgreSQL, una mejora sustancial en la seguridad del SGBD y en el nivel de detalles del sistema de privilegios.</li>
<li><a href="http://wiki.postgresql.org/wiki/NTT%27s_Development_Projects#Synch_Rep" target="_blank"><strong>Replicación Sincrónica</strong></a>: Si algo le faltaba a PostgreSQL es una manera de replicación sincrónica integrada en el gestor. Esperemos que esto sí entre, aunque está <a href="http://archives.postgresql.org/message-id/3f0b79eb0906152313n7d566aa8u80c73516453e5777@mail.gmail.com" target="_blank">bastante</a> <a href="http://archives.postgresql.org/message-id/603c8f070907021902ufbb62cj7ca435f9d8712b4d@mail.gmail.com" target="_blank">discutido</a> el asunto porque es un cambio relativamente &#8220;gordo&#8221; en los internals del código, pero por lo que leí de estas discusiones parece haber consenso en llevarlo adelante e implementarlo. Por mi parte&#8230; ¡lo necesito ya! <img src='http://blog.marcelofernandez.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li><a href="http://archives.postgresql.org/pgsql-hackers/2009-07/msg00158.php" target="_blank"><strong>\dL para listas los lenguajes utilizados en psql</strong></a>: Es una nueva característica en <a href="http://www.postgresql.org/docs/8.3/interactive/app-psql.html" target="_blank">psql</a>, la de poder listar los lenguajes instalados en la base de datos (plpythonu, plpgsql, etc.).</li>
<li><a href="http://archives.postgresql.org/message-id/497CFC84.2070302@paradise.net.nz" target="_blank"><strong>Estadísticas de esperas por bloqueos</strong>:</a> La idea es poder tener un historial de los bloqueos sufridos por los clientes en la BD, para poder detectar problemas y saber bien qué pasa en todo momento.</li>
</ul>
<p>Bueno, de más está decir que no hay ninguna garantía de que todo esto sea finalmente integrado en 8.5, sino que se está evaluando al mejor estilo Software Libre<strong>™</strong>: <a href="http://es.wikipedia.org/wiki/Revisi%C3%B3n_por_pares" target="_blank">peer-review</a>, discusión de estrategias del proyecto, consenso en la comunidad de desarrolladores y posterior aceptación/pedido de mejoras/rechazo. Así que veremos cómo sigue.</p>
<p>Saludos!<br />
Marcelo</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px;">
<h1>\dL for languages</h1>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.marcelofernandez.info/2009/07/postgresql-8-5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
