Archive for November 2010

Master Details View con QML

November 22nd, 2010

Lo bueno de QML es que permite que casos de uso como una simple vista Maestro Detalle pueda ser mejorada agregando animaciones y layouts personalizados con muy poco esfuerzo.

El ejemplo a implementar es muy simple, vamos a usar un archivo XML como data source y para presentar los datos vamos a usar un GridView en donde seleccionaremos el item a mostrar en en el ListView que hace las veces de details view.

La acción central ocurren en el delegate usado para poblar el GridView el cual espera a que se haga click en alguno de los items, para pasar el index al ListView y disparar la animación que remueve el GridView de la escena para cambiar la opacidad del ListView de 0 a 1 para poder hacerlo visible, por ultimo hay en elemento Text que hará de botón para volver a la vista original.

import Qt 4.7

Rectangle {
    width: 360
    height: 640
    id:container

    XmlListModel {
        id: oranjeModel
        source: "http://localhost:3002/players.xml"
        query: "/players/player"
        XmlRole {
            name: "name"
            query: "name/string()"
        }
        XmlRole {
            name: "number"
            query: "number/string()"
        }
        XmlRole {
            name: "position"
            query: "position/string()"
        }
        XmlRole {
            name: "picture"
            query: "picture/string()"
        }
        XmlRole {
            name: "bio"
            query: "bio/string()"
        }
    }

    Component {
        id: oranjeDelegate
        Item {
            width: 80
            height: 110
            Image {
                source: picture
                width: parent.width
                height: parent.height
                fillMode: "Stretch"
                opacity: 0.5
            }
            MouseArea {
                anchors.fill: parent
                focus: true
                onClicked: {
                    oranjeDetails.currentIndex = index
                    container.state = "detailsView"
                }
            }
        }
    }

    Component {
        id: oranjeDetailsDelegate
        Grid {
            rows: 3
            spacing: 6

            Row {
                Image {
                    source: picture
                    width: 160
                    height: 230
                    fillMode: "Stretch"
                }

                Column {
                    Text {
                        text: number
                        font.pointSize: 24
                    }
                    Text {
                        text: name
                        font.pointSize: 18
                    }
                    Text {
                        text: position
                        font.pointSize: 14
                    }
                }
            }

            Row {
                Text {
                    text: bio
                    font.pointSize: 8
                    width: container.width
                    wrapMode: "Wrap"
                }
            }

            Row {
                Text {
                    text: "Back"
                    font.pointSize: 12
                    color: "#ed1e24"
                    width: container.width
                    MouseArea {
                        anchors.fill: parent
                        onClicked: container.state = ""
                    }
                }
            }

        }
    }

    GridView {
        id: oranjeList
        model: oranjeModel
        delegate: oranjeDelegate
        width: container.width
        height: container.height
        cellWidth:90
        cellHeight: 120
    }

    ListView{
        id: oranjeDetails
        model: oranjeModel
        delegate: oranjeDetailsDelegate
        opacity: 0
    }

    states: [
        State {
            name: "detailsView"
            PropertyChanges {
                target: oranjeList
                x: -container.width
            }
        }
    ]

    transitions: [
        Transition {
            from: ""
            to: "detailsView"
            NumberAnimation {
                properties: "x"
                easing.type: "OutBounce"
            }
            PropertyAnimation {
                target: oranjeDetails
                property: "opacity"
                to: 1
            }
        },
        Transition {
            from: "detailsView"
            to: ""
            NumberAnimation {
                properties: "x"
                easing.type: "OutSine"
                duration: 250
            }
            PropertyAnimation {
                target: oranjeDetails
                property: "opacity"
                to: 0
            }
        }
    ]
}
Development, User Interface , , No response

Consumiendo XML con QML

November 19th, 2010

Consumir XML en QML es algo casi trivial, para ello contamos con el elemento XmlListModel que hará de data source de un ListView en el ejemplo a continuación, el XmlListModel cuenta con una id, un source, que en este caso hace uso de la Weather API de Yahoo, luego vienen los XmlRole los cuales describen los datos expuestos, cada uno de ellos tiene un name que sera usado luego para poder acceder a la data del role.

A continuación tenemos un delegate, en donde especificamos que datos vamos a consumir, el layout y la apariencia que tendran, por ultimo el ListView usa el model y el delegate que previamente configuramos, en este caso solo muestra un item (ver imagen abajo) ya que nuestra query solo devuelve un dato, pero si el data source devolviese mas items, cada uno de ellos poblarían el ListView, como bonus, el ListView cuenta con kinetic scroll, el cual nos da unos puntos extras en el apartado de UX con 0 esfuerzo por parte nuestra.

import Qt 4.7

Rectangle {
    width: 640
    height: 360

    XmlListModel {
        id: weatherModel
        source: "http://weather.yahooapis.com/forecastrss?w=468739&u=c"
        query: "/rss/channel/item"
        XmlRole {
            name: "title"
            query: "title/string()"
        }
        XmlRole {
            name: "description"
            query: "description/string()"
        }
    }

    Component {
        id: weatherDelegate
            Item {
                anchors.fill: parent
                Column {
                    Text {
                        text:title
                    }
                    Text {
                        text:description
                    }
                }
            }
        }

    ListView {
        id: weatherList
        anchors.fill: parent
        model: weatherModel
        delegate: weatherDelegate
    }
}

Consumiendo XML con QML

Development , , No response

Novedades desde la MeeGo Conference 2010

November 17th, 2010

MeeGo Conference 2010 ready!
Photo Credits: Quim Gil – Photo License: AttributionShare Alike Attribution, Share Alike

Entre ayer y hoy en Dublin se llevo a cabo la MeeGo Conference 2010, con un concurrencia de mas de 1000 developers y con muchas novedades desde el principio, quizás la noticia mas importante la dio AMD anunciando su ingreso al proyecto, algo lógico de cara al próximo lanzamiento de sus procesadores AMD Zacate orientados al mercado de la netbooks, mercado en el cual Intel quiere empezar a posicionar a MeeGo el año que viene.

También se hizo el anuncio de que para el próximo año se van a realizar dos MeeGo Conferences las primera de ellas en Mayo en San Francisco que va a estar orientada a los partners de hardware y la segunda se realizara a finales de año y estará enfocada en los developers, ademas de estos anuncios se pudieron ver los planes para las próximas versiones de Qt y Meego.

Pasando a las charlas, la temática ha sido variada, tocando todas las versiones de MeeGo (Netbook, Handset, Connected TV e IVI) y por suerte todas ellas han sido grabadas, en este momento ya se encuentran disponibles los vídeos de casi todas las charlas dadas el Día 1 y próximamente estarán disponibles las del Día 2, pueden ver el listado de las mismas aquí, para ver los vídeos o bajar los slides solo hagan click en la charla de su interés, sino pueden ir a la pagina de la Linux Foundation donde también se han subido los vídeos.

Como verán, la comunidad y las empresas que giran en torno de MeeGo no paran de crecer, así que les dejo algunos links con recursos por si están interesados en investigar mas y probar MeeGo.

Community , , , , No response

Accediendo a MySQL con node.js

November 12th, 2010

Es muy extraño ver una aplicación node.js que no haga uso de una solución NoSQL, pero puede presentarse el caso de tener que acceder a una base de datos legacy y casi con seguridad esa DB sea MySQL, el estado de los modulos MySQL en node.js, es muy dispar, pero hay un proyecto liderado por Felix Geisendörfer al que vengo siguiendo desde hace un tiempo, es al que mas fe le tenia, mas que nada, porque cuenta con el patrocinio de Joyent que ha tomado a node.js como algo estratégico para su plan de negocios.

El modulo que estoy usando es node-mysql, el cual es una implementación del protocolo MySQL escrito 100% con node.js, la forma mas fácil de instalarlo es usando npm.

# Instalando node-mysql y sus dependencias vía npm
npm install mysql

El modulo aunque ya esta siendo usando por algunos en producción y las funcionas básicas ya están implementadas, no esta etiquetado como estable, así que hay que tener un poco de cuidado si se quiere hacer uso de el.

Pasemos al ejemplo, como se ve en el código a continuación, la primera parte se encarga de cargar el modulo y todo lo relacionado a la conexión a la DB, luego paso la consulta que quiero ejecutar haciendo uso de client.query y para terminar creo una función que se encargara de mostrar los resultado en la consola o tirar un mensaje de error si algo no va bien.

var Client = require('mysql').Client,
    client = new Client();  
	client.user = 'root';
	client.password = 'password';
	client.host='127.0.01';
	client.port='3306';
	client.database='Oranje'
	client.connect();

	client.query(
		'SELECT * FROM players WHERE name LIKE "Minke%"',
        function selectPlayers(err, results, fields) {
            if (err) {
                console.log("Error: " + err.message);
                throw err;
            }
            console.log("Number of rows: "+results.length);
            console.log(results);
            client.end();
        });

En la siguiente screenshot pueden ver la salida de datos en la consola.

Accediendo a MySQL con node.js

En github pueden encontrar mas información acerca del proyecto, ademas de la documentación.

Development , 8 responses

Integrando QML y Javascript

November 11th, 2010

Una de las características interesantes de QML es la posibilidad de usar Javascript para agregar funcionalidades extras de forma rápida y fácil, básicamente contamos con un entorno igual al que se encuentra en cualquier browser moderno con algunas pequeñas adiciones.

Vamos a comenzar con un ejemplo simple, la idea de este ejemplo es crear una app que muestre numero aleatorios cuando se presione la barra espaciadora o cuando se haga click sobre el elemento Text que mostrara los numeros.

Javascript Inline

Para comenzar vamos a mostrar como integrar el código Javascript de forma inline, esta practica se aconseja siempre y cuando el código a añadir no sea muy extenso, ya que sino la legibilidad y mantenibilidad del código se resiente.

Pasemos ahora al código, en un nuevo proyecto pegamos el siguiente código, como verán luego de declarar un Rectangle y dentro del mismo, agregue un función que genera números aleatorios en este caso hasta el numero 100, luego viene el elemento Text encargado de mostrar el numero aleatorio, el cual contiene un MouseArea que cuando se dispara el evento onClicked toma un numero generado por la función Javascript y se lo asigna al elemento Text, lo mismo pasa a continuación con la función Keys.onPressed seteada para dispararse cuando se presiona la barra espaciadora.

Numerator.qml
import Qt 4.7

Rectangle {
    width: 640
    height: 360
    id:container

    function rand (n){
        return (Math.floor(Math.random() * n + 1));
    }

    Text{
        id: start
        text: "click!"
        font.pointSize: 128
        font.family: "Arial"
        font.bold: true
        color: "#cc0000"
        focus: true
        anchors.horizontalCenter: container.horizontalCenter
        anchors.verticalCenter: container.verticalCenter

        MouseArea {
            id: mouseRegion
            anchors.fill: start
            onClicked: {
                start.text = RandomFunctions.rand (100);
            }
        }

        Keys.onPressed: {
            if (event.key == Qt.Key_Space) {
                start.text = rand(100);
            }
        }
    }
}

Javascript Standalone

Cuando el código Javascript crece en tamaño o si se quiere mantener todo mas ordenado la opción es poner el código Javascript en uno o mas archivos separados, si vamos al caso de nuestro ejemplo podemos mover la función que genera los numero aleatorios a un archivo aparte, en este caso yo lo llame generator.qml, un tip a tener en cuenta es que por convención los nombres de los archivos .js deben comenzar con minúscula.

generator.js
function rand (n){
      return (Math.floor(Math.random() * n + 1));
}

Para poder hacer uso de las funciones ubicadas en un archivo separado debemos hacer un import con la ruta del archivo .js y setear un “alias” el cual debe ser único para cada archivo que importemos, este “alias” lo usaremos para poder invocar las funciones que albergue el archvio .js, un ejemplo de ello pueden verlo en el MouseArea o en la Keys.onPressed del código a continuación.

Numerator.qml
import Qt 4.7
import "generator.js" as RandomFunctions

Rectangle {
    width: 640
    height: 360
    id:container

    Text{
        id: start
        text: "click!"
        font.pointSize: 128
        font.family: "Arial"
        font.bold: true
        color: "#cc0000"
        focus: true
        anchors.horizontalCenter: container.horizontalCenter
        anchors.verticalCenter: container.verticalCenter

        MouseArea {
            id: mouseRegion
            anchors.fill: start
            onClicked: {
                start.text = RandomFunctions.rand (100);
            }
        }

        Keys.onPressed: {
            if (event.key == Qt.Key_Space) {
                start.text = RandomFunctions.ran (100);
            }
        }
    }
}

Como verán el integrar Javascript con QML es muy fácil y nos permite potenciar las posibilidades de QML, en la documentación oficial pueden encontrar mas información, ejemplos y buenas practicas para aplicar a nuestros desarrollos.

Development, User Interface , , , No response