Pagina principala
Informatii
Internationalizarea
pROgrame KDE/Qt
Download
Documentatii
Despre LKR
Contact
Resurse
Harta site-ului

Tutorial programare KDE 3


   Antonio Larrosa
   14 martie 2002

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.



Traducere de Bogdan Daniel Vatra. Adaptare de Claudiu Costin.