Siguiente Anterior Tabla de Contenidos
Aqui se va a mostrar nuestra primera aplicación que se comunicará con otras ( en este caso con p6 ). Aqui esta el código fuente:
#include <kapp.h> #include "p5.h" int main( int argc, char **argv ) { KApplication a( argc, argv, "p5" ); MainWindow *mywindow=new MainWindow( "Tutorial - p5" ); mywindow->resize( 300, 200 ); a.setMainWidget( mywindow ); mywindow->show(); return a.exec(); }
#include <kmainwindow.h> #include <kurl.h> #include <kparts/browserextension.h> class QLineEdit; class KHTMLPart; class QSplitter; class QPushButton; class MainWindow : public KMainWindow { Q_OBJECT public: MainWindow ( const char * titulo ); public slots: void changeLocation(); void openURLRequest(const KURL &url, const KParts::URLArgs & ); void bookLocation(); private: QLineEdit *location; KHTMLPart *browser; QPushButton *bookmark; QSplitter *split; };
#include "p5.h" #include <qvbox.h> #include <qlineedit.h> #include <qpushbutton.h> #include <qsplitter.h> #include <dcopclient.h> #include <kapp.h> #include <kmenubar.h> #include <klocale.h> #include <kpopupmenu.h> #include <khtml_part.h> #include <kdebug.h> MainWindow::MainWindow ( const char * name ) : KMainWindow ( 0L, name ) { setCaption("KDE Tutorial - p5"); QPopupMenu * filemenu = new QPopupMenu; filemenu->insertItem( i18n( "&Quit" ), kapp, SLOT( quit() ) ); QString about = i18n("p5 1.0\n\n" "(C) 1999-2002 Antonio Larrosa Jimenez\n" "larrosa@kde.org\t\tantlarr@supercable.es\n" "Malaga (Spain)\n\n" "Simple KDE Tutorial\n" "This tutorial comes with ABSOLUTELY NO WARRANTY \n" "This is free software, and you are welcome to redistribute it\n" "under certain conditions\n"); QPopupMenu *helpmenu = helpMenu(about); KMenuBar * menu = menuBar(); menu->insertItem( i18n( "&File" ), filemenu); menu->insertSeparator(); menu->insertItem(i18n("&Help"), helpmenu); QVBox * vbox = new QVBox ( this ); location = new QLineEdit ( vbox ); location->setText( "http://localhost" ); connect( location , SIGNAL( returnPressed() ), this, SLOT( changeLocation() ) ); split = new QSplitter ( vbox ); split->setOpaqueResize(); bookmark = new QPushButton ( i18n("Add to Bookmarks"), split ); connect( bookmark, SIGNAL( clicked() ), this, SLOT( bookLocation() ) ); browser=new KHTMLPart( split ); browser->openURL( location->text() ); connect( browser->browserExtension(), SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ), this, SLOT( openURLRequest(const KURL &, const KParts::URLArgs & ) ) ); setCentralWidget( vbox ); DCOPClient *client = kapp->dcopClient(); client->attach(); } void MainWindow::changeLocation() { browser->openURL( location->text() ); } void MainWindow::openURLRequest(const KURL &url, const KParts::URLArgs & ) { location->setText( url.url() ); changeLocation(); } void MainWindow::bookLocation() { DCOPClient *client=kapp->dcopClient(); QByteArray params; QDataStream stream(params, IO_WriteOnly); stream << location->text(); if (!client->send("p6-*", "bookmarkList", "add(QString)", params)) kdDebug() << "Error with DCOP\n"; }
Esta aplicación y p6 son un simple ejemplo de la nueva tecnología para comunicación de escritorio, DCOP. DCOP es un mecanismo de IPC/RPC basado en ICE que usa sockets de dominio unix o sockets TCP/IP de forma transparente.
p6 sera la aplicación que almacene los marcadores (bookmarks) del usuario, y p5 le dira que los almacene. Veamos cuan facilmente podemos hacerlo:
public slots: void changeLocation(); void openURLRequest(const KURL &url, const KParts::URLArgs & ); void bookLocation(); private: QLineEdit *location; KHTMLPart *browser; QPushButton *bookmark; QSplitter *split;
Vamos a usar un nuevo slot que sera llamado cuando el usuario quiera almacenar una dirección en su aplicación de marcadores. Ademas hay un par de nuevos widgets que necesitaremos.
split = new QSplitter ( vbox ); split->setOpaqueResize();
Queremos mostrar un gran botón al lado del widget navegador de html. En vez de hacerlo de un tamaño fijo, dejaremos que el usuario cambie el tamaño del botón, esto se consigue usando un widget QSplitter, este es un widget que distribuye su tamaño entre sus hijos.
Haremos que split
haga un redimensionamiento opaco para
redibujar a los hijos mientras el usuario cambia el tamaño, en vez
de dejar el redibujado para cuando termine de cambiarlo.
bookmark = new QPushButton ( i18n("Add to Bookmarks"), split ); connect( bookmark, SIGNAL( clicked() ), this, SLOT( bookLocation() ) );
Ahora hemos creado un nuevo QPushButton con el texto traducible.
La señal clicked()
la conectamos a nuestro slot bookLocation()
.
browser=new KHTMLWidget( split );
Junto a nuevo botón bookmark
, el browser es ahora un hijo de split
.
Esto se ha hecho así para dejar que split
maneje el tamaño de ambos widgets, tal
como se explico anteriormente.
DCOPClient *client = kapp->dcopClient(); client->attach();
Ya conocemos la macro kapp
, que se usa para referenciar a la instancia
actual de KApplication, de esta forma conseguimos el objeto DCOPClient, y le
decimos que añada (attach
) esta aplicación al servidor DCOP que debe
de estar ejecutandose en el sistema (dcopserver es una parte fundamental del
escritorio, con lo que siempre debera estar ejecutandose).
DCOPClient *client=kapp->dcopClient(); QByteArray params; QDataStream stream(params, IO_WriteOnly);
Cuando el cliente pulsa el botón para añadir el url actual a la lista de bookmarks este slot es llamado. Primero cogemos el objeto DCOPClient de esta aplicación y despues inicializamos un objeto QDataStream.
QDataStream es una clase que se usa para serializar datos de cualquier tipo. Entre sus características se encuentran las de ser completamente independiente del equipo anfitrion (orden de byte, CPU, etc.). De esta forma se puede crear un stream (caudal, conjunto de datos que se envían uno tras otro) en un sistema big-endian y leerlo en una little-endian sin ningún problema.
stream << location->text();
Como el stream puede contener cualquier tipo de datos, lo usaremos para almacenar los parámetros de la función que llamaremos en p6. Almacenamos el texto de la dirección en el stream.
if (!client->send("p6-*", "bookmarkList", "add(QString)", params)) kdDebug() << "Error with DCOP\n";
Finalmente, enviamos (send
) una llamada DCOP a p6.
El primer parámetro es el nombre de la aplicación a la que queremos conectarnos.
El segundo es el nombre del objeto que queremos usar en la aplicación destino, y
el tercero es el nombre del miembro de ese objeto al que queremos llamar.
params
es un stream que contiene los parámetros que queremos pasarle
a ese método.
En otras palabras, p6 es una aplicación que tiene un objeto llamado bookmarkList
,
y este objeto tiene un método llamado add
que tiene un
parámetro QString, con lo que esa simple linea llama el metodo deseado en p6 con
los parámetros dados. Como no queremos obtener un valor de retorno de p6, volvera
enseguida y se continuara ejecutando p5 mientras p6 añade el url a la lista de
bookmarks. ¿ No es bonito ? ;-)
Observa que hemos añadido -*
al nombre de la aplicación. Lo hemos hecho porque
la aplicación p6 obtendrá un nombre en el servidor dcop de la forma "p6-<PID>"
(p.ej. "p6-12532") . Usando un asterisco como último caracter, enviamos la señal
a todas las aplicaciones cuyo nombre coincide con los primeros caracteres. Si la
aplicación que estás desarrollando necesita enviar una señal a una aplicación
específica, entonces seguramente conoces el PID de la aplicación con la que te quieres
comunicar, y por lo tanto, puedes mandar facilmente una sola señal usando "nombreDeLaAplicación-PID".
Estamos ahora chequeando el valor de retorno, por si acaso el dcopserver no ha podido completar la llamada. En este caso, usamos las rutinas de depuración de KDE para dejar que la aplicación nos muestre que hay algo que va mal. Como este mensaje esta dirigido solamente a los desarrolladores no se usa i18n.
kdDebug() devuelve un stream que puedes usar como salida para tus cadenas de depuración. Hay varios niveles de logs : kdDebug, kdWarning, kdError y kdFatal. Con estos indicas la seriedad del mensaje. También se puede especificar un número de area para especificar la zona del programa que emitió el mensaje y activar/desactivar areas para depurar partes específicas de tu aplicación.
Y esto es todo en p5. Deberias ejecutar a la vez p5 y p6 para que trabajen en equipo y ver como se comunican.
Siguiente Anterior Tabla de Contenidos