domingo, 15 de marzo de 2015

Ejemplo libconfig con QtCreator: Leer y escribir en el fichero de configuración

En esta entrada veremos un ejemplo de uso de libconfig en linux para trabajar con ficheros de configuración. Usaremos QtCreator como ide.

Lo primero es instalar el paquete libconfig

Desde debian:
apt-get install libconfig

Desde fedora:
yum install libconfig libconfig-devel


Luego debemos linkear la librería desde nuestro IDE. Para ello damos clic derecho al titulo del proyecto y luego en Add Library. Luego colocamos la dirección de el fichero libconfig.so. 
Por lo general está en /usr/lib64/libconfig.so si es un so de 64 bits
Por lo general está en /usr/lib/libconfig.so     si es un so de 32 bits


Puedes hacer el paso anterior de forma manual agregando la siguiente linea a tu fichero .pro
LIBS += -lconfig

Para este ejemplo utilizamos el siguiente fichero de configuración (example.cfg):

// Nombre
nombre = "Libros, Películas y mas";

// Inventario
inventario =
{
  libros = ( { titulo  = "Treasure Island";
              autor = "Robert Louis Stevenson";
              precio  = 29.99;
              qty    = 5; },
            { titulo  = "Snow Crash";
              autor = "Neal Stephenson";
              precio  = 9.99;
              qty    = 8; }
          );

  peliculas = ( { titulo = "Brazil";
               media = "DVD";
               precio = 19.99;
               qty = 11; },
             { titulo = "MEMEMTO";
               media = "VHS";
               precio = 18.99;
               qty = 5; }
           );
};





Este código lee el fichero, muestra su contenido y cambia el valor de la preferencia 'nombre' a Totona.

#include <stdio.h>
#include <stdlib.h>
#include <libconfig.h>


/* Este ejemplo lee el fichero de configuracion example.cfg
 * y muestra su contenido
 */
int main(int argc, char **argv)
{
    static const char *output_file = "updated.cfg";
    static const char *input_file  = "example.cfg";
    config_t cfg;
    config_setting_t *setting;
    const char *str;

    config_init(&cfg);

    /* Lee el fichero, si hay error lo muestra y sale */
    if(! config_read_file(&cfg, input_file))
    {
        fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
                config_error_line(&cfg), config_error_text(&cfg));
        config_destroy(&cfg);
        return(EXIT_FAILURE);
    }    
    

    /* Obtenemos el nombre. */
    if(config_lookup_string(&cfg, "nombre", &str))
        printf("nombre: %s\n\n", str);
    else
        fprintf(stderr, "No hay un campo 'nombre' en example.cfg.\n");

    /* Mostramos todos los libros del inventerio. */
    setting = config_lookup(&cfg, "inventario.libros");
    if(setting != NULL)
    {
        int count = config_setting_length(setting);
        int i;

        printf("%-30s  %-30s   %-6s  %s\n", "titulo", "autor", "precio", "QTY");

        for(i = 0; i < count; ++i)
        {
            config_setting_t *libro = config_setting_get_elem(setting, i);

            const char *titulo, *autor;
            double precio;
            int qty;

            if(!(config_setting_lookup_string(libro, "titulo", &titulo)
                 && config_setting_lookup_string(libro, "autor", &autor)
                 && config_setting_lookup_float(libro, "precio", &precio)
                 && config_setting_lookup_int(libro, "qty", &qty)))
                continue;

            printf("%-30s  %-30s  $%6.2f  %3d\n", titulo, autor, precio, qty);
        }
        putchar('\n');
    }

    /* Muestra todas las peliculas en inventario. */
    setting = config_lookup(&cfg, "inventario.peliculas");
    if(setting != NULL)
    {
        unsigned int count = config_setting_length(setting);
        unsigned int i;

        printf("%-30s  %-10s   %-6s  %s\n", "Titulo", "Media", "Precio", "QTY");
        for(i = 0; i < count; ++i)
        {
            config_setting_t *movie = config_setting_get_elem(setting, i);

            const char *titulo, *media;
            double precio;
            int qty;

            if(!(config_setting_lookup_string(movie, "titulo", &titulo)
                 && config_setting_lookup_string(movie, "media", &media)
                 && config_setting_lookup_float(movie, "precio", &precio)
                 && config_setting_lookup_int(movie, "qty", &qty)))
                continue;

            printf("%-30s  %-10s  $%6.2f  %3d\n", titulo, media, precio, qty);
        }
        putchar('\n');
    }
    
    /** Actualizamos el valor del nombre **/    
    config_setting_t *root,*nombre;

    root = config_root_setting(&cfg);
    nombre=config_setting_get_member(root,"nombre");

    // Cambiamos el valor del nombre y le colocamos
    config_setting_set_string(nombre,"Totona");

    /* Escribimos el fichero de salida*/
    if(! config_write_file(&cfg, output_file))
    {
        fprintf(stderr, "Error escribiendo en el fichero.\n");
        config_destroy(&cfg);
        return(EXIT_FAILURE);
    }

    fprintf(stderr, "Se ha actualizado el fichero %s y se ha guardado en: %s\n",
            input_file,output_file);


    config_destroy(&cfg);
    return(EXIT_SUCCESS);
}



Links de interés:
http://jpmens.net/2009/09/17/reading-configuration-files-with-libconfig/

sábado, 14 de marzo de 2015

Ajustar imagen a Qlabel en Qt

Para hacer que una imagen se ajuste al tamaño de un QLabel se debe modificar su stylesheet.

Para ello se le da botón secundario al label desde el editor de UI



Luego se agrega la siguiente lineal:
border-image: url(:/URL_DE_LA_IMAGEN) 0 0 0 0 stretch stretch;



y Listo

Antes

Despues

Si lo quiere hacer desde código deberías hacer:

label->setStyleSheet("border-image: url(:/URL_DE_LA_IMAGEN) 0 0 0 0 stretch stretch;");.

sábado, 21 de febrero de 2015

QRegExp: explicación rápida y sin marisqueras

Ejemplo #1: Detectar un número de dos dígitos 
"([0-9]{2,2})"
Explicación
[0-9]: Dígito del 0 al 9
{2,2}: Mínimo 2 y máximo 2 (Modifica al anterior que es [0-9]).

Pruebas:
QRegExp rx("([0-9]{2,2})");
rx.indexIn("123");        // Lo encuentra en 0
rx.indexIn("-asd66");   // Lo encuentra en 4
rx.indexIn("6");            // No encuentra

Ejemplo #2: Detectar las x de un polinomio y sus coeficientes
"([0-9]{,}x)"
Explicación
[0-9]: Dígito del 0 al 9
{ , }: Indica que la x puede tener o no un número adelante (cuando el coeficiente es 1 se no es necesario colocarselo)
x: Carácter x

Pruebas:
QRegExp rx("([0-9]{,}x)");  rx.indexIn("2y+3x");        // Lo encuentra en 3
rx.indexIn("2y+345x");    // Lo encuentra en 3
rx.indexIn("2y+x");          // Lo encuentra en 3
rx.indexIn("2y-5");           // No lo encuentra rx.indexIn("6");               // No encuentra

miércoles, 18 de febrero de 2015

Autologin luego de instalar Plasma 5 en Fedora

Cuando instalas plasma 5 luego de reiniciar la pantalla se queda en modo terminal y debes iniciar con startx.
Para activar el autologin  debes ejecutar el siguiente comando:
systemctl enable --force sddm.service

miércoles, 11 de febrero de 2015

Convertir varias imágenes en un fichero PDF en Fedora 21

En esta entrada veremos como convertir varias imágenes en un fichero .pdf.

Primero debe instalar gtatool-imagemagick


yum -y install gtatool-imagemagick

Luego convierte las imagenes a pdf con

convert imagen1.jpg imagen2.jpg fichero.pdf

En este caso las imagenes que quiero convertir tienen como nombre IMG_*.jpg y las quiero juntar en un fichero llamado fichero.pdf











convert ./IMG_*.jpg fichero.pdf

domingo, 8 de febrero de 2015

Ejemplo Qt5 + Postgres

En la entrada anterior expliqué como se configuraba fedora para conectar qt5 con postgres. Ahora aquí se muestra un ejemplo de una aplicación en Qt que se conecta con una BD en postgres.

Primero creamos la BD de ejemplo desde pgadmin3. En este caso se llama BD_UNEG


CREATE DATABASE "BD_UNEG"
  WITH OWNER = postgres
       ENCODING = 'UTF8'
       TABLESPACE = pg_default
       LC_COLLATE = 'es_VE.UTF-8'
       LC_CTYPE = 'es_VE.UTF-8'
       CONNECTION LIMIT = -1;
-- Table: persona

CREATE TABLE persona
(
  cedula character varying(20) NOT NULL,
  nombre character varying(50),
  tipo character varying(30),
  estatus character varying(30),
  carrera character varying(30),
  CONSTRAINT persona_pkey PRIMARY KEY (cedula)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE persona
  OWNER TO postgres;

qt postgres

Quedaría así


Ahora agrega algo a la BD. 



NOTA: En este ejemplo la clave de postgres es 123456 y el puerto es 5432

Este es el código en Qt que busca todos los elementos de la tabla persona y los muestra

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QSqlDatabase>
#include <QSqlError>
#include <QStringList>
#include <QMessageBox>
#include <QSqlQuery>
#include <QSqlRecord>

bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
    db.setHostName("127.0.0.1");   // Nombre del host
    db.setDatabaseName("BD_UNEG"); // Nombre de la BD
    db.setPort(5432);              // Puerto
    db.setUserName("postgres");    // Usuario
    db.setPassword("123456");      // Contraseña

    // Si esta abierto entonce retorna true
    if (db.isOpen()){
        qWarning() <<"La conexión ya estaba creada";
        return true;
    }

    // Abre la BD
    if (!db.open()) {
        QMessageBox::critical(0, QObject::tr("Database Error"),
                              db.lastError().text());
        return false;
    }
    return true;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << (createConnection() ? "Se crea la conexión :)" : "ERROR al conectar :(");

    QSqlQuery qry;

    qry.prepare( "SELECT * FROM persona" );
     if( !qry.exec() )
       qDebug() << qry.lastError();
     else
     {
       qDebug( "Seleccionado!" );
       QSqlRecord rec = qry.record();
       int cols = rec.count();
       for( int c=0; c<cols; c++ )
         qDebug() << QString( "Columna %1: %2" ).arg( c ).arg( rec.fieldName(c) );

       for( int r=0; qry.next(); r++ )
         for( int c=0; c<cols; c++ )
           qDebug() << QString( "Fila %1, %2: %3" ).arg( r ).arg( rec.fieldName(c) ).arg( qry.value(c).toString() );
     }

    return a.exec();
}





Recuerda agregar QT += sql en el fichero .pro



Links de interes:
http://www.informit.com/articles/article.aspx?p=1405550


http://www.java2s.com/Code/Cpp/Qt/ConnecttoMySqlwithQSqlDatabaseanddoselectupdateinsertanddelete.htm


http://www.ics.com/designpatterns/solutions/qsqldatabase.html

Qt + Postgresql en Fedora 21

Para usar una bd en postgresql usando Qt en fedora 21 primero debes instalar el driver de postgresql

yum install qt5-qtbase-postgresql

Luego en el proyecto agregar la linea sql en el fichero .pro de nuestro proyecto



Listo :) Ahora puesdes probar el driver usando el siguiente código:



#include <QtCore/QCoreApplication>

#include <QDebug>
#include <QSqlDatabase>
#include <QStringList>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "Available drivers: " << QSqlDatabase::drivers();

    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");

    qDebug() << "addDatabase() " << (db.isValid() ? "VALID" : "ERROR");

    return a.exec();
}



Aqui pongo un ejemplo más pulido: