Commit 2a8b3eca authored by Volker Krause's avatar Volker Krause
Browse files

Rework the datatype classes

This now also has a proper C++ API next to the Qt properties.
parent ea434552
#!/bin/bash
find "$@" -name '*.h' -o -name '*.cpp' -o -name '*.qml' -o -name '*.java'| grep -v /3rdparty/ | while read FILE; do
if grep -qiE "Copyright \(C\) [0-9, -]{4,} " "$FILE" ; then continue; fi
thisfile=`basename $FILE`
authorName=`git config user.name`
authorEmail=`git config user.email`
thisYear=`date +%Y`
cat <<EOF > "$FILE".tmp
/*
Copyright (C) $thisYear $authorName <$authorEmail>
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 of the License, 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 Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
EOF
cat "$FILE" >> "$FILE".tmp
mv "$FILE".tmp "$FILE"
done
ecm_add_test(datatypestest.cpp LINK_LIBRARIES Qt5::Test KItinerary)
ecm_add_test(airportdbtest.cpp LINK_LIBRARIES Qt5::Test KItinerary)
add_definitions(-DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
ecm_add_test(structureddataextractortest.cpp LINK_LIBRARIES Qt5::Test KItinerary)
......
/*
Copyright (c) 2018 Volker Krause <vkrause@kde.org>
This library 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 of the License, or (at your
option) any later version.
This library 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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include <KItinerary/BusTrip>
#include <KItinerary/Flight>
#include <KItinerary/Place>
#include <KItinerary/Reservation>
#include <KItinerary/TrainTrip>
#include <KItinerary/Ticket>
#include <KItinerary/JsonLdDocument>
#include <QDebug>
#include <QObject>
#include <QTest>
using namespace KItinerary;
class DatatypesTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testValueTypeSemantics()
{
// Place p; // must not compile
Airport airport;
// Place p = airport; // must not compile!
airport.setName(QLatin1String("Berlin Tegel"));
{
auto ap2 = airport;
QCOMPARE(ap2.name(), QLatin1String("Berlin Tegel"));
ap2.setIataCode(QLatin1String("TXL"));
QVERIFY(airport.iataCode().isEmpty());
}
QVERIFY(!airport.geo().isValid());
QCOMPARE(JsonLdDocument::readProperty(QVariant::fromValue(airport), "className").toString(), QLatin1String("Airport"));
QCOMPARE(JsonLdDocument::readProperty(QVariant::fromValue(airport), "name").toString(), QLatin1String("Berlin Tegel"));
// detach on base properties must not slice
FlightReservation res;
QCOMPARE(JsonLdDocument::readProperty(QVariant::fromValue(res), "className").toString(), QLatin1String("FlightReservation"));
res.setAirplaneSeat(QLatin1String("10E"));
QCOMPARE(res.airplaneSeat(), QLatin1String("10E"));
auto res2 = res;
QCOMPARE(res2.airplaneSeat(), QLatin1String("10E"));
res2.setReservationNumber(QLatin1String("XXX007"));
QCOMPARE(res2.airplaneSeat(), QLatin1String("10E"));
// changing default-created properties should not leak
Flight flight;
QCOMPARE(JsonLdDocument::readProperty(QVariant::fromValue(flight), "className").toString(), QLatin1String("Flight"));
auto v = QVariant::fromValue(flight);
QVERIFY(v.canConvert<Flight>());
JsonLdDocument::writeProperty(v, "departureAirport", QVariant::fromValue(airport));
QCOMPARE(v.value<Flight>().departureAirport().name(), QLatin1String("Berlin Tegel"));
// make sure all meta types are generated
TrainTrip tt;
QCOMPARE(JsonLdDocument::readProperty(QVariant::fromValue(tt), "className").toString(), QLatin1String("TrainTrip"));
BusTrip bus;
QCOMPARE(JsonLdDocument::readProperty(QVariant::fromValue(bus), "className").toString(), QLatin1String("BusTrip"));
Ticket ticket;
QCOMPARE(JsonLdDocument::readProperty(QVariant::fromValue(ticket.ticketedSeat()), "className").toString(), QLatin1String("Seat"));
}
};
QTEST_APPLESS_MAIN(DatatypesTest)
#include "datatypestest.moc"
......@@ -7,8 +7,15 @@ configure_file(config-kitinerary.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kiti
set(kitinerary_lib_srcs
airportdb/airportdb.cpp
datatypes/bustrip.cpp
datatypes/flight.cpp
datatypes/place.cpp
datatypes/reservation.cpp
datatypes/ticket.cpp
datatypes/traintrip.cpp
calendarhandler.cpp
datatypes.cpp
extractor.cpp
extractorengine.cpp
extractorfilter.cpp
......@@ -29,6 +36,7 @@ set_target_properties(KItinerary PROPERTIES
EXPORT_NAME KItinerary
)
target_include_directories(KItinerary INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF5}>")
target_include_directories(KItinerary PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
target_link_libraries(KItinerary
PUBLIC
Qt5::Core
......@@ -52,19 +60,35 @@ ecm_generate_headers(KItinerary_HEADERS
ExtractorRepository
JsonLdDocument
StructuredDataExtractor
PREFIX KItinerary
REQUIRED_HEADERS KItinerary_HEADERS
)
ecm_generate_headers(KItinerary_AirportDb_HEADERS
HEADER_NAMES
AirportDb
PREFIX KItinerary
REQUIRED_HEADERS KItinerary_AirportDb_HEADERS
RELATIVE airportdb
)
ecm_generate_headers(KItinerary_Datatypes_HEADERS
HEADER_NAMES
BusTrip
Datatypes
Flight
Reservation
Place
Ticket
TrainTrip
PREFIX KItinerary
REQUIRED_HEADERS KItinerary_Datatypes_HEADERS
RELATIVE datatypes
)
install(TARGETS KItinerary EXPORT KItineraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES
${KItinerary_HEADERS}
${KItinerary_AirportDb_HEADERS}
${KItinerary_Datatypes_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/kitinerary_export.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KItinerary
)
......@@ -18,15 +18,18 @@
*/
#include "calendarhandler.h"
#include "datatypes.h"
#include "jsonlddocument.h"
#include "semantic_debug.h"
#include <datatypes/place.h>
#include <datatypes/reservation.h>
#include <KCalCore/Alarm>
#include <KLocalizedString>
using namespace KCalCore;
using namespace KItinerary;
QDateTime CalendarHandler::startDateTime(const QVariant &reservation)
{
......@@ -248,12 +251,12 @@ void CalendarHandler::fillLodgingReservation(const QVariant &reservation, const
void CalendarHandler::fillGeoPosition(const QVariant &place, const KCalCore::Event::Ptr &event)
{
const auto geo = JsonLdDocument::readProperty(place, "geo");
if (geo.isNull()) {
const auto geo = JsonLdDocument::readProperty(place, "geo").value<GeoCoordinates>();
if (!geo.isValid()) {
return;
}
event->setHasGeo(true);
event->setGeoLatitude(JsonLdDocument::readProperty(geo, "latitude").toFloat());
event->setGeoLongitude(JsonLdDocument::readProperty(geo, "longitude").toFloat());
event->setGeoLatitude(geo.latitude());
event->setGeoLongitude(geo.longitude());
}
/*
Copyright (c) 2017 Volker Krause <vkrause@kde.org>
This library 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 of the License, or (at your
option) any later version.
This library 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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "datatypes.h"
#include <QLocale>
#include <QTimeZone>
#include <cmath>
GeoCoordinates::GeoCoordinates()
: m_latitude(NAN)
, m_longitude(NAN)
{
}
bool GeoCoordinates::isValid() const
{
return !std::isnan(m_latitude) && !std::isnan(m_longitude);
}
bool Place::operator!=(const Place &other) const
{
return m_geo != other.m_geo || m_address != other.m_address;
}
bool Airport::operator!=(const Airport &other) const
{
return m_iataCode != other.m_iataCode || m_name != other.m_name || Place::operator!=(other);
}
bool Airline::operator!=(const Airline &other) const
{
return m_iataCode != other.m_iataCode || m_name != other.m_name;
}
bool TrainStation::operator!=(const TrainStation &other) const
{
return m_name != other.m_name;
}
bool BusStation::operator!=(const BusStation &other) const
{
return m_name != other.m_name;
}
static QString localizedDateTime(const QDateTime &dt)
{
auto s = QLocale().toString(dt, QLocale::ShortFormat);
if (dt.timeSpec() == Qt::TimeZone || dt.timeSpec() == Qt::OffsetFromUTC) {
s += QLatin1Char(' ') + dt.timeZone().abbreviation(dt);
}
return s;
}
QString Flight::departureTimeLocalized() const
{
return localizedDateTime(m_departureTime);
}
QString Flight::arrivalTimeLocalized() const
{
return localizedDateTime(m_arrivalTime);
}
QString Flight::boardingTimeLocalized() const
{
auto s = QLocale().toString(m_boardingTime.time(), QLocale::ShortFormat);
if (m_boardingTime.timeSpec() == Qt::TimeZone || m_boardingTime.timeSpec() == Qt::OffsetFromUTC) {
s += QLatin1Char(' ') + m_boardingTime.timeZone().abbreviation(m_boardingTime);
}
return s;
}
QString LodgingReservation::checkinDateLocalized() const
{
return QLocale().toString(m_checkinDate.date(), QLocale::ShortFormat);
}
QString LodgingReservation::checkoutDateLocalized() const
{
return QLocale().toString(m_checkoutDate.date(), QLocale::ShortFormat);
}
QString TrainTrip::departureTimeLocalized() const
{
return QLocale().toString(m_departureTime, QLocale::ShortFormat);
}
QString TrainTrip::arrivalTimeLocalized() const
{
return QLocale().toString(m_arrivalTime, QLocale::ShortFormat);
}
QString BusTrip::departureTimeLocalized() const
{
return QLocale().toString(m_departureTime, QLocale::ShortFormat);
}
QString BusTrip::arrivalTimeLocalized() const
{
return QLocale().toString(m_arrivalTime, QLocale::ShortFormat);
}
/*
Copyright (c) 2017 Volker Krause <vkrause@kde.org>
This library 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 of the License, or (at your
option) any later version.
This library 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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef DATATYPES_H
#define DATATYPES_H
#include <QDateTime>
#include <QString>
#include <QUrl>
#include <QVariant>
#define SEMANTIC_GADGET \
Q_GADGET \
Q_PROPERTY(QString className READ className STORED false CONSTANT) \
inline QString className() const { return QString::fromUtf8(staticMetaObject.className()); }
#define SEMANTIC_PROPERTY(Type, Name) \
Q_PROPERTY(Type Name MEMBER m_##Name) \
Type m_##Name;
/** @file
* The classes in here could possibly be auto-generated from the ontology defined by http://schema.org...
*/
class GeoCoordinates
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(float, latitude)
SEMANTIC_PROPERTY(float, longitude)
public:
GeoCoordinates();
bool isValid() const;
};
class PostalAddress
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, streetAddress)
SEMANTIC_PROPERTY(QString, addressLocality)
SEMANTIC_PROPERTY(QString, postalCode)
SEMANTIC_PROPERTY(QString, addressCountry)
};
class Place
{
Q_GADGET
SEMANTIC_PROPERTY(QVariant, address)
SEMANTIC_PROPERTY(QVariant, geo)
public:
bool operator!=(const Place &other) const;
};
class Airport : protected Place
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, name)
SEMANTIC_PROPERTY(QString, iataCode)
public:
bool operator!=(const Airport &other) const;
};
class Airline {
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, name)
SEMANTIC_PROPERTY(QString, iataCode)
public:
bool operator!=(const Airline &other) const;
};
class TrainStation : protected Place
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, name)
public:
bool operator!=(const TrainStation &other) const;
};
class BusStation : protected Place
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, name)
public:
bool operator!=(const BusStation &other) const;
};
/**
* @see https://schema.org/Flight
* @see https://developers.google.com/gmail/markup/reference/flight-reservation
*/
class Flight
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, flightNumber)
SEMANTIC_PROPERTY(Airline, airline)
SEMANTIC_PROPERTY(Airport, departureAirport)
SEMANTIC_PROPERTY(QDateTime, departureTime)
SEMANTIC_PROPERTY(Airport, arrivalAirport)
SEMANTIC_PROPERTY(QDateTime, arrivalTime)
// Google extension for boarding pass data
SEMANTIC_PROPERTY(QDateTime, boardingTime)
SEMANTIC_PROPERTY(QString, departureGate)
Q_PROPERTY(QString departureTimeLocalized READ departureTimeLocalized STORED false CONSTANT)
Q_PROPERTY(QString arrivalTimeLocalized READ arrivalTimeLocalized STORED false CONSTANT)
Q_PROPERTY(QString boardingTimeLocalized READ boardingTimeLocalized STORED false CONSTANT)
private:
QString departureTimeLocalized() const;
QString arrivalTimeLocalized() const;
QString boardingTimeLocalized() const;
};
class LodgingBusiness: protected Place
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, name)
};
class TrainTrip
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, arrivalPlatform)
SEMANTIC_PROPERTY(TrainStation, arrivalStation)
SEMANTIC_PROPERTY(QDateTime, arrivalTime)
SEMANTIC_PROPERTY(QString, departurePlatform)
SEMANTIC_PROPERTY(TrainStation, departureStation)
SEMANTIC_PROPERTY(QDateTime, departureTime)
SEMANTIC_PROPERTY(QString, trainName)
SEMANTIC_PROPERTY(QString, trainNumber)
Q_PROPERTY(QString departureTimeLocalized READ departureTimeLocalized STORED false CONSTANT)
Q_PROPERTY(QString arrivalTimeLocalized READ arrivalTimeLocalized STORED false CONSTANT)
private:
QString departureTimeLocalized() const;
QString arrivalTimeLocalized() const;
};
class BusTrip
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, arrivalPlatform)
SEMANTIC_PROPERTY(BusStation, arrivalStation)
SEMANTIC_PROPERTY(QDateTime, arrivalTime)
SEMANTIC_PROPERTY(QString, departurePlatform)
SEMANTIC_PROPERTY(BusStation, departureStation)
SEMANTIC_PROPERTY(QDateTime, departureTime)
SEMANTIC_PROPERTY(QString, busName)
SEMANTIC_PROPERTY(QString, busNumber)
Q_PROPERTY(QString departureTimeLocalized READ departureTimeLocalized STORED false CONSTANT)
Q_PROPERTY(QString arrivalTimeLocalized READ arrivalTimeLocalized STORED false CONSTANT)
private:
QString departureTimeLocalized() const;
QString arrivalTimeLocalized() const;
};
class Seat
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QString, seatNumber)
SEMANTIC_PROPERTY(QString, seatRow)
SEMANTIC_PROPERTY(QString, seatSection)
};
class Ticket
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QVariant, ticketedSeat)
SEMANTIC_PROPERTY(QString, ticketToken)
};
class Reservation
{
Q_GADGET
SEMANTIC_PROPERTY(QString, reservationNumber)
SEMANTIC_PROPERTY(QVariant, reservationFor)
SEMANTIC_PROPERTY(QVariant, reservedTicket)
// Google extension
SEMANTIC_PROPERTY(QUrl, cancelReservationUrl)
SEMANTIC_PROPERTY(QUrl, modifyReservationUrl)
SEMANTIC_PROPERTY(QString, ticketToken)
SEMANTIC_PROPERTY(QUrl, url)
};
class LodgingReservation : protected Reservation
{
SEMANTIC_GADGET
SEMANTIC_PROPERTY(QDateTime, checkinDate)
SEMANTIC_PROPERTY(QDateTime, checkoutDate)
Q_PROPERTY(QString checkinDateLocalized READ checkinDateLocalized STORED false CONSTANT)
Q_PROPERTY(QString checkoutDateLocalized READ checkoutDateLocalized STORED false CONSTANT)
private:
QString checkinDateLocalized() const;
QString checkoutDateLocalized() const;
};
/**
* @see https://schema.org/FlightReservation
* @see https://developers.google.com/gmail/markup/reference/flight-reservation
*/
class FlightReservation : protected Reservation
{
SEMANTIC_GADGET
// Google extensions
SEMANTIC_PROPERTY(QString, airplaneSeat)
SEMANTIC_PROPERTY(QString, boardingGroup)
SEMANTIC_PROPERTY(QUrl, ticketDownloadUrl)
};
class TrainReservation : protected Reservation
{
SEMANTIC_GADGET
};
class BusReservation : protected Reservation
{
SEMANTIC_GADGET
};
Q_DECLARE_METATYPE(GeoCoordinates)
Q_DECLARE_METATYPE(Airport)
Q_DECLARE_METATYPE(Airline)
Q_DECLARE_METATYPE(Flight)
Q_DECLARE_METATYPE(FlightReservation)
Q_DECLARE_METATYPE(LodgingBusiness)
Q_DECLARE_METATYPE(LodgingReservation)
Q_DECLARE_METATYPE(PostalAddress)
Q_DECLARE_METATYPE(Seat)
Q_DECLARE_METATYPE(Ticket)
Q_DECLARE_METATYPE(TrainStation)
Q_DECLARE_METATYPE(TrainTrip)
Q_DECLARE_METATYPE(TrainReservation)
Q_DECLARE_METATYPE(BusStation)
Q_DECLARE_METATYPE(BusTrip)
Q_DECLARE_METATYPE(BusReservation)
#undef SEMANTIC_GADGET
#endif // DATATYPES_H
/*
Copyright (C) 2018 Volker Krause <vkrause@kde.org>
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 of the License, 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 Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "bustrip.h"
#include "place.h"