Siguiente Anterior Tabla de Contenidos
Ya hemos creado una aplicación simple de KDE en p2, pero en la mayoría de los casos se quedrá usar un interfaz mas complicado que un simple botón :-), asi que veamos como añadir un widget principal standard.
#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(); }
#include <kmainwindow.h> class MainWindow : public KMainWindow { Q_OBJECT public: MainWindow ( const char * name ); public slots: void fileOpen(); void fileSave(); };
#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 ); }
Este código parece mucho mas complejo, pero no lo es :-), echemos un vistazo.
El código en main.cpp no ha cambiado mucho desde p1 o p2. La única diferencia es que ahora creamos un objeto MainWindow en vez de un QPushButton, y que ahora no especificamos un puntero NULL en el widget padre, ya que se toma por defecto.
Además, no conectamos ninguna señal aqui, ya que MainWindow no tiene ninguna señal
de clicked()
.
class MainWindow : public KMainWindow { Q_OBJECT
En p3.h definimos la clase MainWindow, que hereda de KMainWindow, que es incluida en las kdelibs e incluye todos los métodos necesarios para crear una aplicación normal de KDE con un menú, barra de herramientas (toolbar), barra de estado (status bar), etc. Observe que en versiones anteriores del tutorial, heredábamos de KTMainWindow, pero esta clase se considera obsoleta.
Fijémonos que hemos escrito Q_OBJECT
en la declaración de
nuestra clas. Esto es una macro que declara las variables especiales y los
miembros virtuales que necesita el meta objeto para implementar el mecanismo de
señal/slot y otras cosas, y además le dice a moc que este es un QObject y que
puede tener señales y/o slots.
public slots: void fileOpen(); void fileSave();
Como aprendimos en p1, los slots son métodos normales, así que pueden ser
públicos, protegidos o privados (public:
, protected:
o private:
) como cualquier otro. La única diferencia sera que debemos
especificar public slots:
,protected slots:
o
private slots:
, para que moc sepa que son slots.
El preprocesador tendra cuidado de quitar o substituir todas esas marcas especiales para que no molesten al compilador.
Veamos ahora el fichero 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 es un QPopupmenu, esto es, un menú que contiene "items" (elementos) que el usuario pulsara para realizar una acción dada.
Insertamos esos items llamando a insertItem
. El primer parámetro es el
texto que deberá de estar en el menú, con un caracter & justo delante de la
letra que queramos usar como acceso rápido. Usando i18n nos aseguramos que el
texto aparecerá en el lenguaje del usuario.
Cuando el usuario selecciona un elemento, el menú emite una señal que puede
(¡ y debe !) ser conectada a una función para hacer algo. Por conveniencia,
en vez de usar connect
, podemos conectar esta señal directamente
cuando definimos el item. Esta es la forma en la que lo hacemos en el segundo
y tercer parámetros. Conectamos el elemento de menú Open
al
slot fileOpen()
en este (this
) objeto, la entrada Save
al slot fileSave()
en este (this
) objeto, y la
entrada Quit
al slot quit()
en la aplicación, tal como
hicimos en p1 y p2.
Fijemonos en que kapp es una función de conveniencia que puede ser usada para acceder a la instancia actual de KApplication.
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 );
Primero ponemos todas esas cadenas dentro del objeto QString. QString es una clase de cadena de propósito general que se usa para manipular cadenas de muy dicersas formas. Uno de los principales beneficios de QString es el poder usar Unicode en la aplicación de forma automática, sin tener que preocuparse de ello. Ademas provee un mecanismo implicito de compartición de las cadenas que incrementa su eficiencia, ya que cuando se crea una copia de un QString no se copia realmente su contenido hasta que uno de ellos cambia.
Después creamos otro menú popup, pero usando el miembro helpMenu de KMainWindow.
Haciendo eso conseguimos un menú estandard de ayuda, con las entradas para
documentación, un diálogo sobre (about), etc. El diálogo about incluye todo el
texto que hemos escrito en la cadena about
.
KMenuBar *menu = menuBar(); menu->insertItem( i18n( "&File" ), filemenu ); menu->insertSeparator(); menu->insertItem( i18n( "&Help" ), helpmenu );
Ya estamos preparados para terminar la creación de nuestro menú. Primero,
obtenemos la barra de menú usada por nuestra ventana principal usando menuBar()
.
Como no hay barra de menú todavía, este método la creará para nosotros y nos devolverá un
objeto KMenuBar vacío que podemos rellenar. KMenuBar provee un menú
estandard de KDE, con una apariencia común en todas las aplicaciones
Entonces insertaremos los dos QPopupMenus que ya tenemos, con un separador enmedio, y ya hemos terminado de crear el menú.
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 );
Quería que esta aplicación hiciera algo bonito y simple, asi que le vamos
a añadir un widget QTextView. Este widget es un visor bastante útil de texto
enriquecido (Rich Text), donde podemos especificar el tipo de fuente y color entre
otras cosas. Despues de crearlo con el texto anterior lo ponemos como el widget central
( centralWidget
) de esta ventana.
Pero, ¿ que es un widget central ?. Un widget central es el widget que el usuario puede ver bajo el menú (o la toolbar si existe). De esta forma el documento que el usuario tiene abierto, o cualquier cosa que no es parte estandar de KMainWindow (esto es, el menú, la barra de herramientas y la de estado).
KURL filename = KFileDialog::getOpenURL( QString::null, "*", this );
Ahora miramos a la implementación del slot de fileOpen. Este código abre un diálogo de abrir fichero que permite al usuario abrir un fichero existente.
Los tres parámetros indican el directorio en el que se comienza a buscar (no nos importa en cual comienza, asi que dejamos el actual por defecto), los filtros (para ver solo los archivos que cumplen una determinada expresión regular) y el objeto padre.
Ahora tenemos el url que el usuario quiere abrir almacenado en filename
.
Observa que se recomienda encarecidamente el permitir al usuario abrir cualquier URL, no sólo archivos locales. Para esto, hemos utilizado el método getOpenURL, que permite al usuario seleccionar cualquier URL. Mire abajo un ejemplo sobre como usar la librería KIO.
QString msg=QString( i18n("Now this app should open the url %1 .") ).arg(filename.url());
Podemos manipular cadenas con la clase QString, en realidad estamos usando esto para componer el mensaje que vamos a mostrar a continuación (ya que abrir un fichero no se encuentra dentro de los objetivos de este tutorial). El formato es similar al que se usa con sprintf, pero sin necesidad de preocuparse sobre los tipos de los datos, ya que solo habra que usar %1, %2, etc. y despues .arg(var1).arg(var2).arg(var3), etc. Otra cosa buena sobre QString es que no habra problemas cuando la cadena destino no tenga espacio para la cadena resultante, ya que se reservará mas espacio automaticamente.
Por cierto, filename.url() es un QString que contiene la URL guardada en el objeto KURL, o sea, protocolo+nombre del host+camino+query+todolodemás :-).
KMessageBox::information( 0, msg, i18n( "Information" ), "fileOpenInformationDialog" );
Con la clase KMessageBox y sus miembros estáticos, podemos crear una variedad de cajas de mensajes. En este ejemplo, usamos una caja de información para mostrar que fichero se debería de haber abierto. El tercer parámetro es el mensaje que aparecerá como título de la caja, y el cuarto es un identificador, que se usa para almacenar en un fichero de configuración (usualmente ~/.kde/share/config/p3rc) si el usuario quiere que no se le muestre mas este diálogo, cosa que se decide usando un checkbox que aparece en el diálogo.
¡ Fijemonos en que no hemos escrito ninguna forma de volver a mostrar ese
diálogo de nuevo !. Esto se consigue llamando a KMessageBox::enableAllMessages();
,
pero me parece que sería un buén ejercicio para el lector de este tutorial el
añadir un menú que haga esta llamada en p3 :-) .
KURL filename=KFileDialog::getSaveURL( QString::null, "*", this );
Finalmente, en fileSave llamamos a una función análoga a getOpenURL, getSaveURL.
Fijémonos en que si usamos getOpenURL deberíamos de usar la librería KIO para obtener un fichero remoto si eso es lo que quiere el usuario, esto se hace basicamente con el siguiente código:
QString tmpFile; if( KIO::NetAccess::download( "ftp://ftp.kde.org/myfile.tgz", tmpFile ) ) { /* Do whatever you want with a _local_ file stored as tmpFile */ KIO::NetAccess::removeTempFile( tmpFile ); }
Pero esto esta fuera del ámbito de este tutorial, aunque puede que lo incremente en el futuro con un ejemplo de la libreria KIO, libkio.
Bueno, espero que no fuera demasiado dificil.
Siguiente Anterior Tabla de Contenidos