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
}
}
]
}
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
}
}
November 17th, 2010
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.
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.
En github pueden encontrar mas información acerca del proyecto, ademas de la documentación.
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.