clase TTagEver para FivewinHarbour

Una funcionalidad que quería implementar en el Puchero es la gestión de dietas y tolerancias de las recetas. Es decir que para cada receta se pueda poner si es adecuada para gente con colesterol, celíacos, o para dietas de puntos, Dunkan o lo que sea. Esto supone que cada receta podía llevar asociadas múltiples dietas y la verdad es que no tenía claro cómo hacerlo. Muchas veces lo principal no es la funcionalidad sino como se implementa esta funcionalidad lo que hace que esta sea aceptada por los usuarios o no.

El caso es que dándole vueltas a la cabeza recordé el sistema de etiquetado de documentos que usa Evernote. Algo así:

En FWH hay una clase llamada TTagCloud que podía servirme como base. Esta clase la hizo Francisco García Fernández, que creo que es un gran creador de controles para FWH y además un buen amigo mio. Estuve varias semanas dándole vueltas al control sin conseguir avances significativos, hasta que me puse en contacto con Paco para pedirle ayuda. Paco en un par de días hizo el control, y ahora en el Puchero tengo hecha la implementación de las dietas de esta manera.

Aspecto de la clase TTagEver

La clase desarrollada por Paco está disponible en el siguiente repositorio de GitHub: https://github.com/JoseluisSanchez/TTagEver

Mil gracias Paco.

exportando datos a excel

Uno de los pequeños detalles que me faltaban en la actualización de Findemes en la que estoy trabajando era el tema de la exportación de datos a Excel. Es muy útil que cualquier programa permita la exportación de datos para que se puedan tratar en una hoja de cálculo, pero en el caso de un programa de contabilidad personal este aspecto toma mayor relevancia.

2013-04-23_160200

La manera más sencilla de exportar los datos de un xbrowse de FWH a Excel es usar el método toExcel() de la clase, sin embargo esta manera de realizar la exportación presenta algunos problemas. El primero es que la exportación se hace a través del propio Excel, o sea que el usuario tiene que tener Excel instalado, supuesto que no siempre se cumple. El segundo es no he conseguido que la exportación de datos numéricos se realice correctamente. Al pasar un número con formato 999.999,99 a Excel se transforma en 999999.99 con lo cual no se puede operar correctamente con él en la versión en español del programa. El porqué de este cambio escapa a mis conocimientos, pero creo que es debido a los cambios de formato que se utilizan internamente en la clase para la exportación.

2013-04-23_160142

Ante estos problemas recordé haber leído un post en el foro de FWH donde Rafa TheFull había publicado una manera diferente de realizar la exportación. En el post Rafa, que se puede leer en http://forums.fivetechsupport.com/viewtopic.php?f=6&t=19897, habla de los problemas para generar el fichero XLS a través del propio Excel y que no existe la seguridad de que esta manera de realizar la exportación funcione en todas las instalaciones. Ante esto, Rafa propone utilizar la clase XlsFile de Ramón Avendaño, un programador que en su día realizó muchas contribuciones a FWH. El método usado por esta clase consiste en crear un fichero desde cero, escribiendo todos los caracteres necesarios para crear un fichero en formato XLS puro, sin pasar por Excel. El fichero generado se puede abrir con Excel o LibreOffice.

2013-04-23_160417

Al comenzar a utilizar la función de Rafa, me encontré con el problema de la exportación de las columnas en que se muestra una imagen. La manera que he encontrado de de solucionarlo es usar la variable cargo que existe en todas las clases para asignar el valor que se va a mostrar en la exportación y luego comprobar que cuando el tipo de la columna sea de tipo definido por el usuario mostrar la variable cargo. Algo así:

elseif Valtype( cText ) == "U"
@ nFila, nCol XLS SAY oBrw:aCols[x]:Cargo OF oXls

Con esto consigo una exportación más completa que usando el método de la clase, que se realiza independientemente de los programas que tenga instalado el usuario y que se puede abrir con varios editores de hojas de cálculo.

colores en xbrowse

En la actualización de Findemes que estoy preparando he cambiado el aspecto del programa para dotarlo del look de Windows 7 y uno de los cambios introducidos es poner el pintado de las rejillas de datos con el degradado de Windows 7. Como en Findemes las lineas de apunte se pintan de distinto color en función de si son ingresos o gastos para hacer el pintado correctamente hay que modificar el método oBrw:bClrStd de la siguiente manera:


oApp():oGrid:bClrStd := {|| { iif( AP->ApTipo == "I", oApp():cClrIng, oApp():cClrGas ), CLR_WHITE } }

El resultado es el siguiente:

fdm_browse1

Sin embargo hay un problema: el pintado de los colores de ingreso y gasto es correcto en todas las lineas excepto en la linea seleccionada. En esta linea el texto sigue apareciendo en el color por defecto de browse que es el negro. Para que el efecto sea completo hay que modificar el método oBrw:bClrSelFocus de la siguiente manera:


oApp():oGrid:bClrSelFocus := { || { iif( AP->ApTipo == "I", oApp():cClrIng, oApp():cClrGas ),;
{ { 1, RGB( 220, 235, 252 ), RGB( 193, 219, 252 ) } } } }

Ahora el pintado ya es el deseado.

fdm_browse2

resedit

Con el cambio de versión de Windows a Seven, decidí evaluar alternativas a PellesC como editor de recursos. El principal motivo era que PellesC llevaba tiempo dando errores, al final de manera bastante habitual, y también a mi intención de eliminar de mi PC todo aquello que no usase. ¿ Para que quería un compilador de C completo si sólo usaba el editor de recursos ? Ya tengo instalado BCC que es el que uso para compilar cl código C generado con xharbour, así que un compilador de C es suficiente.

Así que decidí probar seriamente un editor de recursos llamado ResEdit que llevaba tiempo siguiendo. Este editor de recursos tenía una característica que llevaba tiempo deseando usar, y que PellesC no tenia, y es un asistente interactivo de alineación de los controles. Esta característica está presente en muchos editores de formularios avanzados, y va mostrando la alineación de un control cuando se coloca o se mueve en el formulario respecto al resto de controles. Realmente es muy útil y permite ajustar los controles de un formulario rapidamente. Otra característica que me gusta mucho de ResEdit es la ordenación automática de los controles para tabulación, que también ahorra mucho tiempo.

El archivo RC que genera ResEdit lo puede convertir a formato RES con el comando BRC del compilador C de Borland que uso habitualmente y luego lo enlazo con mi código objeto para generar los ejecutables sn problemas.

my tools of the trade – windows edition

Vía Joel on Software llegué al blog de UCOSP donde me llamó la atención el post My tools of the trade. Es una lista de aplicaciones preferidas a la hora de programar, y hay varios enlaces a otros blogs de programadores donde dan cuenta de sus preferencias, entre ellos Mike Gunderloy que es un antiguo evangelista de .Net que se ha pasado al bando de Ruby on Rails, haciendo una pirueta realmente espectacular. Estas listas de aplicaciones favoritas me gustan porque siempre aparece alguna aplicación cuya existencia desconoces y que te puede resultar interesante utilizar.

Como la lista de aplicaciones se hace en un entorno de desarrollo profesional, voy a hacer la mia para entorno Windows. Realmente en Mac todavía no he hecho nada serio, y reconozco que la programación en entorno Mac es mi asignatura pendiente. Aqui va mi lista de herramientas.

En cuanto a hardware, utilizo un iMac de 17″, el modelo de principios de 2007, con 2GB de RAM y disco de 250GB. El teclado que venía con el iMac no me gustaba y tuve la suerte de que me regalaron un teclado de aluminio, y puedo decir que es el teclado más cómodo que he usado en mi vida. El ratón es el Mighty Mouse de cable que venía de serie. Además uso un disco duro externo Lacie para hacer copias de seguridad y un lapiz USB de 4GB. Tengo Windows XP instalado en una partición del disco mediante BootCamp y me va de cine. Intento no instalar aplicaciones para probar en este Windows, sino que uso una máquina virtual con VirtualBox con otro XP donde hago todas los experimentos que no me atrevo con el de trabajar.

Software de desarrollo xBase:

  • xharbour, fivewin harbour y las clases de CanalFive.
  • PellesC como editor de recursos.
  • HippoEdit mi editor preferido, ya no uso otro.
  • Free UPX para comprimir los ejecutables.
  • OZS WinDbu para editar ficheros DBF
  • Inno setup para montar los paquetes de instalación.

Otro software:

Cada vez uso menos programas. Antes me pasaba el día probando aplicaciones, pero cada vez hago esto menos. Hace mucho tiempo que no instalo nuevo software en Windows, simplemente no lo necesito y me apaño con lo que tengo. Cosas del decluttering.

Hasta aquí el software que uso en Windows. A ver si los lectores del blog os animais a hacer un post similar y publicais el enlace en los comentarios.

compilación condicional

La compilación condicional es una característica de los lenguajes que usan preprocesador y permite incluir un determinado trozo de código en la compilación en función de una directiva de compilación.  En xHarbour podemos definir una directiva de compilación usando el flag -d al invocar al compilador, de esta manera:

xharbour miprograma.prg -d__directiva__

Dentro de nuestro programa usaremos la sentencia #ifdef para indicar que acción ejecutaremos en caso de tener definida la directiva de compilación:

#ifdef __directiva__Accion1() #else Accion2() #endif

Si al compilar el programa tendremos definida la __directiva__ en el ejecutable unicamente se incluirá la llamada a Accion1(), mientras si no la tenemos definida sólo se incluirá la llamada a Accion2().La pregunta del millón es: ¿ en que difiere esto de usar una variable de nuestra clase aplicación o una variable global ? Pues que si hacemos esto estamos dejando rastro de lo que hacemos, en el ejecutable se incluye la sentencia condicional y se ejecuta cada vez que corre la aplicación. Con la compilación condicional no introducimos la sentencia condicional en el ejecutable, sino unicamente la acción deseada en función de si la directiva está o no presenteal compilar.Usando la compilación condicional es muy sencillo crear versiones distintas de un mismo programa con un mínimo esfuerzo, con la particularidad de que no dejamos ningún rastro en nuestro programa de que tenemos distintas versiones del mismo.

autocompletado en FWH

Prologo: Quitando comboboxes – hace seis años.

En el caso de campos que son claves ajenas sobre otras tablas, pienso que se debe combinar la facilidad de la introducción de los datos correctos con la capacidad para dar de alta valores nuevos en la tabla auxiliar de una manera directa, y esto último no se puede hacer con comboboxes. Para ello utilizo una combinación de cuadro de texto donde el usuario escribe el valor del campo, y un botón que muestra un formulario de selección de valores. Si el usuario quiere escribir el valor de la clave ajena lo puede hacer directamente y el programa lo valida sobre la tabla auxiliar. Si el valor no está dado de alta en la tabla auxiliar el programa pregunta si se quiere dar de alta, y en caso afirmativo presenta el formulario de alta de la tabla auxiliar. Si el usuario no quiere escribir el valor, puede usar el botón que muestra el formulario de selección y elegir un valor o darlo de alta.Esta manera de hacer las cosas está bien, pero no es perfecta. Como me han comentado varios usuarios de mis programas, lo correcto sería que funcionase un autocompletado del campo de texto sobre el campo que es clave ajena en el mismo. Teclear los valores cada vez es pesado y lleva a errores si no recuerdas como has dado de alta cada valor. Por otra parte el soltar el teclado para hacer click en el botón y seleccionar el valor es un engorro que te hace perder tiempo, sobre todo si tienes que dar de alta muchos registros.

Fisgoneando por los foros de Fivetech encontré una clase TAutoGet que hace precisamente esto, un autocompletado sobre un array donde previamente se han introducido los valores. Incorporar esta clase a un programa es muy sencillo, basta con cargar los valores de los arrays de autocompletado antes de editar el campo correspondiente. Los resultados son espectaculares. Conforme tecleas las primeras letras del valor, te van apareciendo los valores que coinciden coon ellas. Una vez tienes el valor que quieres, con un tab validas el nombre y saltas al siguiente campo. Es mucho más cómodo que soltar el teclado, hacer click en el botón de al lado y ponerte a buscar el valor que quieres introducir. Pocas veces una clase tan pequeña me ha dado unos resultados tan espectaculares. Pura dinamita.

Para los perezosos de visitar el foro de Fivetech dejo un fichero con la clase TAutoGet completa: código fuente, fichero de preprocesado y un pequeño ejemplo, todo sacado del foro. Tengo ya el autocompletado implementado en Findemes, y estará disponible en la próxima versión que vamos a publicar el breve. Ahora estoy pensando en si el autocompletado irá en la edición gratuita o unicamente en la registrada, pero eso es otra historia.

msgbox a la windows vista

En mis programas tengo los mensajes del sistema personalizados. De esta manera controlo que mis programas siempre muestren los típicos mensajes de confirmación, información, alerta y parada de la misma manera en todas las versiones de Windows. También uso mis propios iconos para los mensajes, sacados de las colecciones de iconexperience que uso también en mis programas. De esta manera consigo uniformidad en los programas.

En Windows Vista los mensajes del sistema presentan un aspecto distinto a las anteriores versiones de Windows. Además de los iconos característicos de la nueva versión de Windows, el formulario está visualmente dividido en dos zonas, la de arriba es blanca y contiene el icono y el texto del mensaje, mientras que la parte de abajo es del color habitual del formulario y contiene el botón o botones del mismo.Con FWH es fácil hacer un formulario de estas características usando el control Pages. No hay más que definir el formulario con un control pages donde va la zona blanca y luego crear otro formulario que se solapará encima del anterior. La definición del formulario principal en el fichero RC es de la siguiente manera:

UT_INFO DIALOG DISCARDABLE 29, 34, 206, 88
STYLE WS_POPUP|DS_MODALFRAME|WS_CAPTION|WS_SYSMENU
CAPTION "Cuaderno de Bitácora"
FONT 8, "Ms Sans Serif"
{
  CONTROL "&Aceptar", IDOK, "Button", BS_DEFPUSHBUTTON|WS_TABSTOP, 144, 66, 50, 16
  CONTROL "", 110, "Static", SS_WHITERECT, 0, 0, 206, 60
}

El control que va a contener el control page es el identificado con 110. La definición del formulario que va dentro del control Page del formulario principal es como sigue:

UT_INFO_PAGE DIALOG DISCARDABLE 77, 112, 203, 60
STYLE WS_CHILD|WS_CLIPCHILDREN
FONT 8, "MS Sans Serif"
{
  CONTROL "", 10, "Static", WS_GROUP, 48, 8, 142, 44
  CONTROL "", 111, "TBitmap", 0x00000000, 8, 4, 36, 36
}

El código de la función que muestra el formulario es el siguiente:

FUNCTION msginfo(cText, cCaption)
   LOCAL oDlgInfo, oPage
   LOCAL oBmp

   DEFAULT cCaption := oApp():cAppName+oApp():cVersion

   DEFINE DIALOG oDlgInfo RESOURCE "UT_INFO" TITLE cCaption
   oDlgInfo:oFont  := oApp():oFont

   REDEFINE PAGES oPage ID 110 OF oDlgInfo ;
      DIALOGS "UT_INFO_PAGE"
	oPage:oFont := oApp():oFont

   REDEFINE SAY PROMPT cText ID 10 OF oPage:aDialogs[1]
   REDEFINE BITMAP oBmp ID 111 OF oPage:aDialogs[1] RESOURCE "xpinfo" TRANSPARENT

   REDEFINE BUTTON ID IDOK OF oDlgInfo  ;
      ACTION oDlgInfo:End()

   ACTIVATE DIALOG oDlgInfo ;
      ON INIT oDlgInfo:Center( oApp():oWndMain )

RETURN Nil

con lo que conseguimos un formulario como el siguiente:

sobre objeto persistente

Uno de los blogs que leo habitualmente es Objeto Persistente, de mi amigo el troesma René Flores. René es uno de los grandes gurús de los lenguajes Xbase, colaborador habitual de los distintos foros de xharbour y de FivewinHarbour y Xailer. Tiene unos conocimientos enciclopédicos sobre Xbase desde los tiempos de Nantucket, que ya es decir, y sus contestaciones llegan casi al nivel de clase magistral sobre el tema. Tuve la suerte de conocerle personalmente en una reunión de Olivares2000 y es una personal que habla por los codos. Pero lo que me remató fue oirle la traducción simultanea al inglés que le hacía a Patrick Mast de las ponencias de la reunión.

Hay un par de post suyos recientes que me han llamado la atención. Uno es programar con Visual Basic es obsoleto donde le hace un repaso a las versiones de VB y expone que programando con Xbase y sus GUI tiene mejor tecnología que con VB. En el otro, divagaciones sobre el mundo linux da su visión acerca de linux, y expone el motivo por el que no hay aplicaciones empresariales para linux.

No es cuestión de ir punto por punto refutando lo que dice René, pero creo que se equivoca. No se si VB es obsoleto, pero si tengo claro que xHarbour no es un lenguaje innovador. La comunidad de desarrolladores de xHarbour, que es un lenguaje open source, ha hecho un trabajo impresionante en los ultimos años para modernizar el lenguaje, pero todavía le queda tela para ponerse al nivel de Java, Python o C# por poner ejemplos. xHarbour ha clonado los modelos de objetos de estos lenguajes, pero ni tenemos espacios de nombres, ni pruebas unitarias, ni patrones ni servicios web, ni otras características de los lenguajes modernos. Es cierto que tenemos GUI con IDE que si están a la altura de lo que hay por ahí, pero creo el mundo xbase ahora mismo copia de otros lenguajes, y no al revés.

Y sobre Linux… pues creo que hace falta ir cambiando el chip. Ahora mismo es Windows quien copia de otros entornos, y no al revés, lo que nos hace darnos una idea que quien va por delante de quien. Cuando dije que quería comprarme un iMac recuerdo que alguien me dijo si pensaba pasarme al otro lado. Ahora que estoy en los dos lados, me doy cuenta de que la luz está precisamente al otro lado, y que en Windows vemos las sombras de lo que hay en el lado de la luz. Recuerdo que fue precisamente René quien llevaba en su portatitl Windows un dock como el de OS X. Windows anda perdiendo terreno entre los desarrolladores, tal como publicaba hace poco InfoWorld. Casi todas las empresas que conozco que hacen desarrollo para la web usan Linux u OS X, y cada dia más gente se plantea dar el salto con los problemas que están teniendo con Vista. Mis CD de Ubuntu ya han pasado por varias manos y seguro que pasarán por mas.