Parse the train number, to start and see how to proceed
[quandoparte] / application / stationschedulemodel.cpp
1 /*
2
3 Copyright (C) 2011 Luciano Montanaro <mikelima@cirulla.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING.  If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19
20 */
21
22 #include "stationschedulemodel.h"
23
24 #include "dataprovider.h"
25
26 #include <QDebug>
27 #include <QWebElement>
28 #include <QWebFrame>
29 #include <QWebPage>
30 StationScheduleModel::StationScheduleModel(const QString &name, QObject *parent) :
31     QAbstractListModel(parent),
32     m_name(name)
33
34 {
35     DataProvider *provider = DataProvider::instance();
36     QHash<int, QByteArray> roles;
37     roles[TrainRole] = "train";
38     roles[DepartureStationRole] = "departureStation";
39     roles[DepartureTimeRole] = "departureTime";
40     roles[ArrivalStationRole] = "arrivalStation";
41     roles[ArrivalTimeRole] = "ArrivalTime";
42     roles[DetailsUrlRole] = "DetailsUrl";
43     roles[DelayRole] = "delay";
44     roles[DelayClassRole] = "delayClassRole";
45     setRoleNames(roles);
46
47     connect(provider, SIGNAL(stationScheduleReady(QByteArray,QUrl)),
48             this, SLOT(parse(QByteArray,QUrl)));
49 }
50
51 QString & StationScheduleModel::name()
52 {
53     return m_name;
54 }
55
56 void StationScheduleModel::setName(const QString &name)
57 {
58     if (name != m_name) {
59         m_name = name;
60         emit nameChanged();
61     }
62 }
63
64 StationScheduleItem parseResult(const QWebElement &result)
65 {
66     StationScheduleItem item;
67     qDebug() << "result:" << result.toPlainText();
68     QWebElement current = result.findFirst("h2");
69     if (!current.isNull()) {
70         item.setTrain(current.toPlainText());
71     }
72     qDebug() << "train:" << item.train();
73     return item;
74 }
75
76 void StationScheduleModel::parse(const QByteArray &htmlReply, const QUrl &baseUrl)
77 {
78     Q_UNUSED(baseUrl);
79     qDebug() << "--- start of query result --- cut here ------";
80     qDebug() << QString::fromUtf8(htmlReply.constData());
81     qDebug() << "--- end of query result ----- cut here ------";
82
83     emit layoutAboutToBeChanged();
84     beginInsertRows(QModelIndex(), 0, 0);
85     QWebPage page;
86     page.mainFrame()->setContent(htmlReply, "text/html", baseUrl);
87     QWebElement doc = page.mainFrame()->documentElement();
88
89     // Find the first div
90     QWebElement current = doc.findFirst("div");
91
92     QStringList departures, arrivals;
93     qDebug() << "skipping to the departures";
94     // Skip to the first div of class corpocentrale, which contains the first
95     // departure-related contents
96     while (!current.classes().contains("corpocentrale")) {
97         current = current.nextSibling();
98         qDebug() << "skipping to the next element";
99         if (current.isNull())
100             break;
101     }
102     // Mark every div as a departure class element; the next corpocentrale
103     // marks the start of the arrivals section
104     qDebug() << "marking departures";
105     do {
106         if (current.classes().contains("bloccorisultato")) {
107             departures << current.toPlainText();
108             StationScheduleItem schedule = parseResult(current);
109             if (schedule.isValid()) {
110                 m_schedules << schedule;
111             }
112         }
113         current = current.nextSibling();
114         qDebug() << "marking as departures";
115         if (current.isNull())
116             break;
117     } while (!current.classes().contains("corpocentrale"));
118
119     // Mark everything as an arrival, until reaching the footer
120     while (!current.classes().contains("footer")) {
121         if (current.classes().contains("bloccorisultato")) {
122             arrivals << current.toPlainText();
123         }
124         current = current.nextSibling();
125         qDebug() << "marking as arrival";
126         if (current.isNull())
127             break;
128     }
129
130     //qDebug() << "departures list contain:";
131     //qDebug() << departures;
132     //qDebug() << "arrivals list contain:";
133     //qDebug() << arrivals;
134     emit layoutChanged();
135     endInsertRows();
136 }
137
138 void StationScheduleModel::fetch(const QString &name)
139 {
140     DataProvider *provider = DataProvider::instance();
141
142     provider->fetchStationSchedule(name);
143     setName(name);
144 }
145
146 int StationScheduleModel::rowCount(const QModelIndex &parent) const
147 {
148     qDebug() << "there are" << m_schedules.count() << "schedules";
149     return m_schedules.count();
150 }
151
152 QVariant StationScheduleModel::data(const QModelIndex &index, int role) const
153 {
154     qDebug() << "getting data for role" << role;
155     if (!index.isValid()) {
156         return QVariant();
157     }
158     if (index.row() > m_schedules.count()) {
159         return QVariant();
160     }
161     StationScheduleItem item = m_schedules[index.row()];
162     switch (role) {
163     case Qt::DisplayRole:
164     case TrainRole:
165         return QVariant::fromValue(item.train());
166     case DepartureStationRole:
167         return QVariant::fromValue(item.departureStation());
168     case DepartureTimeRole:
169         return QVariant::fromValue(item.departureTime());
170     case ArrivalStationRole:
171         return QVariant::fromValue(item.arrivalStation());
172     case ArrivalTimeRole:
173         return QVariant::fromValue(item.arrivalTime());
174     case DetailsUrlRole:
175         return QVariant::fromValue(item.detailsUrl());
176     case DelayRole:
177         return QVariant::fromValue(item.delay());
178     case DelayClassRole:
179         return QVariant::fromValue(item.delayClass());
180     default:
181         return QVariant::fromValue(QString("Unknown role requested"));
182     }
183 }