IndoorMapPage.qml 10.6 KB
Newer Older
Volker Krause's avatar
Volker Krause committed
1
/*
2
    SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
Volker Krause's avatar
Volker Krause committed
3

4
    SPDX-License-Identifier: LGPL-2.0-or-later
Volker Krause's avatar
Volker Krause committed
5
6
7
8
9
*/

import QtQuick 2.12
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.1 as QQC2
10
import org.kde.kirigami 2.17 as Kirigami
11
import org.kde.solidextras 1.0 as Solid
12
import org.kde.kpublictransport 1.0 as PT
Volker Krause's avatar
Volker Krause committed
13
14
import org.kde.kosmindoormap 1.0
import org.kde.itinerary 1.0
15
import org.kde.kosmindoormap.kpublictransport 1.0
Volker Krause's avatar
Volker Krause committed
16
17

Kirigami.Page {
Volker Krause's avatar
Volker Krause committed
18
    id: root
Volker Krause's avatar
Volker Krause committed
19
    title: {
20
        if (map.mapLoader.isLoading || map.hasError || map.floorLevels.rowCount() == 0)
Volker Krause's avatar
Volker Krause committed
21
22
23
24
25
26
27
28
29
30
            return placeName;
        if (map.floorLevels.hasName(map.view.floorLevel))
            return map.floorLevels.name(map.view.floorLevel);
        return i18n("Floor %1", map.floorLevels.name(map.view.floorLevel));
    }

    property point coordinate
    property string placeName
    property alias map: map

Volker Krause's avatar
Volker Krause committed
31
32
33
34
35
    property string arrivalGateName
    property string arrivalPlatformName
    property string departureGateName
    property string departurePlatformName

Volker Krause's avatar
Volker Krause committed
36
37
    property string region
    property string timeZone
38
39
40
    property date beginTime
    property date endTime

Volker Krause's avatar
Volker Krause committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
    topPadding: 0
    bottomPadding: 0
    leftPadding: 0
    rightPadding: 0

    // prevent swipe to the right changing pages, we want to pan the map instead
    // TODO in theory we could make this conditional to having panned the map all the way to the right
    Kirigami.ColumnView.preventStealing: true

    actions {
        left: Kirigami.Action {
            iconName: "go-down-symbolic"
            enabled: map.floorLevels.hasFloorLevelBelow(map.view.floorLevel)
            onTriggered: map.view.floorLevel = map.floorLevels.floorLevelBelow(map.view.floorLevel)
55
            visible: map.floorLevels.hasFloorLevels
Volker Krause's avatar
Volker Krause committed
56
57
58
59
60
        }
        right: Kirigami.Action {
            iconName: "go-up-symbolic"
            enabled: map.floorLevels.hasFloorLevelAbove(map.view.floorLevel)
            onTriggered: map.view.floorLevel = map.floorLevels.floorLevelAbove(map.view.floorLevel)
61
            visible: map.floorLevels.hasFloorLevels
Volker Krause's avatar
Volker Krause committed
62
63
        }
    }
64
    contextualActions: [
65
66
67
68
69
70
71
72
73
74
75
76
77
78
        Kirigami.Action {
            id: zoomInAction
            text: i18n("Zoom In")
            iconName: "zoom-in-symbolic"
            onTriggered: map.view.setZoomLevel(map.view.zoomLevel + 1, Qt.point(map.width / 2.0, map.height/ 2.0));
            enabled: map.view.zoomLevel < 21
        },
        Kirigami.Action {
            id: zoomOutAction
            text: i18n("Zoom Out")
            iconName: "zoom-out-symbolic"
            onTriggered: map.view.setZoomLevel(map.view.zoomLevel - 1, Qt.point(map.width / 2.0, map.height/ 2.0));
            enabled: map.view.zoomLevel > 14
        },
79
80
81
82
83
84
85
86
87
88
89
        Kirigami.Action {
            id: platformAction
            text: i18n("Find Platform")
            onTriggered: platformSheet.sheetOpen = true
            visible: !platformModel.isEmpty
        },
        Kirigami.Action {
            id: gateAction
            text: i18n("Find Gate")
            onTriggered: gateSheet.sheetOpen = true
            visible: !gateModel.isEmpty
90
        },
91
        Kirigami.Action { separator: true },
92
93
94
95
96
97
98
99
        Kirigami.Action {
            id: equipmentAction
            text: i18n("Show Elevator Status")
            checkable: true
            enabled: !map.mapLoader.isLoading && Solid.NetworkStatus.connectivity != Solid.NetworkStatus.No
            icon.color: Solid.NetworkStatus.metered != Solid.NetworkStatus.No ? Kirigami.Theme.neutralTextColor : Kirigami.Theme.textColor
            onTriggered: queryLiveLocationData();
        },
100
101
102
103
        Kirigami.Action {
            id: rentalVehicleAction
            text: i18n("Show Rental Vehicles")
            checkable: true
104
105
106
            enabled: !map.mapLoader.isLoading && Solid.NetworkStatus.connectivity != Solid.NetworkStatus.No
            icon.color: Solid.NetworkStatus.metered != Solid.NetworkStatus.No ? Kirigami.Theme.neutralTextColor : Kirigami.Theme.textColor
            onTriggered: queryLiveLocationData();
107
        },
108
109
110
111
112
        Kirigami.Action { separator: true },
        Kirigami.Action {
            text: i18n("Open Map");
            onTriggered: NavigationController.showOnMap(map.mapData.center.y, map.mapData.center.x, 18);
        },
113
114
115
116
117
        Kirigami.Action {
            text: i18n("Open wheelmap.org");
            onTriggered: NavigationController.showOnWheelmap(map.mapData.center.y, map.mapData.center.x);
        },

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
        Kirigami.Action {
            id: lightStyleAction
            text: "Light Style"
            onTriggered: map.styleSheet = "breeze-light"
            visible: Settings.developmentMode
        },
        Kirigami.Action {
            id: darkStyleAction
            text: "Dark Style"
            onTriggered: map.styleSheet = "breeze-dark"
            visible: Settings.developmentMode
        },
        Kirigami.Action {
            id: diagnosticStyleAction
            text: "Diagnostic Style"
            onTriggered: map.styleSheet = "diagnostic"
            visible: Settings.developmentMode
135
136
        }
    ]
Volker Krause's avatar
Volker Krause committed
137
138
139

    OSMElementInformationModel {
        id: infoModel
Volker Krause's avatar
Volker Krause committed
140
        debug: Settings.developmentMode
Volker Krause's avatar
Volker Krause committed
141
142
    }

143
    IndoorMapInfoSheet {
Volker Krause's avatar
Volker Krause committed
144
        id: elementDetailsSheet
145
        model: infoModel
146
        mapData: map.mapData
Volker Krause's avatar
Volker Krause committed
147
148
    }

149
150
151
    PlatformModel {
        id: platformModel
        mapData: map.mapData
Volker Krause's avatar
Volker Krause committed
152
153
154
155
156
157

        onPlatformIndexChanged: {
            if (platformModel.departurePlatformRow >= 0) {
                var idx = platformModel.index(platformModel.departurePlatformRow, 0);
                map.view.floorLevel = platformModel.data(idx, PlatformModel.LevelRole)
                map.view.centerOnGeoCoordinate(platformModel.data(idx, PlatformModel.CoordinateRole));
158
159
160
161
162
163
                map.view.setZoomLevel(19, Qt.point(map.width / 2.0, map.height / 2.0));
            } else if (root.departurePlatformName == "" && platformModel.arrivalPlatformRow >= 0) {
                var idx = platformModel.index(platformModel.arrivalPlatformRow, 0);
                map.view.floorLevel = platformModel.data(idx, PlatformModel.LevelRole)
                map.view.centerOnGeoCoordinate(platformModel.data(idx, PlatformModel.CoordinateRole));
                map.view.setZoomLevel(19, Qt.point(map.width / 2.0, map.height / 2.0));
Volker Krause's avatar
Volker Krause committed
164
165
            }
        }
166
167
    }

168
    IndoorMapPlatformSheet {
169
        id: platformSheet
170
        model: platformModel
171
172
173
174
175
    }

    GateModel {
        id: gateModel
        mapData: map.mapData
Volker Krause's avatar
Volker Krause committed
176
177
178
179
180
181

        onGateIndexChanged: {
            if (gateModel.departureGateRow >= 0) {
                var idx = gateModel.index(gateModel.departureGateRow, 0);
                map.view.floorLevel = gateModel.data(idx, GateModel.LevelRole)
                map.view.centerOnGeoCoordinate(gateModel.data(idx, GateModel.CoordinateRole));
182
183
184
185
186
187
                map.view.setZoomLevel(18, Qt.point(map.width / 2.0, map.height / 2.0));
            } else if (root.departureGateName == "" && platformModel.arrivalGateRow >= 0) {
                var idx = platformModel.index(platformModel.arrivalGateRow, 0);
                map.view.floorLevel = platformModel.data(idx, PlatformModel.LevelRole)
                map.view.centerOnGeoCoordinate(platformModel.data(idx, PlatformModel.CoordinateRole));
                map.view.setZoomLevel(19, Qt.point(map.width / 2.0, map.height / 2.0));
Volker Krause's avatar
Volker Krause committed
188
189
            }
        }
190
191
    }

192
    IndoorMapGateSheet {
193
        id: gateSheet
194
        model: gateModel
195
196
    }

197
198
199
200
201
202
203
204
205
206
207
    FloorLevelChangeModel {
        id: floorLevelChangeModel
        currentFloorLevel: map.view.floorLevel
        floorLevelModel: map.floorLevels
    }

    IndoorMapElevatorSheet {
        id: elevatorSheet
        model: floorLevelChangeModel
    }

208
209
    LocationQueryOverlayProxyModel {
        id: locationModel
210
        sourceModel: PT.LocationQueryModel {
211
212
213
214
215
216
            id: locationQuery
            manager: LiveDataManager.publicTransportManager
        }
        mapData: map.mapData
    }

217
218
219
220
221
222
223
    RealtimeEquipmentModel {
        id: equipmentModel
        mapData: map.mapData
        realtimeModel: locationModel.sourceModel
    }

    function queryLiveLocationData()
224
    {
225
        if (rentalVehicleAction.checked || equipmentAction.checked) {
226
227
228
            locationQuery.request.latitude = map.mapData.center.y;
            locationQuery.request.longitude = map.mapData.center.x;
            locationQuery.request.maximumDistance = map.mapData.radius;
229
230
231
            locationQuery.request.types =
                (rentalVehicleAction.checked ? (PT.Location.RentedVehicleStation | PT.Location.RentedVehicle) : 0)
              | (equipmentAction.checked ? PT.Location.Equipment : 0);
232
        } else {
233
            locationQuery.clear();
234
235
236
        }
    }

Volker Krause's avatar
Volker Krause committed
237
238
239
    IndoorMap {
        id: map
        anchors.fill: parent
240
        overlaySources: [ gateModel, platformModel, locationModel, equipmentModel ]
Volker Krause's avatar
Volker Krause committed
241
242
243
244
245
246
247
248
249
250
251
252
253
254

        IndoorMapScale {
            map: map
            anchors.left: map.left
            anchors.top: map.top
            width: 0.3 * map.width
        }

        IndoorMapAttributionLabel {
            anchors.right: map.right
            anchors.bottom: map.bottom
        }

        onElementPicked: {
255
256
257
258
259
260
261
262
263
264
            floorLevelChangeModel.element = element;
            if (floorLevelChangeModel.hasSingleLevelChange) {
                showPassiveNotification(i18n("Switched to floor %1", floorLevelChangeModel.destinationLevelName), "short");
                map.view.floorLevel = floorLevelChangeModel.destinationLevel;
                return;
            } else if (floorLevelChangeModel.hasMultipleLevelChanges) {
                elevatorSheet.sheetOpen = true;
                return;
            }

Volker Krause's avatar
Volker Krause committed
265
266
267
268
269
            infoModel.element = element;
            if (infoModel.name != "" || infoModel.debug) {
                elementDetailsSheet.sheetOpen = true;
            }
        }
270
271
272
273
274
275
276
        onElementLongPressed: {
            // this provides info model access for elements with other interactions
            infoModel.element = element;
            if (infoModel.name != "" || infoModel.debug) {
                elementDetailsSheet.sheetOpen = true;
            }
        }
Volker Krause's avatar
Volker Krause committed
277
278
279
    }

    onCoordinateChanged: map.mapLoader.loadForCoordinate(coordinate.y, coordinate.x);
Volker Krause's avatar
Volker Krause committed
280
281
282
283
284
285
286
287

    Connections {
        target: map.mapLoader
        function onDone() {
            platformModel.setArrivalPlatform(root.arrivalPlatformName, Platform.Rail);
            platformModel.setDeparturePlatform(root.departurePlatformName, Platform.Rail);
            gateModel.setArrivalGate(root.arrivalGateName);
            gateModel.setDepartureGate(root.departureGateName);
Volker Krause's avatar
Volker Krause committed
288
289
            map.region = root.region;
            map.timeZone = root.timeZone;
290
291
            map.view.beginTime = root.beginTime;
            map.view.endTime = root.endTime;
292
            queryLiveLocationData();
Volker Krause's avatar
Volker Krause committed
293
294
        }
    }
Volker Krause's avatar
Volker Krause committed
295
}