Hasta ahora no hemos hecho nada útil, sino aprender a colocar los menúes y barra de herramientas en nuestra aplicación. En este artículo tampoco vamos a hacer algo muy útil, solo vamos a ver cómo se usan las clases de KDE para navegar por nuestros archivos, cómo mostrar un archivo de texto en pantalla y cómo guardarlo si se han hecho modificaciones. En otras palabras, un editor de texto extremadamente rudimentario, solo para mostrar el uso de algunas clases de KDE que necesitaremos más adelante y el funcionamiento de los slots.
Las clases encargadas de manejar todo lo referente a entrada y salida se encuentra en la biblioteca libkio. En nuestro caso usaremos la clase KFileDialog encargada de mostrar un navegador de archivos para permitir al usuario seleccionar un archivo; una vez seleccionado guardamos su nombre y ubicación en la variable Archivo del tipo QString. Ahora que tenemos el nombre y ubicación del archivo, lo abrimos usando la clase QFile y lo mostramos en un objeto de la clase KTextEdit. Para leer el archivo hacemos uso de la clase QTextStream y asignamos el stream al texto del KTextEdit. Todo ésto lo realiza el slot encargado de procesar la señal emitida por la acción Abrir. La clase QTextStream tiene un funcionamiento parecido a la clase stringstream de C++ mientras que la clase QString es derivada de la clase string, ambas pertenecientes a la STL. Si el lector quiere comprender un poco su funcionamiento, se recomienda leer este enlace con la ayuda para estas clases.
Para guardar el archivo usamos un procedimiento inverso. Añadimos una nueva acción, llamada actGuardar usando la clase KStdAction y creamos el slot para procesar su señal cuando se haga clic en dicha acción; llamemos al slot slotGuardar. Luego se redirecciona el texto del KTextEdit al QTextStream para luego escribirlo en el archivo de salida. Ahora tenemos un sencillo editor de texto plano, pero que se carga muy rápido. Nuestro código quedaría ahora así:
Archivo KMiMainWindow.h
#include <kmainwindow.h> class KAction; class KTextEdit; class QString; class KMiMainWindow : public KMainWindow { Q_OBJECT public: KMiMainWindow(QWidget *parent = 0, const char *name = 0); private: // Variables privadas KAction *actAbrir; KAction *actCopiar; KAction *actCortar; KAction *actGuardar; KAction *actPegar; KAction *actSalir; KTextEdit *txtEditor; QString Archivo; // Funciones Privadas void CrearAcciones(void); void CrearMenu(void); void CrearToolbar(void); private slots: void slotAbrir(void); void slotCopiar(void); void slotCortar(void); void slotGuardar(void); void slotPegar(void); void slotSalir(void); };
Archivo KMiMainWindow.cpp
#include "KMiMainWindow.h" #include <kaction.h> #include <kmenubar.h> #include <kmessagebox.h> #include <kpopupmenu.h> #include <kstdaction.h> #include <ktoolbar.h> // Encabezados añadidos #include <kfiledialog.h> #include <ktextedit.h> #include <qfile.h> #include <qtextstream.h> /****************************************************************************** * Constructor de la clase. * ******************************************************************************/ KMiMainWindow::KMiMainWindow(QWidget *parent, const char *name) : KMainWindow(parent, name) { setGeometry(0, 0, 400, 400); setCaption("MiMainWindow"); txtEditor = new KTextEdit(this, "txtEditor"); setCentralWidget(txtEditor); CrearAcciones(); CrearMenu(); CrearToolbar(); } /****************************************************************************** * Procedimiento encargado de crear las acciones que usaremos en el programa * ******************************************************************************/ void KMiMainWindow::CrearAcciones(void) { actAbrir = KStdAction::open (this, SLOT(slotAbrir()), actionCollection()); actCopiar = KStdAction::copy (this, SLOT(slotCopiar()), actionCollection()); actCortar = KStdAction::cut (this, SLOT(slotCortar()), actionCollection()); actGuardar = KStdAction::save (this, SLOT(slotGuardar()), actionCollection()); actPegar = KStdAction::paste(this, SLOT(slotPegar()), actionCollection()); actSalir = KStdAction::quit (this, SLOT(slotSalir()), actionCollection()); } /****************************************************************************** * Procedimiento para crear el menú y añadir las acciones * ******************************************************************************/ void KMiMainWindow::CrearMenu(void) { KMenuBar *mb = new KMenuBar(this, "MenuBar"); KPopupMenu *p = new KPopupMenu(this, "PopupArchivo"); actAbrir->plug(p); actGuardar->plug(p); p->insertSeparator(); actSalir->plug(p); mb->insertItem("&Archivo", p); p = new KPopupMenu(this, "PopupEdicion"); actCopiar->plug(p); actCortar->plug(p); actPegar->plug(p); mb->insertItem("&Edición", p); } /****************************************************************************** * Procedimiento para crear la barra de herramientas y añadir las acciones. * ******************************************************************************/ void KMiMainWindow::CrearToolbar(void) { KToolBar *tb = new KToolBar(this, QMainWindow::Top, false, "Toolbar", true, false); actAbrir->plug(tb); actGuardar->plug(tb); tb->insertLineSeparator(); actCopiar->plug(tb); actCortar->plug(tb); actPegar->plug(tb); tb->insertLineSeparator(); actSalir->plug(tb); } /****************************************************************************** * SLOT para procesar la acción Abrir * ******************************************************************************/ void KMiMainWindow::slotAbrir(void) { // Primero obtenemos el nombre del archivo a abrir. Archivo = KFileDialog::getOpenFileName(); QFile ArchEntr(Archivo); // Lo abrimos en modo lectura if (ArchEntr.open(IO_ReadOnly)) { // Lo leemos QTextStream ts(&ArchEntr); // Llenamos el txtEditor con el contenido del archivo txtEditor->setText(ts.read()); // Actualizamos el título de la ventana setCaption("MiMainWindow - " + Archivo); } } /****************************************************************************** * SLOT para procesar la acción Copiar * ******************************************************************************/ void KMiMainWindow::slotCopiar(void) { txtEditor->copy(); } /****************************************************************************** * SLOT para procesar la acción Cortar * ******************************************************************************/ void KMiMainWindow::slotCortar(void) { txtEditor->cut(); } /****************************************************************************** * SLOT para procesar la acción Guardar * ******************************************************************************/ void KMiMainWindow::slotGuardar(void) { // Abrimos el archivo en modo escritura QFile ArchSal(Archivo); if (ArchSal.open(IO_WriteOnly)) { // Asignamos el stream de salida al archivo QTextStream ts(&ArchSal); // Guardamos en el archivo el contenido de txtEditor ts << txtEditor->text(); } } /****************************************************************************** * SLOT para procesar la acción Pegar * ******************************************************************************/ void KMiMainWindow::slotPegar(void) { txtEditor->paste(); } /****************************************************************************** * SLOT para procesar la acción Salir * ******************************************************************************/ void KMiMainWindow::slotSalir(void) { close(); }
Para poder compilar nuestro código debemos modificar nuestro archivo de proyecto para que se incluya la biblioteca libkio donde se encuentra la función getOpenFileName. Aprovechamos para modificar otras cositas más que le darán un poco de orden a nuestro proyecto, pues ahora le indicamos dónde se colocan los archivos .moc, .o, .h y .cpp. Ahora nuestro archivo de proyecto tiene el siguiente contenido:
# Opciones de compilación INCLUDEPATH = /usr/kde/3.5/include/ ./include LIBS = -lkdeui -lkio -L/usr/kde/3.5/lib TEMPLATE = app TARGET = kaplicacion DEPENDPATH = . # Archivos con código fuente HEADERS += include/KMiMainWindow.h SOURCES += src/KMiMainWindow.cpp src/kapp.cpp # Directorios de destino DESTDIR = bin MOC_DIR = moc OBJECTS_DIR = obj
Esta vez para compilar y ejecutar nuestra aplicación escribimos:
qmake && make && bin/kaplicacion
Con nuestro nuevo archivo de proyecto, la estructura de directorio de los archivos de nuestro proyecto debe quedar así una vez compilado:
. |-- Makefile |-- bin | `-- kaplicacion |-- include | `-- KMiMainWindow.h |-- kapp.pro |-- moc | `-- moc_KMiMainWindow.cpp |-- obj | |-- KMiMainWindow.o | |-- kapp.o | `-- moc_KMiMainWindow.o |-- src | |-- KMiMainWindow.cpp | `-- kapp.cpp
Es de hacer notar que para nuestro programa no hace falta tener los slots slotCopiar, slotCortar y slotPegar ya que la clase QTextEdit, de la cual deriva KTextEdit, tiene los slots para manejar esas señales: copy(), cut() y paste(), que son llamados dentro de nuestros slots, quedando nuestro código más simple al eliminar las funciones mencionadas anteriormente tanto del archivo .h como del archivo .cpp y modificando lo siguiente en nuestro archivo KMiMainWindow.cpp:
actCopiar = KStdAction::copy (txtEditor, SLOT(copy()), actionCollection()); actCortar = KStdAction::cut (txtEditor, SLOT(cut()), actionCollection()); actPegar = KStdAction::paste(txtEditor, SLOT(paste()), actionCollection());
Un screenshot de la aplicación se muestra a continuación: