📜 ⬆️ ⬇️

Writing a desktop widget under Maemo5 on Qt. Part one

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.
image
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:

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.
image
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.
image
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:

Disadvantages:

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_rf
Run 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:
image
It differs from the canonical implementation , but it is not very difficult to understand .

Implementation.


That's what I ended up with:
image
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):
image
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:

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 .

Source: https://habr.com/ru/post/98091/


All Articles