Mostrando entradas con la etiqueta QT. Mostrar todas las entradas
Mostrando entradas con la etiqueta QT. Mostrar todas las entradas

viernes, 7 de febrero de 2014

Calling Android's Text to Speech from QT 5.2. An example of QT Android Extras

I wrote this post (in Spanish) a couple of weeks ago as a reminder just in case I have to do something similar in the future. Sometimes I found QT documentation is not all good  I would desire and with Android Extras I had to spend quite a lot of time to solve some problems. What I wanted to do is to call Adroid's TexToSpeech class from  QT so I used QtAndroidExtras documentation as a reference, this example of notifications and this post of someone else trying to do the same.

At the beginning, it seemed enough to me, in fact, changing a little the notification example with some code from the QT forum should have been a good solution. But the guy on the forum did not have a working code, he asked for help and there was no response. On the other hand, the sample code in QT notification example calls a static method and I wanted to create a Java class that inherited TextToSpeech (something that in the end I did not get).


As I said before, these are a set of notes I want to keep regarding some problems I found and how I solved them. So, the format is something like a personal notes, a FAQ or if you prefer, a conversation with myself.

1. I usually write code in QT but I have no experience as Android programmer.
Well, there is no solution for this. The only thing is to google searching for examples. Anyway, I wrote the resources I used at the beginning of this post.

2. After studying the examples, I see it is required to have access to the activity context so, it is necessary to create an object from a class with an activity context parameter in his constructor.
Your new class should extend QtActivity, it will provide the proper context when you invoke TextToSpeech class.

3. But it is required to implement onListener in my class and it is already inheriting QtActivity!
No problem, you can do both things at the same time:

public class TestAndroidClient extends QtActivity implements TextToSpeech.OnInitListener


4. I've created my class but I don't know the correct location in the file tree, moreover it isn't included in the apk when the project is build.
See the notification example and make a similar structure. At your project's root folder create a directory called android-source and a src one within it. From the last one you should have the rest of the structure for your java files, i.e.  org/qtproject/example/your-app-name/YourClass.java



Be sure to have these two lines in your project's .pro:

QT+=android-extras
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-source

Check the build directory (normally named build-xxxx) for your class file. In linux you can use find:

find . -name YourClass.java





5. When I launch the application it crashes and closes without showing any exception report and the error is previous to my class invocation.
Maybe this is because the class is not found. Check your manifest.xml and look your activity tag, it should point to your class


    
        
   

6. But I want to write a class that inherits TextToSpeech so everything would be more object oriented.
Well... I don't have a solution for this. To tell the truth I failed to do a non static method, furthermore I haven't found an example doing that.

7. I'm trying a call my static method from the C++ code and nothing happens.
Take a look to your parameters signature. It is also important to use the right javaobject from C++to being recognised by the Java function. Having the following Java function:

    public static void test(String msg)
    {
        System.out.println(msg );
        tts.speak(msg, TextToSpeech.QUEUE_FLUSH, null);

    }

The appropriate C++ call will be:

    QAndroidJniObject javaMessage = QAndroidJniObject::fromString(msg);
    QAndroidJniObject::callStaticMethod("org/qtproject/example/testandroidextras/TestAndroidClient",
                                              "test",
                                              "(Ljava/lang/String;)V",
                                              javaMessage.object());

8. I need a example!!
Ok, you can grab the source code from GitHub

viernes, 10 de enero de 2014

Un ejemplo de Qt Android Extras: usando el Text To Speech de Android

Escribo esto como recordatorio por si me vuelve a tocar hacerlo otra vez. A veces la documentación de QT no es todo lo extensa que uno querría y con los extras de Android me he tenido que pegar un buen rato. Lo que quería hacer es llamar a la clase TexToSpeech del SDK de Android desde QT y lo que tenía como referencia era la documentación de QtAndroidExtras, el ejemplo de notificaciones que proporcionan y el intento de otra persona de hacer lo mismo que yo en un foro de QT.

Parecía que era suficiente, de hecho, cambiando un poco el ejemplo de las notificaciones por el código del foro debería haber sido más que suficiente. Pero el tipo del foro no tenia un código funcional, el mismo pedía ayuda y no había respuesta. Por otro lado el código de ejemplo de QT no hace más que llamar a un método estático y yo quería crear una clase Java que heredase TextToSpeech (cosa que al final no conseguí).

Pues bien, como decía, a modo de recordatorio dejaré una serie de problemas que me he encontrado y como los he ido sorteando. El formato del siguiente guión es el de notas mentales, o si lo preferís, un diálogo conmigo mismo.

1. Me defiendo en QT pero no tengo ni idea de programar en el SDK de Android.
No  hay mucha solución a esto, o aprendes o te buscas la vida buscando ejemplos. Ya se han citado los ingredientes a utilizar.

2. Se necesita crear un objeto de una clase en cuyo constructor toma como parámetro el contexto de la actividad.
La clase que escribas debe extender QtActivity, esta proporcionará el contexto a la hora de crear la otra, en este caso TextToSpeech.

3. Pero necesito que mi clase implemente onListener y ya hereda QtActivity.
Bueno... una cosa no quita la otra:

public class TestAndroidClient extends QtActivity implements TextToSpeech.OnInitListener


4. He creado la clase java y no se dónde ponerla, de hecho creo que no se instala a través del apk
Fíjate en el ejemplo de las notificaciones y crea una estructura similar. En la raíz de tu proyecto crea un directorio llamado android-source y dentro de este otro con el nombre src. A partir de ahí tendrás los subsiguientes, por ejemplo: org/qtproject/example/nombre-de-tu-app/TuClase.java



Asegúrate de que en el .pro del proyecto están las siguientes líneas:

QT+=android-extras
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-source

En linux, una vez constrido, puedes hacer en el directorio de construcción (build-xxxx) en un terminal:

find . -name TuClase.java

y comprobar que la ruta es la correcta




5. Cuando trato de ejecutar la aplicación se cierra sin mostrar excepción y esto ocurre al llamar a mi clase.
Esto seguramente es porque no la encuentra. Comprueba que tienes creado el manifest.xml y que referencia correctamente a tu clase en un tag activity


    
        
   

6. Pero yo quiero hacer una clase que herede de TextToSpeech y que sea todo más dinámico.
Bueno pues no tengo solución para esto. De hecho, no he conseguido hacer una llamada que no sea estática a la clase Java creada. A decir verdad, tampoco he encontrado un ejemplo que lo haga.

7. Estoy intentando llamar a un método estático desde el código C++ y sigo sin conseguirlo.
Hay que fijarse en la firma de los parámetros de entrada y salida. También es importante usar el javaobject correcto desde C++ para que la función Java lo reconozca. Si tienes la siguiente función en java:

    public static void test(String msg)
    {
        System.out.println(msg );
        tts.speak(msg, TextToSpeech.QUEUE_FLUSH, null);

    }

La correspondiente llamada en C+++ será:

    QAndroidJniObject javaMessage = QAndroidJniObject::fromString(msg);
    QAndroidJniObject::callStaticMethod("org/qtproject/example/testandroidextras/TestAndroidClient",
                                              "test",
                                              "(Ljava/lang/String;)V",
                                              javaMessage.object());


Finalmente, el código fuente lo podéis encontrar en GitHub

jueves, 31 de octubre de 2013

Me he equivocado otra vez. Me estoy volviendo loco por hacer una aplicación de escritorio con QtQuick Controls

Cuesta admitirlo pero me precipité al querer hacer un navegador de archivos con QtQuick Controls. Hablo de precipitación porque la moraleja para mi es que no están lo suficientemente maduros.

Justo hace un año hice una primera prueba con la beta de Qt 5. En ese momento sí que me di cuenta de que a la cosa le faltaba bastante cocción, lo dejé pronto. Pero con la salida de Qt 5.1 y el anuncio de la primera versión, también estable, de QtQuick Controls, me lancé, a mitades de Agosto, a crear el frontend de DFileBrowser en QML. Lo que me encontré fue lo siguiente:

 

Velocidad de desarrollo

Pronto tuve la sensación de que todo costaba más tiempo que usando widgets. Crear un ListView para ver los archivos me ha parecido un mundo. Echaba de menos esa capacidad de decir si es multiselección o no, si tiene scrollbar, etc. Todo se lo tiene que guisar uno mismo.

 

Otro ejemplo de esto fue el tener que hacer mi propio componente para seleccionar iconos, el
conocido rectángulo que trazas manteniendo apretado el botón izquierdo del ratón. Además tenía que calcular si los iconos estaban en el interior del rectángulo o dejaban de estarlo y, por supuesto, pintarlos como seleccionados según el caso.

Podría buscar mas casos pero creo que con esto es suficiente para hacerse una idea.

Cosas básicas que están pero no funcionan bien. 

Al salir Qt 5.1.1 me di cuenta que la SplitView fallaba, había dejado de funcionar. Así que metí mi primer bug en la página habilitada para tal cosa por el proyecto Qt. Lo positivo fue que en unos pocos días estaba corregido y asignado a la próxima versión del SDK (5.1.2)

Cosas que necesitaba y están por llegar. 

Ahora llegamos a lo último que descubrí, el drag and drop sólo funciona en la propia aplicación. Lo tenía implementado y me había dado cuenta de que sólo podía usarlo entre los dos navegadores que se pueden tener disponibles en DFileBrowser. Pensé que no me funcionaba con otras aplicaciones externas porque no había hecho algo bien, así que me anoté eso como un bug propio y me lo dejé para el final, pero tras un par de pruebas y rebuscar un poco por foros y listas de correo encontré que no era posible comunicarse con otros programas usando esta funcionalidad.


Moraleja

Como he dicho en un principio, pienso que me precipité. Debí darme cuenta de algunas de estas cosas antes o haberme documentado más. También es cierto que es relativamente difícil encontrar que tal cosa está disponible o no cuando das por hecho que así es por analogía con los widgets. En fin, al final el segundo punto y el tercero no dejan de ser anécdotas sabiendo que la versión 5.2 ya incluirá el drag and drop. Lo que me preocupa realmente es que continúe con la sensación de que todo es mucho más costoso y de que tienes que hacerte cosas que antes las tenías hechas y las podías incluir con una línea de código.

viernes, 26 de julio de 2013

Creando un componente simple de QML para usar en mapas. Un ejemplo con QT Location en QT 5


Ayer andaba buscando iconos para usar en una aplicación con mapas y me encontré con un recurso bastante interesante llamado Map Icons Designer. Como podréis ver tienen una pinta bastante atractiva y, si seguís viendo su página, encontraréis que por un lado se nos proporcionan los pines y por otro los símbolos.  La solución, evidentemente, es juntar ambas cosas con algo de coherencia y en el caso que se muestra a continuación se hará mediante un componente QML creado a partir de dos imágenes.

Primero un componente QML facilón

La cosa es bastante fácil, sólo hay que posicionar el símbolo sobre el marcador y para ello usaremos la propiedad "anchor": la posición relativa de ambos tendrá el mismo centro horizontal, después alinearemos el borde superior del símbolo al pin pero dándole un margen adecuado.

anchors.top: parent.top
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter

Por otro lado, aunque vamos a usar sólo uno de los marcadores que se nos proporcionan, los iconos a situar en el interior los deberemos elegir dinámicamente. Esto lo conseguiremos creando una propiedad, usando "property alias", en la que indicaremos el elemento que queremos.

property alias symbol:symbol.source

Además podemos meter todas las imágenes en un archivo .qrc y darles una alias para facilitar el acceso desde la aplicación. En la captura que hay a continuación se puede ver que hay definidos dos prefijos uno para los pines y otro para los símbolos.


De momento, el componente queda tal y como se muestra aquí:

import QtQuick 2.0

Image {
    property alias symbol:symbol.source
    id: pin
    source: "qrc:/pins/blue"
    Image{
        id: symbol
        anchors.top: parent.top
        anchors.topMargin: 10
        anchors.horizontalCenter: parent.horizontalCenter
    }
} 

Un ejemplo con QT Location

En cuanto a su utilización, para obtener algo similar a la imagen que se encuentra más abajo, puede incluirse dentro en un Map del módulo QT Location, pintándolo a traves de un MapQuickItem:

   
Map {
        id: nmap
        center {
            latitude: -27
            longitude: 153
        }

        zoomLevel: 10
        plugin : Plugin {name : "osm"} 
        MapQuickItem {
            coordinate: nmap.center
            anchorPoint: "0,0"
            sourceItem: Marker{symbol:"qrc:/symbols/car"}
        }
} 
Pero esto nos llevará a pensar que, puestos a usarlo con qtLocation, será mejor si el propio componente es un MapQuickItem, con lo que heredará todas sus propiedades. Además, añadiremos un par de cosas: 
  • Por un lado corregiremos el posicionamiento del elemento. En QML nuestros elementos se posicionan tomando como referencia el vértice superior izquierdo y, como se puede ver, el pin tiene una punta abajo y centrada para indicar el punto exacto en el que se localiza. Esto lo solucionamos indicando lo siguiente:
  
    anchorPoint.x: pin.width/2
    anchorPoint.y: pin.height
  • Además añadiremos un  MouseArea para detectar eventos sobre el marcador. En el ejemplo solo se trata el click pero podrían ponerse más
Por tanto, el componente nos queda así:
  
import QtQuick 2.0
import QtLocation 5.0

MapQuickItem{
    id: root
    property alias symbol:symbol.source
    signal clicked()

    anchorPoint.x: pin.width/2
    anchorPoint.y: pin.height

    sourceItem: Image {
        id: pin
        source: "qrc:/pins/blue"
        Image{
            id: symbol
            anchors.top: parent.top
            anchors.topMargin: 10
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }
    MouseArea{
        anchors.fill:parent
        onClicked: root.clicked()
    }
}
Y podremos usarlo de la siguiente manera::
  
import QtQuick 2.0
import QtLocation 5.0

Rectangle{
    width: 480;
    height: 300;

    Map {
        id: nmap
        width: parent.width
        height: parent.height
        anchors.centerIn: parent

        center {latitude: -27;longitude: 153}
        zoomLevel: 10

        gesture.flickDeceleration: 3000
        gesture.enabled: true
        plugin : Plugin { name : "osm"}

        Marker {
            symbol:"qrc:/symbols/car"
            coordinate{
                latitude:-27
                longitude:153
            }
            onClicked: console.log("clicked!")
        }

        Marker {
            symbol:"qrc:/symbols/food"
            coordinate{
                latitude:-27.1
                longitude:153.1
            }
        }
    }
}

El proyecto en GitHub 

 Para terminar sólo queda decir que el proyecto está disponible en GitHub, lo tenéis aquí. Se debe tener en cuenta que hay que descargar a parte los iconos, el autor no permite la redistribución, y que se trata de un proyecto en QT5 por tanto hay  que compilar QT Location por nuestra cuenta, ya que es un módulo externo.

jueves, 10 de noviembre de 2011

Dfilebrowser 1.1 para Plasma Active

Nueva versión de Dfilebrowser disponible para Plasma Active. Esta vez la compilación corre sobre Open Suse. Las novedades se corresponden con mejoras en la usabilidad y la experiencia de usuario al manejar la aplicación.

Dfilebrowser 1.1 on Plasma Active

Dfilebrowser 1.1
  • La vista por defecto para tablets es una lista.
  • Colores alternantes para las filas en las listas de archivos
  • Aumentado el tamaño disponible para la rejilla de iconos del modo de vista "iconview"
  • Mejoras en el modo de vista de lista con detalles de archivo: mejoras en la distribución de las columnas
  • Bugfix: en Plasma Active sobre Open Suse los archivos no se abrían al hacer "tap`"

miércoles, 19 de octubre de 2011

Dfilebrowser un navegador de archivos para Plasma Active One

Dfilebrowser corriendo en Plasma Active One

La semana pasada comentaba que echaba en falta un navegador de archivos en Plasma Active One. Hoy voy a aportar mi granito de arena para solucionarlo, aunque de todos modos sigo pensando que sus creadores  no tardarán en incorporar un gestor de archivos propio

Resulta que cuando empecé a probar Plasma Active me hallaba a su vez creando un gestor de archivos para usar embebido en Acid Rain. Por alguna razón, decidí desarrollarlo de forma que fuera un componente independiente, así que cuando me surgió la necesidad de usarlo como navegador de archivos en Plasma Active se encontraba bastante encaminado.

En realidad es bastante elemental y tiene cosas por pulir (consideradlo una beta) pero creo que es lo suficientemente útil como para que se empiece a usar. La idea es tener todos los botones y las opciones de menú del tamaño suficiente como para poder meter el dedo, así de simple. A modo de manual rápido:
  • Haciendo un toque corto con un dedo (tap), abrimos la carpeta o el archivo
  • Con un toque largo (long tap o tambien tap and hold) sacamos el menú contextual.
  • Podemos cambiar el tipo de vista con el último botón del menú superior.
  • En caso de usar un teclado, podemos usar las combinaciones de teclas habituales. Sí, ya sé que estamos hablando de un tablet pero la aplicación se ha pensado para que funcione también en un escritorio convencional:

    Dfilebrowser corriendo en Windows XP
En caso de que lo adoptes no olvides establecerlo como herramienta preferida para la gestión de archivos (lanzando  desde un terminal systemsettings o buscándolo en el lanzador de aplicaciones de Plasma Active One). Una vez  hecho esto, selecciona "Aplicaciones predeterminadas" y en la siguiente ventana, a la izquierda, "Gestor de archivos". Sólo os quedará añadir dfilebrowser como aplicación preferida.

Dfilebrowser es open source y tiene licencia GPLv3, el código fuente puede encontrarse aquí y para los que tengan Plasma Active One corriendo sobre Meego 1.2 sólo tenéis que descargaros este rpm.

jueves, 20 de enero de 2011

Un tutorial rápido de QT: evaluador de expresiones regulares

Estaba dándome cabezazos contra la mesa el otro día porque no conseguía hacer funcionar una expresión regular en el código de Acid Rain sin encontrar la explicación. La situación me llevaba casi a la decepción por haber olvidado toda esa teoría cuando se me ocurrió buscar alguna web donde probar lo que hacía. Al encontrarla me di cuenta de que no era tan mentecato, algo fallaba ya que la expresión regular funcionaba. Tan loco me estaba volviendo que decidí hacer una aplicación en QT en donde testar de forma rápida las expresiones, ya que con la que estaba trabajando realmente me costaba un poco llegar al punto donde se evaluaba la expresión.


Y así fue que me puse a hacer una aplicación muy parecida a la web que he comentado antes. En poco más de cinco minutos la tenía hecha y se me ocurrió que sería un buen ejemplo para iniciarse en QT. Es tan sólo un poco más complicado que un "Hola mundo" y de paso se ve como utilizar aspectos esenciales de QT Creator, signals/slots y cómo trabajar con la disposición de los elementos en un formulario. ¡Vamos al tema!

Creando el proyecto

 Lo primero será crear el proyecto eligiendo "QT C++ Project" y como subopción  "QT GUI Application"


 Ahora le damos un nombre apropiado a la aplicación y apretamos sobre "Next"


 Como se nos crea un formulario, debemos definir su nombre y el de la clase asociada al mismo


En cuanto a la creación del proyecto sólo nos queda aceptar el resumen.


Lo que queremos hacer

Lo que nos interesa es tener un texto sobre el que queremos hacer alguna prueba, usando una expresión regular para reemplazar parte del él por otro texto determinado. Así pues necesitaremos unos cuantos campos etiqueta, tres campos de entrada y uno de salida.
Los campos de de entrada serán: el de la expresión regular, el de la cadena que queremos introducir y el del texto inicial sobre el que trabaja. Para los dos primeros campos nos bastará con un "line edit" mientras que para el texto usaremos un "text edit". El resultado lo mandaremos a otra caja de texto ("text edit") de salida que tendrá marcada la propiedad "read only".
En cuanto le demos al botón "Test"  se evaluará la expresión regular y, para hacerlo mas emocionante y poder probar más rápido nuestras expresiones, también se evaluará con cada cambio que hagamos en el campo de entrada de la expresión, con lo que veremos los resultados al vuelo mientras la escribimos.
En cuanto a la disposición de los elementos, usaremos dos frames para agrupar por un lado los campos del formulario y por otro el botón "Test".

Insertando los elementos de la ventana

Lo primero que haremos será insertar los dos frames, arrastrándolos a la ventana.


Lo segundo debe ser elegir la disposición de la ventana (hay que asegurarse de que está seleccionada), en este caso le daremos una disposición vertical "Layout vertically"


Es el momento de darle vida a todo esto. En el marco superior dejamos caer cuatro campos "label", los dos "line edit" y los dos "text edit"


Ahora hay que seleccionar el marco superior y después pinchar sobre "Lay out in a form layout". Todavía no quedará muy bonito asi que habrá que corregir  la posición de los elementos. También podemos redimensionar un poco el formulario haciendo uso del ratón para que no quede todo tan ahogado en cuanto espacio.
Vamos con el marco inferior: hay que añadir un "Push Button",  después seleccionar "layout horizontally" para el marco y finalmente añadirle un espaciador horizontal.


El siguiente paso es cambiar el texto que muestran las etiquetas y el botón y darle un nombre correcto a cada uno de ellos para que sea más intuitivo utilizarlos desde el código. Los nombres podrían ser estos (según el orden del formualrio):
lblRegEx | leRegEx 
lblReplace | leReplace 
lblText | teText
lblResult | teResult
         pbTest
Aprovecharemos para seleccionar teResult y marcar la propiedad "read only"


Jugando con los slots

No voy a entrar mucho en esto, tan solo una breve explicación. En QT la comunicación entre objetos se hace mediante signals  y slots. Por un lado hay determinados eventos de los objetos que lanzan señales (al hacer clic sobre un botón, al cambiar el texto en un campo de texto, etc) Por otro lado los objetos también tienen asociadas una serie de funciones llamadas slots cuya finalidad es ser receptoras de señales de otros objetos ( por ejemplo setText(QString) en un campo text edit). Uniendo ambas cosas podemos hacer que al hacer clic sobre un boton "clear" se borre todo el contenido de una caja de texto.
Volvamos a lo nuestro. Seleccionando el botón "Test", apretamos el botón derecho de nuestro ratón para obtener el menú contextual y buscamos la opción "Go to slot..."


Se nos abrirá una ventana en la que elegiremos la señal clciked() y se nos creará automáticamente la cabecera y el cuerpo vacío de un slot llamado "on_pbTest_clicked". Internamente ya se ha relacionado la señal "clicked" con el nuevo slot, así que sólo tendremos que añadir el código que queramos al mismo (cosa que haremos luego) y este se ejecutará al pinchar el botón en nuestra aplicación.


Lo anterior sirve cuando es un objeto  llamándose a si mismo, pero ¿cómo hacemos algo similar entre dos objetos distintos? Pues ahora lo vemos, recordemos antes que queríamos evaluar la expresión al vuelo mientras la escribíamos así que vamos a relacionar la señal "textChanged" del campo leRegExp con la ranura "clicked" del botón pbTest. Para ello nos vamos al modo de edición "edit signals/slots" mediante f4 o haciendo uso del botón de la parte superior de QT Creator. Una vez cambiado el modo, arrastramos el ratón desde el campo de entrada hasta el botón y se nos abrirá una nueva ventana de selección. En la izquierda escogemos la señal "textChanged" y en la derecha el slot "click", aceptamos y los tendremos ya relacionados. Esto quiere decir que cuando haya cualquier cambio en la expresión regular será a todos los efectos, como si pulsásemos el botón "Test" con lo que se irá evaluando al vuelo.


Un poquito de código

Bueno, ya tenemos todo relacionado pero esto todavía no hace nade de nada. Vamos a insertar el código, para ello abrimos el archivo "regextextwindow.cpp" y buscamos la función que QT Creator nos ha insertado. Bastará con dejarla así:

void RegExTestWindow::on_pbTest_clicked()
{
 ui->teResult->setText(ui->teText->toPlainText().replace(QRegExp(ui->leRegExp->text()),ui->leReplace->text()));
}

Lo que significa que asigne como texto del campo "teResult" lo obtenido al reemplazar en el texto de prueba que hemos dejado en "teText" todo lo que encaje con la expresión regular contenida en "leRegExp". Todo lo que encaje con la expresión se sustituye por el valor de "leReplace"
¡Ya está!
Pues si todo ha ido bien  le damos al botón de ejecución y se nos lanzará la apliación. Sólo nos queda desengrasar nuestros conocimientos en expresiones regulares :) Cuando tenga un rato colgaré el código fuente y la aplicación en esta web para los más perezosos.

Sobre mi estupidez

Tal vez os hayáis quedado pensando en lo que contaba al principio del post. Resulta que cuando probé la expresión en la aplicación test la cosa funcionaba. Así que tenía lo siguiente: funcionaba en la web, funcionaba en el testador y fallaba en mi código. Cuando pasan cosas así siempre piensas lo mismo "tiene que ser una estupidez como un piano" Efectivamente así era, no se me había pasado por la cabeza el escapar el carácter de escape, que perogrullada más infernal.
Una expresión valida como \s\d+/\d+\s escrita en código es \\s\\d+/\\d+\\s
Perder tanto tiempo con una tontería semejante suele llevarme, cuando encuentro la solución, al segundo pensamiento típico: "que empanado que estoy" 

martes, 16 de noviembre de 2010

De cal y de arena

"Guru meditation" era un mensaje de error que salía en los Commodore Amiga muy similar a la pantalla azul de la muerte en Windows, vamos que si te salía la habías cagado y no podías hacer nada. Pese a la frustración que producía hoy en día se puede encontrar de vez en cuando en los mensajes de error de un servidor web o alguna aplicación creada por algún antiguo "amiguero" nostalgico. Umm... esto me recuerda (y me estoy partiendo) mis andanzas con los servicios de atención al cliente de los proveedores de internet cuando surgieron las tarifas planas a mitades de los 90 y yo me conectaba con mi Amiga A1200, pero es otra historia... El  caso es que para no deteriorar mi nivel de frikismo he caído en la trampa de hacer un pequeño tributo a esa vieja máquina. Pero vamos por partes:

A principios de esta semana todo parecía positivo, en parte porque había dejado temporalmente de lado el problema de informar sobre la transferencia de archivos, así que pude centrarme en la gestión de conflictos. En estos momentos Acid Rain ya detecta problemas y conflictos y al hacerlo abre un formulario para dar al usuario la posibilidad de elegir como gestionarlo. De momento es bastante básico pero funciona.

En realidad la mejor noticia que puedo dar hoy es que ya estoy usando Acid Rain de forma personal para sincronizar los archivos de mis ordenadores. Hasta ahora no lo había hecho porque no me fiaba de mi propio invento. En otras palabras, he cogido los archivos que tengo guardados en ese servicio cuyo nombre no me dejan usar y los he pasado ya a Acid Rain. También hay unos cuantos iconos adornando el menú del programa.

 Y en cuanto a las malas, en fin, hoy se ha producido una aunque realmente la esperaba. No quiero contar mucho de momento, no tiene nada que ver con el programa en si, digamos que es logística. En fin, se hará lo que se pueda al respecto también.
Con todo esto lo próximo es acabar el wizzard de la primera configuración, reparar bugs, traducir al español y empaquetar la primera versión. La idea es distribuirla solo a un par de cientos de usuarios para que hagan beta testing, pero aún tengo que pensar como limitar esta distribución. Mientras, se me tendrá que ocurrir como solucionar el problema de las narices.
Ah! y no quiero acaba sin dar las gracias a los pocos que lo estáis probando

jueves, 11 de noviembre de 2010

Un mojón en la bandeja de sistema

Hoy para variar sigo contando y aburriendo con mis batallitas binarias respecto a Acid Rain.
Estoy enzarzado con unos cuantos problemas sin poder centrarme en la parte con la que me quería estar pegando a estas alturas. Empezaré con uno que más o menos está ya resuelto:

Enmarronado con el icono mojón
Resulta que uno de los iconos que aparecía cuando el programa esta pausado se asemejaba bastante a un excremento. El primero en advertírmelo fue Álvaro  pero, como tiene la extraña habilidad de parecer una persona seria cuando se está quedando contigo, admito que no le hice caso. Al día siguiente Jesús me dijo más o menos lo mismo, bueno creo que la comparación fue con una deposición de Arale.


De acuerdo lo reconozco, lo que pasaba es que yo no lo veía así porque sé que es naranja, pero la mezcla con el gris y la reducción del tamaño hace que realmente parezca un mojón. No es que me sienta mal, el Sr. Mojón siempre fue uno de mis personajes preferidos de South Park, pero de alguna manera he llenado de mierda las bandejas de sistema de unos cuantos amigos.

Notificar al usuario que mercurial sigue transfiriendo
Iconos a aparte, mis verdaderos quebraderos de cabeza andan por otro lado, el de conseguir notificar de algún modo la actividad de descarga o subida al usuario. El problema viene dado porque no encuentro la manera de "preguntarle" a mercurial cuanta transferencia ha hecho.  Me explico, el programilla (me refiero ahora a Acid Rain) va bastante bien pero cuando añades un archivo grande a tu directorio de documentos y la nube cambia a la que tiene la lluvia azul (que indica que se está produciendo una subida o bajada) esa es la ultima noticia que recibes de que algo está pasando hasta que termine el proceso (la ejecución de la transferencia que hace mercurial). Pondré un ejemplo real:
Copié archivos por un tamaño aproximado de un giga a la carpeta de documentos, con lo que empezaron a subirse al servicio de hosting con el que estoy probando. Mi proveedor de internet tiene una limitación de ancho de banda de subida de unos 50 KB/sec, con lo que... tachan, tachan, el tiempo de la operación sería de unas 6 horas. 6 horas con un icono naranja y azul en las que sólo puedes hacer un acto de fe.
Las cosas que se me han ocurrido para solucionarlo no están funcionando y me parece un defecto bastante grande desde el punto de vista de la usabilidad.
Unas pocas buenas noticias por favor
Por lo anterior estoy un poco pesimista así que vamos con las buenas noticias:
  • Hay unos cuantos iconos nuevos que representan más estados y además el icono mojón ha desaparecido.
  • También hay un segundo conjunto de iconos en blanco y negro. No son una maravilla pero encajarán mejor en Windows 7 y KDE 4.5. La selección del juego de iconos se puede hacer desde la ventana de configuración.
  • Se han solucionado unos cuantos bugs y el modo de trabajo con repositorio remoto va funcionando mejor.
  • Ya lo había probado en Windows y en una OpenSuse (Linux con entorno KDE) pero esta semana también he podido probarlo en Ubuntu con éxito (Linux con entorno Gnome)
  •  Y sobre todo la mejor noticia: ¡funciona en Mac! ¡Gracias Jesús!

Acid Rain en un Mac
Acid Rain en Ubuntu




martes, 3 de marzo de 2009

Hoy ha salido QT Creator 1.0 y yo sigo volviendo a mis orígenes

Acaba de aparecer en la página QTSoftware la versión 1.0 de QT Creator. Llevo unos cuantos días trasteando con este IDE (versiones previas a esta claro) y la verdad es que pinta muy bien.

En realidad yo me manejaba relativamente bien hace años con QT Designer con el que llegué a hacer un prototipo, o esbozo si se prefiere, de aplicación, nada serio. Lamentablemente dejé el C++ de lado al empezar a dedicarme profesionalmente a la programación web en PHP.

Ahora QT Designer forma parte de Creator y ya no es necesario recurrir a qmake en la linea de comandos ni a un editor de código fuente.

¿Y por qué elegir QT?

Básicamente por la portabilidad: programando en QT nos aseguramos una aplicación portable a Linux, Windows y Mac. Además pronto podrán hacerse aplicaciones para Symbian en QT. Como muchos sabreis Nokia se hizo con Trolltech hace unos cuantos meses. Tuve la suerte de asistir a una presentación de la Symbian Fundation en el MWC de Barceona y comentaron que a mitades de este año sacarían un entorno de "runtime" para Symbian S60 3rd Ed. Seguro que pronto veremeos en QT Creator la posibilidad de crear proyectos para teléfonos con este sistema operativo.

Un rápido Hola Mundo.

No me las daré de gurú de QT porque lo poco que sabía se perdió en el tiempo como lágrimas en la lluvia. Lo que he podido recuperar estos días me da lo justo para un "Hola Mundo". Aquí va:

Primero crearemos el proyecto escogiendo la opción QT4 GUI Application y por supuesto le asignaremos un nombre. No es necesario que añadamos ningún módulo extra en el tercer paso del asistente de creación de proyecto. Por último se nos propondrán una serie de nombres para las clases principales de la aplicación y el resto de archivos .cpp, .h y .ui


Al terminar con el último paso se nos habrán creado los archivos mencionados anteriormente y los veremos en el panel de la izquierda


Seleccionemos el archivo con extensión .ui y añadamos a la ventana de nuestra aplicación un Push Button y un Text Browser. Después de esto podemos especificar un layout vertical para que sea mas vistoso y el redimensionamiento de la ventana afecte a los dos elementos que le hemos incorporado.

Podemos también añadir un spacer para darle un poco de oxígeno al resultado aunque desde luego esta ventana no está muy cargada :p


Solo nos queda el último paso, nos situamos sobre el PushButton y pulsamos el botón derecho de nuestro ratón, en el menú contextual seleccionamos "Go to slot..." Nos aparecerá una ventana para escoger la señal correspondiente y elegiremos "clicked" Al hacer esto nos encontraremos en el editor de código y añadiremos la siguiente linea a la función del slot:

void MainWindow::on_pushButton_clicked()

{

ui->textBrowser->append("Hello world!");

}



¡Y se acabo! Le damos al icono verde de play y eso construirá la aplicación y nos la lanzará. Sólo tendremos que clicar en el botón y veremos nuestro maravilloso mensaje aparecer en la caja de texto.