Commit 62c87941 authored by Volker Krause's avatar Volker Krause

Port the QML facing API of timeline model to batches too

This ensures we are always using the batch id for batch operations, rather
than a random one of the batch, which isn't guaranteed to work. With this
live data access for multi-traveler batches should work correctly too.
parent 3a171a4d
......@@ -169,7 +169,7 @@ private Q_SLOTS:
QCOMPARE(model.rowCount(), 4);
// delete a split element
const auto resId = model.data(model.index(1, 0), TimelineModel::ReservationIdsRole).toStringList().value(0);
const auto resId = model.data(model.index(1, 0), TimelineModel::BatchIdRole).toString();
QVERIFY(!resId.isEmpty());
resMgr.removeReservation(resId);
QCOMPARE(rmSpy.size(), 4);
......@@ -211,7 +211,7 @@ private Q_SLOTS:
QCOMPARE(model.index(4, 0).data(TimelineModel::ElementTypeRole), TimelineModel::TodayMarker);
// remove the GB flight should also remove the GB country info
auto resId = model.index(1, 0).data(TimelineModel::ReservationIdsRole).toStringList().value(0);
auto resId = model.index(1, 0).data(TimelineModel::BatchIdRole).toString();
resMgr.removeReservation(resId);
QCOMPARE(model.rowCount(), 3);
QCOMPARE(model.index(0, 0).data(TimelineModel::ElementTypeRole), TimelineModel::CountryInfo);
......@@ -219,7 +219,7 @@ private Q_SLOTS:
QCOMPARE(model.index(2, 0).data(TimelineModel::ElementTypeRole), TimelineModel::TodayMarker);
// remove the US flight should also remove the US country info
resId = model.index(1, 0).data(TimelineModel::ReservationIdsRole).toStringList().value(0);
resId = model.index(1, 0).data(TimelineModel::BatchIdRole).toString();
resMgr.removeReservation(resId);
QCOMPARE(model.rowCount(), 1);
QCOMPARE(model.index(0, 0).data(TimelineModel::ElementTypeRole), TimelineModel::TodayMarker);
......@@ -361,9 +361,9 @@ private Q_SLOTS:
QCOMPARE(fc.dateTime(), QDateTime(QDate::currentDate().addDays(5), QTime(0, 0)));
// clean up
auto resId = model.index(13, 0).data(TimelineModel::ReservationIdsRole).toStringList().value(0);
auto resId = model.index(13, 0).data(TimelineModel::BatchIdRole).toString();
resMgr.removeReservation(resId);
resId = model.index(4, 0).data(TimelineModel::ReservationIdsRole).toStringList().value(0);
resId = model.index(4, 0).data(TimelineModel::BatchIdRole).toString();
resMgr.removeReservation(resId);
QCOMPARE(model.rowCount(), 11);
......@@ -401,8 +401,8 @@ private Q_SLOTS:
QCOMPARE(model.index(0, 0).data(TimelineModel::ElementTypeRole), TimelineModel::Flight);
QCOMPARE(model.index(1, 0).data(TimelineModel::ElementTypeRole), TimelineModel::Flight);
QCOMPARE(model.index(2, 0).data(TimelineModel::ElementTypeRole), TimelineModel::TodayMarker);
QCOMPARE(model.index(0, 0).data(TimelineModel::ReservationIdsRole).toStringList().size(), 2);
QCOMPARE(model.index(1, 0).data(TimelineModel::ReservationIdsRole).toStringList().size(), 2);
QCOMPARE(resMgr.reservationsForBatch(model.index(0, 0).data(TimelineModel::BatchIdRole).toString()).size(), 2);
QCOMPARE(resMgr.reservationsForBatch(model.index(1, 0).data(TimelineModel::BatchIdRole).toString()).size(), 2);
// already existing data
model.setReservationManager(nullptr);
......@@ -411,13 +411,13 @@ private Q_SLOTS:
QCOMPARE(model.index(0, 0).data(TimelineModel::ElementTypeRole), TimelineModel::Flight);
QCOMPARE(model.index(1, 0).data(TimelineModel::ElementTypeRole), TimelineModel::Flight);
QCOMPARE(model.index(2, 0).data(TimelineModel::ElementTypeRole), TimelineModel::TodayMarker);
QCOMPARE(model.index(0, 0).data(TimelineModel::ReservationIdsRole).toStringList().size(), 2);
QCOMPARE(model.index(1, 0).data(TimelineModel::ReservationIdsRole).toStringList().size(), 2);
QCOMPARE(resMgr.reservationsForBatch(model.index(0, 0).data(TimelineModel::BatchIdRole).toString()).size(), 2);
QCOMPARE(resMgr.reservationsForBatch(model.index(1, 0).data(TimelineModel::BatchIdRole).toString()).size(), 2);
// update splits element
updateSpy.clear();
insertSpy.clear();
auto resId = model.index(1, 0).data(TimelineModel::ReservationIdsRole).toStringList().value(0);
auto resId = model.index(1, 0).data(TimelineModel::BatchIdRole).toString();
QVERIFY(!resId.isEmpty());
auto res = resMgr.reservation(resId).value<FlightReservation>();
auto flight = res.reservationFor().value<Flight>();
......@@ -467,25 +467,25 @@ private Q_SLOTS:
model.setWeatherForecastManager(&weatherMgr);
ModelVerificationPoint vp0(QLatin1String(SOURCE_DIR "/data/timeline/daychange-r0.model"));
vp0.setRoleFilter({TimelineModel::ReservationIdsRole});
vp0.setRoleFilter({TimelineModel::BatchIdRole});
QVERIFY(vp0.verify(&model));
// changing the day should move the today marker
model.setCurrentDateTime(QDateTime({2196, 10, 15}, {0, 15}));
ModelVerificationPoint vp1(QLatin1String(SOURCE_DIR "/data/timeline/daychange-r1.model"));
vp1.setRoleFilter({TimelineModel::ReservationIdsRole});
vp1.setRoleFilter({TimelineModel::BatchIdRole});
QVERIFY(vp1.verify(&model));
// load something to define the current location, so we get weather
resMgr.importReservation(readFile(QLatin1String(SOURCE_DIR "/data/flight-txl-lhr-sfo.json")));
ModelVerificationPoint vp2(QLatin1String(SOURCE_DIR "/data/timeline/daychange-r2.model"));
vp2.setRoleFilter({TimelineModel::ReservationIdsRole});
vp2.setRoleFilter({TimelineModel::BatchIdRole});
QVERIFY(vp2.verify(&model));
// changing the day should move the today marker and weather one day forward
model.setCurrentDateTime(QDateTime({2196, 10, 16}, {19, 30}));
ModelVerificationPoint vp3(QLatin1String(SOURCE_DIR "/data/timeline/daychange-r3.model"));
vp3.setRoleFilter({TimelineModel::ReservationIdsRole});
vp3.setRoleFilter({TimelineModel::BatchIdRole});
QVERIFY(vp3.verify(&model));
}
......@@ -521,7 +521,7 @@ private Q_SLOTS:
// check state is correct for data imported at the start
ModelVerificationPoint vp(QLatin1String(SOURCE_DIR "/data/timeline/") + baseName + QLatin1String(".model"));
vp.setRoleFilter({TimelineModel::ReservationIdsRole, TimelineModel::TripGroupIdRole});
vp.setRoleFilter({TimelineModel::BatchIdRole, TimelineModel::TripGroupIdRole});
QVERIFY(vp.verify(&model));
// retry with loading during runtime
......
......@@ -91,22 +91,22 @@ private Q_SLOTS:
proxy.expand(addSpy.at(2).at(0).toString());
ModelVerificationPoint vp0(QLatin1String(SOURCE_DIR "/data/tripgroupproxy/expand-collapse-r0.model"));
vp0.setRoleFilter({TimelineModel::ReservationIdsRole, TimelineModel::TripGroupIdRole});
vp0.setRoleFilter({TimelineModel::BatchIdRole, TimelineModel::TripGroupIdRole});
QVERIFY(vp0.verify(&proxy));
proxy.collapse(addSpy.at(0).at(0).toString());
ModelVerificationPoint vp1(QLatin1String(SOURCE_DIR "/data/tripgroupproxy/expand-collapse-r1.model"));
vp1.setRoleFilter({TimelineModel::ReservationIdsRole, TimelineModel::TripGroupIdRole});
vp1.setRoleFilter({TimelineModel::BatchIdRole, TimelineModel::TripGroupIdRole});
QVERIFY(vp1.verify(&proxy));
proxy.collapse(addSpy.at(1).at(0).toString());
ModelVerificationPoint vp2(QLatin1String(SOURCE_DIR "/data/tripgroupproxy/expand-collapse-r2.model"));
vp2.setRoleFilter({TimelineModel::ReservationIdsRole, TimelineModel::TripGroupIdRole});
vp2.setRoleFilter({TimelineModel::BatchIdRole, TimelineModel::TripGroupIdRole});
QVERIFY(vp2.verify(&proxy));
proxy.collapse(addSpy.at(2).at(0).toString());
ModelVerificationPoint vp3(QLatin1String(SOURCE_DIR "/data/tripgroupproxy/expand-collapse-r3.model"));
vp3.setRoleFilter({TimelineModel::ReservationIdsRole, TimelineModel::TripGroupIdRole});
vp3.setRoleFilter({TimelineModel::BatchIdRole, TimelineModel::TripGroupIdRole});
QVERIFY(vp3.verify(&proxy));
proxy.expand(addSpy.at(2).at(0).toString());
......
......@@ -71,7 +71,7 @@ App.TimelineDelegate {
Component {
id: detailsComponent
App.BusPage {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -41,7 +41,7 @@ App.DetailsPage {
// ticket barcode
App.TicketTokenDelegate {
Kirigami.FormData.isSection: true
resIds: root.resIds
resIds: _reservationManager.reservationsForBatch(root.batchId)
}
// departure data
......
......@@ -71,7 +71,7 @@ App.TimelineDelegate {
Component {
id: detailsComponent
App.CarRentalPage {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -25,10 +25,10 @@ import "." as App
Kirigami.ScrollablePage {
id: root
/** One ore more ids of the reservations shown in this element. */
property var resIds
/** The reservation batch identifier (@see ReservationManager). */
property var batchId
/** @deprecated */
readonly property var reservation: _reservationManager.reservation(root.resIds[0]);
readonly property var reservation: _reservationManager.reservation(batchId);
/** Reservation::reservationFor, unique for all travelers on a multi-traveler reservation set */
readonly property var reservationFor: reservation.reservationFor
property var editor
......@@ -48,7 +48,7 @@ Kirigami.ScrollablePage {
text: i18n("Delete")
icon.name: "edit-delete"
onClicked: {
_reservationManager.removeReservations(root.resIds);
_reservationManager.removeBatch(root.batchId);
applicationWindow().pageStack.pop();
}
}
......
......@@ -25,9 +25,9 @@ import "." as App
Kirigami.ScrollablePage {
id: root
property var resIds
readonly property string resId: resIds[0]
readonly property var reservation: _reservationManager.reservation(root.resId);
property var batchId
property var resIds: _reservationManager.reservationsForBatch(root.batchId)
readonly property var reservation: _reservationManager.reservation(root.batchId);
property alias dateTimeEditSheet: _dateTimeEditSheet
......@@ -35,7 +35,7 @@ Kirigami.ScrollablePage {
main: Kirigami.Action {
iconName: "document-save"
onTriggered: {
root.save(resId, reservation);
root.save(batchId, reservation);
pageStack.pop();
}
}
......
......@@ -61,7 +61,7 @@ App.TimelineDelegate {
Component {
id: detailsComponent
App.EventPage {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -40,7 +40,7 @@ App.DetailsPage {
App.TicketTokenDelegate {
Kirigami.FormData.isSection: true
resIds: root.resIds
resIds: _reservationManager.reservationsForBatch(root.batchId)
}
QQC2.Label {
......
......@@ -110,7 +110,7 @@ App.TimelineDelegate {
Component {
id: detailsComponent
App.FlightPage {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -26,9 +26,10 @@ import "." as App
App.DetailsPage {
id: root
title: i18n("Flight")
property var resIds: _reservationManager.reservationsForBatch(root.batchId)
editor: Component {
App.FlightEditor {
resIds: root.resIds
batchId: root.batchId
}
}
......@@ -46,7 +47,7 @@ App.DetailsPage {
// ticket barcode
App.TicketTokenDelegate {
Kirigami.FormData.isSection: true
resIds: root.resIds
resIds: _reservationManager.reservationsForBatch(root.batchId)
}
// flight details
......
......@@ -58,7 +58,7 @@ App.TimelineDelegate {
Component {
id: detailsComponent
App.HotelPage {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -52,7 +52,7 @@ App.TimelineDelegate {
Component {
id: detailsComponent
App.RestaurantPage {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -28,7 +28,7 @@ App.DetailsPage {
title: i18n("Restaurant Reservation")
editor: Component {
App.RestaurantEditor {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -24,12 +24,14 @@ import "." as App
Kirigami.AbstractCard {
id: root
/** One ore more ids of the reservations shown in this element. */
property var resIds
/** Reservation batch identifier (@see _reservationManager). */
property var batchId
/** All reservations that are part of this patch. */
property var resIds: _reservationManager.reservationsForBatch(root.batchId)
/** A random reservation object, in case there's more than one.
* Use this only for accessing properties that will be the same for all travlers.
*/
readonly property var reservation: _reservationManager.reservation(root.resIds[0]);
readonly property var reservation: _reservationManager.reservation(root.batchId);
/** Reservation::reservationFor, unique for all travelers on a multi-traveler reservation set */
readonly property var reservationFor: reservation.reservationFor
property var rangeType
......
......@@ -41,56 +41,56 @@ Kirigami.ScrollablePage {
Component {
id: flightDelegate
App.FlightDelegate {
resIds: modelData.reservationIds
batchId: modelData.batchId
rangeType: modelData.rangeType
}
}
Component {
id: hotelDelegate
App.HotelDelegate {
resIds: modelData.reservationIds
batchId: modelData.batchId
rangeType: modelData.rangeType
}
}
Component {
id: trainDelegate
App.TrainDelegate {
resIds: modelData.reservationIds
batchId: modelData.batchId
rangeType: modelData.rangeType
}
}
Component {
id: busDelegate
App.BusDelegate {
resIds: modelData.reservationIds
batchId: modelData.batchId
rangeType: modelData.rangeType
}
}
Component {
id: restaurantDelegate
App.RestaurantDelegate {
resIds: modelData.reservationIds
batchId: modelData.batchId
rangeType: modelData.rangeType
}
}
Component {
id: touristAttractionDelegate
App.TouristAttractionDelegate {
resIds: modelData.reservationIds
batchId: modelData.batchId
rangeType: modelData.rangeType
}
}
Component {
id: eventDelegate
App.EventDelegate {
resIds: modelData.reservationIds
batchId: modelData.batchId
rangeType: modelData.rangeType
}
}
Component {
id: carRentalDelegate
App.CarRentalDelegate {
resIds: modelData.reservationIds
batchId: modelData.batchId
rangeType: modelData.rangeType
}
}
......
......@@ -24,7 +24,7 @@ import "." as App
App.TimelineDelegate {
id: root
readonly property var touristAttraction: _reservationManager.reservation(root.resIds[0]).touristAttraction
readonly property var touristAttraction: _reservationManager.reservation(root.batchId).touristAttraction
headerIconSource: "meeting-attending" // TODO better icon, e.g. something like 🎢?
headerItem: RowLayout {
......@@ -53,7 +53,7 @@ App.TimelineDelegate {
Component {
id: detailsComponent
App.TouristAttractionPage {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -25,7 +25,7 @@ import "." as App
App.DetailsPage {
id: root
readonly property var touristAttraction: _reservationManager.reservation(root.resIds[0]).touristAttraction
readonly property var touristAttraction: _reservationManager.reservation(root.batchId).touristAttraction
title: i18n("Tourist Attraction")
Kirigami.FormLayout {
......
......@@ -24,8 +24,8 @@ import "." as App
App.TimelineDelegate {
id: root
property var arrival: _liveDataManager.arrival(resIds[0])
property var departure: _liveDataManager.departure(resIds[0])
property var arrival: _liveDataManager.arrival(batchId)
property var departure: _liveDataManager.departure(batchId)
headerIconSource: "qrc:///images/train.svg"
headerItem: RowLayout {
......@@ -104,7 +104,7 @@ App.TimelineDelegate {
Component {
id: detailsComponent
App.TrainPage {
resIds: root.resIds
batchId: root.batchId
}
}
......
......@@ -26,8 +26,8 @@ import "." as App
App.DetailsPage {
id: root
title: i18n("Train Ticket")
property var arrival: _liveDataManager.arrival(resIds[0])
property var departure: _liveDataManager.departure(resIds[0])
property var arrival: _liveDataManager.arrival(batchId)
property var departure: _liveDataManager.departure(batchId)
Kirigami.FormLayout {
width: root.width
......@@ -43,7 +43,7 @@ App.DetailsPage {
// ticket barcode
App.TicketTokenDelegate {
Kirigami.FormData.isSection: true
resIds: root.resIds
resIds: _reservationManager.reservationsForBatch(root.batchId)
}
// departure data
......
......@@ -245,12 +245,6 @@ void ReservationManager::removeReservation(const QString& id)
m_reservations.remove(id);
}
void ReservationManager::removeReservations(const QStringList& ids)
{
for (const auto &id : ids)
removeReservation(id);
}
const std::vector<QString>& ReservationManager::batches() const
{
return m_batches;
......
......@@ -52,7 +52,6 @@ public:
Q_INVOKABLE void addReservation(const QVariant &res);
Q_INVOKABLE void updateReservation(const QString &resId, const QVariant &res);
Q_INVOKABLE void removeReservation(const QString &id);
Q_INVOKABLE void removeReservations(const QStringList &ids);
void importReservation(const QByteArray &data);
void importReservations(const QVector<QVariant> &resData);
......
......@@ -220,8 +220,8 @@ QVariant TimelineModel::data(const QModelIndex& index, int role) const
}
return i18nc("weekday, date", "%1, %2", QLocale().dayName(elem.dt.date().dayOfWeek(), QLocale::LongFormat), QLocale().toString(elem.dt.date(), QLocale::ShortFormat));
}
case ReservationIdsRole:
return m_resMgr->reservationsForBatch(elem.batchId);
case BatchIdRole:
return elem.batchId;
case ElementTypeRole:
return elem.elementType;
case TodayEmptyRole:
......@@ -269,7 +269,7 @@ QHash<int, QByteArray> TimelineModel::roleNames() const
{
auto names = QAbstractListModel::roleNames();
names.insert(SectionHeader, "sectionHeader");
names.insert(ReservationIdsRole, "reservationIds");
names.insert(BatchIdRole, "batchId");
names.insert(ElementTypeRole, "type");
names.insert(TodayEmptyRole, "isTodayEmpty");
names.insert(IsTodayRole, "isToday");
......
......@@ -38,7 +38,7 @@ class TimelineModel : public QAbstractListModel
public:
enum Role {
SectionHeader = Qt::UserRole + 1,
ReservationIdsRole,
BatchIdRole,
ElementTypeRole,
TodayEmptyRole,
IsTodayRole,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment