English translation of the article by Joaquin del Cerro.
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.
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:
I´ve assumed that is the selected layer when the script is launched.
The script result would be something similar to:
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