P5: Deschiderea de comunicatii!
P5 este prima aplicatie care va comunica cu alte aplicatii
(in cazul nostru P6).
#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();
}
main.cpp
#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 * name );
public slots:
void changeLocation();
void openURLRequest(const KURL &url, const KParts::URLArgs &);
void bookLocation();
private:
QLineEdit *location;
KHTMLPart *browser;
QPushButton *bookmark;
QSplitter *split;
};
p5.h
#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";
}
p5.cpp
Programul acesta si P6 sint simple exemple ale noii tehnologii pentru
comunicarea in mediul grafic, DCOP.
DCOP este un mecanism IPC/RPC bazat pe ICE care foloseste transparent
socluri "UNIX domain" sau TCP/IP.
P6 va fi o aplicatie care stocheaza semnele de carte caruia P5
ii comunica sa le salveze. Haideti sa vedem cit de usor se face:
public slots:
void changeLocation();
void openURLRequest(const KURL &url, const KParts::URLArgs &);
void bookLocation();
private:
QLineEdit *location;
KHTMLPart *browser;
QPushButton *bookmark;
QSplitter *split;
Vom folosi un slot care va fi apelat cind utilizatorul vrea sa salveze o
legatura in aplicatia de semne de carte. Mai sint si alte
widget-uri pe care le vom folosi.
split = new QSplitter(vbox);
split->setOpaqueResize();
Vrem sa afisam un buton mare linga widget-ul de HTML.
In loc sa-l facem de marime fixa, vom lasa utilizatorul sa-i schimbe
dimensiunile, folosind widget-ul QSplitter. Acesta
isi distribuie spatiul ocupat intre copii sai.
Vom seta separatorul sa faca redimenisonarea copiilor opac,
copiii vor fi redesenati in timp ce utilizatorul schimba
dimensiunile, nu dupa ce utilizatorul a terminat de mutat.
bookmark = new QPushButton(i18n("Add to Bookmarks"), split);
connect(bookmark, SIGNAL(clicked()),
this, SLOT(bookLocation()));
Cream un buton QPushButton cu suport pentru internationalizare.
Semnalul clicked() il conectam la slotul bookLocation().
browser=new KHTMLWidget(split);
Impreuna cu butonul bookmark, browser este si el copil
al split, asa ca il vom lasa pe split sa aiba grija
de dimensiunile ambelor widget-uri.
DCOPClient *client = kapp->dcopClient();
client->attach();
Deja stim de existenta lui kapp, folosit ca instanta curenta
a KApplication, asa ca putem lua obiectul DCOPClient si
atasam (attach) aplicatia la serverul DCOP, care ar trebui sa
ruleze in sistem (dcopserver este parte fundamentala din
a mediului grafic, motiv pentru care ar trebui sa ruleze intotdeauna)
DCOPClient *client=kapp->dcopClient();
QByteArray params;
QDataStream stream(params, IO_WriteOnly);
Cind utilizatorul da clic pe buton sa adauge legatura curenta in
lista de semne de carte, acest slot va fi apelat. Intii luam
obiectul DCOPClient al aplicatiei si initializam obiectul
QDataStream.
Clasa QDataStream este folosita pentru serializarea
datelor de orice tip. Ea prelucreaza date complet independent
de arhitectura masinii unde este executata (ordinea octetilor,
procesor etc.). Astfel, puteti genera un flux de date pe un
sistem big-endian si sa-l cititi fara probleme
pe un calculator little-endian.
stream << location->text();
Deoarece fluxul poate contine orice tip de data, punem in el parametrii
functiei pe care o va apela in P6.
Deci vom pune locatia.
if (!client->send("p6-*", "bookmarkList", "add(QString)", params))
kdDebug() << "Error with DCOP\n";
In cele din urma folosim send ca DCOP sa apeleze P6.
Primul parametru este numele aplicatiei la care vrem sa ne conectam. Al doilea
este numele obiectului din aplicatie, pe care vream sa-l folosim si al treilea
este numele membrului obiectului care trebuie apelat. In params
se afla legatura pe care o trimitem la metoda apelata.
Cu alte cuvinte, P6 este o aplicatie care
are un obiect numit bookmarkList si acest obiect are o metoda
numita add, metoda primind ca parametru un QString, deci
aceasta linie de cod apeleaza metoda din P6, cu parametrii dati.
Deoarece nu trebuie sa primim nici o valoare pe care ar intoarce-o P6,
P5 va primi imediat controlul, in timp ce P6 adauga legatura
in lista de semne de carte.
Observatie: am adaugat la numele aplicatiei -*, deoarece
aplicatia P6 va primi in dcopserver un nume in forma
"p6-<PID>" (de exemplu:"p6-12532").
Caracterul final fiind asterix, trimitem semnalul tuturor aplicatiilor care
se potrivesc cu primele litere. Daca vrem ca aplicatia sa trimita un semnal
la o singura aplicatie, trebuie sa stim PID-ul aplicatiei cu care vrem sa
comunicam si vom trimite semnalul folosind "numeleaplicatie-PID".
Verificam valoarea intoarsa doar sa vedem daca dcopserver nu a putut
executa apelul. In cazul acesta folosim rutinele de depanare KDE sa
aratam daca, si ce nu este in ordine. Deoarece mesajele sint doar pentru
dezvoltare/depanare, nu este nevoie sa folosim i18n().
kdDebug() intoarce un stream (flux) pe care il puteti folosi
pentru afisare. Exista urmatoarele nivele de jurnalizare:
kdDebug, kdWarning, kdError si
kdFatal. Fiecare este folosit in functie de seriozitatea mesajelor.
De asemenea puteti specifica un numar de zona pentru a indica ce parte
anume a aplicatiei doriti sa depanati. Astfel veti putea activa/dezactiva
fluxuri de depanare in functie de componentele KDE pe care doriti
sa le urmariti.
Cam asta este in P5. Ar trebui sa rulati P5 si
P6 in acelasi timp ca sa vedeti
cum comunica.
|