Commit f72d460e authored by Volker Krause's avatar Volker Krause
Browse files

Pick suitable defaults for new journeys based on the timeline position

This pre-selects date/time, the country for searching stops and the
departure stop if available based on the current timeline position,
as long as that is in the future.
parent ca4e234c
Pipeline #112780 passed with stage
in 1 minute and 20 seconds
......@@ -52,6 +52,7 @@
"state": "Pending",
"to": {
"@type": "Location",
"country": "DE",
"latitude": 52.55970001220703,
"longitude": 13.287799835205078,
"name": "Tegel",
......
......@@ -164,6 +164,7 @@
"state": "Pending",
"to": {
"@type": "Location",
"country": "DE",
"latitude": 52.55379867553711,
"longitude": 13.29319953918457,
"name": "Tegel",
......@@ -253,6 +254,7 @@
"floatingLocationType": "Reservation",
"from": {
"@type": "Location",
"country": "FI",
"latitude": 60.315799713134766,
"longitude": 24.968599319458008,
"name": "Helsinki-Vantaa",
......@@ -401,6 +403,7 @@
"state": "Pending",
"to": {
"@type": "Location",
"country": "FI",
"latitude": 60.315799713134766,
"longitude": 24.968599319458008,
"name": "Helsinki-Vantaa",
......@@ -490,6 +493,7 @@
"floatingLocationType": "FavoriteLocation",
"from": {
"@type": "Location",
"country": "DE",
"latitude": 52.55379867553711,
"longitude": 13.29319953918457,
"name": "Tegel",
......
......@@ -16,6 +16,14 @@ Kirigami.Page {
id: root
property var publicTransportManager
/**
* Pre-selected country in the location pickers.
* If not specified the country from the current locale is used.
*/
property string initialCountry
/** Pre-selected departure time. */
property date initialDateTime: new Date()
property var departureStop
property var arrivalStop
......@@ -47,6 +55,7 @@ Kirigami.Page {
StopPickerPage {
title: i18nc("departure train station", "Select Departure Stop")
publicTransportManager: root.publicTransportManager
initialCountry: root.initialCountry
// force a deep copy, otherwise this breaks as soon as the other stop picker page is shown...
onLocationChanged: root.departureStop = PublicTransport.copyLocation(location);
}
......@@ -56,6 +65,7 @@ Kirigami.Page {
StopPickerPage {
title: i18nc("arrival train station", "Select Arrival Stop")
publicTransportManager: root.publicTransportManager
initialCountry: root.initialCountry
onLocationChanged: root.arrivalStop = PublicTransport.copyLocation(location)
}
}
......@@ -105,9 +115,11 @@ Kirigami.Page {
Layout.fillWidth: true
Addon.DateInput {
id: dateInput
selectedDate: root.initialDateTime
}
Addon.TimeInput {
id: timeInput
value: root.initialDateTime
}
}
}
......
......@@ -14,6 +14,11 @@ import org.kde.kpublictransport 1.0
Kirigami.ScrollablePage {
id: root
property var publicTransportManager
/**
* Initially selected country.
* If not specified the country from the current locale is used.
*/
property string initialCountry: Qt.locale().name.match(/_([A-Z]{2})/)[1]
property var location
QQC2.ActionGroup { id: sortActionGroup }
......@@ -85,9 +90,8 @@ Kirigami.ScrollablePage {
}
width: parent ? parent.width : undefined
}
// TODO prefer previous itinerary location if known
Component.onCompleted: {
countryCombo.currentIndex = countryCombo.indexOfValue(Qt.locale().name.match(/_([A-Z]{2})/)[1])
countryCombo.currentIndex = countryCombo.indexOfValue(root.initialCountry)
}
}
Kirigami.SearchField {
......
......@@ -35,7 +35,44 @@ Kirigami.ScrollablePage {
text: i18n("Add train trip...")
iconName: "list-add-symbolic"
visible: Settings.developmentMode
onTriggered: applicationWindow().pageStack.push(Qt.resolvedUrl("JourneyRequestPage.qml"), { publicTransportManager: LiveDataManager.publicTransportManager })
onTriggered: {
// find date/time at the current screen center
var row = -1;
for (var i = listView.contentY + listView.height * 0.8; row == -1 && i > listView.contentY; i -= 10) {
row = listView.indexAt(0, i);
}
const idx = listView.model.index(row, 0);
var dt = listView.model.data(idx, TimelineModel.StartDateTimeRole);
// clamp to future times and round to the next plausible hour
const now = new Date();
if (!dt || dt.getTime() < now.getTime()) {
dt = now;
}
const HOUR = 60 * 60 * 1000;
if (dt.getTime() % HOUR == 0 && dt.getHours() == 0) {
dt.setTime(dt.getTime() + HOUR * 8);
} else {
dt.setTime(dt.getTime() + HOUR - (dt.getTime() % HOUR));
}
// determine where we are at that time
const place = TimelineModel.locationAtTime(dt);
var country = Settings.homeCountryIsoCode;
var departureLocation;
if (place) {
country = place.address.addressCountry;
departureLocation = PublicTransport.locationFromPlace(place, undefined);
departureLocation.name = place.name;
}
applicationWindow().pageStack.push(Qt.resolvedUrl("JourneyRequestPage.qml"), {
publicTransportManager: LiveDataManager.publicTransportManager,
initialCountry: country,
initialDateTime: dt,
departureStop: departureLocation
});
}
}
]
}
......
......@@ -63,15 +63,15 @@ KPublicTransport::Location PublicTransport::locationFromPlace(const QVariant& pl
if (JsonLd::isA<FlightReservation>(reservation) || JsonLd::isA<TrainReservation>(reservation) || JsonLd::isA<BusReservation>(reservation)) {
loc.setName(KItinerary::LocationUtil::name(place));
} else {
const auto addr = KItinerary::LocationUtil::address(place);
loc.setStreetAddress(addr.streetAddress());
loc.setPostalCode(addr.postalCode());
loc.setLocality(addr.addressLocality());
loc.setRegion(addr.addressRegion());
loc.setCountry(addr.addressCountry());
}
const auto addr = KItinerary::LocationUtil::address(place);
loc.setStreetAddress(addr.streetAddress());
loc.setPostalCode(addr.postalCode());
loc.setLocality(addr.addressLocality());
loc.setRegion(addr.addressRegion());
loc.setCountry(addr.addressCountry());
const auto geo = KItinerary::LocationUtil::geo(place);
loc.setCoordinate(geo.latitude(), geo.longitude());
......
......@@ -38,7 +38,7 @@ public:
* @param reservation The enclosing reservation object of this place.
* This matters to decide how to interpret the name/address/etc of the place.
*/
static KPublicTransport::Location locationFromPlace(const QVariant &place, const QVariant &reservation);
Q_INVOKABLE static KPublicTransport::Location locationFromPlace(const QVariant &place, const QVariant &reservation);
/** Create a KItinerary place type from the given KPublicTransport::Location. */
template <typename T>
......
......@@ -205,7 +205,7 @@ QVariant TimelineModel::data(const QModelIndex& index, int role) const
const auto &elem = m_elements.at(index.row());
switch (role) {
case SectionHeader:
case SectionHeaderRole:
// see TimelineSectionDelegateController
return elem.dt.date().toString(Qt::ISODate);
case BatchIdRole:
......@@ -257,6 +257,8 @@ QVariant TimelineModel::data(const QModelIndex& index, int role) const
return elem.content();
}
break;
case StartDateTimeRole:
return elem.dt;
}
return {};
}
......@@ -264,7 +266,7 @@ QVariant TimelineModel::data(const QModelIndex& index, int role) const
QHash<int, QByteArray> TimelineModel::roleNames() const
{
auto names = QAbstractListModel::roleNames();
names.insert(SectionHeader, "sectionHeader");
names.insert(SectionHeaderRole, "sectionHeader");
names.insert(BatchIdRole, "batchId");
names.insert(ElementTypeRole, "type");
names.insert(TodayEmptyRole, "isTodayEmpty");
......
......@@ -31,7 +31,7 @@ class TimelineModel : public QAbstractListModel
public:
enum Role {
SectionHeader = Qt::UserRole + 1,
SectionHeaderRole = Qt::UserRole + 1,
BatchIdRole,
ElementTypeRole,
TodayEmptyRole,
......@@ -43,7 +43,9 @@ public:
TripGroupIdRole,
TripGroupRole,
TransferRole,
StartDateTimeRole,
};
Q_ENUM(Role)
explicit TimelineModel(QObject *parent = nullptr);
~TimelineModel() override;
......@@ -65,7 +67,7 @@ public:
QString currentBatchId() const;
/** The location we are in at the given date/time. */
QVariant locationAtTime(const QDateTime &dt) const;
Q_INVOKABLE QVariant locationAtTime(const QDateTime &dt) const;
// for unit testing
void setCurrentDateTime(const QDateTime &dt);
......
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