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

P9: Utilizarea XMLGUI

Acum vom simplifica P7 si ii vom mari flexibilitatea folosind tehnologia XMLGUI pentru a construi interfata cu utilizatorul.


#include <kapp.h>
#include <kcmdlineargs.h>
#include <klocale.h>
#include <kaboutdata.h>
#include "p9.h"

int main( int argc, char **argv )
{
  KAboutData *aboutdata = new KAboutData("p9",
    I18N_NOOP("KDE Tutorial - p9"),
    "1.0", I18N_NOOP("Step 9 of a simple tutorial"),
    KAboutData::License_GPL,
    "(C) 2000, 2001 Antonio Larrosa Jimenez","",
    "http://devel-home.kde.org/~larrosa/tutorial.html");
  aboutdata->addAuthor("Antonio Larrosa Jimenez",
    I18N_NOOP("Original Developer/Mantainer"),
    "larrosa@kde.org",
    "http://devel-home.kde.org/~larrosa/index.html");

  KCmdLineArgs::init(argc, argv, aboutdata);

  KApplication a;

  MainWindow *mywindow=new MainWindow( "Tutorial - p9" );
  mywindow->resize( 300, 200 );

  a.setMainWidget( mywindow );
  mywindow->show();

  return a.exec();
}
main.cpp


#include <dcopobject.h>
 
class p9Iface : virtual public DCOPObject
{
   K_DCOP
 
k_dcop:
   virtual void setURL( const QString s )=0;
 
};
p9Iface.h


#include "p9Iface.h"
#include <kmainwindow.h>
#include <kurl.h>
#include <kparts/browserextension.h>
#include <qvaluestack.h>
 
class QLineEdit;
class KHTMLPart;

class MainWindow : public KMainWindow, virtual public p9Iface
{
  Q_OBJECT
public:
    MainWindow ( const char * titulo );

    virtual void setURL ( const QString url );

public slots:
    void fileSetDefaultPage();
    void changeLocation();
    void bookLocation();
    void gotoPreviousPage();
    void openURLRequest(const KURL &url, const KParts::URLArgs &);

private:
    QLineEdit *location;
    KHTMLPart *browser;
    QValueStack <QString> history;
};
p9.h


#include "p9.h"
#include <qvbox.h>
#include <qlineedit.h>
#include <dcopclient.h>
#include <kfiledialog.h>
#include <kapp.h>
#include <kaction.h>
#include <klocale.h>
#include <khtml_part.h>
#include <kdebug.h>
#include <kconfig.h>
#include <kstdaction.h>

MainWindow::MainWindow(const char * name) : KMainWindow(0L, name),
                                           DCOPObject("browser")
{

  KStdAction::quit(this, SLOT(close()), actionCollection());

  (void)new KAction(i18n("&Set default page"), "gohome", 0, this,
     SLOT(fileSetDefaultPage()),
     actionCollection(), "set_default_page");

  (void)new KAction(i18n("Add to Bookmarks"), "reload", 0, this,
     SLOT(bookLocation()),
     actionCollection(), "add_to_bookmarks");

  (void)new KAction(i18n("Back to previous page"), "back", 0, this,
     SLOT(gotoPreviousPage()), actionCollection(), "back");

  actionCollection()->action("back")->setEnabled(false);

  createGUI("p9ui.rc");

  QVBox * vbox = new QVBox ( this );

  location = new QLineEdit ( vbox );

  KConfig *config=kapp->config();
  config->setGroup("Settings");
  location->setText(config->readEntry("defaultPage",
                       "http://localhost"));

  connect(location , SIGNAL( returnPressed()),
      this, SLOT(changeLocation()));

  browser=new KHTMLPart( vbox );
  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();
  client->registerAs("p7");
}


void MainWindow::changeLocation()
{
  history.push( browser->url().url() );
  actionCollection()->action("back")->setEnabled(true);
  browser->openURL( location->text() );
}

void MainWindow::setURL( const QString url )
{
  location->setText( url );
  changeLocation();
}

void MainWindow::openURLRequest(const KURL &url,
                                const KParts::URLArgs &)
{
  setURL( url.url() );
}

void MainWindow::gotoPreviousPage()
{
  location->setText( history.pop() );
  if (history.isEmpty())
    actionCollection()->action("back")->setEnabled(false);
  browser->openURL( location->text() );
}

void MainWindow::bookLocation()
{
  DCOPClient *client=kapp->dcopClient();
  QByteArray params;
  QDataStream stream(params, IO_WriteOnly);
  stream << location->text();
  if (!client->send("p8-*", "bookmarkList", "add(QString)", params))
    kdDebug << "Error with DCOP";
}

void MainWindow::fileSetDefaultPage()
{
  KConfig *config=kapp->config();

  config->setGroup("Settings");
  config->writeEntry( "defaultPage", browser->url().url() );
}
p9.cpp

KAboutData *aboutdata = new KAboutData("p9",
  I18N_NOOP("KDE Tutorial - p9"),
  "1.0", I18N_NOOP("Step 9 of a simple tutorial"),
  KAboutData::License_GPL,
  "(C) 2000, Antonio Larrosa Jimenez","",
  "http://devel-home.kde.org/~larrosa/tutorial.html");

Cind credeati ca nu vom mai schimba nimic la main.cpp, iata o modificare pentru a genera automat dialogul "Despre...".

Clasa KAboutData este folosita pentru a stoca datele pentru dialogul "Despre...". Primul parametru este numele intern al aplicatiei, numele "real" (cel care va fi afisat), versiunea, o descriere simpla, licenta, mentiunea referitoare la drepturile de autor, un text oarecare (in cazul nostru nimic) si adresa site-ului de web unde puteti gasi aplicatia.

Retineti ca nu am folosit functia i18n(), ci macroul I18N_NOOP, deoarece nu putem folosi i18n() inainte sa cream obiectul KApplication. De aceea folosim I18N_NOOP care "marcheaza" textul pentru a fi tradus mai incolo.

aboutdata->addAuthor("Antonio Larrosa Jimenez",
  I18N_NOOP("Original Developer/Mantainer"),
	"larrosa@kde.org",
  "http://devel-home.kde.org/~larrosa/index.html");

Acum adaugam informatiile despre un autor (putem adauga mai multe informatii, pentru citi autori este nevoie). Primul paramentru este numele, apoi exista cel pentru rolul avut la dezvoltarea aplicatiei, adresa de email si pagina personala de web a autorului.

KCmdLineArgs::init(argc, argv, aboutdata);

KApplication a;

Acum initializam argumentele si obiectul aboutdata dindu-le ca parametrii la metoda (statica) KCmdLineArgs::init().

Retine ca doar acum puteti folosi parametii impliciti pentru constructorul clasei KApplication, deoarece vom lua toate informatiile din obiectul aboutdata.

Sa ne uitam la p9.cpp:

#define TOOLBAR_ID_ADDBOOKMARK 1
#define TOOLBAR_ID_BACK 2
#define TOOLBAR_ID_QUIT 3

In primul rind vedem ca aceste linii nu mai exista. Vom folosi alta modalitate care este mult mai intuitiva si astfel vom simplifica codul.

Vom folosi obiectul KAction. Acesta este o optiune noua si deosebit de puternica ce ne permite simplificarea crearii si intretinerii interfetei grafice cu utilizatorul.

Vom crea un obiect KAction pentru fiecare actiune pe care o poate intreprinde utilizatorul. Sint doua tipuri de actiuni: cele standard (precum deschiderea unui fisier, salvarea, refacerea, terminarea etc.) si cele particularizate (cele specifice fiecarei aplicatii).

KStdAction::quit(this, SLOT(close()), actionCollection());

Mai intii cream o actiune de "terminare" (quit), care este conectata la obiectul this si la slotul close(). Parametrul actionCollection() este obiectul care colecteaza toate actiunile aplicatiei.

(void)new KAction(i18n("&Set default page"), "gohome",
   0, this,
   SLOT(fileSetDefaultPage()),
   actionCollection(), "set_default_page")

Acum vom crea o noua actiune. Primul parametru este textul care va fi afisat cind actiunea este intr-o bara de meniu, iar al doilea este numele iconitei care va fi afisata daca actiunea este pe o bara de unelte sau pe o bara de meniu. Observati ca am specificat numele iconitei, si nu iconita insasi. Aceasta permite librariilor sa faca lucruri interesante cu ea, cum ar fi aplicarea de efecte si alegerea corecta a dimensiunilor iconitei pentru bara de meniu si de unelte. Al treilea parametru este tasta sau combinatia de taste pe care utilizatorul poate sa o apese pentru activarea actiunii. In continuare precizam obiectul si slotul care vor fi apelate cind actiunea este activata si obiectul actionCollection().

In cele din urma vom seta numele pentru actiune. Numele trebuie sa identifice actiunea. El trebuie sa fie unic.

Retineti ca nu am folosit nici o variabila pentru a stoca actiunea, pentru ca va avea grija obiectul intors de actionCollection()

(void)new KAction(i18n("Add to Bookmarks"),
   "reload", 0, this,
   SLOT(bookLocation()),
   actionCollection(), "add_to_bookmarks");

(void)new KAction(i18n("Back to previous page"),
   "back", 0, this,
   SLOT(gotoPreviousPage()),
    actionCollection(), "back");

Mai cream citeva actiuni: sa adaugam pagina curenta la semnele de carte, sa ne intoarcem la pagina anterioara.

actionCollection()->action("back")->setEnabled(false);

Cu acest apel dezactivam butonul "back". Cerem lui actionCollection() obiectul actiunii cu numele "back", dupa care apelam metoda setEnabled(false) a acestei actiuni, pentru a o dezactiva.

Marele avantaj este ca nu trebuie sa avem grija de elementele meniului si barei de unelte, ci doar dezactivam actiunea, iar elementul corespunzator din meniu si din bara de unelte se va dezactiva automat. Nu tebuie sa mai definim ID-uri pentru fiecare element al meniului si alte ID-uri pentu bara de unelte.

createGUI("p9ui.rc");

Apelind createGUI() conectam actiunile la meniu si la barele de unelte.

Acum vom vedea ce contine fisierul p9ui.rc:


<!DOCTYPE kpartgui>
<kpartgui name="p9">
<MenuBar>
  <Menu name="file"><text>&File</text>
    <Action name="set_default_page"/>
  </Menu>
</MenuBar>
<ToolBar fullWidth="true" name="mainToolBar">
  <Action name="add_to_bookmarks"/>
  <Action name="back"/>
  <Separator/>
  <Action name="file_quit"/>
</ToolBar>
</kpartgui>
p9ui.rc

<kpartgui name="p9">

Spunem ca P9 este aplicatia pentru care este creat GUI-ul.

<MenuBar>
  <Menu name="file"><text>&File</text>
    <Action name="set_default_page"/>
  </Menu>
</MenuBar>

Intii definim in sectiunea MenuBar bara de meniu. Pentru fiecare meniu vom avea cite o sectiune Menu cu numele acestuia. In cazul nostru avem doar meniul "File" deoarece meniul de ajutor este adaugat automat si in fiecare sectiune Menu vom pune actiunile care vrem sa apara in meniu.

<ToolBar fullWidth="true" name="mainToolBar">
  <Action name="add_to_bookmarks"/>
  <Action name="back"/>
  <Separator/>
  <Action name="file_quit"/>
</ToolBar>

Acum definim bara de unelte (de fapt mainToolBar deoarece putem avea mai multe). Scriem doar actiunile care vrem sa apara in meniu, cu citiva separatori (optional).

Apropos, aceeasi sintaxa pentru separatori poate fi folosita si la inserarea acestora in meniuri.

Intorcindu-ne la p9.cpp, observam ca am inregistrat aplicatia tot ca "p7" in serverul dcopserver. Facem asta ca sa putem folosi P8 cu P9 la fel cum am folosit-o cu P7.

Este interesant sa comparam numarul de linii din p7.cpp si p9.cpp:

  wc p7/p7.cpp p9/p9.cpp
     124     324    3454 p7/p7.cpp
     102     238    2687 p9/p9.cpp

In p9.cpp avem cu 22 linii mai putin ca in p7.cpp!

Am scos 17.7 procente din sursa si am dat utilizatorului posibilitatea de a-si configura interfata aplicatiei. Trebuie doar sa modifice fisierul XML si sa ruleze din nou aplicatia, fara a fi nevoit sa o recompileze!

Daca doriti sa aflati mai multe despre KXMLGUI, nu uitati sa cititi excelentul tutorial scris Kurt Granroth si aflat la http://developer.kde.org/documentation/tutorials/xmlui/preface.html.

Aceasta este ultima etapa a tutorialului. Sper ca ati invatat multe lucruri si va veti decide sa incepeti propria aplicatie KDE. Daca asa vor sta lucrurile, aruncati o privire la sugestiile din Introducere unde veti gasi instructiuni in rezolvarea problemelor si citeva idei cum sa va incepeti aplicatia.

Va multumesc ca ati citit acest tutorial.



Traducere de Bogdan Daniel Vatra. Adaptare de Claudiu Costin.