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.
|