Un semplice aggregatore di news Introduzione Gambas è, descrive il suo sito, "un ambiente di sviluppo libero, basato su un interprete BASIC con estensioni ad oggetti, come Visual Basic(ma non ne è un clone !)" Se siete curiosi sui perchè e le motivazioni di Gambas, consiglio di leggere l'introduzione ufficiale. Questo articolo mira ad introdurre l'ambiente Gambas mediante lo sviluppo di un piccolo programma; un aggregatore di news. In questo modo potremo lavorare con alcuni componenti(HttpClient, Xml e oggetti grafici) per vedere quanto sia semplice assemblare applicativi con questo strumento, anche per programmatori non propriamente esperti.
Introduzione Gambas è, descrive il suo sito, "un ambiente di sviluppo libero, basato su un interprete BASIC con estensioni ad oggetti, come Visual Basic(ma non ne è un clone !)" Se siete curiosi sui perchè e le motivazioni di Gambas, consiglio di leggere l'introduzione ufficiale. Questo articolo mira ad introdurre l'ambiente Gambas mediante lo sviluppo di un piccolo programma; un aggregatore di news. In questo modo potremo lavorare con alcuni componenti(HttpClient, Xml e oggetti grafici) per vedere quanto sia semplice assemblare applicativi con questo strumento, anche per programmatori non propriamente esperti.
Creare un progetto Dopo aver lanciato l'IDE, selezionare "New Project" e seguire il wizard. Abbiamo bisogno di creare un progetto grafico, scegliergli un nome e un titolo, selezionare/creare una cartella che lo contenga, e siamo a posto.
| | | | Alcune immagini del wizard | Sul treeView di sinistra, click destro su "Forms", selezionare "New" e poi "Form". Teniamo i valori di default, verrà chiamato automaticamente "Form1" e sarà la classe di partenza. Ora abbiamo bisogno di importare alcuni componenti. Dal menu principale selezioniamo "Project->Properties" e da li il tab "Components". Assicuriamoci che siano selezionati i seguenti componenti: - gb
- gb.net
- gb.net.curl
- gb.qt
- gb.qt.ext
- gb.xml
Ora è tempo di creare il layout dell'aggregatore, usando gli oggetti grafici nella Palette a destra. Abbiamo bisogno di una comboBox per la scelta del feed da scaricare, una listView per la lista degli articoli e un textView per leggere il testo degli articoli stessi. Non dovrebbero esserci troppi problemi, e il risultato potrebbe essere qualcosa del genere:
Bene, ora scriviamo un pò di codice. La classe "Items" La chiamiamo "classe" nell'accezione di Gambas, non in quella orientata agli oggetti. Ci serve una sorta di oggetto in cui memorizzare i dati degli articoli quando scarichiamo dalla rete un feed, che possa essere interrogato per ottenere link, descrizione e titolo degli articoli. Per cui click destro su "Classes" nella treeView di sinistra, "New->Class" e diamo nome "Items". Ecco il codice da metterci dentro:
last_checked AS Date titles AS NEW String[100] descriptions AS NEW String[100] links AS NEW String[100] last_index AS Integer current_index AS Integer PUBLIC SUB Main() current_index = 0 last_index = 0 last_checked = Now END Qui dichiariamo alcuni arrays(descriptions,links and titles) che memorizzeranno i dati. La dimensione massima è 100 ma possimao anche definire diversamente. last_checked tiene data/ora dell'ultimo aggiornamento dalla rete del feed, e last_index e current_index il numero di articoli presenti nel feed e l'articolo correntemente selezionato. Il metodo Main, una sorta di costruttore, inizializza alcune di queste variabili. PUBLIC SUB addItem(title AS String, description AS String, item_link AS String) last_index = last_index + 1 titles[last_index] = title descriptions[last_index] = description links[last_index] = item_link END PUBLIC SUB reset() current_index = 0 END PUBLIC SUB clear() current_index = 0 last_index = 0 titles = NEW String[100] links = NEW String[100] descriptions = NEW String[100] END PUBLIC FUNCTION next() AS Boolean IF last_index = current_index THEN RETURN FALSE ELSE current_index = current_index + 1 RETURN TRUE END IF END Alcune semplici azioni sul feed: reset porta il cursore sul primo articolo, clear fa quello quello che dice e next muove il cursore al successivo articolo, se ce ne sono altri. PUBLIC FUNCTION getTitle() AS String RETURN titles[current_index] END PUBLIC FUNCTION getDescription() AS String RETURN descriptions[current_index] END PUBLIC FUNCTION getLink() AS String RETURN links[current_index] END PUBLIC FUNCTION getCurrentIndex() AS Integer RETURN current_index END Questi metodi restituiscono i dati dell'articolo correntemente selezionato. PUBLIC FUNCTION seek(index AS Integer) AS Boolean IF index <= last_index AND index >= 0 THEN current_index = index RETURN TRUE ELSE RETURN FALSE END IF END e questo muove il cursore all'indice dato, se esiste, Questa è tutta la logica per manipolare i feed. Ora vediamo come scaricarli e parsarli.
Il codice della Form A questo punto possiamo scrivere il codice per: gestire l'interfaccia grafica, scaricare i feed dalla rete, parsarli e mostrare i dati mediante la classe Items. Il codice che va in Form è il seguente.
PUBLIC P AS HttpClient PUBLIC items AS NEW Items PUBLIC feeds AS String[4] PUBLIC SUB Form_Open() items = NEW Items P = NEW HttpClient AS "P" feeds[0] = "http://rss.freshmeat.net/freshmeat/feeds/fm-releases-unix" feeds[1] = "http://rss.slashdot.org/Slashdot/slashdot" feeds[2] = "http://www.repubblica.it/rss/homepage/rss2.0.xml" combobox1.Add("Freshmeat", 0) combobox1.Add("Slashdot", 1) combobox1.Add("La Repubblica", 2) END Per prima cosa dichiariamo un oggetto HttpClient per scaricare i feed, un oggetto Items per memorizzare i dati e un array feeds[] per memorizzare le url dei feed. Mel metodo "Form_Open"(il punto d'ingresso della "Form") popoliamo l'array dei feed e la combobox per selezionarli. Da notare che lo facciamo staticamente; ovviamente un programma più completo permetterebbe di aggiungere/modificare/cancellare elementi dalla lista, ma per ora mantieniamo il tutto semplice. PUBLIC SUB P_finished() DIM buffer AS String IF Lof(P) THEN READ #P, buffer, Lof(P) parseFeed(buffer) fillList()
END questo metodo è "guidato da eventi". Quando l'oggetto Httpclient finisce di ricevere dati un evento viene generato e viene chiamato questo metodo. Definiamo un buffer, lo riempiamo con i dati ricevuti da HttpClient, parsiamo e popoliamo la lista di articoli. Per una spiegazione di parseFeed e fillList, vedere sotto. PUBLIC SUB ListView1_Select() DIM key AS Integer key = listview1.Current.Key items.seek(key) textview1.Text = items.getDescription() & "\n" & items.getLink() END
PUBLIC SUB Button1_Click() P.URL = feeds[combobox1.Index] P.Get
END Questi sono metodi chiamati da eventi, quando viene effettuata una selezione sulla listView o viene cliccato il pulsante. nel primo caso prendiamo l'indice dell'elemento selezionato dalla listView, che è anche l'indice del corrispondente articolo nell'oggetto "Items", così possiamo utilizzarlo per cercare l'articolo che ci interessa(metodo seek) e mostrarne il testo nella textView. La pressione del pulsante invece, fa puntare l'oggetto HttpClient all'url selezionata nella comboBox e ne lancia lo scaricamento da rete. SUB parseFeed(data AS String) DIM xml AS NEW XmlDocument DIM node AS XmlNode xml.FromString(data) node = xml.Root items.clear parseNode(node) END
SUB parseNode(node AS XmlNode) DIM t, t1 AS Integer DIM node1 AS XmlNode DIM buf AS String DIM title, description, item_link AS String FOR t = 0 TO node.Children.Count - 1 node1 = node.Children[t] IF node1.name = "item" THEN FOR t1 = 0 TO node1.Children.Count - 1 buf = node1.Children[t1].name IF buf = "title" THEN title = node1.Children[t1].value ELSE IF buf = "description" THEN description = node1.Children[t1].value ELSE IF buf = "link" THEN item_link = node1.Children[t1].value END IF NEXT items.addItem(title, description, item_link) ELSE IF node1.Children.Count > 0 THEN parseNode(node1) END IF NEXT END Ora la gestione dell'xml scaricato.parseFeed accetta del testo xml come argomento, crea un documento xml, pone il nodo radice del documento come nodo corrente e lo passa a parseNode, che fa il lavoro sporco.parseNode è una funzione ricorsiva che estrae descrizione,link e titolo da un nodo se questo è di tipo "item", altrimenti applica a questo la ricorsione, fino a che non raggiunga la fine del documento xml. I dati estratti dai nodi vengono salvati nell'oggetto "Items". Quando il metodo termina, abbiamo un oggetto "Items" che contiene tutti gli articoli del feed selezionato. SUB fillList() listview1.Clear items.reset WHILE items.next() listview1.Add(items.getCurrentIndex(), items.getTitle()) WEND END fillList popola la listView con i titoli degli articoli estratti. Ora è possibile lanciare/compilare il programma e testarlo.
Ecco come appare il programma una volta lanciato:
Cosa manca Il programma è molto semplice e ci sono bachi da risolvere e migliorie da apportare. Per i bachi in particolare, utilizziamo una textView per mostrare il testo degli articoli perchè questa è in grado di elaborare codice html, ma dato che non ci stiamo curando dei mime types, eventuali immagini verranno mostrate come rettangoli grigio-scuri. Per le migliorie, alcune interessanti potrebbero essere: menu,gestione dinamica della lista dei feed, auto aggiornamento dei feed, etc. Magari scriverò un ulteriore articolo su questi punti, anche come opportunità per vedere nuovi componenti di gambas. Conclusioni Abbiamo visto quanto sia semplice usare Gambas. Si hanno a portata di mano sia un RAD facile,comodo e potente, sia tutta una serie di utili componenti. Questa volta abbiamo utilizzato xml,http e alcuni oggetti grafici, ma abbiamo a disposizione: db, opengl, integrazione con kde e tutti quegli "stravaganti" componenti che tornano utili quando si lavora su una piattaforma di sviluppo.
Hasta la proxima.
|