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

P3: Adaugam primul meniu

Deja am creat o aplicatie KDE simpla, dar nu este de ajuns doar un simplu buton, asa ca haideti sa vedem cum adaugam un widget principal.


#include <kapp.h>
#include "p3.h"

int main( int argc, char **argv )
{
    KApplication a( argc, argv, "p3");

    MainWindow *window=new MainWindow( "Tutorial - p3" );
    window->resize( 400, 300 );

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

    return a.exec();
}
main.cpp


#include <kmainwindow.h>

class MainWindow : public KMainWindow
{
   Q_OBJECT
  public:

    MainWindow ( const char * name );

  public slots:
    void fileOpen();
    void fileSave();
};
p3.h


#include "p3.h"
#include <kfiledialog.h>
#include <kapp.h>
#include <kmenubar.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kpopupmenu.h>
#include <qtextview.h>

MainWindow::MainWindow ( const char * name ) : KMainWindow ( 0L, name )
{
    setCaption("KDE Tutorial - p3");

    QPopupMenu *filemenu = new QPopupMenu;
    filemenu->insertItem( i18n( "&Open" ), this, SLOT(fileOpen()) );
    filemenu->insertItem( i18n( "&Save" ), this, SLOT(fileSave()) );
    filemenu->insertItem( i18n( "&Quit" ), kapp, SLOT(quit()) );
    QString about =
        i18n("p3 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 );

    QTextView *hello=new QTextView(
       i18n("<H2>Hello World !</H2><BR>This is a simple"
	" window with <I><font size=5><B>R<font color=red"
	" size=5>ich </font><font color=blue size=5>Text"
	"</font></B></I> capabilities<BR>Try to resize"
	" this window, all this is automatic !"), "", this );
    setCentralWidget( hello );

}

void MainWindow::fileOpen()
{
    KURL filename = KFileDialog::getOpenURL( QString::null, "*", this );
    QString msg = QString(i18n("Now this app should open the url %1 ."
                        )).arg(filename.url());
    KMessageBox::information( 0, msg, i18n( "Information" ),
		"fileOpenInformationDialog" );
}

void MainWindow::fileSave()
{
   KURL filename=KFileDialog::getSaveURL( QString::null, "*", this );
}
p3.cpp

Aplicatia pare mult mai complexa, dar nu este asa. Sa vedem ce se intimpla.

Sursa din main.cpp nu este prea diferita de P1 sau P2. Singura diferenta consta in faptul ca acum in loc sa cream un obiect QPushButton, cream unul MainWindow la care nu mai trebuie specificat pointerul catre parinte ca NULL deoarece il are implicit.

Ar mai fi ceva de remarcat: nu se mai conecteaza nici un semnal in main.cpp, deoarece MainWindow nu are un semnal numit clicked() la care sa se poata conecta un slot.

class MainWindow : public KMainWindow
{
  Q_OBJECT

In fisierul p3.h, definim obiectul MainWindow. Dupa cum se vede mosteneste clasa KMainWindow, clasa care are incluse in ea toate metodele necesare crearii unei aplicatii normale KDE, adica o aplicatie care are un meniu, o bara de unelte, o bara de stare etc.

Trebuie saretineti faptul ca in declaratia obiectului am scris Q_OBJECT. Acesta este un macro care declara variabilele speciale si membrii virtuali folositi la implementarea mecanismului semnal-slot. El ii spune utilitarului moc ca este o clasa care mosteneste QObject si poate avea semnale si/sau sloturi.

public slots:
  void fileOpen();
  void fileSave();

Dupa cum am invatat in P1, sloturile sunt metode normale. Ele pot fi de tipul public:, protected: sau private:. Singura diferenta in cazul sloturilor este ca dupa public, protected sau private se pune slots: adica "public slots:", "protected slots:" sau "private slots:", astfel incit utilitarul moc sa stie ca sint sloturi.

Preprocesorul va avea grija sa le scoata sau sa le substitue astfel incit compilatorul nu se va incurca in ele.

Partea frumoasa este in fisierul p3.cpp:

QPopupMenu *filemenu = new QPopupMenu;
filemenu->insertItem( i18n( "&Open" ), this, SLOT(fileOpen()) );
filemenu->insertItem( i18n( "&Save" ), this, SLOT(fileSave()) );
filemenu->insertItem( i18n( "&Quit" ), kapp, SLOT(quit()) );

filemenu este un obiect de tip QPopupmenu. Dupa cum probabil ca va-ti dat seama, filemenu este un meniu care contine elemente ("items") pe care utilizatorul le poate accesa.

Inseram aceste elemente cu metoda insertItem(). Primul parametru este textul care va aparea in meniu. Caracterul & pus in fata unei litere desemneaza ca acea litera va fi subliniata si utilizatorul poate accesa meniul mai repede folosind o combinatie de taste accelerator (Alt+<litera>). Folosind functia i18n() ne asiguram ca meniul va aparea in limba utilizatorului (daca a fost tradus textul specificat de dumneavoastra).

Cind utilizatorul alege un element (din meniu), acesta emite un semnal care ar trebui (sau mai bine spus trebuie) sa fie conectat la un slot care sa faca ceva. Metoda insertItem() ne permite sa facem acest lucru mai usor (nu mai trebuie sa folosim connect()) prin al doilea si al treilea parametru. Vom conecta deci, elementul Open la metoda fileOpen() al obiectului this, Save la slotul fileSave() al obiectului this si optiunea Quit la metoda quit() a aplicatiei, la fel cum am facut in P1 si P2.

Retineti faptul ca (prin conventie) kapp este un pointer la instanta curenta a obiectul KApplication (kapp == &a). kapp NU este o functie ci o variabila.

QString about = i18n("p3 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 );

Tot textul il punem intr-un obiect QString. QString este o clasa care se foloseste la manipularea sirurilor de caractere. Unul din principalele avantaje este ca putem folosi Unicode in aplicatii fara nici un fel de probleme (clasa C++ string, de exemplu, nu stie Unicode). In plus, are un mecanism implicit de partajare care creste eficienta la copierea obiectelor QString: copierea efectiva a unui asemenea obiect are loc numai dupa modificarea continutului unuia din ele (sursa sau destinatia).

In continuare cream un alt meniu popup, dar de data aceasta utilizam helpMenu care este membru al clasei KMainWindow. Prin aceasta operatie obtinem un meniu de ajutor standard cu itemi pentru documentatie, un dialog de informatii despre aplicatie etc. Dialogul de informatii include tot textul pe care l-am scris in sir de text about.

  KMenuBar *menu = menuBar();
  menu->insertItem( i18n( "&File" ), filemenu );
  menu->insertSeparator();
  menu->insertItem( i18n( "&Help" ), helpmenu );

Sintem gata sa terminam meniul. In primul rind obtinem pointerul catre bara de menuri folosita de aplicatie, utilizind menuBar(). Deoarece nu mai exista un meniu, metoda va crea unul gol. KMenuBar ne ofera un meniu standard KDE, comun ca infatisare la majoritatea aplicatiilor.

Inseram cele doua QPopupMenu-uri pe care le-am creat mai sus cu un separator intre ele si cu asta am terminat de creat meniul.

  QTextView *hello=new QTextView(
  i18n("<H2>Hello World !</H2><BR>This is a simple"
  " window with <I><font size=5><B>R<font color=red"
  " size=5>ich </font><font color=blue size=5>Text"
  "</font></B></I> capabilities<BR>Try to resize"
  " this window, all this is automatic !"), "", this );

  setCentralWidget( hello );

Am vrut ca aplicatia sa faca ceva frumos si simplu, de aceea am adaugat widget-ul QTextView. Acest widget este o componenta grafica de afisare de Rich Text foarte folositoare, in care poti formata texte cu diferite fonturi, in multe culori s.a.m.d. Dupa creare il setam ca widget central al ferestrei.

Dar ce inseamna widget central? Un widget central este ceea ce vede utilizatorul sub bara de meniu (sau bara de unelte, daca exista) si poate fi orice widget care nu este o parte standard a KMainWindow (meniu, bara de unelte si de stare).

KURL filename = KFileDialog::getOpenURL(QString::null,
       "*", this );

Sa aruncam o privire asupra implementarii slotului fileOpen(). Acest cod deschide un dialog care permite utilizatorului sa aleaga un fisier existent si sa-l incarce.

Sint trei parametrii: primul indica directorul care va fi deschis (nu ne intereseaza ce director asa ca lasam directorul curent ca implicit), filtrul si parintele.

Dupa executie avem in filename URL-ul/fisierul pe care utilizatorul vrea sa-l deschida.

Incurajez folosirea folosirea lui getOpenURL care permite utilizatorului sa deschida orice locatie, nu numai fisiere locale. Vom vedea in exemplele urmatoare cum folosim libraria KIO.

QString msg=QString(i18n(
    "Now this app should open the url %1 .")
    ).arg(filename.url());

Putem manipula sirurile de caractere cu clasa QString. De fapt o folosim pentru compunerea mesajului pe care il vom afisa (deschiderea unui fiser nu tine de acest tutorial). Formatul este asemanator cu cel al lui sprintf. Diferenta consta in faptul ca nu trebuie sa mai avem grija de tipul datelor pe care le dam ca parametru, ci pur si simplu folosim %1, %2 etc. dupa care adaugam .arg(var1).arg(var2).arg(var3) etc. Nu trebuie sa ne facem griji ca QString nu are destul spatiu pentru intregul text. El va aloca cit trebuie deoarece cunoaste dimensiunea sirului de caractere.

Apropos, filename.url() intoarece un QString care contine URL-ul/fisierul, adica protocolul + gazda + locatia + cererea + totul.

KMessageBox::information(0, msg, i18n( "Information" ),
    "fileOpenInformationDialog");

Cu clasa KMessageBox si membrii statici (information() de exemplu), putem crea o multitudine de dialoguri pentru mesaje (message boxes). In exemplul nostu folosim un dialog infomational in care afisam URL-ul/fisierul care ar trebui deschis. Al treilea parametru este titlul ferestrei, al patrulea un identificator care este folosit pentru a salva intr-un fiser de configurare (de obicei ~/.kde/share/config/p3rc) daca utilizatorul doreste sa nu mai vada acest dialog altadata (lucru pe care poate sa-l faca bifind optiunea din dialog)

Daca vrem sa vedem dialogurile din nou, trebuie doar sa apelam KMessageBox::enableAllMessages();.

KURL filename=KFileDialog::getSaveURL(QString::null,
          "*",this);

Si in cele din urma getSaveURL(), care este analogul lui getOpenURL().

Trebuie avut in vedere ca daca folosim getOpenURL(), ar trebui sa utilizam libraria KIO, in sensul in care descarcam un fisier. Descarcarea se face ceva in genul:

QString tmpFile;
if (KIO::NetAccess::download("ftp://ftp.kde.org/myfile.tgz",
                             tmpFile ) )
  {
    /* Utilizam fisierul salvat local ca tmpFile */
    KIO::NetAccess::removeTempFile( tmpFile );
  }

Oricum acest exemplu este un pic peste scopul acestul tutorial. Totusi, e e posibil sa adaug in viitor si un exemplu de folosire a librariei libkio.

Sper ca nu a fost prea dificil.



Traducere de Bogdan Daniel Vatra. Adaptare de Claudiu Costin.