X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=application%2Fstationschedulemodel.cpp;h=27151ab9d909cf19ddc545a9a8060b859322f6a0;hb=1444c0646f63e354c4cdc3198ec86c28edc880ff;hp=314a19a42246d9cfc83d20723092d1df7ac8ef5a;hpb=013dfe2c0b14b116038a9179ffd13bb60a225577;p=quandoparte diff --git a/application/stationschedulemodel.cpp b/application/stationschedulemodel.cpp index 314a19a..27151ab 100644 --- a/application/stationschedulemodel.cpp +++ b/application/stationschedulemodel.cpp @@ -22,14 +22,32 @@ Boston, MA 02110-1301, USA. #include "stationschedulemodel.h" #include "dataprovider.h" +#include "settings.h" #include +#include +#include +#include StationScheduleModel::StationScheduleModel(const QString &name, QObject *parent) : - QStringListModel(parent), + QAbstractListModel(parent), m_name(name) { + DataProvider *provider = DataProvider::instance(); + QHash roles; + roles[TrainRole] = "train"; + roles[DepartureStationRole] = "departureStation"; + roles[DepartureTimeRole] = "departureTime"; + roles[ArrivalStationRole] = "arrivalStation"; + roles[ArrivalTimeRole] = "arrivalTime"; + roles[DetailsUrlRole] = "detailsUrl"; + roles[DelayRole] = "delay"; + roles[DelayClassRole] = "delayClassRole"; + setRoleNames(roles); + + connect(provider, SIGNAL(stationScheduleReady(QByteArray,QUrl)), + this, SLOT(parse(QByteArray,QUrl))); } QString & StationScheduleModel::name() @@ -39,24 +57,223 @@ QString & StationScheduleModel::name() void StationScheduleModel::setName(const QString &name) { - m_name = name; - emit nameChanged(); + if (name != m_name) { + m_name = name; + emit nameChanged(); + } +} + +StationScheduleModel::ScheduleType StationScheduleModel::type() +{ + return m_scheduleType; +} + +void StationScheduleModel::setType(StationScheduleModel::ScheduleType type) +{ + if (type != m_scheduleType) { + emit layoutAboutToBeChanged(); + beginResetModel(); + m_scheduleType = type; + emit typeChanged(); + endResetModel(); + emit layoutChanged(); + Settings *settings = Settings::instance(); + settings->setShowArrivalsPreferred(m_scheduleType == ArrivalSchedule ? true : false); + } +} + +static void parseDelayClass(const QWebElement &element, StationScheduleItem &item) +{ + if (!element.isNull()) { + QWebElement image = element.findFirst("img"); + if (!image.isNull()) { + int delayClass = 42; + QString imageName = image.attribute("src"); + if (!imageName.isEmpty()) { + QRegExp delayClassRegexp("pallinoRit([0-9])\\.png"); + int pos = delayClassRegexp.indexIn(imageName); + qDebug() << "regexp matched at pos:" << pos << "match:" << delayClassRegexp.cap(0); + delayClass = (pos >= 0) ? delayClassRegexp.cap(1).toInt() : 0; + } + item.setDelayClass(delayClass); + } else { + qDebug() << "img not found"; + } + } else { + qDebug() << "div.bloccotreno not found"; + } +} + +static void parseDetailsUrl(const QWebElement &element, StationScheduleItem &item) +{ + if (!element.isNull()) { + QWebElement link = element.findFirst("a"); + QString url = link.attribute("href"); + item.setDetailsUrl(url); + } else { + qDebug() << "link not found"; + } +} + +static void parseTrain(const QString &text, StationScheduleItem &item) +{ + QRegExp filter("^(Per|Da) (.*)\\n" + "Delle ore (.*)\n" + "Binario Previsto: (.*)\n" + "Binario Reale: (.*)\n" + "(.*)$"); + int pos = filter.indexIn(text); + if (pos >= 0) { + if (filter.cap(1) == "Per") { + item.setDepartureStation(filter.cap(2)); + item.setDepartureTime(filter.cap(3)); + } else { + item.setArrivalStation(filter.cap(2)); + item.setArrivalTime(filter.cap(3)); + } + item.setDelay(filter.cap(6)); + } else { + qDebug() << "could not parse" << text; + } +} + +StationScheduleItem parseResult(const QWebElement &result) +{ + StationScheduleItem item; + + QWebElement current = result.findFirst("h2"); + if (!current.isNull()) { + item.setTrain(current.toPlainText()); + } + parseDetailsUrl(result, item); + current = result.findFirst("div.bloccotreno"); + parseDelayClass(current, item); + QString rawText = current.toPlainText(); + parseTrain(rawText, item); + + qDebug() << "train:" << item.train(); + qDebug() << "delayClass:" << item.delayClass(); + qDebug() << "detailsUrl:" << item.detailsUrl(); + qDebug() << "departureStation:" << item.departureStation(); + qDebug() << "departureTime:" << item.departureTime(); + qDebug() << "arrivalStation:" << item.arrivalStation(); + qDebug() << "arrivalTime:" << item.arrivalTime(); + qDebug() << "delay:" << item.delay(); + return item; } void StationScheduleModel::parse(const QByteArray &htmlReply, const QUrl &baseUrl) { Q_UNUSED(baseUrl); qDebug() << "--- start of query result --- cut here ------"; - qDebug() << htmlReply; + qDebug() << QString::fromUtf8(htmlReply.constData()); qDebug() << "--- end of query result ----- cut here ------"; + + emit layoutAboutToBeChanged(); + beginResetModel(); + QWebPage page; + page.mainFrame()->setContent(htmlReply, "text/html", baseUrl); + QWebElement doc = page.mainFrame()->documentElement(); + + // Find the first div + QWebElement current = doc.findFirst("div"); + + QStringList departures, arrivals; + qDebug() << "skipping to the departures"; + // Skip to the first div of class corpocentrale, which contains the first + // departure-related contents + while (!current.classes().contains("corpocentrale")) { + current = current.nextSibling(); + qDebug() << "skipping to the next element"; + if (current.isNull()) + break; + } + // Mark every div as a departure class element; the next corpocentrale + // marks the start of the arrivals section + qDebug() << "marking departures"; + do { + if (current.classes().contains("bloccorisultato")) { + departures << current.toPlainText(); + StationScheduleItem schedule = parseResult(current); + if (schedule.isValid()) { + m_departureSchedules << schedule; + } + } + current = current.nextSibling(); + qDebug() << "marking as departures"; + if (current.isNull()) + break; + } while (!current.classes().contains("corpocentrale")); + + // Mark everything as an arrival, until reaching the footer + while (!current.classes().contains("footer")) { + if (current.classes().contains("bloccorisultato")) { + arrivals << current.toPlainText(); + StationScheduleItem schedule = parseResult(current); + if (schedule.isValid()) { + m_arrivalSchedules << schedule; + } + } + current = current.nextSibling(); + qDebug() << "marking as arrival"; + if (current.isNull()) + break; + } + endResetModel(); + emit layoutChanged(); } void StationScheduleModel::fetch(const QString &name) { DataProvider *provider = DataProvider::instance(); - connect(provider, SIGNAL(stationScheduleReady(QByteArray,QUrl)), - this, SLOT(parse(QByteArray,QUrl))); provider->fetchStationSchedule(name); setName(name); } + +int StationScheduleModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (m_scheduleType == DepartureSchedule) { + qDebug() << "schedule.count" << m_departureSchedules.count(); + return m_departureSchedules.count(); + } else { + qDebug() << "schedule.count" << m_arrivalSchedules.count(); + return m_arrivalSchedules.count(); + } +} + +QVariant StationScheduleModel::data(const QModelIndex &index, int role) const +{ + qDebug() << "getting data for role" << role; + if (!index.isValid()) { + return QVariant(); + } + const QList &schedules = + (m_scheduleType == DepartureSchedule) ? m_departureSchedules : m_arrivalSchedules; + if (index.row() < 0 || index.row() >= schedules.count()) { + return QVariant(); + } + StationScheduleItem item = schedules[index.row()]; + switch (role) { + case Qt::DisplayRole: + case TrainRole: + return QVariant::fromValue(item.train()); + case DepartureStationRole: + return QVariant::fromValue(item.departureStation()); + case DepartureTimeRole: + return QVariant::fromValue(item.departureTime()); + case ArrivalStationRole: + return QVariant::fromValue(item.arrivalStation()); + case ArrivalTimeRole: + return QVariant::fromValue(item.arrivalTime()); + case DetailsUrlRole: + return QVariant::fromValue(item.detailsUrl()); + case DelayRole: + return QVariant::fromValue(item.delay()); + case DelayClassRole: + return QVariant::fromValue(item.delayClass()); + default: + return QVariant::fromValue(QString("Unknown role requested")); + } +}