Good day habrachelovek. I continue to write articles about the N900. This time I address it to the developers. And not only to developers for the N900, but to all developers in general.
I’m addressing all the developers, as there is a lot of controversy that writing for the N900 isn’t promising. At least I got the impression after reading the comments in the discussions of
my previous article . Here in this article I will try to show that it is not.

In this and the next article I will demonstrate how to create an application for the N900 on Qt. And this is not a simple application, but a desktop widget. Baseline data will be:
- lack of knowledge of Hildon and GTK;
- lack of specific knowledge of mobile platforms in general;
- little knowledge of developing desktop applications in Qt / C ++ or in any other language (in this case, you will have to spend a little more time reading Qt documentation);
- a little assiduity and interest (although this is the last point, but it is clear that it is the most important).
Thus, I intend to demonstrate that building Qt applications really does not require knowledge of the specifics of the platform in the vast majority of cases. And if the application uses only Qt API, then it is absolutely portable between the officially supported platforms.
Introduction
And so, what will we do?
I decided to kill two birds with one stone: not only to prove my point of view (what to write for the N900 is easy and promising), but also to make the application I need. And this application - the schedule of movement of electric trains. It is simple enough to make an introductory course on the basis of it and useful enough to improve my life (and I hope someone else).
I often use electric trains (I don’t have to stand in traffic jams and have the opportunity to read or watch movies, since I don’t need to concentrate on driving), but those who drive this type of transport know that sometimes you get into a situation where there is a big pause between the trains. and you have to wait on the platform (the platform in this case is a concrete structure, so that it would be more convenient to enter high railway cars, and not a
computer platform ). The presence in your pocket schedule of the nearest trains can improve the situation.

Naturally it will be more convenient if the application is in the N900 in the most prominent place - on the desktop. This can be implemented by making the application in the form of a widget. In addition, we will write on Qt, since this is the official development tool for Maemo5 (despite the fact that Maemo5 is a GTK / Hildon platform).
Moreover, the application can be easily converted into a plasmoid or just a small utility that will hang and show the schedule on the desktop. Anyway, this application is not limited to trains. Maybe someone uses buses that go on a schedule or any other type of transport (maybe even a ferry :-)).
Where to get the schedule?
Before proceeding with the design of the application, it is necessary to determine where to get the information itself.

Considering that the application should not be tied to a specific schedule provider (at least for now), since this can take a lot of time from the organizational side, I decided to devote a minimum of time to this issue and focus on developing the application itself. The easiest option that immediately catches the eye is to write an application - which parses the html page with the schedule and converts it to a single view that the application understands.
Advantages of the approach:
- the application is not tied to a specific source of information (it may not even be an html page);
- allows you to transparently scale the application without changing the source code (for example, you can provide an application from static content, a web service or a proxy service).
Disadvantages:
- you need to independently monitor the relevance of the content and write a converter for each source of the schedule;
- the schedule is static, simply as a “station to station” type table, that is, if you need to go from station 1 to station 2, you need one schedule, and if you already want to see the schedule from station 1 to station 3 (even if you are traveling through the station 2), then you need another separate schedule;
- There is no possibility to select a schedule from the program itself.
Given the shortcomings of the approach, I immediately decided that this was all temporary. And later it will be necessary to rework the data format in such a way as to be able to dynamically select the following points.
What are we going to parse? I was immediately struck by the
service from Yandex and the presence of a
mobile version convinced me that this is the easiest source for writing and debugging an application. But to my disappointment, I found that in this way I violate the
user agreement from Yandex . It clearly states:
The materials posted on the website of the Service (hereinafter - the Materials) are intended solely for personal non-commercial use. At the same time, any copying, reproduction, processing, distribution, placement in free access (publication) on the Internet, any use in the media and / or for commercial purposes without the prior written permission of the copyright holder is prohibited.
Therefore, I warn you that you cannot use my parser, it violates this user agreement. It should be used only for informational purposes with the principle of the application.
Later I found legal sources of information, at least in these sources I did not find information that use for my own purposes is prohibited. For example,
directly on the site of the Russian Railways there is a schedule of suburban trains in the xls format (but without prompt changes in the schedule). Plus in the user agreement from Yandex is a list of sources of information. I didn’t find any restrictions on the use of the information provided on many of them either. Therefore, I believe that these are legal sources. But they are scattered and motley. Therefore, we take Yandex as a starting point, although not legal.
Parser Yandex.
Since the solution with the parser for Yandex is a temporary solution, and the main task at the moment is to create a Qt-widget on the desktop, I decided to devote a minimum of time to this issue. The easiest solution for me was to write a parser in Python using the Beautiful Soap library. I ask python connoisseurs to evaluate the code and make their corrections, if necessary. Since I am not a python connoisseur, I will be very grateful for any constructive criticism.
You can see the code
here .
To get the necessary xml output, you need to “feed” the script with the desired URL of the mobile timetable from Yandex. For example, the URL for the timetable for the Leningrad direction from Ostankino station to Khovrino is:
m.rasp.yandex.ru/suburban_search?direction=msk_len&station_from_suggest=&station_to_suggest=&station_to=9603505&mode=all_station_rfRun the script:
python ./rasp.py " m.rasp.yandex.ru/suburban_search?direction=msk_len&station_from_suggest=&station_to_suggest=&station_to=9603505&mode=all&station_from=9603877 "
and get the xml output.
< rasp name =" " >
< train >
< time >
11:04
</ time >
< url >
not realized
</ url >
< note >
</ note >
</ train >
.......................
</ rasp >
* This source code was highlighted with Source Code Highlighter .
')
Then we put this file in the network (on your hosting or somewhere else, from where it will be available at the URL). I put it in the
dropbox public folder .
All data preparation is complete. The file of the format we need lies in the network and is available at the above address. Now you can go to the design of the application.
Design.
The appearance of the application, I think should be simple and clear. In the header of the article you can see the drawing of the widget, which I took
from the article on the development of desktop widgets for Maemo .
It's simple: a list of the nearest electric trains with departure times, notes (canceled, only on weekends and so on) and when you click you can go to the page / tab with the route of this particular train (bus or plane).
Below are three buttons: the previous schedule, update and the next schedule. At a minimum, you will need 2 schedules: back and forth.
If there are designers ready to draw this widget - I will be very happy. Need substrates and buttons and a general view with the names and sizes of fonts. If there are no such people, you will have to invent them yourself. Design reward - contributing studio / person to co-developers. Who knows, maybe this project will grow into a serious product.
The interior design is also not original. I used the standard for Qt MVC template and standard classes that implement it. Qt's MVC implementation looks like this:

It differs from the
canonical implementation , but it
is not very difficult to understand .
Implementation.
That's what I ended up with:

According to the scheme, it can be traced that the information from the site is parsed by the Python script and is provided in the form of the above xml file to the application via http.
RaspParser is a QXmlStreamReader descendant that parses this xml. Analysis is carried out by the recursive descent technique. This is a Qt implementation of the
Pull parser .
The entire main part of the implementation fits into several lines:
void RaspParser::readRaspItem()
{
Q_ASSERT(xml.isStartElement() && xml.name() == "train" );
RaspItem theItem;
while (xml.readNextStartElement()) {
if (xml.name() == "time" )
theItem.time = QTime::fromString(xml.readElementText().trimmed(), "hh:mm" );
else if (xml.name() == "url" )
theItem.url = QUrl(xml.readElementText().trimmed());
else if (xml.name() == "note" )
theItem.note = xml.readElementText().trimmed();
else
xml.skipCurrentElement();
}
items->append(theItem);
}
* This source code was highlighted with Source Code Highlighter .
The data is returned to the model - YandexHttpRaspModel (the name is not successful, it is possible that it will refactor). This is a QAbstractListModel heir that returns the departure time of the trains. To ensure the operation of the model, it is necessary to block several methods:
int rowCount ( const QModelIndex & parent = QModelIndex() ) const ;
QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const ;
* This source code was highlighted with Source Code Highlighter .
The implementation also does not strike the imagination:
int YandexHttpRaspModel::rowCount ( const QModelIndex & parent) const
{
Q_UNUSED(parent);
Q_D( const YandexHttpRaspModel);
return d->items.count();
}
QVariant YandexHttpRaspModel::data ( const QModelIndex & index, int role) const
{
Q_D( const YandexHttpRaspModel);
if (!index.isValid())
return QVariant();
if (index.row() >= d->items.size())
return QVariant();
if (role == Qt::DisplayRole)
return d->items.at(index.row()).time;
else if (role == Qt::UserRole+1)
return d->items.at(index.row()).note;
else if (role == Qt::UserRole+2)
return d->items.at(index.row()).url;
else
return QVariant();
}
* This source code was highlighted with Source Code Highlighter .
But a little clarification is needed. The class is written using the pimpl template
I described earlier . It also has a
private slot .
The data method involved two roles: Qt :: UserRole + 1 and Qt :: UserRole + 2. Since we have 3 fields (time, note and link), and a model in the form of a one-dimensional list, the delegate will need to somehow find out information about the note and link (“departure time” is returned directly as data, through the role of Qt :: DisplayRole ) if necessary. It is through these roles that the delegate will be able to access this data.
Of course, it could be done in the form of a table and not a list, but in this case I decided that the list represents the data, and how to display additional information is the task of the delegate (according to the template).
And the last link in the link: QListView. This is a standard Qt widget for displaying information from a model that provides information in the form of a list (inherited from QAbstractListModel).
The delegate, for a beautiful display of information, while we will not implement.
Result.
As a result of the build and launch, you should get something like this application (the application is only desktop):

At this stage, I consider the first part completed. We have a practically working application (or rather, a prototype) capable of displaying information about the timetable in the form of a list.
Time Spent:
Schedule search and schedule sources - 1 hour.
Writing a parser on python - 15 minutes.
Writing and debugging applications - 1 hour.
Total costs in the first stage: 2 hours and 15 minutes of pure time.
Please note that writing this paper with the design, including creating images, took me about 6 hours of clean time.
What we will do in the next article.
There is still plenty of work to complete the second part (it is impossible to completely complete the development of the application, the last 1 percent of development lasts forever). At least 2 hours.
Here is the estimated list:
- arrange the application as a widget on the desktop for the N900;
- make the address settings from where to ship (now "zahardkozheno");
- make a delegate to display beautiful items and buttons (really looking forward to participating designers to participate);
- make the display from the current time point, the functionality of the "nearest trains";
- make several bookmarks, several schedules with settings for each one and implement the “previous” and “next” schedule buttons;
- display the names of the schedule and the direction itself.
I think after the implementation of these points, the application can be considered to have passed to the preliminary alpha stage.
In the comments waiting for feedback, comments and suggestions.
PS: source codes for this first stage can
be found here .