gvSIG 2.2 RC1: help us to test the first gvSIG 2.2 Release Candidate distribution

testingSuch as it was planned, the first gvSIG 2.2 Release Candidate (gvSIG 2.2 RC1) is now available. It’s the moment at which the gvSIG Community help us to test and refine this version in order to get the final version as soon as possible.

You can download this version from here.

Besides a huge quantity of fixed errors, the main new features that you can find at this version are:

  • New editing extension, including new functionalities, and improvements respecting the previous version.
  • Labelling by scale
  • Legend by scale
  • Hyperlink to folders
  • OGC services publishing
  • Seismic formats
  • Sailing symbols library

We are interested in the testing of the new editing extension specially, since it supposes a big change respecting the previous version and, therefore, it can be a source of non identified errors.

Any error that you find can be sent to the mailing list.

In parallel to the development of this version a new manual has been created. At this moment this manual is available in Spanish, but it’s been translated to English, French and Portuguese. If you want to collaborate in this translation you can contact to info@gvsig.com.

We encourage you to test the new gvSIG!

Thank you!

Posted in opinion | 1 Comment

gvSIG 2.2 RC1: ayúdanos a testear la primera distribución candidata a final

testingTal y como estaba previsto ya está disponible gvSIG 2.2 RC1, distribución candidata a final. Es el momento de que la Comunidad gvSIG nos ayude a testear y depurar esta versión para tener lo antes posible la final.

Podéis descargarla aquí.

Además de un considerable número de errores solucionados, las principales novedades que podéis encontrar en esta versión son:

  • Nueva edición incluyendo nuevas funcionalidades y mejoras considerables en usabilidad respecto a la anterior edición.
  • Etiquetado por escalas .
  • Leyendas por escalas .
  • Hiperenlace a carpetas.
  • Publicación servicios OGC.
  • Formatos de sísmica .
  • Biblioteca de símbolos de navegación.

Estamos interesados especialmente en que testéis la nueva edición, ya que supone un cambio notable respecto a la anterior versión y, por tanto, puede ser fuente de errores todavía no identificados.

Cualquier error que encontréis podéis enviarlo a través de la lista de usuarios.

En paralelo al desarrollo de esta versión se ha elaborado un nuevo manual.

¡Os animamos a testear el nuevo gvSIG!

¡Gracias!

Posted in community, development, gvSIG Desktop, spanish, testing | Tagged | 1 Comment

Testeando la nueva edición de gvSIG

Con gvSIG 2.2 llega una novedad importante que viene a mejorar considerablemente uno de los apartados que más lo requerían: las herramientas de edición.

Se ha desarrollado una nueva edición mucho más ágil, completa e intuitiva que estamos seguros que va a hacer de gvSIG un software mucho más potente.

Estamos ultimando los detalles para publicar la primera candidata a final de gvSIG 2.2, para la que os pediremos la máxima colaboración en testeo, especialmente con las herramientas de edición.

Para ir abriendo boca os dejo con un vídeo de un pequeño testeo que he realizado sobre una capa de polígonos.

Posted in gvSIG Desktop, spanish, testing | Tagged , | 9 Comments

Forma parte activa de la Comunidad gvSIG de tú país

Desde la Asociación gvSIG siempre hemos expresado nuestro deseo de que sea la comunidad la que lidere el proceso de crecimiento de este proyecto. Entendemos a la Comunidad gvSIG en un sentido amplio e inclusivo, con diferentes perfiles de colaboración, desde distintas zonas geográficas, interesados en temáticas diversas, para así llegar a cada rincón de nuestro planeta.

Creemos firmemente que cualquier persona puede contribuir a hacer más grande gvSIG. Hay un montón de maneras de involucrarse con la Comunidad gvSIG.

Por eso desde hace tiempo venimos impulsando la creación de Comunidades geográficas que ayuden a impulsar “desde el terreno” el modelo de desarrollo de geomática que propone gvSIG. ¿Qué Comunidades gvSIG están ya en marcha? Puedes echar un vistazo en el apartado de Comunidades de la web de gvSIG.

Hay Comunidades más activas que otras, casos de sinergias entre comunidades y un buen número de actividades que solo son posibles gracias a su trabajo, colaboración y solidaridad, como son las innumerables jornadas que se vienen desarrollando año a año.

Nuestros retos como proyecto son los más altos, y para ello necesitamos que las Comunidades existentes sigan creciendo y nuevas se vayan creando.

Con este post queremos animarte a que formes parte activa de la Comunidad de tú país. Y si no hay una Comunidad creada…¡anímate a formar una!

¡Contamos contigo!

Si estás interesado, puedes contactar con nosotros: info@gvsig.com

Posted in community, opinion, spanish | 1 Comment

Comienzo próximo del MOOC “Introducción a Scripting en gvSIG 2.1” en español gratuito

Sigue abierto el proceso de inscripciones de una nueva edición del MOOC gratuito “Introducción a Scripting en gvSIG 2.1” en español, organizado por la Asociación gvSIG, que dará comienzo el 4 de mayo de 2015.

El objetivo de este MOOC es el de dar a conocer un poco más sobre el potencial de la programación geoespacial, la posibilidad de crear nuevas herramientas, nuevos geoprocesos o análisis de datos, que nos aumentarán la potencia de gvSIG adaptándose a nuestras necesidades. También la automatización de tareas, que nos podrían generar un ahorro de tiempo y de trabajo considerable.

El curso estará en modalidad de inscripción gratuita y abierta, pudiendo inscribirse o completarse en el momento en que el alumno lo desee.

Para realizar este curso no se necesitan conocimientos previos sobre programación, será un nivel básico, además de explicar cada línea de código. El curso está realizado con el lenguaje de programación Python, el favorito para comenzar a programar, muy intuitivo y rápido de aprender.

Realizar este curso es completamente gratuito. Aquellos que lo completen y quieran recibir un Certificado de Aprovechamiento, correspondiente a 30 créditos del programa de Certificación de gvSIG, solo tendrán que aportar una contribución de 40 Euros, además de realizar un proyecto personal sobre un Script en gvSIG que será subido al Repositorio [1] y estará disponible para toda la comunidad.

Más información sobre el temario, inscripción, etc.:
http://web.gvsig-training.com/index.php/es/quienes-somos-2/noticias-2/140-massive-online-open-course-de-introduccion-a-scripting-en-gvsig-2-1

Para poder matricularse al curso se debe entrar en “Matriculación” al final de la página, y aceptar después el “Acuerdo con las Condiciones del Sitio”. Finalmente se debe realizar el registro.

[1] http://outreach.gvsig.org/scripts/

Posted in community, development, gvSIG Desktop, scripting, spanish, training | Tagged | 1 Comment

Free MOOC Cycle “GIS for Users” starting soon

We remind you that the registration period for the MOOC cycle “gvSIG for Users” in English, offered by gvSIG Association in collaboration with GISMAP, continues open.

This cycle is made up of three different Modules:

  • Module 1: “Introduction to GIS” (starting on the 4th of May 2015)
  • Module 2: “Layer Editing” (starting on the 25th of May 2015)
  • Module 3: “Raster Analysis” (starting on Autumn 2015)

It will lead participants to how to use and exploit the potentiality of the open source software gvSIG while performing the most common GIS activities. This Course is both addressed to beginners and skilled GIS users who want to learn how to use this software.

The Course is open in continuous form and each module requires a participants engagement of around thirty hours.

Participants can thus plan individually the time to allocate to the course and complete all the scheduled activities without interfering with their daily work.

This Course is completely free of charge except for those participants asking for the corresponding credits of the gvSIG user certification program from the gvSIG Association, that is submitted to the payment of 40 Euros for each module or 100 Euros for the whole cycle.

For further information about topics, goals…:
http://web.gvsig-training.com/index.php/es/quienes-somos-2/noticias-2/145-the-free-mooc-cycle-gvsig-for-users

For registration, you have to press “Enroll” at the corresponding Module, and then accept the “Site policy agreement”. Finally you will have to register at the web page, or login if you were registered already.

Posted in community, english, gvSIG Desktop, training | Tagged | 4 Comments

Nuevo manual de gvSIG

manual-154693_640Tal y como anunciamos en su momento estamos ya muy cerca de publicar la primera versión candidata a final de gvSIG 2.2. Una versión en la que además de encontrar nuevas extensiones, continuar depurando la aplicación y añadiendo pequeñas mejoras, se ha añadido como gran novedad una nueva edición.

En paralelo al desarrollo de esta versión hemos estado trabajando en un nuevo manual de gvSIG, del que ahora presentamos un primer borrador para que podáis revisarlo y ayudarnos a detectar cualquier posible incoherencia.

Aprovecho para volver a solicitar colaboración en la traducción a otros idiomas. En estos momentos tenemos un par de equipos muy activos traduciendo el documento a inglés y portugués, y estaríamos encantados de que más gente se uniera a ayudar a tener lo antes posible el manual al menos en estos idiomas.

Por otro lado, aunque este manual es para gvSIG 2.2, al margen de las novedades, puede ser también un documento de trabajo para los actuales usuarios de gvSIG 2.1.

El manual en PDF podéis descargarlo aquí.

Posted in gvSIG Desktop, spanish, testing | Tagged , , | 5 Comments

Recomendaciones y trucos para desarrollar con gvSIG 2.1 (1). Recorriendo datos

Hola a todos de nuevo,

De vez en cuando echo un vistazo al código de proyectos gvSIG realizados por otros desarrolladores y veo algunos fragmentos con pequeñas erratas que se repiten a lo largo del código. Algunas ni siquiera pueden considerarse erratas, sino que simplemente sería recomendable hacer las cosas de otra forma. He recogido aquí unas pocas de ellas e intentaré ir recogiendo algunas más para ir contándolas en otros artículos.

En este vamos a ver algunos trucos o buenas prácticas relacionadas con:

  • Liberación de recursos
  • Usar FeatureReference
  • Iterar sobre un conjunto de features

Liberación de recursos

Empecemos por la parte de liberación de recursos.

Cuando estamos creando código que accede a fuentes de datos a través de DAL, hay que tener en cuenta que dependiendo del proveedor de datos que estemos utilizando es importante que liberemos los recursos cuando terminemos de usarlos. Algunos proveedores, como los de acceso a base de datos, mantienen conexiones
abiertas con la base de datos que deberían ser liberadas al terminar de usarlas. En general cualquier “artefacto” que implemente el interface “Disposable” deberíamos cerciorarnos de que lo liberamos al terminar de usarlo.

Veamos un fragmento de código:

...
final List<FeatureReference> tmpFeatures = new ArrayList<FeatureReference>();
boolean showWarningDialog = false;
DisposableIterator it = null;
FeatureSet featureSet = null;

try {
  featureSet = featureStore.getFeatureSet();
  it = featureSet.fastIterator();
} catch (DataException ex) {
  String message = String.format(
    "Error getting feature set or fast iterator of %1",
    featureStore);
  LOG.info(message, ex);
  return;
}
while (it.hasNext()) {
Feature feature = (Feature) it.next();
  if (hasMoreThanOneGeometry(feature)
    || feature.getDefaultGeometry() == null) {
    showWarningDialog = true;
  } else {
    tmpFeatures.add(feature.getCopy().getReference());
  }

}

it.dispose();
featureSet.dispose();

if (showWarningDialog) {
  showWarningDialog();
}
...

En este fragmento de código podemos observar que se crea un “FeatureSet”, al que se le pide un iterador para recorrernos las features de un “FeatureStore”, y al final del proceso se invoca al método “dispose” de ambos para liberar los recursos que estos tengan asociados.

Si el proceso que se realiza va bien, es decir, no se producen errores, no pasará nada y los recursos se liberarán correctamente al ejecutarse las últimas dos líneas… pero ¿Qué sucede si se produce un error durante la ejecución de las líneas previas a invocar al método dispose?

Lo normal es que si el FeatureStore sobre el que se está trabajando es un tabla de una base de datos, deje “pillada” al menos una conexión con la base de datos. Y esta ya no se liberará hasta que se cierre gvSIG. Si el usuario insiste y repite el proceso y le sigue fallando, en un momento dado dejaremos al servidor de base de datos sin conexiones disponibles, y estas no se liberarán hasta que el usuario cierre gvSIG.

El escenario puede llegar a bloquear el acceso a un gestor de base de datos y no solo al usuario de gvSIG.

La recomendación es que cuando se esté trabajando con recursos “disposables” se utilice siempre una construcción “try…finally” tal como se muestra a continuación:

...
Disposable recurso = null;
try {
  ...
  recurso = ...
  ...
} finally {
  DisposeUtils.disposeQuietly(recurso);
}
...

El método “DisposeUtils.disposeQuietly” es un método de utilidad que comprueba si es null el recurso pasado, y solo intenta liberarlo en caso de que no lo sea. Además atrapa los errores y los ignora; bueno, se limita a enviarlos al registro de errores, en caso de que se produzcan al invocar al método “dispose” del recurso.

Si no queremos que se ignoren los errores usaremos “DisposeUtils.dispose”. En el código de ejemplo esto quedaría como:

...
final List<FeatureReference> tmpFeatures = new ArrayList<FeatureReference>();
boolean showWarningDialog = false;
DisposableIterator it = null;
FeatureSet featureSet = null;
try {

  try {
    featureSet = featureStore.getFeatureSet();
    it = featureSet.fastIterator();
  } catch (DataException ex) {
    String message = String.format(
      "Error getting feature set or fast iterator of %1",
      featureStore);
    LOG.info(message, ex);
    return;
  }
  while (it.hasNext()) {
    Feature feature = (Feature) it.next();
    if (hasMoreThanOneGeometry(feature)
      || feature.getDefaultGeometry() == null) {
        showWarningDialog = true;
    } else {
      tmpFeatures.add(feature.getCopy().getReference());
    }
  }

  if (showWarningDialog) {
    showWarningDialog();
  }
} finally {
  DisposeUtils.disposeQuietly(it);
  DisposeUtils.disposeQuietly(featureSet);
}
...

Usar FeatureReference

Cuando tenemos una Feature y queremos guardárnosla para acceder a sus datos más tarde normalmente tendríamos que guardarnos una copia de esta utilizando el método “getCopy”. Sin embargo, a veces no nos interesa guardarnos la feature completa, sino quedarnos con una referencia a ella. Para hacer esto utilizaremos el método “getReference” de la feature.

¿ En qué se diferencia la “feature” de su “referencia” ?
¿ Qué es una “referencia” a una “feature” ?

La “feature” es una estructura de datos que contiene todos los valores de los distintos atributos de esta, mientras que la referencia” es un estructura de datos que contiene la información mínima para poder recuperar la feature completa de su almacén de datos. En ocasiones sera un OID, en otras una clave primaria, siendo el proveedor de datos el encargado de decidir con cual quiere trabajar y de que tipo será ese OID.

Por ejemplo, una referencia a una feature de un shape usa un OID para referenciar a la feature dentro del shape, que normalmente será la posición de la feature dentro del shape, mientras que una feature de una tabla de base de datos tendrá los valores de los campos que constituyen la clave primaria de esa feature.

Tenemos que tener en cuenta que dependiendo de la fuente de datos subyacente, recuperar la información de una FeatureReference puede ser costoso. Las usaremos con cuidado y siendo conscientes de lo que se puede estar haciendo.

Por ejemplo, si tenemos una referencia a una feature de un shape, si invocamos a su método “getFeature”, esto provocará que se vaya a la posición asociada a la feature del shape y se cargue esta en memoria. El coste es asumible sin problemas. Sin embargo, si se trata de una referencia a una feature de una tabla de base de datos, provocará que se lance una consulta contra la base de datos para obtener el registro asociado a la feature y se pueda cargar en memoria. Hay que tener cuidado con esto, ya que si tenemos un List de referencias y las dereferenciamos, provocaremos que se lance una consulta contra la base de datos por cada referencia que tengamos, lo que puede no ser admisible.

Cuando usemos referencias, tendremos que tener en cuenta que recuperar sus features puede ser costoso, y tendremos que valorar si la aproximación que estamos realizando es la adecuada.

Con esto en mente… echemos un vistazo de nuevo al fragmento de código de antes:

...
while (it.hasNext()) {
  Feature feature = (Feature) it.next();
  if (hasMoreThanOneGeometry(feature)
    || feature.getDefaultGeometry() == null) {
      showWarningDialog = true;
    } else {
      tmpFeatures.add(feature.getCopy().getReference());
     }

    }
    ...

Observamos que está recorriéndose las features para guardarse las referencias a algunas features en un List. Sin embargo, para hacerlo hace “feature.getCopy().getReference()”, que provoca la creación de una copia de la feature original para después desecharla y quedarse con su referencia, que será la misma que si se la hubiésemos pedido a la feature original. Podríamos eliminar la obtención de la copia de la feature y pedir a la feature original su referencia y obtendríamos el mismo resultado.

...
while (it.hasNext()) {
  Feature feature = (Feature) it.next();
  if (hasMoreThanOneGeometry(feature)
     || feature.getDefaultGeometry() == null) {
      showWarningDialog = true;
    } else {
      tmpFeatures.add(feature.getReference());
    }

  }
  ...

Ahora observemos otro fragmento de código:

...
private List<FeatureReference> features;
...

int[] currIndexs = getSelectedIndexs();
// If selected is the first row, do nothing
if (currIndexs.length <= 0 || currIndexs[0] == 0) {
  return;
}
List<FeatureReference> selectedFeatures = new ArrayList<FeatureReference>();
for (int i = 0; i < currIndexs.length; i++) {
  FeatureReference selected = null;
  try {
    selected = features.get(currIndexs[i]).getFeature().getReference();
  } catch (DataException ex) {
    LOG.info("Error getting feature", ex);
    return;
  }
  selectedFeatures.add(selected);
}
if (!selectedFeatures.isEmpty()) {
...

El código llena un List de FeatureReference con parte de las referencias obtenidas de otra lista. Nos centraremos ahora mismo en el código:

...
selected = features.get(currIndexs[i]).getFeature().getReference();
...

Si pensamos que está haciendo esto, tendremos que:

  • Primero recuperamos una FeatureReference de la lista de “referencias a features”
  • Luego construimos la “feature” asociada a esa referencia, con lo que eso provoca que se acceda al almacén de fearures subyacente para recuperarla.
  • Y por último le pedimos a la nueva feature su referencia y descartamos la feature.

Todo ello además dentro de un bucle.

Si estamos trabajando con una fuente basada en base de datos, se lanzará una consulta para recuperar cada una de las features, lo que en si puede llevar bastante mas tiempo del deseable. De todos modos, hasta aquí aún tenemos suerte. Tenemos una referencia a la que le pedimos su feature para obtener su referencia. No es necesario recuperar la feature para obtener la referencia, ¡ya la tenemos!. Nos bastaría con guardarnos en “selected” la referencia original:

...
selected = features.get(currIndexs[i]);
...

En el código que estamos viendo se guarda las referencias en un List que luego usará para
mostrarlo en un JTable. Cada vez que el JTable tenga que acceder a los valores de las features a mostrar tendrá que dereferenciarlas para obtener así la feature. Si la tabla tiene muchas líneas, y las features están en base de datos se hará un consumo intensivo de base de datos, un acceso a la base de datos por cada línea de la tabla. Podría suceder que la herramienta no fuese a trabajar nunca con una fuente de datos “pesada” a la hora de recuperar features a partir de sus referencias, pero si no es así tendremos que plantearnos una implementación alternativa para este tipo de problema.

Por último, una cuestión más a tener en cuenta relacionada con las FeatureReference. No se puede garantizar que tras terminar la edición en un FeatureStore, las FeatureReference que te hayas guardado sean válidas. Hay fuentes de datos como shapes o dxfs, que usan como OID la posición de la feature dentro del fichero, y tras terminar la edición este orden puede cambiar. Sin embargo, en otras fuentes de datos como las de BBDD la referencia puede seguir siendo válida dependiendo de su clave primaria.

Iterar sobre un conjunto de features

Cuando queremos recorrer un conjunto de features, normalmente intentamos obtener un iterador y recorrerlo. Sin embargo la recomendación es que siempre que podamos para recorrer los datos usemos un visitor en lugar de un iterador.

Veámoslo con un ejemplo. Retomaremos el fragmento de código que vimos al principio:

...
final List<FeatureReference> tmpFeatures = new ArrayList<FeatureReference>();
boolean showWarningDialog = false;
DisposableIterator it = null;
FeatureSet featureSet = null;
try {

  try {
    featureSet = featureStore.getFeatureSet();
    it = featureSet.fastIterator();
  } catch (DataException ex) {
    String message = String.format(
      "Error getting feature set or fast iterator of %1",
      featureStore);
    LOG.info(message, ex);
    return;
  }
  while (it.hasNext()) {
    Feature feature = (Feature) it.next();
    if (hasMoreThanOneGeometry(feature)
      || feature.getDefaultGeometry() == null) {
        showWarningDialog = true;
    } else {
      tmpFeatures.add(feature.getCopy().getReference());
    }
  }

  if (showWarningDialog) {
    showWarningDialog();
  }
} finally {
  DisposeUtils.disposeQuietly(it);
  DisposeUtils.disposeQuietly(featureSet);
}
...

Veamos que hace:

  • Obtenemos un FeatureSet a partir del FeatureStore
  • Le pedimos un iterador
  • Nos recorremos todas las features y nos quedamos una referencia a ellas.
  • Al final mostramos un mensaje si se ha encontrado multigeometrias o no.

Usando “visitor” podría quedar algo como:

...
final MutableBoolean showWarningDialog = new MutableBoolean(false);
try {
  featureStore.accept(new Visitor() {
    public void visit(Object obj) throws VisitCanceledException, BaseException {
      Feature feature = (Feature) obj;
      if (hasMoreThanOneGeometry(feature)
        || feature.getDefaultGeometry() == null) {
        showWarningDialog.setValue(true);
      } else {
        tmpFeatures.add(feature.getReference());
      }
    }
  });
} catch (BaseException ex) {
  ... exception handling ...
}

if (showWarningDialog.isTrue() ) {
  showWarningDialog();
}
...

Como nos estamos recorriendo todas las features del store, podríamos visitar directamente el store. No pedimos un FeatureSet ni un iterador, así que no tendremos que preocuparnos de liberarlos. Tendremos que preocuparnos de atrapar las excepciones del método “visit”, pero también teníamos que hacerlo cuando creábamos el FeatureSet.

En este fragmento de código he utilizado algo que puede parecer extraño. Habia un flag que se modificaba dentro del bucle, “showWarningDialog”. Como hemos sustituido el cuerpo del bucle por una clase interna anónima, no podemos utilizar una variable “boolean” ya que esta no puede ser final. Así que en lugar de usar un “boolean”, he usado un “MutableBoolean” para almacenar el flag. Esta clase forma parte de la librería de “apache commons lang” que va de base con gvSIG.

Resumiendo

Recomendaciones en general:

  • Que cuando se este trabajando con recursos “disposables” se utilice siempre una construcción “try…finally“, usando “DisposeUtils.disposeQuietly” para liberar los recursos.
  • Una FeatureReference referencia a la feature, no precisas obtener una copia para pedirle la referencia.
  • Dereferenciar una FeatureReference llamando a “getFeature” puede ser un proceso “pesado”.
  • No asumiremos que tras terminar la edición en un FeatureStore las FeatureReference que tengamos guardadas sean válidas.
  • Siempre que podamos, para recorrer los datos usemos un visitor en lugar de un iterador.

Bueno, y por hoy asta aquí llego. Otro día ya contaré sobre algunas otras cosas…

Un saludo a todos!

 

Posted in development, gvSIG Desktop, spanish | Tagged | 1 Comment

gvSIG 2.1: Italian and Bulgarian translations updates

Italian and Bulgarian translations have been updated, and they are now available for the gvSIG 2.1 final version, thanks to Antonio Falciano (Italian), and Zahari Savov and Jordan Tsvetkov (Bulgarian).

If you installed the gvSIG 2.1 final version, you can update these languages now from the add-ons manager. From gvSIG, you have to go to Tools->Addons manager, then select the Installation from URL option and finally you have to select the “Official gvSIG repository for this version” option. When packages appears at the window you have to select the “Internationalization” option at the left side, and then the “Translations” package (1.0.0-27 version).

Translations

After installing it and restarting gvSIG the translation will be updated.

We encourage you to translate the gvSIG interface to new languages or update the existing ones. If you are interested you can contact us (mcarrera at gvsig.com).

Posted in community, english, gvSIG Desktop | 1 Comment

How to work with a form, browsing selected records using scripting in gvSIG 2.1

English translation of the article by Joaquin del Cerro.

Hi everyone…

Yesterday, someone in gvSIG users mailing list asked about how to make something with scripting.

Basically what was intended was to present a custom form using a script that showed the data of the selected record in a layer, and if they had multiple selected records, the buttons first / previous / next / last will be presenting the different selected records.

I´ve added one extra thing and here you can find, one possible implementation: even when there are not selected records, you will be able to move for all the records of the layer.

The idea is that when we load the form, we save the selected records in one list and we will have them easily handy. This action with the selected records could be more or less acceptable, but if we are scrolling all of the records in one table, it could be impossible, because the table can have a vast amount of records and we are not going to load in memory. Also, it could happen if we select thousands of records, but this is less usual.

I will comment only on the piece that is responsible for working with the entire table because it is the “darkest” part. As I said, to load all records from one table in a list may not be feasible for the table size, so in gvSIG, we have the possibility of using a paging mechanism on the table and we show it as an ongoing list, regardless of this “pager” take care of loading and unloading records required depending on the size of page indicated by us. The code would correspond to the LoadFullTable function.

def loadFullTable(table):
  # Obtain a pager based on data table, paging in groups of 200 records.
  pager = DALLocator.getDataManager().createFeaturePagingHelper(table,200)
  # Obtain one paged list from the pager.
  return pager.asList()

The code at the end is very easy. We call a function to which we pass the table and the maximum number of records which we want to be loaded simultaneously in the memory:

pager = DALLocator.getDataManager().createFeaturePagingHelper(table,200)

and then, we ask to the pager that we have obtained, to return us a list based on it.

return pager.asList()

This list can already be handled as if it were a normal list, but being the pager responsible for retrieving records from disk as it needs them.

I will not tell many more things, I think the rest of the code is clear enough if it has already been playing with python and scripting in gvSIG environment.

For the example, I´ve used the layer zonas_basicas_salud (It means health basic zones), available for downloading in:

http://downloads.gvsig.org/download/geodata/vector/SHP2D/zonas_basicas_salud.navarra.zip

I´ve assumed that is the selected layer when the script is launched.
The script result would be something similar to:

resultado

And the full script would be:


from gvsig import *

from org.gvsig.fmap.dal import DALLocator

table = None
data = None
currentRecord=0

def loadRecord():
 codzone = dialog.find("codzone")
 area = dialog.find("area")
 zone = dialog.find("zone")
 sector = dialog.find("sector")
 actual = dialog.find("current")

 record = data[currentRecord]

 dialog.setString(codzone,"text", "%s" % record.get("codzona"))
 dialog.setString(area,"text", record.get("Area"))
 dialog.setString(zone,"text", record.get("Zona"))
 dialog.setString(sector,"text", record.get("Sector"))

 dialog.setString(actual,"text", "%d / %d" %(currentRecord+1, len(data)) )

 #selectRecord(record)

def selectRecord(record):
 selection = table.getFeatureSelection()
 selection.deselectAll()
 selection.select(record)

def loadFullTable(table):
 # Obtain a pager based on data table, paging in groups of 200 records.
 pager = DALLocator.getDataManager().createFeaturePagingHelper(table,200)
 # Obtain one paged list from the pager.
 return pager.asList()

def loadSelection(table):
 data = list()
 selection = table.getFeatureSelection()
 for record in selection.iterator():
 data.append(record)
 return data

def onload(*args):
 global data
 global table
 # For being easier, assume that current layer is zonas_basicas_salud
 layer = currentLayer()
 # Obtain the table related to the layer
 table = layer().getFeatureStore()

 selection = table.getFeatureSelection()
 if selection.isEmpty():
 data = loadFullTable(table)
 else:
 data = loadSelection(table)
 currentRecord=0
 loadRecord()

def next():
 global currentRecord

 if currentRecord<len(data)-1 :
 currentRecord +=1
 loadRecord()

def previous():
 global currentRecord

 if currentRecord>0 :
 currentRecord -=1
 loadRecord()

def first():
 global currentRecord

 currentRecord = 0
 loadRecord()

def last():
 global currentRecord

 currentRecord = len(data)-1
 loadRecord()

Here is the xml of the form, to let us know the references names that I´ve used in the code:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- generated by ThinG, the Thinlet GUI editor -->
<panel columns="1" gap="4">
    <panel columns="2" gap="2">
        <label text="Zone code"/>
        <textfield name="codzone" weightx="1"/>
        <label text="Area"/>
        <textfield name="area"/>
        <label text="Zone"/>
        <textfield name="zone"/>
        <label text="Sector"/>
        <textfield name="sector"/>
    </panel>
    <panel gap="2">
        <label text="  "/>
        <button action="first" name="first" text="First"/>
        <button action="previous" name="previous" text="Previous"/>
        <textfield editable="false" end="3" name="current" start="3" text="0/0"/>
        <button action="next" name="next" text="Next"/>
        <button action="last" name="last" text="Last"/>
        <label text="  "/>
    </panel>
</panel>

Greetings to all and I hope you find it useful

Posted in development, english, gvSIG Desktop, gvSIG development, scripting | 1 Comment