Logo Umeet2001

ESPAÑOL
Presentación

Programa

Desarrollo

ENGLISH

Presentation

Programa

Desarrollo


fernandoveamos
antlarrLos que esteis esperando para la charla sobre programación con KDE  podeis ir bajándoos el tutorial que hay en http://perso.wanadoo.es/antlarr/bin/kdetutorial-1.1.2.tar.bz2
fernandoEn breves instantes va a comenzar la conferencia sobre KDE
fernandoRecuerden que más tarde teneoms una interesante ponencia sobre comercio electrónico y linux en perú
fernandoSi les parece, empezamos
fernandoHola a todos
fernandoAhora tenemos el placer de presentar la conferencia de Antonio Larrosa.
fernandoEs un desarrollador de KDE, proyecto con el que colabora desde 1997.
fernandoEstudia matemáticas en la Universidad de Málaga
fernandoQueremos agradecer a todos su presencia aquí, y a Antonio muy
fernandoesspecialmente por haber preparado esta interesante conferencia.
fernandoEsta
fernandoépoca es especialmente mala para los estudiantes, con muchos exámenes y
fernandotodas esas cosas desagradables ;)
fernandoHoy nos va a hablar de Desarrollo de aplicaciones en KDE
fernandoSr. Larrosa...
antlarrMuchas gracias fernando
antlarrBuenas noches a todos
antlarrComo ya ha dicho Fernando, voy a tratar de explicar cómo se programa en KDE
antlarrpara ello, voy a exponer primero una introducción sobre programación en Qt
antlarry después pasaré a explicar un tutorial que he escrito y que podeis encontrar en
antlarrhttp://perso.wanadoo.es/antlarr/bin/kdetutorial-1.1.2.tar.bz2
antlarrSi quereis verlo "online" podeis acceder a http://perso.wanadoo.es/antlarr/tutorial/index.html
antlarrEn el tutorial empezaré desde cero, y cuando lo terminemos habremos construido dos aplicaciones
antlarruna es un navegador de internet con soporte HTML4, CSS1 y 2, Flash, Javascript, etc.
antlarr(incluso soporte para historial)
antlarry la otra aplicación es un gestor de "favoritos" que se comunica con el navegador
antlarrpara gestionarlos
antlarrtodo eso lo haremos en sólo 9 pasos (agrandando poco a poco el programa), e intentaré explicar linea a linea como funciona
antlarrsólo necesitareis un poco de experiencia en C++ (si sabeis C, creo que podeis enteraros de algo también :) )
antlarrSi quereis hacer alguna pregunta, haré una parada al final de cada paso para que me pregunteis sobre lo que estaba hablando
antlarrAdemás, al final haremos otro turno de preguntas más generales y para lo temas que se os hayan quedado "atascados"
antlarrBien, empezaré primero por explicar sobre Qt
antlarrComo la mayoría de vosotros sabréis, Qt es una librería multiplataforma desarrollada por Trolltech, y que está disponible para entornos Unix bajo la GPL (además de otras licencias para uso comercial)
antlarrEscribiendo un único código fuente, podeis compilar el mismo programa en Linux, Windows, Mac e incluso para dispositivos PDA
antlarrPor ello, han desarrollado una extensa gama de clases para casi todo
antlarrPor ejemplo, los que programeis en C estaréis acostumbrados a usar "char *" para vuestras cadenas de texto
antlarry los que uséis C++ con la STL, usareis "string"
antlarrQt implementa una clase que se llama QString que sirve para almacenar una cadena de texto
antlarrLa gracia de esta clase es que obtenemos "gratuitamente" (en el sentido de "sin esfuerzo por nuestra parte") una cadena de texto que puede contener caracteres unicode
antlarry que es muy fácil de usar
antlarrAdemás, tiene cosas como "shallow copy" que significa que cuando copias una cadena en otra, lo que hace realmente es copiar una referencia de forma que es mucho más rápido que copiar la cadena entera "de verdad"
antlarrasí, luego implementa el "copy on change" para hacer la copia real cuando alguna de las cadenas es modificada
antlarrOtros ejemplos de clases útiles son QChar, que guardan caracteres.
antlarrQList <template> nos sirve para guardar una lista de objetos
antlarr(de punteros a objetos)
antlarrEs una lista doblemente enlazada que podemos utilizar muy facilmente. Por ejemplo:
antlarrQList <MiObjeto> lista();
antlarrlista.append(unobjeto);
antlarrlista.append(otroobjeto);
antlarrademás, hay iteradores para recorrer la lista.
antlarrPor otra parte, hay clases que en vez de guardar una lista de punteros a objetos, guardan una lista de objetos en sí (por valor).
antlarrArrays, Pilas (Stacks), etc.
antlarrPor otra parte, tenemos otra colección de objetos que implementa Qt que son más específicos
antlarrel más básico de estos es QObject
antlarrComo ya he comentado, Qt extiende el lenguaje definido por C++ para añadir nuevas funcionalidades
antlarrAlgunas de las más importantes son el soporte de señales/slots, y el soporte de propiedades (por nombrar sólo algunos ejemplos)
antlarrEstas funcionalidades las añade por medio de la clase QObject, que es donde se implementa este soporte.
antlarrAlgunos de vosotros os preguntareis qué son señales y slots, así que voy a intentar dar una breve descripción.
antlarrGeneralmente, en los sistemas de ventanas, las aplicaciones realizan tareas de acuerdo a determinados eventos
antlarrel gestor de ventana (o XWindows en nuestro caso) genera los eventos y en nuestro código tenemos un enorme bloque switch(evento) { .... }; que trata todos los posibles eventos
antlarren vez de realizar esto así, nosotros vamos a hacerlo de una forma más cómoda y mucho más extensible (el código que se obtiene es realmente más reutilizable), usando señales
antlarrLas señales son eventos que las clases generan cuando cambian de estado, y los slots son funciones (funciones miembros de cualquier clase) a las que se conectan las señales
antlarrde esta forma, en nuestro código "conectamos" una señal con un slot, de forma que cuando el objeto primero cambie su estado de alguna forma, el objeto segundo haga algo.
antlarrPor ejemplo,
antlarrSupongamos que tenemos un botón (clase QPushButton) que queremos que descargue el correo cada vez que se pulse.
antlarrY tenemos una función (en un objeto nuestro "lectorDeCorreo" ) que descarga el correo
antlarrlo único que tenemos que hacer es tratar a esa función como un slot y poner en nuestro código
antlarrconnect(boton, SIGNAL(clicled()), lectorDeCorreo, SLOT(descargaCorreo()));
antlarrconnect(boton, SIGNAL(clicked()), lectorDeCorreo, SLOT(descargaCorreo()));
antlarr:-)
antlarrcomo veis, el botón genera una señal (con nombre "clicked()" ) cada vez que es pulsado (de hecho, pulsado y soltado, ya que hay otras señales "pressed()" y "released()" )
antlarrAdemás, si queremos que además de descargar el correo, el botón haga sonar un fichero wav (cosa que hacemos en nuestra función "tocaMusica()" )
antlarrsólo tenemos que añadir otra conexión al botón, ya que podemos tener tantas conexiones de una misma señal a cuantos slots queramos
antlarrtambién podemos tener muchas señales conectadas a un mismo slot
antlarrla gracia de esto es que el botón no sabe para qué se utilizan las señales, simplemente las emite y "se olvida", y los slots no saben por qué se han llamado, simplemente ejecutan su función. Con lo que se consigue muchísima más reusabilidad de objetos que con otros métodos
antlarrsupongo que alguno de vosotros se preguntará por qué he usado paréntesis así "()" al final de cada nombre de señales o slots
antlarrLo he hecho así, porque en realidad ambas cosas no son más que funciones, que en este caso no tenían parámetros, pero que podrían tenerlos (y de cualquier tipo, no sólo de tipos básicos)
antlarrpor ejemplo, una barra de scroll (o barra de desplazamiento) tiene un valor dentro de un rango.
antlarrcuando el usuario mueve la barra, el objeto genera una señal llamada "valueChanged(int)"
antlarrque podemos conectar a una función de un objeto nuestro que se llame por ejemplo mueveLaPantalla(int v);
antlarrBien, pues toda esta funcionalidad está implementada en QObject, y por tanto tenemos que heredar de ese objeto si queremos tener señales/slots en un objeto nuestro.
antlarrDe QObject hereda otra clase muy importante que se llama QWidget
antlarrun QWidget es cualquier cosa que veais en la pantalla de vuestro ordenador, un botón, un menú, una barra de herramientas, una barra de scroll, la barra de título de vuestras ventanas, etc.
antlarrQWidget es la base de la que heredan por tanto clases como QButton, QMenuBar, QToolBar, QScrollBar, etc.
antlarrY bueno, creo que ya estoy acabando la introducción
antlarrhay alguna pregunta antes de que pasemos a hacer nuestro primer programa ?
fernandopreguntas
fernandopodrías comentar por encima algunos modelos alternativos al que acabas de contarnos ?
antlarrsi quieres programar en KDE, es el único modelo a seguir :)
fernandojaja
fernandome refería a la competencia
antlarren Windows por ejemplo, según tengo entendido se sigue el modelo que ya he explicado basado en eventos
pekesansi, pero hay ke dar bastantes mas vueltas para manejar los eventos en windows
pekesan;P
antlarrsí, hay que hacer muchas definiciones (tipo #define) generalmente en Windows :)
antlarres más fácil si usas el propio API de vuestro programa como "mensajería"
antlarren Gtk por ejemplo creo que usan algo parecido a señales y slots
antlarrpero prefiero no hablar del tema porque no he programado practicamente nada en Gtk
antlarrUna cosa muy importante de Qt es la estandarización de los nombres que una vez que te acostumbras es muy cómoda.
lucredonde se puedo dar clases particulares?
antlarrPor ejemplo, sabes que si quieres obtener el ancho de un objeto de tipo QPixmap, sólo tienes que llamar a mipixmap.width()
antlarres decir, siempre vas a utilizar el nombre de la "propiedad" que quieres obtener
antlarrnada de unas veces width(), otras veces Width(), getWidth(), get_width(), etc.
fernandoeso me recuerda otra pregunta, relativa a algo que dijiste antes
fernandohablaste de Qstring (o algo asi)
pekesanklaro, todas derivan de QObject no...supongo ke se redefine el metodo no?
antlarrsiempre, cuando se quiere obtener un valor, se llama a una función que tiene el nombre de la propiedad, y cuando se quiere establecer, se llama a set... seguido de la propiedad (por ejemplo, setWidth(nuevoAncho) )
fernandolas funciones de manejo de cadenas en qt, son robustas, consistentes y todo eso?
fernandoo se parecen a las de C ?
antlarrson _muy_ robustas :)
antlarrpekesan: un momento
antlarrpor ejemplo, ya he comentado que soportan unicode, soportan escritura bidireccional, y como he comentado son _muy_ rápidas.
antlarrPor supuesto, han tenido en cuenta que hay casos en los que no hace falta unicode (que como sabeis, utiliza 16 bits por carácter en vez de 8) y también hay otra clase llamada QCString que es más parecida a lo que sería un char *
antlarrAdemás, QString facilita mucho el tema de las traducciones del software a otros idiomas
antlarrya que puedes poner por ejemplo:
antlarrQString micadena("this is test number %1");
antlarrmicadena.arg(numero);
antlarrperdón, quería decir, al principio:
antlarrQString micadena(tr("this is test number %1"));
antlarr(para que lo traduzca :) )
antlarrasí, al programador le da igual si la cadena en el lenguaje de Yoda se traduce como "el test numero %1 éste es"
antlarrya que QString se encarga de cambiar %1 esté donde esté.
antlarrPor otra parte, y contestándote fernando más directamente, QString no tiene problemas de desbordamiento con los equivalentes a sprintf y todo eso, con lo que se eliminan muchos problemas de seguridad
antlarrpekesan: contestando tu pregunta, si casi todas las clases heredan de QObject
antlarrpero ni QString por ejemplo, ni los tipos de datos básicos lo hacen porque realmente no necesitan el manejo de señales
antlarr¿alguna pregunta más?
antlarrBien, pues continuamos con el paso 1 : un "Hola Mundo" escrito en Qt
antlarrEs un programa que muestra un botón con el texto "hola mundo" y que se cierra cuando lo pulsamos.
antlarrEl programa nos va a caber entero en un fichero:
antlarr#include <qapplication.h>
antlarr#include <qpushbutton.h>
antlarrint main( int argc, char **argv )
antlarr{
antlarr    QApplication a( argc, argv );
antlarr    QObject::connect( hello, SIGNAL(clicked()), &a, SLOT(quit()) );
antlarr    a.setMainWidget( hello );
antlarr    return a.exec();
antlarr}
antlarreso es todo
antlarrlos include los escribimos para poder utilizar esas clases, así que la primera linea del programa en sí es
antlarr    QObject::connect( hello, SIGNAL(clicked()), &a, SLOT(quit()) );
antlarr    a.setMainWidget( hello );
antlarr    return a.exec();
antlarr}
antlarr QApplication a( argc, argv );
antlarr¿Qué es lo que hace QApplication?
antlarrBien, QApplication es un objeto que debe existir siempre en cualquier aplicación que hagamos y que gestiona aspectos básicos de cualquier programa
antlarrpor ejemplo, los parámetros estándares de XWindows como -geometry, etc.
fernando(programa en http://perso.wanadoo.es/antlarr/tutorial/p1.html )
antlarrpara ello, creamos el objeto a y al constructor le pasamos los parámetros argc y argv que son los que teníamos de nuestro main
antlarr(gracias fernando, se me había olvidado :) )
antlarrEn la segunda linea
antlarrlo que hacemos es crear un objeto de tipo QPushButton, es decir, un botón que se puede pulsar
antlarr(además de botones que se pueden pulsar, hay botones que tienen dos estados (QCheckBox) o botones que se agrupan y sólo uno de ellos puede estar activo a la vez (QRadioButton) )
antlarrEl primer parámetro es el texto que va a contener ("Hello world!")
antlarry el segundo parámetro es el "padre" de este botón (en este caso, 0 o sea, sin padre, lo que significa que debe aparecer como una ventana independiente)
antlarrRecuerdo que se dice que un widget (un botón es un widget al fin y al cabo) es hijo de otro si está dentro de otro.
antlarr(al que se considera, padre)
antlarrllama a la función resize del botón para cambiarle el tamaño a una cosa adecuada para el texto que estamos escribiendo
antlarrcon  QObject::connect( hello, SIGNAL(clicked()), &a, SLOT(quit()) );
antlarrlo que hacemos es conectar la señal "clicked()" del botón hello al slot "quit()" de nuestra aplicación a.
antlarrEs decir, cierra la aplicación cuando el botón se pulse.
antlarr a.setMainWidget( hello ); le especifica al objeto QApplication que hello va a ser nuestro widget principal
antlarres decir, el bucle de eventos que va a llamar a los slots apropiados cada vez que ocurra algo en nuestra aplicación, etc.
antlarrlos que hayais bajado el tutorial, supongo que ya lo habreis compilado y lo habreis probado
antlarr¿hay alguna pregunta al respecto?
fernandopreguntas ?
antlarr¿ha sido muy dificil? ¿facil? ¿seguimos?
antlarrPues sigamos con el paso 2 donde vamos a hacer el mismo programa, pero utilizando las librerías de KDE
antlarrLas librerías de KDE lo que hacen es extender Qt allí donde nos hace falta a nosotros para hacer la programación más fácil todavía
antlarr(hay que recordar que KDE es un proyecto de voluntarios de todo el mundo, con lo que intentamos hacer que sea lo más divertido posible :) )
antlarrEl programa ahora es
antlarr#include <kapp.h>
antlarr#include <klocale.h>
antlarr#include <qpushbutton.h>
antlarrint main( int argc, char **argv )
antlarr{
antlarr    KApplication a( argc, argv , "p2");
antlarr    QObject::connect( hello, SIGNAL(clicked()), &a, SLOT(quit()) );
antlarr    a.setMainWidget( hello );
antlarr    return a.exec();
antlarr}
antlarrLa primera diferencia está en que en vez de QApplication, usamos un KApplication que se encarga de más tareas todavía que QApplication (por ejemplo, poner los colores y el tema definidos por el usuario, etc.)
antlarrAdemás, en vez de utilizar directamente "Hello World!", el texto que utilizamos ahora es el que devuelve la función i18n, es decir, la traducción del texto "Hello World!"
antlarrde hecho, es la traducción al idioma que el usuario ha configurado en su panel de control
antlarrcomo estamos utilizando un texto que desconocemos en principio, no sabemos como de larga va a ser la cadena en cualquier idioma, con lo que no podemos hacer un resize como antes
antlarrLo que usamos es "setAutoResize" para hacer que el botón se ajuste automaticamente al texto que contiene.
antlarry el resto es igual que antes.
antlarrEl programa que obtenemos ahora es un botón que se integra en nuestro escritorio (ya que usa el tema y colores especificados por el usuario para todos los programas) y que muestra el texto "hola mundo !" en el idioma en que el usuario tiene configurado su sistema
antlarr¿alguna pregunta?
antlarrEspero que no os hayais dormido todavía, porque poco a poco vamos llegando a cosas interesantes :)
antlarren el siguiente paso vamos a añadir un menú y texto con formato (fijo)
antlarry en el siguiente (p4) vamos a hacer un navegador de internet casi con el mismo soporte que IE 6.0 (y en muchos casos superior a IE5.5 o a Netscape 4.x)
antlarrbueno, pues sigamos.
antlarrEl paso 3 lo he dividido en varios ficheros
antlarrmain.cpp que es casi como antes:
antlarr#include <kapp.h>
antlarr#include "p3.h"
antlarrint main( int argc, char **argv )
antlarr{
antlarr    KApplication a( argc, argv, "p3");
antlarr    a.setMainWidget( window );
antlarr    return a.exec();
antlarr}
antlarrp3.h :
antlarr#include <kmainwindow.h>
fernandovaya
fernandoenseguida volverá el conferenciante ;)
antlarrBueno, MainWindow es el objeto que vamos a utilizar como nuestra ventana principal
antlarrEn p3.h ponemos:
antlarr#include <kmainwindow.h>
antlarrclass MainWindow : public KMainWindow
antlarr{
antlarr   Q_OBJECT
antlarr  public:
antlarr   MainWindow ( const char * name );
antlarr  public slots:
antlarr    void fileOpen();
antlarr    void fileSave();
antlarr};
antlarry en p3.cpp :
antlarr#include "p3.h"
antlarr#include <kfiledialog.h>
antlarr#include <kapp.h>
antlarr#include <kmenubar.h>
antlarr#include <klocale.h>
antlarr#include <kmessagebox.h>
antlarrBueno, podeis ver el resto del programa en http://perso.wanadoo.es/antlarr/tutorial/p3.html :)
fernando;)
antlarrComo decía, ahora vamos a usar un MainWindow que hereda de KMainWindow como nuestra ventana principal
antlarrKMainWindow se va a encargar de gestionar por nosotros la barra de menú, de herramientas, la barra de estado, y el "área de documentos" (lo que queda entre la barra de herramientas y la de estado)
antlarrUna de las nuevas cosas que hacemos es
antlarrpublic slots:
antlarr    void fileOpen();
antlarr    void fileSave();
antlarren p3.h
antlarresto especifica a Qt que fileOpen y fileSave no sólo son funciones públicas de nuestro objeto, sino que deben ser tratadas como slots a los que se pueden conectar señales
antlarralgunos os preguntareis si esto no quiere decir que hemos dejado de programar en C++ "estandar" y estamos programando en una derivación de C++
antlarresto sucede "sólo en parte"
antlarrComo comenté antes, Qt extiende a C++, en este sentido añade una nueva sintaxis que sólo el precompilador de Qt (moc, o "Meta Object Compiler" ) entiende
antlarrlo que moc hace es analizar nuestros ficheros .h (sólo para las clases que heredan de QObject) y genera código C++ estandar en otro fichero
antlarrsólo tenemos que añadir este fichero a nuestro proyecto y ya tenemos un programa completo en C++ estandar
antlarrya que cuando "public slots:"  pasa por el precompilador de C++ (el cpp estandar), se queda en "public:" que es lo que realmente llega a nuestro compilador de C++ (g usualmente)
antlarrya que cuando "public slots:"  pasa por el precompilador de C++ (el cpp estandar), se queda en "public:" que es lo que realmente llega a nuestro compilador de C++ (g++ usualmente)
antlarrBien, las lineas de tipo
antlarrdeberían estar claras (añaden menús y hacen que cuando el usuario los seleccione, llame a este objeto (this) al slot fileOpen() )
antlarrQTextView es una clase que permite mostrar texto con formato (pseudo html)
antlarry setCentralWidget hace que ese QTextView sea precisamente el widget que aparezca como principal en nuestra ventana
antlarrO mejor dicho, abrir una URL cualquiera. Esto lo hacemos así porque con KDE se puede acceder desde cualquier aplicación a ficheros que estén en cualquier sitio de internet
antlarrPor ejemplo, abrir una página web en un editor de texto es tan fácil como abrir la ventana de "abrir fichero" y especificar en el nombre del fichero "http://mi.servidor/mi/pagina.html"
antlarr¿Alguna pregunta respecto a esta aplicación?
antlarr(voy más rápido porque me gustaría llegar al menos al siguiente paso que es donde hacemos el navegador)
fernandotengo una pregunta
fernandosi entiendo bien
fernandoesto ya no es c++ sino algo que se traduce a c++
fernandoes correcto ?
antlarrEs C++
pekesanpuedo preguntar?
antlarrel compilador debe compilar p3.cpp (p3.h) y _además_  p3.moc (generalmente, se llama p3_moc.cpp)
antlarrlo que pasa es que en las cabeceras de Qt hay una linea parecida a:
antlarr#define slots
fernandoajá
antlarres decir, que define slots como "nada"
pekesanke es eso del  formato pseudo-html?
antlarrde forma que cuando el compilador llega a "public slots:" lo que lee es "public:"
antlarrpekesan: Admite etiquetas como <P>, <font>, <BR>, <I>, <H1>, <IMG> etc. pero no cosas más avanzadas
antlarrpara eso hace falta un motor de renderizado de páginas html, que es lo que usamos en p4
antlarrpasemos a p4
antlarrpodeis verlo en  http://perso.wanadoo.es/antlarr/tutorial/p4.html
antlarrLas diferencias con p3 son:
antlarren p4.h añadimos:
antlarr public slots:
antlarr    void changeLocation();
antlarr    void openURLRequest(const KURL &url, const KParts::URLArgs & );
antlarrprivate:
antlarr    QLineEdit *location;
antlarr    KHTMLPart *browser;
antlarrQLineEdit es una clase que permite al usuario editar una linea de texto
antlarrla vamos a utilizar para que el usuario nos diga la página que queremos ver
antlarrKHTMLPart es un widget que se implementa en las librerías de KDE y que permite ver una página web
antlarrchangeLocation será el slot que se llame cuando el usuario pulse la tecla <enter> (o <intro>) y que cogerá el texto de la linea de edición para saber qué página abrir
antlarrSi vemos p4.cpp, changeLocation es sólo una linea:
antlarry openURLRequest es una función que se llamará cuando el usuario pulse en un enlace que haya en una página web
antlarrEs decir, es una petición para que abramos una página determinada (indicada en el parámetro url). Podemos ignorar el segundo parámetro de esta función porque se usa para cosas más avanzadas
antlarrEl código de esa función queda:
antlarr    changeLocation();
antlarres decir, pone el texto en la barra de edición y llama a la función anterior (changeLocation() )
antlarrNos fijamos ahora en como hemos construido nuestros objetos y cómo hemos hecho las conexiones de las señales:
antlarrconnect( location , SIGNAL( returnPressed() ),
antlarr                this, SLOT( changeLocation() ) );
antlarr        SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ),
antlarr        this, SLOT( openURLRequest(const KURL &, const KParts::URLArgs & ) ) );
antlarrcomo veis es todo completamente lógico, y yo diría que incluso legible para alguien que se añada ahora mismo a nuestra conversación.
antlarrvbox es un objeto de tipo QVBox
antlarrlos QVBox (y QHBox) son widgets que permiten especificar una disposición de los widgets hijos
antlarrson "invisibles" por decirlo de alguna manera
antlarry "sólo" se utilizan para que automaticamente, los widgets hijos se añadan uno debajo de otro
antlarrEl resultado lo podeis ver en  http://perso.wanadoo.es/antlarr/tutorial-umeet.jpg
antlarr(de hecho, esa imagen es de p9, pero es muy parecido a p4)
antlarrAhí podeis ver a p9 navegando por la página web de umeet
antlarrSi quereis continuar viendo el tutorial, podeis visitar la página web en http://perso.wanadoo.es/antlarr/tutorial.html
antlarrRecordad que el tutorial continúa con comunicación entre procesos usando DCOP, y muchas más cosas interesantes :)
antlarrespero que hayais pasado un rato agradable al igual que yo :)
antlarrmuchas gracias por vuestra atención
fernandoplas plas plas plas plas plas plas plas plas plas plas plas
Oroz gracias a ti Antonio :)
fernandoplas plas plas plas plas plas plas plas plas plas plas plas
fernandoplas plas plas plas plas plas plas plas plas plas plas plas
fernandoplas plas plas plas plas plas plas plas plas plas plas plas
fernandoplas plas plas plas plas plas plas plas plas plas plas plas
Stonantlarr: disculpa los "plas" de ahorita ;)
Stonplas plas plas plas plas plas plas plas plas plas plas
Stonplas plas plas plas plas plas plas plas plas plas plas
Stonplas plas plas plas plas plas plas plas plas plas plas
fernandoahora es el momento ston ;)
Stonplas plas plas plas plas plas plas plas plas plas plas
Stonplas plas plas plas plas plas plas plas plas plas plas
fernandoandele
antlarrSton: :-)
Orozjeje
fernandoEste seguramente es un buen momento para agradecer a todos ustedes su  asistencia
StonX)
fernandoy a Antonio Larrosa por su intersantísimo mini-curso
fernandoNo olviden que en breves instantes comenzará la conferencia sobre comercio electrónico y la experiencia en Perú
antlarrha sido un placer. Espero que de esta charla aparezcan nuevos programadores que serán por supuesto bienvenidos en las listas de desarrollo de KDE.
antlarr(si alguien tiene alguna pregunta, por favor, hacédmela en privado para no molestar a la próxima conferencia)
Orozcr0ut: estás?
bodhiola
antlarrBuenas noches

Generated by irclog2html.pl by Jeff Waugh - find it at freshmeat.net!


Mas información: umeet@uninet.edu