Monday, June 13, 2011
Wednesday, July 28, 2010
Solution: webrat's save_and_open_page and open_error_files are not opening the browser automatically
Tuesday, July 20, 2010
Passing parameters to before_filter methods in Rails
Monday, May 24, 2010
Installing Mono 2.6 (or the latests version) on Ubuntu 10.4(or the latest version)
- I'm not an expert installing Mono from Sources, so this is all at your own risk.
- Don't remove your existing Mono Runtine, you still need it.
- I recommend you to keep your existing Mono Runtime(the one you installed via APT) side by side with the version that you are going to configure.
- autotools-dev
- autoconf
- libtool
- bison
- gettext
Wednesday, December 9, 2009
Usando un Viewbox para hacer un efecto “Fisheye” en TabControl/WPF
He creado un estilo para mis TabControl de manera que el icono de cada uno de sus TabItem aumente con el mouseover al estilo fisheye, esto es sencillo lograrlo combinando un ViewBox, el ContentPresenter del TabItem y un par de Storyboards. También uso DropShadowEffect para hacer el efecto de iluminación alrededor del iconos seleccionado.
Screenshots:
Nota:
- No funciona en Silverlight.
- La version minima de WPF es .NET 3.5 SP1 y la version usada para crear el ejemplo es Visual Studio 2008 y Blend3.
- Esta optimizado para TabStripPlacement: Left
- Libre de uso Personal y Comercial.
Descarga: FishEyeTabControl.zip
Disfruten :)
Wednesday, November 18, 2009
Reemplazar Cursor con UIElement
He creado un pequeño metodo para reemplazar el cursor de una ventana con un UIElement de WPF:
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace SDKSamples
{
public static class WPFCursor
{
public static void ReplaceCursor(this Window wnd, UIElement cursor)
{
wnd.Cursor = Cursors.None;
Grid cursorHostContainer = wnd.Content as Grid;
if (cursorHostContainer == null) return;
Canvas host = new Canvas();
host.IsHitTestVisible = false;
Canvas.SetZIndex(cursor, int.MaxValue);
cursorHostContainer.Children.Add(host);
host.Children.Add(cursor);
wnd.MouseMove += (s, e) =>
{
var absoluteWindowMousePosition = e.GetPosition(wnd);
Canvas.SetTop(cursor, absoluteWindowMousePosition.Y);
Canvas.SetLeft(cursor, absoluteWindowMousePosition.X);
};
wnd.MouseEnter += (s, e) =>
{
cursor.Visibility = Visibility.Visible;
};
wnd.MouseLeave += (s, e) =>
{
cursor.Visibility = Visibility.Collapsed;
};
}
}
}
Espero les sirva, se usa de la siguiente forma en el constructor de la ventana a la cual le necesitamos reemplazar el cursor, en este ejemplo mi nuevo cursor sera una instancia de un UserControl llamado MySuperCursor.
1: public MainWindow()
2: {
3: InitializeComponent();
4: this.ReplaceCursor(new MySuperCursor());
5: }
Por ultimo, el unico requerimiento que tiene es que la ventana tenga un Grid como elemento contenido principal:
1: <Window x:Class="SDKSamples.Window2"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: Title="Window2" Height="300" Width="300">
5: <Grid>
6: </Grid>
7: </Window>
he aqui un screenshot:
Tuesday, November 10, 2009
Controles WPF Multi-Contenido con ContentPresenter
He estado usando ContentPresenter en muchos escenarios y quiero compartir algunos tips acerca de como usarlo y de la flexibilidad que este ofrece para crear controles multi-contenido. Para demostrarlo he creado un control que soporta una contenido ‘Lista’ y otro ‘Detalle o Editor’ muy común en aplicaciones de edición de datos. Al final del articulo se encuentra el vinculo de descarga.
Este es un screenshot de una aplicación de ejemplo que he creado para demostrar el control multi-contenido:
Soluciones con ContentPresenter
Al igual que un control HeaderedItemsControl el cual tiene propiedades Content y Header, nosotros estaremos usando el mismo ContentPresenter pero para mostrar distinta información del control establecidas en las siguientes propiedades:
Como el control debe ser full personalizable usamos las siguientes propiedades para mejorar la presentación:
Podemos imaginarnos dos partes visuales en el control de la siguiente forma:
Para usarlo aplicamos un ControlTemplate,ListTemplate y CurrentItemTemplate de la siguiente forma:
1: <listeditors:ListEditor List="{Binding OrderDetails}">
2: <listeditors:ListEditor.ListTemplate>
3: <DataTemplate>
4: <ListView Width="220" ItemsSource="{Binding}"
5: SelectedItem="{Binding CurrentItem,Mode=TwoWay,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type listeditors:ListEditor}}}">
6: <ListView.View>
7: <GridView>
8: <GridView.Columns>
9: <GridViewColumn Width="100" Header="Product" DisplayMemberBinding="{Binding ProductCode}"/>
10: <GridViewColumn Width="100" Header="Quantity" DisplayMemberBinding="{Binding Quantity}"/>
11: </GridView.Columns>
12: </GridView>
13: </ListView.View>
14: </ListView>
15: </DataTemplate>
16: </listeditors:ListEditor.ListTemplate>
17: <listeditors:ListEditor.CurrentItemTemplate>
18: <DataTemplate>
19: <StackPanel>
20: <DockPanel>
21: <TextBlock Text="Product Code" Width="100"/>
22: <TextBox Text="{Binding ProductCode}"></TextBox>
23: </DockPanel>
24: <DockPanel>
25: <TextBlock Text="Quantity" Width="100"/>
26: <TextBox Text="{Binding Quantity}"></TextBox>
27: </DockPanel>
28: <DockPanel>
29: <TextBlock Text="Comments" Width="100"/>
30: <TextBox Height="30" Text="{Binding Comment}"></TextBox>
31: </DockPanel>
32: </StackPanel>
33: </DataTemplate>
34: </listeditors:ListEditor.CurrentItemTemplate>
35: <listeditors:ListEditor.Template>
36: <ControlTemplate TargetType="listeditors:ListEditor">
37: <DockPanel>
38: <ContentPresenter Margin="4" DockPanel.Dock="Left" ContentSource="List" />
39: <ContentPresenter Margin="4" ContentSource="CurrentItem" />
40: </DockPanel>
41: </ControlTemplate>
42: </listeditors:ListEditor.Template>
43: </listeditors:ListEditor>
Uso de ContentPresenter
Preste atencion a los ContentPresenter que estan en las lineas 38 y 39. El primero mostrara los datos de la propiedad ‘List’ usando el DataTemplate configurado entre las lineas 2-16 y el Segundo ContentPresenter mostrara los datos de la propiedad ‘CurrentItem’ usando el DataTemplate configurado entre las lineas 17-34.
Realmente quien hace todo el trabajo es el ContentPresenter con sus propiedades Content,ContentTemplate y ContentTemplateSelector que se asignan automáticamente con las propiedades del control donde pertenece el ControlTemplate basándose en el nombre establecido en la propiedad ContentSource.
Ejemplo. Esta es una configuración correcta de ContentPresenter en un ControlTemplate:
<ContentPresenter ContentSource="CurrentItem" ContentTemplate="{TemplateBinding CurrentItemTemplate}" ContentTemplateSelector="{TemplateBinding CurrentItemTemplateSelector}" />
Sin embargo se puede resumir con ContentSource:
<ContentPresenter Margin="4" ContentSource="CurrentItem" />
Desestimare de algunos ‘Mitos’ sobre ContentPresenter:
- ContentPresenter PUEDE usarse en cualquier ControlTemplate para mostrar cualquier propiedad del Control donde aplicamos el ControlTemplate.
- ContentPresenter busca AUTOMATICAMENTE las propiedades ‘Content’,‘ContentTemplate’ y ‘ContentTemplateSelector’ en el control donde se aplica el ControlTemplate a menos que se asignen directamente via TemplateBinding o usando ContentSource. Esto es para minimizar la configuración en Controles de tipo ContentControl.
- ContentPresenter NO REQUIERE que el Control al que le estamos aplicando el Template herede de la clase ContentControl. Sin embargo, es necesario configurar ‘ContentSource’ para la propiedad que necesitemos mostrar como fue el caso de nuestro control.
- ContentPresenter SOLAMENTE REQUIERE una propiedad para Content. Tanto ContentTemplate como ContentTemplateSelector son opcionales y se usan automaticamente(via ContentSource) solo si están presentes.
- La funcionalidad de ContentSource SOLO ESTA DISPONIBLE en ControlTemplate’s y no en DataTemplate’s esto se debe a que el mecanismo de asignación automática de propiedades se hace atreves de TemplatedParent que se asigna solo dentro del contexto de un DataTemplate.
DataContext y Enlace de Datos
El DataContext es asignado automaticamente dentro del DataTemplate por el ContentPresenter, es por eso que en la linea 4 podemos ver como se enlaza el ItemsSource del ListView usando la extension Binding de Forma sencilla. Recordemos que este DataTemplate es usado por el ContentPresenter de la propiedad ‘List’ asi que el DataContext contiene el mismo valor asignado a la propiedad ‘List’ del control que ha sido enlazada en la linea 1.
El mismo caso sucede con el DataTemplate de ‘CurrentItemTemplate’ el cual en su DataContext tiene el valor del la propiedad CurrentItem(nuevamente asignado automaticamente por el ContentPresenter).
Actualizando propiedades del Control desde el DataTemplate
Además de Visualizar la lista de elementos, El ListTemplate debe establecer en la propiedad CurrentItem cual es el elemento seleccionado en la lista. Si en vez de trabajar con DataTemplate usáramos ControlTemplate podríamos usar TemplateBinding para hacer esto de forma sencilla pero TemplateBinding solo funciona en ControlTemplate por lo que debemos usar Binding + Relative Source/Ancestor en modo TwoWay como se mostro en la línea 5.
SelectedItem="{Binding CurrentItem,Mode=TwoWay,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type listeditors:ListEditor}}}"
Esto causa que cuando se cambie el elemento seleccionado en el ListView se actualice la propiedad CurrentItem.
Nota: Inicialmente antes de estar consiente del uso tan practico del ContentPresenter yo solía usar propiedades de tipo ControlTemplate. Esta practica no tiene ningún sentido ya que aunque puedo cargar los elementos visuales del ControlTemplate usando su metodo LoadContent() el TemplatedParent de los controles internos siempre estaba en null(Nothing en Visual Basic) ya que solo los Controles deberian usar ControlTemplate directamente.
Conclusión
ContentPresenter es una excelente solución para desarrollar controles multi-contenido. Otros controles que hacen uso de este son los siguientes:
Descargue el proyecto de ejemplo para Visual Studio 2008 LobListEditor.sln
Friday, October 23, 2009
22 Tips para un blog exitoso
Espero les sea util.
- El lector de tu blog no quiere saber lo interesante que eres, te leen para saber que tan interesante pueden llegar a ser ellos. Lo que expreses en cada post debe ser de utilidad para ellos y así puedan compartirlo.
- Aprende lo suficiente para ser un experto en el tema.
- Los visitantes de tu blog son solo curiosos, los seguidores de tu blog les gusta el tema del que hablas, por eso es importante tener un tema central.
- Escribe con un tono adecuado para el público al que te diriges. Si el tema del blog es de interés global evita usar slangs locales de tu región.
- Es importante acostumbrar a los seguidores a una cierta cantidad de información en cada entrega. Tener como meta un número mínimo y máximo de palabras en cada post es una buena práctica.
- Posts cortos son fáciles y rápidos de digerir aunque la lectura está cargada de información. Inconscientemente el seguidor se acostumbrara a leer tu blog aunque tenga poco tiempo porque sabe que los posts son cortos y concisos. Esto requiere una mayor frecuencia de nuevos posts. Sin embargo, posts demasiado cortos con mucha frecuencia hacen el blog irrelevante para leer lo cual no es conveniente.
- Post largos y con mucho detalle tiene un público muy exclusivo por lo que no es necesario crear contenido con tanta frecuencia. Post demasiado largos y cargados de poca información hacen que el seguidor omita tu blog para leerlo cuando tengan más tiempo lo cual tampoco es conveniente sino es que deja de seguir tu blog.
- Como el tema de tu blog está centrado en un solo tema, cada post nuevo debería tener al menos 1 link a un post anterior.
- Da el crédito a quien te inspiro, eso le da credibilidad al tema.
- Al menos 1 de cada 10 posts debe invitar al lector a participar directamente. Las encuestas con un límite de tiempo son una buena opción ya que cuando finalice el resultado de la misma y su análisis son un tema para un nuevo post.
- Escribe solo cuando tengas algo muy relevante que decir.
- Tanto el titulo del blog, como el tema visual y el titulo de post deben tener un estilo y personalidad que se ajuste al tema.
- El titulo de cada post, además de tener un estilo particular debe ser llamativo e intrigante para llamar la atención al contenido, esto es particularmente útil si el lector es seguidor de tu blog via Feeds.
- La introducción de cada post debe hacer interesante y rápida (no más de dos líneas) para hacer relevante la lectura de todo el post. Evita que la introducción involucre las últimas cosas divertidas que ha hecho tu mascota favorita a menos que tu blog sea acerca de tu mascota o de mascotas divertidas.
- No interrumpas el contenido del post colocando más de un link sin antes introducir de que se trata cada uno de ellos o porque están relacionados.
- Si colocas Twitter como contacto: Considera la posibilidad de seguir a quien te sigue.
- Si colocas Facebook como contacto: Acepta a quien te agregue como amigo.
- Si colocas tu Correo electrónico como contacto: Responde los mails.
- Si tienes activado los comentarios en tu blog: Lee y responde los comentarios que formulen preguntas directas a ti.
- Cada post debe ser considerada como una obra de arte. Usa un procesador de palabras (Word,Writer,etc) para minimizar errores de ortografía y gramática y en cada post pide a un amigo que lea tu post cuanto antes en busca de incoherencias y corrige cualquier error cuanto antes.
- Cuando sea posible usa imágenes en cada post. Si el blog se trata de acontecimientos actuales (noticias de última hora, eventos, etc) la imagen de introducción debe ser obligatoria y de gran tamaño y aun más interesante que la lectura misma. Si el blog se trata de material complementario (Temas Geek, HowTo’s) la imagen no debe distraer al lector del contenido.
- Sigue este blog.
Tuesday, October 20, 2009
Bloggin: La superficial satisfacción de ser admirado
Cuando inicie este blog en 2006 solo tenía un sencillo objetivo: Tener un blog.
Eso fue fácil de lograr y sin saber que tener un ritmo de blogging y un tema centrado eran claves para tener un blog exitoso, yo hacia un post cada 2 días y solo posteaba relacionado a lenguajes de programación por lo que para mediados de 2007 tenía un promedio de 4000 visitas únicas mensuales, número que significaba mucho para mí siendo un novato en la web 2.0. Con el pasar del tiempo cambie de objetivo: Tener muchos lectores. Seis meses después casi había abandonado mi blog. ¿Porque razón? Mi primera excusa era que no tenía tiempo para escribir, la segunda fue que blogger.com no formateaba bien mi código y así sucesivamente hasta que deje de escribir. Finalmente descubrí porque razón no continuaría: Porque la superficial satisfacción de ser admirado ya no me llenaba.
Entonces te podrás preguntar para que esté escribiendo esta vez, ¿será que es así como un blogger confundido hace su propia autobiografía? Tal vez alguna día sea así pero no esta vez, he encontrado un objetivo bien claro para bloggear el cual descubrirán mis lectores con cada post. Hablando de buenas prácticas en blogging les recomiendo leer los siguientes blogs que he venido leyendo religiosamente por más de un año:
Ninguno de ellos tiene necesidad de que yo les haga un link, pero me siento tan agradecido que siento que de alguna forma les devuelvo el favor, en mi siguiente post les comentare que he aprendido de estos grandes Gurús en marketing y web media y como han contribuido al objetivo de mi blog: ¿y tú ya tienes claro cuál es el objetivo del tuyo?
Sunday, March 16, 2008
Cambiar Dinamicamente el Titulo del Modulo en Symfony
default:
http_metas:
content-type: text/html
metas:
title: Productos
robots: index, follow
description: Administracion de Productos
keywords: Administrar Productos Articulos
language: es
Sin embargo el mismo titulo para todo el modulo puede causar dolores de cabeza al usuario del sitio web cuando tiene muchas ventadas a diferentes acciones de un mismo modulo por lo que considero bueno cambiarlo dinamicamente de acuerdo a la accion, esto se hace usando la funcion setTitle del sfWebResponse como sigue:
$this->getResponse()->setTitle('Producto - ' .$this->product->getName());
Ejemplo:
public function executeShow()
{
&this->product = ProductPeer::retrieveByPk($this->getRequestParameter('id'));
$this->forward404Unless($this->product);
$this->getResponse()->setTitle('Producto - ' .$this->product->getName());
}
Bien Sencillo :)
Monday, February 25, 2008
Comillas para Nombres de Tabla Oracle en Symfony
Estoy trabajando en un proyecto usando el PHP Symfony, la base de datos que uso es Oracle 10g y encontrado unos detalles que quiero compartir.
Problema
En la version 1.0.10 existe un problema con el Creole-Propel y es que el comando symfony propel-build-sql genera un archivo SQL con comillas en los nombres de los objetos, para Oracle esto significa que se hace distincion de mayusculas de Minusculas en estos nombres. Por otra parte los comandos generados por Creole para el OM mediante el comando propel-build-model generan Sentencias SQL sin comillas asi que las consultas fallan al no encontrar las tablas y sequencias con el nombre adecuado.
Solucion
Editar el archivo config/propel.ini del proyecto y agregar la siguiente linea:
propel.disableIdentifierQuoting=true
Wednesday, January 9, 2008
Mover Proyecto Symfony de Ubuntu a Redhat
Actualmente estoy trabajando con PHP Symfony y instalado un proyecto en Redhat que fue generado y construido en Ubuntu por lo que al instalar el symfony usando pear(al igual que ubuntu) la ruta de los archivos de symfony es diferente y al ejecutar cualquier comando de symfony('symfony cc' por ejemplo) ocurren errores al hacer los includes.
Ejemplo:
jhernandez@POSEIDON-LINUX:~/WebApps/$ symfony cc
Warning: include(/usr/share/pear/data/symfony/bin/symfony.php): failed to open stream: No such file or directory in /usr/bin/symfony on line 39
Warning: include(): Failed opening '/usr/share/pear/data/symfony/bin/symfony.php' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /usr/bin/symfony on line 39
Esto sucede porque el archivo config/config.php apunta a una direccion de los archivos de symfony invalida.
En Ubuntu por ejemplo, el archivo config/config.php debe verse similar a este:
// symfony directories
$sf_symfony_lib_dir = '/usr/share/php/symfony';
$sf_symfony_data_dir = '/usr/share/php/data/symfony';
En Redhat por ejemplo, el archivo config/config.php debe verse similar a este:
// symfony directories
$sf_symfony_lib_dir = '/usr/share/pear/symfony';
$sf_symfony_data_dir = '/usr/share/pear/data/symfony';
Esto se debe a que el PEAR instala los archivos de php symfony en diferentes rutas de acuerdo a la distribucion. Solo es cuestion de corregirlo para que el problema se solucione.
Monday, December 3, 2007
Como funciona HTTP como Separador de Mensajes TCP
Tal como ya había comentado en un post anterior, TCP es un Protocolo de Control de Flujo de Datos, no de Mensaje de Datos por lo que es necesario implementar un separador de Mensajes sobre TCP. ¿Qué exactamente Hace un Separador de Mensajes? Un separador de Mensajes es un conjunto de reglas que se aplican sobre la transmisión de datos para saber de que parte de que flujos comienzan o finalizan los mensajes, casi siempre el Separador de Mensajes se implementa con un Encabezado y un Contenido donde una de las múltiples funciones del encabezado es el de informar del tamaño total del cuerpo del mensaje en caso de que exista. Protocolos como HTTP implementan su propio separador de Mensajes. Ejemplo:
HTTP/1.1 POST /
Content-Length:16
txtNombre=Johan
El ejemplo anterior es un mensaje HTTP, se compone de un encabezado y un cuerpo. El encabezado se compone de un conjunto de Líneas separadas por un tabulado LFCR?? Que se separa del cuerpo del mensaje por una línea en blanco. Si el encabezado contiene una línea Content-Length entonces después de la línea en blanco se recibirá como cuerpo del mensaje el número total de bytes que se especifico en la línea Content-Length, si no se especifica Content-Length, entonces el mensaje se compone solo del encabezado y los siguientes bytes recibidos después de la línea en blanco son tomados como el Encabezado de otro Mensaje.
Para el ejemplo del Mensaje HTTP que se mostro anteriormente corresponde a el siguiente conjunto de bytes:
72, 84, 84, 80, 47, 49, 46, 49, 32, 80, 79, 83, 84, 32, 47, 10,13,67, 111, 110, 116, 101, 110, 116, 45, 76, 101, 110, 103, 116, 104, 58, 49, 54,10,13,10,13,116, 120, 116, 78, 111, 109, 98, 114, 101, 61, 74, 111, 104, 97, 110
Debido a que el encabezado del Mensaje HTTP es siempre ASCII cada byte del encabezado corresponde a un carácter ASCII, la combinación de byte 10(LF, Representado en Espace Unicode de C# como ‘\n’) y 13(CR, Representado en Escape Unicode de C# como ‘\r’) indican que finaliza una Linea del Encabezado HTTP. El dato binario anterior compone un mensaje HTTP completo pero ese dato binario puede recibirse en multiples flujos de datos TCP de cualquier tamaño, Es decir, que podríamos recibir:
72, 84, 84, 80, 47, 49, 46, 49, 32, 80, 79, 83, 84, 32, 47, 10
13,67, 111, 110, 116, 101, 110, 116, 45, 76
101, 110, 103, 116, 104, 58, 49, 54,10,13,10,13,116, 120, 116
78, 111, 109, 98, 114, 101
61, 74, 111, 104, 97, 110
Cuando se está percibiendo datos TCP y haciendo un parsing para Formatear Mensajes, se tiene que saber que bytes corresponden a el encabezado del mensaje actual, el contenido del mensaje actual o el encabezado de los siguientes mensajes que se recibirán. Las operaciones a realizar son las siguientes:
Leer todas las líneas del encabezado hasta encontrar una línea en blanco, que equivale a encontrar la secuencia de bytes 10,13,10,13.
Si el encabezado contiene una sentencia Content-Length y su valor es mayor a 0, entonces después del encabezado se tomaran cuantos bytes se reciban como contenido del Mensaje hasta agotar la cantidad especificada. Ejemplo: Si se recibe en el encabezado la línea ‘Content-Length:3563’, entonces se tomaran los 3563 bytes que se reciban en uno o más flujos de datos después de encontrar la secuencia 10,13,10,13.
Ejemplo:
| Ultima Línea del Encabezado | Fin de Línea en Blanco |
| |||||||
| 56 | 34 | 673 | 10 | 13 | 10 | 13 | 43 | 48 | 34 |
| Final de Encabezado HTTP | Contenido | ||||||||
En una proxima entrega explicare como se ha implementado este Procolo en C#.
Siguiendo Tutorial de PHP Symfony en Ubuntu
Desde hoy me han encargado de un proyecto en PHP, especificamente con PHP Symfony(un framework MVC) asi que me he descargado el Symfony Sandbox y configurado en mi Apache2 pero he encontrado algunas dificultades con los comandos de symfony al ejecutar el Tutorial y por eso escribi este post para guiarles acerca de los paquetes necesarios para seguir correctamente el Tutorial.
Los paquetes con los siguientes:
php5-xsl
php5-sqlite
Debido a que el tutorial trabaja con SQLLite para almacenar los datos, se debe reiniciar apache2 para que el php de apache cargue los modulos recientemente instalados:
$apache2ctl restart
o
$/etc/init.d/apache1 restart
El libro se pude descargar por eMule o en la pagina oficial de Symfony.
Suerte con PHP Symfony.
Wednesday, November 28, 2007
Seminario: "Capacidades de Ubuntu Linux 7.10 Gutsy Gibbon" en Kapacita
Hoy 28 de Noviembre estare dictando un seminario de Ubuntu Linux en Kapacita, un instituto de Tecnologia aqui en la ciudad de Caracas que esta introduciendo excelentes Cursos para Certificacion en Linux y Ubuntu. Pronto estaremos impartiendo otro seminario que puede ser de tu interes, escribeme un comentario o enviame un correo a johan@ubuntu.org.ve o a thepumpkin1979@gmail.com.
El 8 de Diciembre tambien estare en la ciudad de Maracaibo para un evento de Ubuntu, pronto les dare mas detalles. Si eres de Maracaibo tambien podras asistir.
Saludos.