Saturday, October 4, 2008

MItem

Bueno, pues después de oir las duras críticas de Óscar, Magmax y las mías propias le he hecho algunos cambios al ModelCol. No supone un cambio muy importante, de hecho internamente no hay ningún cambio, solo en el API.

Lo primero es que ha cambiado de nombre, ahora se llama MItem, que viene a ser algo así como "elemento del modelo". Si el modelo es una tabla, el MItem puede describir una columna, que es el caso habitual, pero también se podría ver como una fila si se requiere.

No está ligado a TreeModel o TreeView, ni siquiera a GTK. A pesar de ello, lo voy a describir como el modelo de ListStore para que la explicación no quede tan abstracta. El MItem tiene los siguientes campos (todos opcionales):

  • title (str): Es el título de la cabecera de la columna.

  • render (str): Identifica al encargado de representar el dato en ese columna (en el caso de TreeView, será un CellRenderer). Si no se indica, el render por defecto es "text". El significado real del render depende del encargado de representar el modelo, por ejemplo, el skin_list.

  • id (int). Es una prioridad para esa columna. Lo usamos para crear los índices de ordenación. El "id" más alto es la columna de ordenación por defecto. Si una columna no tiene "id", no se puede ordenar por ella.

  • var (bool). Indica (si es True) que para una misma fila, los valores de esa columna pueden cambiar con el tiempo. Por ejemplo, en un inspector que muestra la lista de unidades de disco, la columna de "espacio libre" sería "var". Si no se indica, es "False" por defecto.

Los parámetros de MItem se indican como un diccionarios (kargs que se dice en Python). A parte de los anteriores, se pueden indicar como clave cualquier palabra que pueda ser utilizada para identificar una propiedad de la columna que describe, en nuestro caso, hasta ahora solo los hemos utilizado para indicar propiedades de los CellRendereres de los TreeViewColumn.

El valor de esas propiedades se puede indicar de dos modos:
  • Por instancia (o fila). En este caso, el identificador va precedido de un guión bajo (_nombre) y el valor es el nombre de un atributo de un objeto del modelo. Cada fila tiene un valor propio para esa propiedad. Suena complicado, pero en los ejemplos vais a ver que es muy sencillo.

  • Fijo (por columna). En este caso, el identificador debe ir precedido de un doble guión bajo (__nombre). El valor indicado se interpreta como un literal y se aplica a toda la columna.

Limitaciones

  • Los nombres de las propiedades no pueden empezar por guión bajo.
  • Los nombres de las propiedades tienen que ser identificadores Python válidos. En el caso de propiedades gobject, como "stock-id" el consumidor del metamodelo deberá hacer las transformaciones oportunas.

Ejemplos:

Voy a poner la versión MItem de los mismos ejemplo que para ModelCol. Si los comparáis veréis que el interfaz es más genérico y para el mismo caso es más corto casi siempre.

MItem(title='Name')
- Etiqueta de la columna: 'Name'
- Renderer: 'text'
- Asignar a la propiedad 'text' del renderer, el valor del atributo 'Name'

MItem(title='Name', _text='filename')
- Asignar a la propiedad 'text' el valor del atributo 'filename'

MItem(title='Name', id=10)
- Ordenar por esta columna, prioridad: 10

MItem(title='Value', _text='val', __xalign=1)
- Asignar a la propiedad 'text' el valor del atributo 'val'
- Justificar el texto de esta columna a la derecha

MItem(title="Level", _markup="level", id=10)
- Asignar a la propiedad 'markup' el valor del atributo 'level'
- Ordenar por esta columna, prioridad: 10

MItem(title='Variable', _text='key',
__background='gray', __background-set=True)
- Asignar a la propiedad 'text' el valor del atributo 'key'
- Fijar color de fondo de esta columna a 'gray'

MItem(render='pixbuf', __stock-id='gtk-file')
- Columna sin título
- Renderer: 'pixbuf'
- Fijar la propiedad 'stock-id' a 'gtk-file' para cualquier fila

MItem(title='Identity', _text='key', _markup='format')
- Asignar a la propiedad 'text' el valor del atributo 'key'
- Asignar a la propiedad 'markup' el valor del atributo 'format'

MItem(render='pixbuf', _stock-id='icon')
- Columna sin título
- Renderer: 'pixbuf'
- Asignar a la propiedad 'stock-id' el valor del atributo 'icon'

MItem(title="Installed", render="toggle", _active='installed',
__activatable=True)
- Renderer: 'toggle'
- Asignar a la propiedad 'active' el valor del atributo 'installed'
- Fijar la propiedad 'activatable' a True para todas las filas

Thursday, September 18, 2008

Chrome tabs?

En los primeros prototipos de twinpanel, teníamos la "barra de direcciones" dentro de la página del notebook pero la barra de herramientas fuera. Pensamos que por "usabilidad" era mejor dejar las dos cosas fuera del notebook como hacen (hacían) todos los navegadores.

El problema es que eso complica un poco la construcción del interfaz, porque al cambiar de solapa hay que configurar tanto la uri como la barra de botones de acuerdo al panel activo. Luego salió Google Chrome con su diseño "innovador" y me lo estoy volviendo a plantear: solapas arriba o solapas abajo? Tened en cuenta que de hacer el cambio, TwinPanel tendría una barra de herramientas y otra de URI en cada "side", lo que obviamente nos hace desperdiciar algo de espacio en la interfaz (no mucho).


by Google Chrome

Monday, September 1, 2008

ModelCol

Como ya explicaba hace tiempo disponemos de un sistema muy versátil y sencillo para construir TreeView, gracias a los skin_list y skin_treeview y una especificación desacoplada del modelo (un metamodelo). Hasta ahora hemos podido implementar cualquier listado utilizando unicamente estos dos skins independientemente del número de columnas o su tipo. Un metamodelo está formado por una lista (vector de Python) de instancias de la clase ModelCol. Nombre muy largo por cierto, seguramente lo renombraré a MCol o algo más corto.

Lo siguiente es una lista de ejemplos de uso de ModelCol comentados. Quede aquí para futuras referencias. Este mismo listado lo meto en el fichero HowTo.ModelCol que está(rá) en el repo, y que iré ampliando.


ModelCol(title='Name')
- Etiqueta de la columna: 'Name'
- Renderer: Text
- Asignar a la propiedad 'text' del renderer, el valor del atributo 'Name'

ModelCol(title='Name', attr='filename')
- Asignar a la propiedad 'text' el valor del atributo 'filename'

ModelCol(title='Name', id=10)
- Ordenar por esta columna, prioridad: 10

ModelCol(title='Value', attr='val', static={'xalign':1})
- Asignar a la propiedad 'text' el valor del atributo 'val'
- Justificar el texto de esta columna a la derecha

ModelCol(title="Level", attr="level", id=10, prop='markup')
- Asignar a la propiedad 'markup' el valor del atributo 'level'
- Ordenar por esta columna, prioridad: 10

ModelCol(title='Variable', attr='key', static={'background':'gray',
'background-set':True})
- Asignar a la propiedad 'text' el valor del atributo 'key'
- Fijar color de fondo de esta columna a 'gray'

ModelCol(render='pixbuf', static={'stock-id':'gtk-file'})
- Columna sin título
- Renderer: pixbuf
- Fijar la propiedad 'stock-id' a 'gtk-file' para todas las filas

ModelCol(title='Identity', attr='key', props={'markup':'format'})
- Asignar a la propiedad 'text' el valor del atributo 'key'
- Asignar a la propiedad 'markup' el valor del atributo 'format'

ModelCol(attr='icon', render='pixbuf', prop='stock-id')
- Columna sin título
- Renderer: Pixbuf
- Asignar a la propiedad 'stock-id' el valor del atributo 'icon'

ModelCol(title="Installed", render="toggle", prop="active", attr="installed",
static={'activatable': True})
- Renderer: Toggle
- Asignar a la propiedad 'active' el valor del atributo 'installed'
- Fijar la propiedad 'activatable' a True


Aunque tiene muchas posibilidades, no es la panacea. Le faltan algunas cosas, pero creo que se podrá hacer sin demasiado problema. En especial:

- Soporte para desactivación/ocultación de columnas del modelo, a elección del usuario. Esto requiere un gestor de configuración que es en si mismo todo un reto (hablaremos de esto otro día)
- Soporte para formato de las columnas. Los datos se almacenan en crudo en el modelo. Por ejemplo, las fechas se almacenan en tiempo UNIX. Es el usuario el que elige el formato en el que desea que se representen (año-mes-día, mes-año, con hora, GMT, etc). De nuevo esto tiene mucho que ver con el gestor de configuración.

Después de lo cual concluyo que el soporte de ModelCol y de los skins es casi lo de menos. Necesitamos un gestor de configuración, que por la pinta va a ser casi tan complejo como el propio TwinPanel... mañana hablamos del tema...


PD: Una de las limitaciones que comentaba en el post de "probando, probando" está solventada como veis en los ejemplos. Me refiero a la que decía:
Cada elemento del metamodelo sólo puede afectar a un atributo de la columna correspondiente. Esta puede que sea una limitación inadmisible, habrá que discutirlo. Puede que en este caso esté justificado enriquecer el metamodelo para hacerlo posible.


PD: No dejéis esa cantidad abrumadora de comentarios que se me van a quitar las ganas de seguir escribiendo ;-)

Sunday, August 31, 2008

Seguimos vivos

A pesar de que el blog ha estado completamente parado durante prácticamente un año, el desarrollo de TwinPanel ha avanzado muchísimo. Aunque ha habido altibajos, el desarrollo no ha estado completamente parado en ningún momento. Gran parte de la culpa de la "desconexión" con el blog se debió al cambio de gnome-vfs a GIO por parte de GNOME.

Como ya comenté, decidimos utilizar gnome-vfs como backend para todos los inspectores relacionados con el sistema de ficheros, sftp, ftp, samba y demás. Al producirse el cambio a GIO, decidimos dejar en suspenso el desarrollo de esos inspectores hasta que estuvieran disponibles los bindings de Python para GIO, que por fin ha llegado. No pensé que tardaran tanto...

Aunque hay disponibles algunos inspectores funcionales, tengo claro que son demasiado específicos como para que TP pueda llamar la atención de potenciales usuarios beta-testers. Sin duda, disponer de los inspectores básicos de manejo de ficheros (gracias a GIO) permitirá dar un uso cotidiano a TP y podremos plantearnos en breve lanzar una primera release funcional que pueda descargarse, instalar y usar cualquiera que tenga interés en ello.

En breve escribiré un post hablando del diseño de TP, que en esencia ha seguido las directrices iniciales. También está en la recamara otro post sobre el sistema de instlación de plugins y su interacción con el sistema de gestión de paquetes de la distro. Óscar está escribiendo un tutorial para desarrollar un inspector desde cero. Espero que sea la primera piedra del futuro "Manual de TwinPanel para Desarrolladores". Y no menos importante, en los próximos días subiremos al repo de GNA! la primera versión funcional del core de TwinPanel y algunos inspectores y skins(las antiguas "vistas") para ir abriendo boca.

Hasta pronto.

Monday, August 18, 2008

¿Sabias que... usamos python-sexy?

Si instalas el paquete python-sexy, ciertos widgets tendrán una apariencia y herramientas diferentes. Por ejemplo, es común que el 'GtkEntry' que aparece en los mensajes de error ahora tenga un icono para copiar la URI malformada y pegarla donde desees.