diff --git a/engine/departureinfo.cpp b/engine/departureinfo.cpp index 674e9f8..f2a68d8 100644 --- a/engine/departureinfo.cpp +++ b/engine/departureinfo.cpp @@ -1,369 +1,436 @@ /* * Copyright 2012 Friedrich Pülz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Header #include "departureinfo.h" // Own includes #include "global.h" // Qt includes #include PublicTransportInfo::PublicTransportInfo(QObject* parent): QObject(parent) { } PublicTransportInfo::~PublicTransportInfo() { } PublicTransportInfo::PublicTransportInfo( const QHash< Enums::TimetableInformation, QVariant >& data, Corrections corrections, QObject *parent ) : QObject(parent), m_data(data) { m_isValid = false; // Insert -1 as Delay if none is given (-1 means "no delay information available") if ( !contains(Enums::Delay) ) { insert( Enums::Delay, -1 ); } if ( corrections.testFlag(DeduceMissingValues) ) { // Guess date value if none is given, // this could produce wrong dates (better give DepartureDate in scripts) if ( !contains(Enums::DepartureDate) && contains(Enums::DepartureTime) ) { QTime departureTime = value( Enums::DepartureTime ).toTime(); if ( departureTime < QTime::currentTime().addSecs(-5 * 60) ) { qDebug() << "Guessed DepartureDate as tomorrow"; insert( Enums::DepartureDate, QDate::currentDate().addDays(1) ); } else { qDebug() << "Guessed DepartureDate as today"; insert( Enums::DepartureDate, QDate::currentDate() ); } } } if ( corrections.testFlag(CombineToPreferredValueType) ) { // Convert date value from string if not given as date if ( !contains(Enums::DepartureDateTime) ) { if ( contains(Enums::DepartureTime) ) { const QTime time = value( Enums::DepartureTime ).toTime(); QDate date; if ( contains(Enums::DepartureDate) ) { date = value( Enums::DepartureDate ).toDate(); } else if ( time < QTime::currentTime().addSecs(-5 * 60) ) { qDebug() << "Guessed DepartureDate as tomorrow"; date = QDate::currentDate().addDays( 1 ); } else { qDebug() << "Guessed DepartureDate as today"; date = QDate::currentDate(); } insert( Enums::DepartureDateTime, QDateTime(date, time) ); remove( Enums::DepartureDate ); remove( Enums::DepartureTime ); } else { qDebug() << "No DepartureDateTime or DepartureTime information given"; } } } if ( corrections.testFlag(TestValuesForCorrectFormat) ) { // Check RouteTimes values if ( contains(Enums::RouteTimes) ) { if ( value(Enums::RouteTimes).canConvert(QVariant::List) ) { QVariantList vars = value( Enums::RouteTimes ).toList(); foreach ( const QVariant &var, vars ) { // Convert from QVariant to QTime if ( !var.canConvert(QVariant::DateTime) || !var.toDateTime().isValid() ) { // Value for DepartureTime is not QDateTime qWarning() << "Invalid time in RouteTimes:" << var; remove( Enums::RouteTimes ); break; } } } else { // No list of values given for RouteTimes, remove the invalid value qWarning() << "RouteTimes value is invalid (not a list of values): " << value(Enums::RouteTimes); remove( Enums::RouteTimes ); } } } } JourneyInfo::JourneyInfo( const TimetableData &data, Corrections corrections, QObject *parent ) : PublicTransportInfo( data, corrections, parent ) { if ( corrections.testFlag(DeduceMissingValues) ) { // Guess arrival date value if none is given, // this could produce wrong dates (better give ArrivalDate eg. in scripts) if ( !contains(Enums::ArrivalDateTime) && !contains(Enums::ArrivalDate) && contains(Enums::ArrivalTime) ) { QTime arrivalTime = value(Enums::ArrivalTime).toTime(); if ( arrivalTime < QTime::currentTime().addSecs(-5 * 60) ) { insert( Enums::ArrivalDate, QDate::currentDate().addDays(1) ); } else { insert( Enums::ArrivalDate, QDate::currentDate() ); } } // Deduce Duration from DepartureDateTime and ArrivalDateTime if ( value(Enums::Duration).toInt() <= 0 && contains(Enums::DepartureDateTime) && contains(Enums::ArrivalDateTime) ) { QDateTime departure = value( Enums::DepartureDateTime ).toDateTime(); QDateTime arrival = value( Enums::ArrivalDateTime ).toDateTime(); int minsDuration = departure.secsTo( arrival ) / 60; if ( minsDuration < 0 ) { qWarning() << "Calculated duration is negative" << minsDuration << "departure" << departure << "arrival" << arrival; insert( Enums::Duration, -1 ); } else { insert( Enums::Duration, minsDuration ); } } } // TODO Move to PublicTransportInfo? ...or is it already in there? if ( corrections.testFlag(TestValuesForCorrectFormat) ) { // Test departure time format if ( contains(Enums::DepartureTime) && !value(Enums::DepartureTime).canConvert(QVariant::Time) ) { // Value for DepartureTime is not QTime qWarning() << "DepartureTime needs to be convertable to QTime:" << value(Enums::DepartureTime); remove( Enums::DepartureTime ); } // Test departure date format if ( contains(Enums::DepartureDate) && (!value(Enums::DepartureDate).canConvert(QVariant::Date) || !value(Enums::DepartureDate).toDate().isValid()) ) { qWarning() << "DepartureDate needs to be convertable to QDate:" << value( Enums::DepartureDate ); remove( Enums::DepartureDate ); } // Check ArrivalDate value if ( contains(Enums::ArrivalDate) && (!value(Enums::ArrivalDate).canConvert(QVariant::Date) || !value(Enums::ArrivalDate).toDate().isValid()) ) { qWarning() << "ArrivalDate needs to be convertable to QDate:" << value(Enums::ArrivalDate); remove( Enums::ArrivalDate ); } // Check Duration value if ( contains(Enums::Duration) && value(Enums::Duration).toInt() <= 0 && value(Enums::Duration).canConvert(QVariant::String) ) { qWarning() << "Duration needs to be convertable to int:" << value(Enums::Duration); remove( Enums::Duration ); } // Check RouteTimesDeparture values if ( contains(Enums::RouteTimesDeparture) ) { if ( !value(Enums::RouteTimesDeparture).canConvert(QVariant::List) ) { qWarning() << "Value for RouteTimesDeparture needs to be a list" << value(Enums::RouteTimesDeparture); remove( Enums::RouteTimesDeparture ); } else { QVariantList vars = value( Enums::RouteTimesDeparture ).toList(); foreach( const QVariant &var, vars ) { if ( !var.canConvert(QVariant::DateTime) ) { qWarning() << "Invalid time in RouteTimesDeparture" << var; remove( Enums::RouteTimesDeparture ); break; } } } } // Check RouteTimesArrival values if ( contains(Enums::RouteTimesArrival) ) { if ( !value(Enums::RouteTimesArrival).canConvert(QVariant::List) ) { qWarning() << "Value for RouteTimesArrival needs to be a list" << value(Enums::RouteTimesArrival); remove( Enums::RouteTimesArrival ); } else { QVariantList vars = value( Enums::RouteTimesArrival ).toList(); foreach( const QVariant &var, vars ) { if ( !var.canConvert(QVariant::DateTime) ) { qWarning() << "Invalid time in RouteTimesArrival" << var; remove( Enums::RouteTimesArrival ); break; } } } } } if ( corrections.testFlag(CombineToPreferredValueType) ) { // If the duration value is invalid, but there are departure and arrival date and time // values available, calculate the duration between departure and arrival if ( value(Enums::Duration).toInt() <= 0 && contains(Enums::DepartureDate) && contains(Enums::DepartureTime) && contains(Enums::ArrivalDate) && contains(Enums::ArrivalTime) ) { QDateTime departure( value(Enums::DepartureDate).toDate(), value(Enums::ArrivalTime).toTime() ); QDateTime arrival( value(Enums::ArrivalDate).toDate(), value(Enums::ArrivalTime).toTime() ); int minsDuration = departure.secsTo( arrival ) / 60; if ( minsDuration < 0 ) { qDebug() << "Calculated duration is negative" << minsDuration << "departure" << departure << "arrival" << arrival; insert( Enums::Duration, -1 ); } else { insert( Enums::Duration, minsDuration ); } } // Combine ArrivalTime and ArrivalDate to ArrivalDateTime if ( !contains(Enums::ArrivalDateTime) ) { if ( contains(Enums::ArrivalTime) ) { const QTime time = value( Enums::ArrivalTime ).toTime(); QDate date; if ( contains(Enums::ArrivalDate) ) { date = value( Enums::ArrivalDate ).toDate(); } else if ( time < QTime::currentTime().addSecs(-5 * 60) ) { qDebug() << "Guessed ArrivalDate as tomorrow"; date = QDate::currentDate().addDays( 1 ); } else { qDebug() << "Guessed ArrivalDate as today"; date = QDate::currentDate(); } insert( Enums::ArrivalDateTime, QDateTime(date, time) ); remove( Enums::ArrivalDate ); remove( Enums::ArrivalTime ); } else { qWarning() << "No ArrivalDateTime or ArrivalTime information given"; } } } m_isValid = contains(Enums::DepartureDateTime) && contains(Enums::ArrivalDateTime) && contains(Enums::StartStopName) && contains(Enums::TargetStopName); } +QString JourneyInfo::startStopName() +{ + TimetableData data = this->data(); + return data[Enums::StartStopName].toString(); +} + +QString JourneyInfo::destinationStopName() +{ + TimetableData data = this->data(); + return data[Enums::TargetStopName].toString(); +} + +QStringList JourneyInfo::routeStops() +{ + TimetableData data = this->data(); + return data[Enums::RouteStops].toStringList(); +} + +QStringList JourneyInfo::shortenedRouteStops() +{ + TimetableData data = this->data(); + return data[Enums::RouteStopsShortened].toStringList(); +} + StopInfo::StopInfo( QObject *parent ) : PublicTransportInfo(parent) { m_isValid = false; } StopInfo::StopInfo( const QHash< Enums::TimetableInformation, QVariant >& data, QObject *parent ) : PublicTransportInfo(parent) { m_data.unite( data ); m_isValid = contains( Enums::StopName ); } StopInfo::StopInfo( const QString &name, const QString& id, int weight, qreal longitude, qreal latitude, const QString &city, const QString &countryCode, QObject *parent ) : PublicTransportInfo(parent) { insert( Enums::StopName, name ); if ( !id.isNull() ) { insert( Enums::StopID, id ); } if ( longitude != 0.0 ) { insert( Enums::StopLongitude, longitude ); } if ( latitude != 0.0 ) { insert( Enums::StopLatitude, latitude ); } if ( !city.isNull() ) { insert( Enums::StopCity, city ); } if ( !countryCode.isNull() ) { insert( Enums::StopCountryCode, countryCode ); } if ( weight != -1 ) { insert( Enums::StopWeight, weight ); } m_isValid = !name.isEmpty(); } +QString StopInfo::stopName() +{ + TimetableData data = this->data(); + return data[Enums::StopName].toString(); +} + + DepartureInfo::DepartureInfo( QObject *parent ) : PublicTransportInfo(parent) { m_isValid = false; } DepartureInfo::DepartureInfo( const TimetableData &data, Corrections corrections, QObject *parent ) : PublicTransportInfo( data, corrections, parent ) { if ( (contains(Enums::RouteStops) || contains(Enums::RouteTimes)) && value(Enums::RouteTimes).toList().count() != value(Enums::RouteStops).toStringList().count() ) { int difference = value(Enums::RouteStops).toList().count() - value(Enums::RouteTimes).toList().count(); if ( difference > 0 ) { // More route stops than times, add invalid times qDebug() << "The script stored" << difference << "more route stops than route times " "for a departure, invalid route times will be added"; QVariantList routeTimes = value( Enums::RouteTimes ).toList(); while ( difference > 0 ) { routeTimes << QDateTime(); --difference; } } else { // More route times than stops, add empty stops qDebug() << "The script stored" << -difference << "more route times than route " "stops for a departure, empty route stops will be added"; QStringList routeStops = value( Enums::RouteStops ).toStringList(); while ( difference < 0 ) { routeStops << QString(); ++difference; } } } m_isValid = contains( Enums::TransportLine ) && contains( Enums::Target ) && contains( Enums::DepartureDateTime ); } QStringList JourneyInfo::vehicleIconNames() const { if ( !contains(Enums::TypesOfVehicleInJourney) ) { return QStringList(); } QVariantList vehicles = value( Enums::TypesOfVehicleInJourney ).toList(); QStringList iconNames; foreach( QVariant vehicle, vehicles ) { iconNames << Global::vehicleTypeToIcon( static_cast( vehicle.toInt() ) ); } return iconNames; } QStringList JourneyInfo::vehicleNames( bool plural ) const { if ( !contains( Enums::TypesOfVehicleInJourney ) ) { return QStringList(); } QVariantList vehicles = value( Enums::TypesOfVehicleInJourney ).toList(); QStringList names; foreach( QVariant vehicle, vehicles ) { names << Global::vehicleTypeToString( static_cast( vehicle.toInt() ), plural ); } return names; } + +QDate DepartureInfo::arrivalDate() +{ + TimetableData data = this->data(); + return data[Enums::ArrivalDate].toDate(); +} + +QTime DepartureInfo::arrivalTime() +{ + TimetableData data = this->data(); + return data[Enums::ArrivalTime].toTime(); +} + +QDateTime DepartureInfo::arrivalDateTime() +{ + TimetableData data = this->data(); + return data[Enums::ArrivalDateTime].toDateTime(); +} + +QDate DepartureInfo::departureDate() +{ + TimetableData data = this->data(); + return data[Enums::DepartureDate].toDate(); +} + +QTime DepartureInfo::departureTime() +{ + TimetableData data = this->data(); + return data[Enums::DepartureTime].toTime(); +} + +QDateTime DepartureInfo::departureDateTime() +{ + TimetableData data = this->data(); + return data[Enums::DepartureDateTime].toDateTime(); +} \ No newline at end of file diff --git a/engine/departureinfo.h b/engine/departureinfo.h index 6327c39..953d95f 100644 --- a/engine/departureinfo.h +++ b/engine/departureinfo.h @@ -1,206 +1,221 @@ /* * Copyright 2012 Friedrich Pülz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file * @brief This file contains classes to store departure / arrival / journey information. * @author Friedrich Pülz */ #ifndef DEPARTUREINFO_HEADER #define DEPARTUREINFO_HEADER // Own includes #include "enums.h" // Qt includes #include #include #include #include /** * @brief LineService-Flags. * @see LineService **/ Q_DECLARE_FLAGS( LineServices, Enums::LineService ) /** * @brief This is the abstract base class of all other timetable information classes. * * @see JourneyInfo * @see DepartureInfo **/ class PublicTransportInfo : public QObject { public: /** @brief Options for stop names, eg. use a shortened form or not. */ enum StopNameOptions { UseFullStopNames, /**< Use the full stop names, as received from the service provider. */ UseShortenedStopNames /**< Use a shortened form of the stop names. */ }; /** @brief Constructs a new PublicTransportInfo object. */ PublicTransportInfo( QObject *parent = 0 ); enum Correction { NoCorrection = 0x0000, DeduceMissingValues = 0x0001, TestValuesForCorrectFormat = 0x0002, CombineToPreferredValueType = 0x0004, /**< eg. combine DepartureHour and * DepartureMinute into the preferred value type DepartureTime. * TODO Update TimetableInformation enum documentation. */ CorrectEverything = DeduceMissingValues | TestValuesForCorrectFormat | CombineToPreferredValueType }; Q_DECLARE_FLAGS( Corrections, Correction ) /** * @brief Contructs a new PublicTransportInfo object based on the information given * with @p data. * * @param data A hash that contains values for TimetableInformations. **/ explicit PublicTransportInfo( const TimetableData &data, Corrections corrections = CorrectEverything, QObject *parent = 0 ); virtual ~PublicTransportInfo(); bool contains( Enums::TimetableInformation info ) const { return m_data.contains(info); }; QVariant value( Enums::TimetableInformation info ) const { return m_data[info]; }; void insert( Enums::TimetableInformation info, const QVariant &data ) { m_data.insert( info, data ); }; void remove( Enums::TimetableInformation info ) { m_data.remove(info); }; /** @brief Returns the TimetableData object for this item. */ TimetableData data() const { return m_data; }; /** * @brief Wheather or not this PublicTransportInfo object is valid. * * @return true if the PublicTransportInfo object is valid. * @return false if the PublicTransportInfo object is invalid. **/ virtual bool isValid() const { return m_isValid; }; protected: bool m_isValid; TimetableData m_data; }; /** * @brief This class stores information about journeys with public transport. * * @see DepartureInfo * @see PublicTransportInfo */ class JourneyInfo : public PublicTransportInfo { public: /** * @brief Contructs a new JourneyInfo object based on the information given with @p data. * * @param data A hash that contains values for at least the required * TimetableInformations: DepartureDateTime, ArrivalDateTime, StartStopName and * TargetStopName. Instead of DepartureDateTime, DepartureDate and DepartureTime can be used. * If only DepartureTime gets used, the date is guessed. The same is true for ArrivalDateTime. **/ explicit JourneyInfo( const TimetableData &data, Corrections corrections = CorrectEverything, QObject *parent = 0 ); QStringList vehicleIconNames() const; QStringList vehicleNames( bool plural = false ) const; + + Q_INVOKABLE QString startStopName(); + Q_INVOKABLE QString destinationStopName(); + Q_INVOKABLE QStringList routeStops(); + Q_INVOKABLE QStringList shortenedRouteStops(); }; /** * @brief This class stores information about departures / arrivals with public transport. * * @see JourneyInfo * @see PublicTransportInfo */ class DepartureInfo : public PublicTransportInfo { public: /** @brief Constructs an invalid DepartureInfo object. */ DepartureInfo( QObject *parent = 0 ); /** * @brief Contructs a new DepartureInfo object based on the information given with @p data. * * @param data A hash that contains values for at least the required * TimetableInformations: TransportLine, Target, DepartureDateTime. Instead of * DepartureDateTime, DepartureDate and DepartureTime can be used. If only DepartureTime * gets used, the date is guessed. **/ explicit DepartureInfo( const TimetableData &data, Corrections corrections = CorrectEverything, QObject *parent = 0 ); /** @brief Wheather or not the departing / arriving vehicle is a night line. */ bool isNightLine() const { return m_lineServices.testFlag( Enums::NightLine ); }; /** @brief Wheather or not the departing / arriving vehicle is an express line. */ bool isExpressLine() const { return m_lineServices.testFlag( Enums::ExpressLine ); }; + Q_INVOKABLE QDate departureDate(); + Q_INVOKABLE QTime departureTime(); + Q_INVOKABLE QDateTime departureDateTime(); + + Q_INVOKABLE QDate arrivalDate(); + Q_INVOKABLE QTime arrivalTime(); + Q_INVOKABLE QDateTime arrivalDateTime(); + private: LineServices m_lineServices; }; /** * @brief Stores information about a stop. Used for stop suggestions. * * @see DepartureInfo * @see JourneyInfo **/ class StopInfo : public PublicTransportInfo { public: /** @brief Constructs an invalid StopInfo object. */ StopInfo( QObject *parent = 0 ); /** * @brief Contructs a new StopInfo object based on the information given with @p data. * * @param data A hash that contains values for at least the required TimetableInformations * (StopName). */ StopInfo( const QHash &data, QObject *parent = 0 ); /** * @brief Constructs a new StopInfo object. * * @param name The name of the stop. * @param id The ID for the stop @p name, if available. * @param weight The weight of this stop suggestion, if available. Higher values are set for * more important / better matching stops. * @param city The city in which the stop is, if available. * @param countryCode The code of the country in which the stop is, if available. */ StopInfo( const QString &name, const QString &id = QString(), int weight = -1, qreal longitude = 0.0, qreal latitude = 0.0, const QString &city = QString(), const QString &countryCode = QString(), QObject *parent = 0 ); + + Q_INVOKABLE QString stopName(); }; typedef DepartureInfo ArrivalInfo; typedef QSharedPointer< PublicTransportInfo > PublicTransportInfoPtr; typedef QSharedPointer< DepartureInfo > DepartureInfoPtr; typedef QSharedPointer< ArrivalInfo > ArrivalInfoPtr; typedef QSharedPointer< JourneyInfo > JourneyInfoPtr; typedef QSharedPointer< StopInfo > StopInfoPtr; typedef QList< PublicTransportInfoPtr > PublicTransportInfoList; typedef QList< DepartureInfoPtr > DepartureInfoList; typedef QList< ArrivalInfoPtr > ArrivalInfoList; typedef QList< JourneyInfoPtr > JourneyInfoList; typedef QList< StopInfoPtr > StopInfoList; #endif // DEPARTUREINFO_HEADER