A simple news feed aggregator Introduction Gambas is, as its site states, "a free development environment based on a Basic interpreter with object extensions, like Visual Basic (but it is NOT a clone !)" If you're curious about the whys and motivations of Gambas please read the official introduction. This article focuses on introducing Gambas environment with a real, maybe useful program; a news feed aggregator. This will allow us to overview some components(HttpClient,Xml features and graphical widgets) to see how easy it is to assemble applications with this tool, even for relatively newbies programmers.
Creating the project First things first. After launching the IDE choose "New Project" and follow the wizard. We need to create a graphical project, choose a name and a title for it, select/create a directory to host it and we're done with it.
| | | | Some screenshots of the project wizard | On the left tree view right click on "Forms" and select "New" and then "Form". We can keep the default values, it will be automatically called "Form1" and will be the startup class. Now we need to import the components we need. From the menu choose Project->Properties and from there the Components tab.Make sure the following components are selected: - gb
- gb.net
- gb.net.curl
- gb.qt
- gb.qt.ext
- gb.xml
Now it's time to design the layout of the aggregator, using the widgets on the right palette. We need a ComboBox to choose feeds from with a Button for reloading, a listView for the list of items of a feed and a TextView for reading the actual news. Shouldn't be too complicated, the result could be something like this:
Good, let's write some code now. The "Items" class We'll call this "class" in the gambas sense, not the object oriented sense. What we need is a kind of object that stores news data when a feed is retrieved from the net, and that can be queried for link,description and title of news. So right click on "Classes" in the left tree view of the IDE, New->Class and name it Items. And here is the code to put inside it:
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 Here we declare some arrays (descriptions,links and titles) that will store the news data. Their max size to 100 but this can be different. last_checked stores the date/time the feed has been last retrieved, and last_index and current_index the number of news contained and the currently shown news item. The Main sub, kinda contructor, initializes some of those variables. 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 Some easy actions on the feed: reset sets the cursor to the first element,clear just does what it says and next moves the cursor to the next item in the feed if there are more. 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 These retrieve data of the currently selected news item. 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 and this moves the cursor to the given index, if it exists. This is all our business logic to manage news feeds. Now let's see how to retrieve and parse them. The Form code At this point we can write the code to handle the GUI, retrieve feeds xml data, parse them and store/show data using the Items class. The code that goes in our Form1 follows.
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 We first declare an HttpClient object to retrieve feeds from the net,an Items object to store data and a feeds[] array to store feeds url. In the "Form_Open" method(the entry point for the Form) we fill the feeds url array and the combobox for choosing them. Note that we are doing this statically; obviously a more complete program would allow users to add/edit/delete feeds from the list, but let's keep it simple for now. PUBLIC SUB P_finished() DIM buffer AS String IF Lof(P) THEN READ #P, buffer, Lof(P) parseFeed(buffer) fillList()
END This method is event managed. When the HttpClient object finishes receiving data this event is generated and the method called. We define a buffer, fill it with data retrieved by HttpClient, parse it and use parsed data to fill the news list. For an explaination of parseFeed and fillList, see below. 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 These are event methods called when a selection is made on the listview or the button is clicked. In the first case we take the index of the selected item from the listview,this is also the index of the correspondent item in our Items object, so we can use it to seek the specific news item and show it in the textview. In case of a button click, we set the url of the httpclient object to that of the selected feed in the combobox, and retrieve it. 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 Now the xml parsing part. parseFeed takes the xml text as argument, create an xml document out of it, sets the root node as the current node and passes it to parseNode, which does the dirty job. is a recursive sub that takes description,link and title out of a node if this is an item node, otherwise recurses it, until it reaches the end of the xml document. Data taken from item nodes are put into our Items object. When this method finishes, we have an Items object containing all the news of the selected feed. SUB fillList() listview1.Clear items.reset WHILE items.next() listview1.Add(items.getCurrentIndex(), items.getTitle()) WEND END fillList just fills the listview with the titles of the retrieved news. You can now run/compile your program and test it. Here is how the running program looks like:
What's next The program is pretty basic and there are bugs to be fixed and enhancements to be made. In particular, referring to bugs, we're using a textView for showing news articles as it is capable of rendering html code, but as far as we're not handling mime types, images will be rendered as dark gray squares inside the textView. As for enhancements, interesting ones could be: menus, dynamic handling of feeds, auto refresh for feeds and so on. I'll maybe write a further article focusing on these points, as an opportunity to introduce other gambas components. Conclusions We've seen here how easy it is to use Gambas. You have at your fingertips both an easy, comfortable and powerful RAD and lots of nice components. This time we've used xml, http and graphical widgets, but available are: db, opengl, xsl,kde integration and all those "fancy" components you would like to have when working with a development platform.
Hasta la proxima.
|