Siguiente Anterior Tabla de Contenidos
En este paso, estamos preparados para aumentar la usabilidad de p5 para aprender como usar otras cuantas clases standars de KDE que deberán de ser usadas casi en todas las aplicaciones.
#include <kapp.h> #include "p7.h" int main( int argc, char **argv ) { KApplication a( argc, argv, "p7" ); MainWindow *mywindow=new MainWindow( "Tutorial - p7" ); mywindow->resize( 300, 200 ); a.setMainWidget( mywindow ); mywindow->show(); return a.exec(); }
#include <dcopobject.h> class p7Iface : virtual public DCOPObject { K_DCOP k_dcop: virtual void setURL( QString s )=0; };
#include "p7Iface.h" #include <kmainwindow.h> #include <kurl.h> #include <kparts/browserextension.h> #include <qvaluestack.h> class QLineEdit; class KHTMLPart; class MainWindow : public KMainWindow, virtual public p7Iface { 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; };
#include "p7.h" #include <qvbox.h> #include <qlineedit.h> #include <dcopclient.h> #include <kfiledialog.h> #include <kapp.h> #include <kmenubar.h> #include <ktoolbar.h> #include <klocale.h> #include <kpopupmenu.h> #include <khtml_part.h> #include <kdebug.h> #include <kconfig.h> #include <kiconloader.h> #define TOOLBAR_ID_ADDBOOKMARK 1 #define TOOLBAR_ID_BACK 2 #define TOOLBAR_ID_QUIT 3 MainWindow::MainWindow ( const char * name ) : KMainWindow ( 0L, name ), DCOPObject ( "browser" ) { setCaption("KDE Tutorial - p7"); QPopupMenu * filemenu = new QPopupMenu; filemenu->insertItem( i18n( "&Set default page" ), this, SLOT( fileSetDefaultPage() ) ); filemenu->insertItem( i18n( "&Quit" ), kapp, SLOT( quit() ) ); QString about = i18n("p7 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); KToolBar *toolbar=new KToolBar(this); toolbar->insertButton(BarIcon("reload"), TOOLBAR_ID_ADDBOOKMARK, SIGNAL(clicked(int)),this,SLOT(bookLocation()),TRUE, i18n("Add to Bookmarks")); toolbar->insertButton(BarIcon("back"), TOOLBAR_ID_BACK, SIGNAL(clicked(int)),this,SLOT(gotoPreviousPage()), FALSE, i18n("Back to previous page")); toolbar->insertButton(BarIcon("exit"), TOOLBAR_ID_QUIT, SIGNAL(clicked(int)),kapp,SLOT(quit()),TRUE, i18n("Quit the application")); addToolBar(toolbar); 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() ); toolBar()->setItemEnabled( TOOLBAR_ID_BACK, TRUE); browser->openURL( location->text() ); } void MainWindow::setURL( 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()) toolBar()->setItemEnabled( TOOLBAR_ID_BACK, 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\n"; } void MainWindow::fileSetDefaultPage() { KConfig *config=kapp->config(); config->setGroup("Settings"); config->writeEntry( "defaultPage", browser->url().url() ); }
Lo primero que hacemos es añadir un interfaz DCOP en p7 para usarlo en p8, que será la siguiente generación de listas de marcadores :-). Es muy similar a lo que usamos en p6, asi que no lo comentare mas.
#define TOOLBAR_ID_ADDBOOKMARK 1 #define TOOLBAR_ID_BACK 2 #define TOOLBAR_ID_QUIT 3
Bien, ahora estamos mirando al principio de p7.cpp. Aqui definimos algunos identificadores para identificar a los botones de la barra de herramientas (toolbar). Esto no es siempre necesario, ya que se puede dejar a la toolbar que le asigne indentificadores por defecto. Pero como vamos a habilitar y deshabilitar algunos botones queda mas claro si se hace así.
MainWindow::MainWindow ( const char * name ) : KMainWindow ( 0L, name ), DCOPObject ( "browser" ) { QPopupMenu * filemenu = new QPopupMenu; filemenu->insertItem( i18n( "&Set default page" ), this, SLOT( fileSetDefaultPage() ) );
La clase MainWindow ahora hereda además de p7Iface, asi que tenemos que
llamar al constructor DCOPObject. Vamos a llamar a este objeto browser
.
Ahora hay otro elemento en el menú de fichero que será usado para que la
página actual sea la se cargue por defecto cuando se ejecute la aplicación. Así
mostraremos como almacenar una variable de configuración.
KToolBar *toolbar=new KToolBar(this);
La clase KToolBar
es la que implementa una toolbar en KDE.
Usandola se obtiene automaticamente una apariencia standard en las toolbar,
entre otras cosas.
toolbar->insertButton(BarIcon("reload"), TOOLBAR_ID_ADDBOOKMARK, SIGNAL(clicked(int)),this,SLOT(bookLocation()),TRUE, i18n("Add to Bookmarks")); toolbar->insertButton(BarIcon("back"), TOOLBAR_ID_BACK, SIGNAL(clicked(int)),this,SLOT(gotoPreviousPage()), FALSE, i18n("Back to previous page")); toolbar->insertButton(BarIcon("exit"), TOOLBAR_ID_QUIT, SIGNAL(clicked(int)),kapp,SLOT(quit()),TRUE, i18n("Quit the application"));
Vamos a añadir tres botones, el primero se usará en vez del gran botón (y si se me permite, feo) que usamos en p5. El segundo botón se usará para volver a las páginais visitadas previamente, así que habrá que manejar un historial de las páginas visitadas. El tercer botón se usará para salir de la aplicación. (Nota: Las autoridades en diseño de interfaz de usuario recomiendan no poner un botón en la toolbar para salir de la aplicación, como esto no es una aplicación real, vamos a omitir ese serio consejo).
La función BarIcon("reload")
automaticamente busca el icono
de reload
(recargar), esté donde esté, siempre que sea en un
sitio estandard para los iconos de la toolbar, como $KDEDIR/share/toolbar o
$KDEDIR/share/apps/<appname>/toolbar, y devuelve un objeto QPixmap válido que
lo almacena.
El siguiente parámetro es el identificador que vamos a usar para después referirnos
a este botón, después viene la señal que vamos a conectar y el objeto que la
recivirá, seguido por el slot que será llamado. En la mayoría de los casos
no habra que preocuparse por los botones de la toolbar, con lo que se puede
usar 0 como identificador para cada botón, ya que no hay que asignar un único
identificador a cada uno. Una excepción a esto es cuando se quiere habilitar/
deshabilitar un botón. tal como queremos hacer con el botón de vuelta (back
.
addToolBar(toolbar);
Hemos terminado de construir la barra de herramientas, así que la añadimos
al widget principal con addToolBar
. addToolBar
no sigue la misma nomenclatura que setMenu porque no se esta restringido
a usar una sola barra de herramientas (como es el caso de los menús), así
que no la estas poniendo, sino añadiéndo.
KConfig *config=kapp->config(); config->setGroup("Settings"); location->setText( config->readEntry( "defaultPage", "http://localhost") );
Ya sabemos lo que es kapp, pero no hemos usado el metodo de configuración
( config()
) antes. Este método devuelve el objeto KConfig activo
para esta aplicación. KConfig es usado para almacenar las variables de
configuración de la aplicación. Automaticamente almacena los campos de
configuración en el fichero de configuración de la aplicación y la
recupera cuando se ejecuta la aplicación de nuevo.
Una vez que tenemos el objeto de configuración, ponemos el grupo activo a
Settings
para trabajar en el. Los grupos se usan para estructurar
los ficheros de configuración.
Finalmente, en vez de usar la cadena "http://localhost"
como
dirección por defecto, la leemos de la configuración de la aplicación.
El nombre del campo que queremos leer es defaultPage
, y
"http://localhost"
es el valor por defecto que se devuelve si el
fichero de configuración no contiene ningún valor para ese campo.
Además se pueden leer valores enteros con KConfig::readNumEntry
,
valores booleanos con KConfig::readBoolEntry
, etc.
DCOPClient *client = kapp->dcopClient(); client->attach(); client->registerAs("p7");
Finalmente añadimos esta aplicación al servidor DCOP y la registramos como
p7
, ya que queremos que p8 puede llamarla para poner una página.
void MainWindow::setURL( QString url ) { location->setText( url ); changeLocation(); }
Este miembro es ahora usado para poner de forma genérica un url. Actualmente
esta función puede ser llamada por el interface DCOP o cuando el usuario
pulsa sobre un enlace. Primero hacemos que el texto de la dirección contenga
el url, y entonces llamamos a la función changeLocation
.
void MainWindow::changeLocation() { history.push( browser->url() ); toolBar()->setItemEnabled( TOOLBAR_ID_BACK, TRUE); browser->openURL( location->text() ); }
changeLocation
(que además está conectada a la señal
enterPressed()
en el objeto location) se usa como el lugar
central para cargar una nueva página una vez que el url este en la barra
de direcciones. Esto se realiza para implementar la capacidad de almacenar
un historial de direcciones en p7.
Nos fijamos ahora en que definimos un objeto historia ( history
)
en p7.h del tipo QValueStack <QString> . QValueStack es una clase de Qt que
implementa una pila usando un template (plantilla) como tipo de datos para sus
elementos. La diferencia entre QValueStack y QStack es que el primero almacena
el valor de los elementos que se añaden, creando una copia de cada elemento
(debe de haber un constructor de copia para eso), mientras el segundo simplemente
almacena punteros a los elementos que se añaden, asi que habría que tener cuidado
de no borrarlos mientras permanecen en la pila.
Como la clase QString comparte los datos entre todas las copias de la cadena hasta que se realiza un cambio a una de ellas, no hay apenas penalización por crear copias de los urls.
Ahora tenemos la barra de herramientas por defecto ( si hubiera mas, podriamos
conseguir las otras usando un identificador como parámetro a toolBar
),
y activar el botón de vuelta (back
) para que el usuario pueda usarlo.
Finalmente abrimos la nueva url en el widget navegador ( browser
)
cogiendo la url de la barra de dirección.
void MainWindow::gotoPreviousPage() { location->setText( history.pop() );
Cuando el usuario quiera volver hacia atra a una página anterior simplemente tomaremos el último elemento insertado en la pila del historial ( con un pop, ya que es una pila después de todo :-) ), y lo ponemos en la barra de direcciones. La cadena es eliminada de la pila, con lo que la próxima vez que se haga un pop tomará el siguiente y así sucesivamente hasta que se vacíe la pila.
if (history.isEmpty()) toolBar()->setItemEnabled( TOOLBAR_ID_BACK, FALSE); browser->openURL( location->text() ); }
Si la pila está vacía, mejor deshabilitamos el botón back
, una
vez que añadimos un elemento el botón es habilitado de nuevo en
changeLocation()
. Entonces abrimos el url que sacamos (popped) de la
pila en el browser.
void MainWindow::fileSetDefaultPage() { KConfig *config=kapp->config(); config->setGroup("Settings"); config->writeEntry( "defaultPage", browser->url() ); }
Finalmente implementamos el método que es conectado al elemento del menú
Set default page
. Este método almacena el url actual en el fichero
de configuración de esta aplicación.
Primero cogemos el objeto KConfig y lo activamos el grupo de Settings
,
tal como hicimos en el constructor. Entonces escribimos una nueva entrada con
writeEntry
.
El primer parámetro es el nombre del campo, y el segundo el valor que le queremos asignar. Gracias a la sobrecarga de funciones podemos usar writeEntry con diferentes tipos de datos en el segundo parámetro ( int, bool, float, QString, QStringList, QFont , etc. ).
Ahora estamos llegando al final del tutorial, pero primero tenemos que hacerle un pequeño cambio a p6 para que se pueda comunicar con p7 para poner la página actual cuando se pulse sobre un url en la lista de marcadores, ya que en otro caso no tendría mucho sentido tener una lista de marcadores :-).
Siguiente Anterior Tabla de Contenidos