<- PW: Bash - Archivio Generale - Copertina - PW: YaaCs ->

PlutoWare


Gosh

di Giuseppe Lucarelli


L'articolo

GOSH è un programma che permette di inserire e manipolare a runtime dei dati in un database con una struttura variabile, gestita dall'utente. Rilasciato sotto licenza GPL, scaturisce dall'esigenza di catalogare l'importante collezione di dipinti posseduta dalla Galleria Doria Pamphily di Roma; l'attuale versione del programma è la 0.2, gestibile anche attraverso il web da quegli utenti che scegliessero di non installare Linux sul lato client. Questo articolo descrive il programma nei principi e nell'attuale realizzazione.



Indice



Introduzione

GOSH è un programma che permette di inserire e manipolare a runtime dei dati in un database con una struttura variabile, gestita dall'utente. E' rilasciato sotto licenza GPL, gira in ambiente UNIX, utilizza le librerie grafiche GTK+/Gnome oltre alle librerie Glib, gnome-xml e come database MySql.
E' stato realizzato e sviluppato attualmente da Giuseppe Lucarelli (giu.lucarelli@tiscali.it), ed è disponibile all'indirizzo http://www.pluto.linux.it...

Come nasce, per capire che fa

GOSH nasce dall'esigenza di catalogare la collezione dei dipinti su tela, posseduta dalla Galleria Doria Pamphily di Roma, da parte dell'Istituto Centrale del Restauro (Anna Marcone, Bianca Paris e Giancarlo Buzzanca).
Inizialmente è stato sviluppato in Microsoft Access(tm) (sic!) in ambiente win32 con una struttura fissa dei dati; erano fissi quindi e ben definiti numero, dimensione e tipologia dei campi (testo, immagine, casella combinata, ecc.). La continua crescita sia del numero che dei controlli della struttura iniziale, unita alla necessità di utilizzare un linguaggio decisamente più potente, hanno portato a dover permettere all'utente di gestire sia il numero che il tipo di dati, ed alla scelta di passare al linguaggio C in ambiente Linux.
Da qui ad accorgersi che il programma poteva essere utilizzato per altre tipologie di oggetti all'interno dell'ICR, il passo è stato breve. Questo perché ognuna di loro ha una parte di dati in comune con tutte le altre (es numero inventario, possessore, descrizione, ecc).
Il risultato finale è che con questo software è stato possibile catalogare oggetti differenti, stabilendo un certo numero di definizioni comuni inserite in una sezione iniziale fissa, e inserendo il resto dei dati utilizzando sezioni specifiche per ogni categoria di appartenenza.
Il passo successivo (non ci voleva poi molto del resto) è stato accorgersi che catalogare quadri, coccetti e statue equestri non è molto differente dal catalogare il magazzino di un ferramenta, per esempio: una quantità molto grande di articoli, alcuni dei quali necessitano di una descrizione minima, ed altri che richiedono molti più campi.

Struttura

Vediamo ora la struttura del programma. Creando per esempio un nuovo database, avremo:

$ create_db pluto articoli


verrà creato il db pluto strutturato in questo modo:

                UTENTI       CONFIG                             ARTICOLI
                +--------+   +-------------------+            +-------------+
CONNESSIONE---->| root   |-->| articoli-default  |----------->|(vuoto)      |--> GUI
                | wwwrun |   +-------------------+            +-------------+
                +--------+

La struttura del db pluto sarà:

CONFIG Contiene 1 record composto da un campo chiave, che identifica il nome della tabella e la tipologia a cui fa riferimento, ed un campo testo senza limite di grandezza che contiene la descrizione in formato XML, con la relativa struttura.
'articoli-default','<?xml version=\"1.0\"?>\n<project>\n<name>default</name>\n<user>default....'
UTENTI Contiene l'utente root (non collegato con /etc/passwd) che è l'amministratore, senza password (consigliabile assegnarle un valore in seguito) e l'utente wwwrun, senza password e con il solo privilegio di lettura, necessario per l'interrogazione via web browser (spiegato in seguito)
ARTICOLI In questa tabella, vuota per il momento, vengono memorizzati i dati. La struttura è ridotta al minimo, contiene infatti solo i campi obbligatori. Sarà possibile comunque aggiungere e/o modificarne sia il numero che la tipologia, oltre a poter aggiungere eventuali sezioni.
Il tracciato record si presenterà in questo modo:

#
# Table structure for table 'articoli'
#
CREATE TABLE articoli (
  idtabella mediumint(7) unsigned NOT NULL auto_increment,
  tipologia set('default','') NOT NULL default '',
  dataReg varchar(8) NOT NULL default '',
  dataRev varchar(8) NOT NULL default '',
  des varchar(20) NOT NULL default '',
  note0 text,
  rowLock char(1) default NULL,
  PRIMARY KEY  (idtabella),
  KEY des (des)
) TYPE=MyISAM;

Il campo rowLock è utilizzato per la multiutenza

La gui si presenterà in questo modo:

Ed ecco invece quella che può essere la struttura di un db più complesso, icr per esempio :

                             CONFIG                             OGGETTI
                             +---------------------+            +-------------+
                UTENTI       | oggetti-default     |----------->|record 1.....|
                +--------+   | oggetti-tele        |----------->|             |-+-> GUI
                | root   |   | oggetti-bronzi      |----------->|             | |
CONNESSIONE --> | wwwrun |-->| oggetti-isi         |----------->|             | |
                | bianca |   | cantieri-default    |-------+    +-------------+ |
                | anna   |   | studenti-default    |-----+ |                    |
                | buzzer |   | (altre tipologie).. |     | |    CANTIERI        |
                +--------+   +---------------------+     | |    +-------------+ |
                                       |                 | +--->|record 1.....|-+
                                       |                 |      |             | |
                                       |                 |      +-------------+ |
                                      \|/                |                      |
                                (altre tabelle)          |      STUDENTI        |
                                                         |      +-------------+ |
                                                         +----->| record 1....+-+
                                                                |             |
                                                                +-------------+

Due esempi di tipologie differenti all'interno della stessa tabella:


La configurazione

Qui è necessario chiarire un concetto molto importante.
Per tabelle che hanno un'unica tipologia, il db pluto ad esempio, connettendoci con tabella->articoli e tipologia->default modifichiamo la struttura effettiva di inserimento/manipolazione dei dati. Per db come icr invece, connettendoci con tabella->oggetti e tipologia->default, cambiamo la struttura fissa di tutte le tipologie della tabella oggetti (tele, bronzi, ...), lasciando però inalterate le sezioni variabili di ognuna di queste. Solo connettendosi con una specifica tipologia sarà possibile modificarne le sezioni variabili (se esistenti), eliminarle o aggiungerne altre.
Non verrà utilizzata in questo caso la tipologia default per inserire/modificare dati.

Sperando di non confondere uleriormente le idee vediamo il tracciato record:

#
# Table structure for table 'oggetti'
#
CREATE TABLE oggetti (
  idtabella mediumint(7) unsigned NOT NULL auto_increment,
  tipologia set('default','bronzi','cantieri','isi','tele','') default NULL,
  dataReg varchar(8) NOT NULL default '',
  dataRev varchar(8) NOT NULL default '',
  cantiere text,
  edificio text,
  inventario text,
  provenienza text,
  piano varchar(15) NOT NULL default '',
  ambiente set('si','no','') default NULL,
  soggetto varchar(20) default NULL,
  misure varchar(5) default NULL,
  misure_y varchar(5) default NULL,
  misure_z varchar(5) default NULL,
  secolo set('XX ac','XIX ac','XVII ac','XVI ac','XV ac','XIV ac','XIII ac','XII ac','XI ac',
'X ac','IX ac','VIII ac','VII ac','VI ac','V ac','IV ac','III ac','II ac','I ac','I dc','II dc',
'III dc','IV dc','V dc','VI dc','VII dc','VIII dc','IX dc','X dc','XI dc','XII dc','XIII dc',
'XIV cd','XV dc','XVI dc','XVII dc','XVIII dc','XIX dc','XX dc','XXI dc','') default NULL,
  opera varchar(20) NOT NULL default '',
  formato set('rotondo','ellittico','') default NULL,
  autoreC text,
  autoreN varchar(20) default NULL,
  anno varchar(10) default NULL,
  frazione set('I` quarto','II` quarto','III` quarto','IV` quarto','') default NULL,
  mostre text,
  restauri text,
  tecnica set('tecnica nuo','tecnica due','') default NULL,
  sezione1 text,
  sezione2 text,
  sezione3 text,
  sezione4 text,
  sezione5 text,
  sezione6 text,
  sezione7 text,
  sezione8 text,
  sezione9 text,
  sezione10 text,
  note0 text,
  note1 text,
  note2 text,
  note3 text,
  note4 text,
  note5 text,
  note6 text,
  note7 text,
  note8 text,
  note9 text,
  note10 text,
  rowLock char(1) default NULL,
  PRIMARY KEY  (idtabella),
  KEY dataReg (dataReg),
  KEY dataRev (dataRev),
  KEY piano (piano),
  KEY opera (opera)
) TYPE=MyISAM;

I dati fino al campo sezione1 (escluso) corrispondono alla sezione fissa. I successivi corrispondono alle restanti sezioni; esse, se sono utilizzate ed opportunamente configurate, ne conterranno i dati.

Vediamo ora l'esempio pratico:

Connettendoci con db->icr / tabella->oggetti / tipologia->tele scegliamo la voce struttura dati dal menu configura.



Configura Globali Permette di definire alcuni parametri globali relativi alla tipologia in fase di modifica
nome nome della tipologia
utente nome del proprietario
gruppo gruppo del proprietario
predefinito nome del campo da visualizzare/accettare se associato ad altre tabelle nello stesso db (per default des)
max.sezioni numero massimo di sezioni per una determinata tipologia, 10 in questo caso
cartella immagini identifica la cartella contenente le immagini. Questo perché quando ne viene selezionata una viene memorizzato solo il nome assoluto e non l'intero pathname. Se viene utilizzata anche la parte web, la directory deve essere visibile dal server web, /var/www/html/icr/images per esempio
eventi pulsantiera è qui possibile associare una macro (script) ad ognuno dei pulsanti elencati. Questo si rivela molto utile nei casi in cui l'operazione da effetturare corrisponde all'intero record e non ad un singolo campo. Nel db legatura per esempio, al pulsante nuovo viene associata una macro che determina i dati dell'ultima partita inserita e inizializza il record con questi, incrementando di 1 il numero riga. Nel caso di eventuali movimenti di magazzino si può eseguire l'aggiornamento di giacenza, q.tà venduta/acquistata o altro associando una macro al pulsante salva (e cancella per eventuali aggiornamenti in negativo)


Configura Sezione con questa maschera è possibile gestire il numero e la definizione di ogni sezione, elencate in alto a sinistra. In basso a sinistra sono elencati i campi della sezione selezionata
nome sezione nome della sezione
tipologia tipologia della sezione. I valori possibili sono:
FISSA: è la parte fissa della tabella, non modificabile in questo caso. E' possibile farlo solo accedendo con tipologia default e possedendo gli adeguati permessi.
TESTO: definita ed utilizzata come un unico campo testo e utilizzata normalmente per inserire descrizioni o info abbastanza estese
VARIABILE: può contenere un numero illimitato (o quasi) di sottocampi

Di seguito vengono confrontati due campi differenti, il primo relativo alla sezione variabile del db esaminato, l'altro alla sezione fissa del db legatura:

Segue la descrizione dei campi meno intuitivi

Configura Riga Definisce le specifiche, comprese eventuali macro, del campo
nome nome visualizzato del campo (obbligatorio)
codice codice (non obbligatorio)
tipo definisce la tipologia del campo. In base al valore vengono visualizzati o meno i campi sottostanti. Può assumere un valore tra questi:

ENTRY accetta qualsiasi tipo di carattere ASCII
CHECK visualizza un elenco di valori ognuno dei quali associato ad una casella di spunta; se ne possono selezionare più di uno.
Utilizzabile solo per sezioni variabili
RADIO identico al precedente tranne per il fatto che è selezionabile un solo valore.
Utilizzabile solo per sezioni variabili
COMBO Anche in questo caso è selezionabile un valore da un elenco ma, oltre alla possibilità di un elenco con un numero maggiore di possibilità, è utilizzabile anche nella sezione fissa
IMAGE Accetta il nome assoluto di un'immagine (gif, jpg,..) anche visualizzando un'anteprima.
Utilizzabile solo per sezione variabile
DATA Permette di inserire un campo data
TABLE Permette di gestire in modo trasparente le relazioni tra tabelle. La relazione è del tipo UNO -> UNO
per esempio FATTURA -> CLIENTE
TABLELIST Come sopra, ma la relazione è del tipo MOLTI -> UNO
per esempio nel db BILBLIO è utilizzato per associare uno o più autori ad una singola informazione bibliografica
RELAT E' l'inverso dei due precedenti campi ed è solo di visualizzazione, in quanto non esiste nel tracciato record della tabella.
es CLIENTE -> FATTURE
DISPLAY E' utilizzato per visualizzazioni, normalmente valori di ritorno dopo esecuzione di macro. Anch'esso non definito nel tracciato record
BUTTON Permette di inserire un pulsante in un punto qualsiasi della sezione, associabile ad una macro.
Utilizzabile solo nella sezione fissa
LINK Lancia il browser di default con un URL definito in fase di configurazione.
Utilizzabile solo nella sezione fissa
macro Permette di associare una macro ad un evento compreso nella lista. (non obbligatorio)
tipologia rel. Attivo solo per TABLE e TABLELIST. Indica la tipologia della tabella associata (obbligatorio)
tabella rel. Insieme al precedente definisce il nome della tabella con cui stabilire la relazione. Creata se inesistente (obbligatorio)


Configura Eventi Permette di associare macro ad un evento del campo
plugin nome della libreria (ancora da implementare)
macro pathname dello script da eseguire quando si verifica l'evento selezionato. Corrisponde all'URL della chiamata HTTP al server web, quindi non viene specificata nel PATH la directory DOCUMENT_ROOT (/var/www per esempio).
Si può utilizzare qualsiasi tipo di linguaggio (bash, perl, python, ruby o altro)
args definisce uno o più campi il cui valore viene passato allo script da eseguire (metodo POST), il quale riceve una stringa strutturata in questo modo:
host=localhost&argomento1=valore1&argomento2=valore2&...argomento#=valore#
is null determina l'esecuzione della macro, quando si verifica l'evento, solo se il campo non ha nessun valore. Utilizzato normalmente con l'evento focus_in_event (quando cioè il campo viene selezionato con il mouse o con il tasto TAB
after valido per il momento solo per gli eventi della pulsantiera. Esegue la macro non all'inizio della funzione (SALVA per esempio) ma alla fine


Il Web

Non voglio installare Linux! Questa è stata la frase che ha determinato lo sviluppo di una serie di pagine web per poter gestire, tramite browser, funzioni di interrogazione/inserimento all'interno di una rete mista, composta cioè da un server linux e client win.
Per il momento non esistono funzioni di amministrazione (configurazione utenti, tipologie e altro), ma non è escluso, tempo permettendo, che in futuro vengano implementate.
L'utilizzo è molto intuitivo, anche se decisamente più lento rispetto al programma in C.
Ecco un esempio di scheda all'interno del browser:

HTML e javascript a parte, è stato utilizzato il PHP come linguaggio di sviluppo.
Un aspetto decisamente interessante è quello relativo alle macro: un qualsiasi script utilizzato da un campo ed associato ad uno specifico evento, viene utilizzato allo stesso modo sia dal programma C che dalla pagina web, in quanto entrambi utilizzano il server web.

Conclusione

Attualmente il programma è alla versione 0.2, essendo stata riscritta almeno la metà del codice iniziale. Va ricercata quindi una sufficiente affidabilità, oltre a produrre una adeguata documentazione.
Ciò che penalizza maggiormente il programma, e che attualmente ne limita un maggiore uso all'interno di altre strutture della pubblica amministrazione, è la mancanza di funzioni di stampa. Essendo questa fortemente necessaria per la maggior parte dei possibili utilizzatori, l'alternativa (speranza più che altro) alla scrittura di un bel po di codice (probabilmente le gnome-print), potrebbe essere l'utilizzo di programmi esistenti, gnumeric per esempio (tramite corba), datavision o altri.



L'autore

Giuseppe Lucarelli <giu.lucarelli@tiscali.it> lavora come programmatore presso la Biblioteca di Storia Moderna e Contemporanea di Roma, per la quale sviluppa programmi da una vita senza guadagnare una lira (euro?). Comincia a programmare su macchine Texas nel 1980 (in TPL ehehe), poi 15 anni di COBOL, collaborando con diverse S.H. specialmente per contabilità e magazzino/fatturazione, 2 anni di Visual Basic prima di approdare finalmente a C su Linux. Ha una moglie, una figlia e due cucciole.



<- PW: Bash - Archivio Generale - Copertina - PW: YaaCs ->