Warning, /pim/itinerary/src/app/IndoorMapPage.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 import QtQuick
0008 import QtQuick.Layouts
0009 import QtQuick.Controls as QQC2
0010 import org.kde.kirigami as Kirigami
0011 import org.kde.kirigamiaddons.components as Components
0012 import org.kde.solidextras as Solid
0013 import org.kde.kpublictransport as PT
0014 import org.kde.kosmindoormap
0015 import org.kde.itinerary
0016 import org.kde.kosmindoormap.kpublictransport
0017 import org.kde.osm.editorcontroller
0018 
0019 Kirigami.Page {
0020     id: root
0021     title: {
0022         if (map.mapLoader.isLoading || map.hasError || map.floorLevels.rowCount() == 0)
0023             return placeName;
0024         if (map.floorLevels.hasName(map.view.floorLevel))
0025             return map.floorLevels.name(map.view.floorLevel);
0026         return i18n("Floor %1", map.floorLevels.name(map.view.floorLevel));
0027     }
0028 
0029     property point coordinate
0030     property string placeName
0031     property alias map: map
0032 
0033     property string arrivalGateName
0034     property alias arrivalPlatformName: platformModel.arrivalPlatform.name
0035     property alias arrivalPlatformMode: platformModel.arrivalPlatform.mode
0036     property alias arrivalPlatformIfopt: platformModel.arrivalPlatform.ifopt
0037 
0038     property string departureGateName
0039     property alias departurePlatformName: platformModel.departurePlatform.name
0040     property alias departurePlatformMode: platformModel.departurePlatform.mode
0041     property alias departurePlatformIfopt: platformModel.departurePlatform.ifopt
0042 
0043     property string region
0044     property string timeZone
0045     property date beginTime
0046     property date endTime
0047 
0048     topPadding: 0
0049     bottomPadding: 0
0050     leftPadding: 0
0051     rightPadding: 0
0052 
0053     // prevent swipe to the right changing pages, we want to pan the map instead
0054     // TODO in theory we could make this conditional to having panned the map all the way to the right
0055     Kirigami.ColumnView.preventStealing: true
0056 
0057     actions: [
0058         Kirigami.Action {
0059             id: zoomInAction
0060             text: i18n("Zoom In")
0061             icon.name: "zoom-in-symbolic"
0062             onTriggered: map.view.setZoomLevel(map.view.zoomLevel + 1, Qt.point(map.width / 2.0, map.height/ 2.0));
0063             enabled: map.view.zoomLevel < 21
0064         },
0065         Kirigami.Action {
0066             id: zoomOutAction
0067             text: i18n("Zoom Out")
0068             icon.name: "zoom-out-symbolic"
0069             onTriggered: map.view.setZoomLevel(map.view.zoomLevel - 1, Qt.point(map.width / 2.0, map.height/ 2.0));
0070             enabled: map.view.zoomLevel > 14
0071         },
0072         Kirigami.Action {
0073             id: platformAction
0074             icon.name: "search"
0075             text: i18n("Find Platform")
0076             onTriggered: platformSheet.open()
0077             visible: !platformModel.isEmpty
0078         },
0079         Kirigami.Action {
0080             id: gateAction
0081             icon.name: "search"
0082             text: i18n("Find Gate")
0083             onTriggered: gateSheet.open()
0084             visible: !gateModel.isEmpty
0085         },
0086         Kirigami.Action {
0087             id: amenityAction
0088             icon.name: "search"
0089             text: i18n("Find Amenity")
0090             onTriggered: amenitySheet.open()
0091         },
0092         Kirigami.Action { separator: true },
0093         Kirigami.Action {
0094             id: equipmentAction
0095             text: i18n("Show Elevator Status")
0096             checkable: true
0097             enabled: !map.mapLoader.isLoading && Solid.NetworkStatus.connectivity != Solid.NetworkStatus.No
0098             icon.color: Solid.NetworkStatus.metered != Solid.NetworkStatus.No ? Kirigami.Theme.neutralTextColor : Kirigami.Theme.textColor
0099             onTriggered: queryLiveLocationData();
0100         },
0101         Kirigami.Action {
0102             id: rentalVehicleAction
0103             icon.name: "car"
0104             text: i18n("Show Rental Vehicles")
0105             checkable: true
0106             enabled: !map.mapLoader.isLoading && Solid.NetworkStatus.connectivity != Solid.NetworkStatus.No
0107             icon.color: Solid.NetworkStatus.metered != Solid.NetworkStatus.No ? Kirigami.Theme.neutralTextColor : Kirigami.Theme.textColor
0108             onTriggered: queryLiveLocationData();
0109         },
0110         Kirigami.Action { separator: true },
0111         Kirigami.Action {
0112             text: i18n("Open Map");
0113             icon.name: "map-globe"
0114             onTriggered: NavigationController.showOnMap(map.mapData.center.y, map.mapData.center.x, 18);
0115         },
0116         Kirigami.Action {
0117             icon.name: "kaccess"
0118             text: i18n("Open wheelmap.org");
0119             onTriggered: NavigationController.showOnWheelmap(map.mapData.center.y, map.mapData.center.x);
0120         },
0121 
0122         Kirigami.Action {
0123             separator: true
0124             visible: Settings.osmContributorMode || Settings.developmentMode
0125         },
0126         Kirigami.Action {
0127             text: i18n("Edit with iD")
0128             icon.name: "document-edit"
0129             visible: Settings.osmContributorMode
0130             onTriggered: Settings.osmContributorMode && EditorController.editBoundingBox(root.map.view.mapSceneToGeo(root.map.view.viewport), Editor.ID)
0131         },
0132         Kirigami.Action {
0133             text: i18n("Edit with JOSM")
0134             icon.name: "org.openstreetmap.josm"
0135             visible: Settings.osmContributorMode && EditorController.hasEditor(Editor.JOSM)
0136             onTriggered: EditorController.editBoundingBox(root.map.view.mapSceneToGeo(root.map.view.viewport), Editor.JOSM)
0137         },
0138         Kirigami.Action {
0139             text: i18n("Edit with Vespucci")
0140             icon.name: "document-edit"
0141             visible: Settings.osmContributorMode && EditorController.hasEditor(Editor.Vespucci)
0142             onTriggered: EditorController.editBoundingBox(root.map.view.mapSceneToGeo(root.map.view.viewport), Editor.Vespucci)
0143         },
0144 
0145         Kirigami.Action {
0146             id: lightStyleAction
0147             icon.name: "lighttable"
0148             text: "Light Style"
0149             onTriggered: map.styleSheet = "breeze-light"
0150             visible: Settings.developmentMode
0151         },
0152         Kirigami.Action {
0153             id: darkStyleAction
0154             icon.name: "lighttable"
0155             text: "Dark Style"
0156             onTriggered: map.styleSheet = "breeze-dark"
0157             visible: Settings.developmentMode
0158         },
0159         Kirigami.Action {
0160             id: diagnosticStyleAction
0161             icon.name: "tools-report-bug"
0162             text: "Diagnostic Style"
0163             onTriggered: map.styleSheet = "diagnostic"
0164             visible: Settings.developmentMode
0165         }
0166     ]
0167 
0168     OSMElementInformationModel {
0169         id: infoModel
0170         debug: Settings.developmentMode
0171     }
0172 
0173     IndoorMapInfoSheet {
0174         id: elementDetailsSheet
0175         model: infoModel
0176         mapData: map.mapData
0177         parent: root.overlay
0178     }
0179 
0180     PlatformModel {
0181         id: platformModel
0182         mapData: map.mapData
0183 
0184         onPlatformIndexChanged: {
0185             if (platformModel.departurePlatformRow >= 0) {
0186                 var idx = platformModel.index(platformModel.departurePlatformRow, 0);
0187                 map.view.floorLevel = platformModel.data(idx, PlatformModel.LevelRole)
0188                 map.view.centerOnGeoCoordinate(platformModel.data(idx, PlatformModel.CoordinateRole));
0189                 map.view.setZoomLevel(19, Qt.point(map.width / 2.0, map.height / 2.0));
0190             } else if (root.departurePlatformName == "" && platformModel.arrivalPlatformRow >= 0) {
0191                 var idx = platformModel.index(platformModel.arrivalPlatformRow, 0);
0192                 map.view.floorLevel = platformModel.data(idx, PlatformModel.LevelRole)
0193                 map.view.centerOnGeoCoordinate(platformModel.data(idx, PlatformModel.CoordinateRole));
0194                 map.view.setZoomLevel(19, Qt.point(map.width / 2.0, map.height / 2.0));
0195             }
0196         }
0197     }
0198 
0199     IndoorMapPlatformSheet {
0200         id: platformSheet
0201         model: platformModel
0202         parent: root.overlay
0203     }
0204 
0205     GateModel {
0206         id: gateModel
0207         mapData: map.mapData
0208 
0209         onGateIndexChanged: {
0210             if (gateModel.departureGateRow >= 0) {
0211                 var idx = gateModel.index(gateModel.departureGateRow, 0);
0212                 map.view.floorLevel = gateModel.data(idx, GateModel.LevelRole)
0213                 map.view.centerOnGeoCoordinate(gateModel.data(idx, GateModel.CoordinateRole));
0214                 map.view.setZoomLevel(18, Qt.point(map.width / 2.0, map.height / 2.0));
0215             } else if (root.departureGateName == "" && platformModel.arrivalGateRow >= 0) {
0216                 var idx = platformModel.index(platformModel.arrivalGateRow, 0);
0217                 map.view.floorLevel = platformModel.data(idx, PlatformModel.LevelRole)
0218                 map.view.centerOnGeoCoordinate(platformModel.data(idx, PlatformModel.CoordinateRole));
0219                 map.view.setZoomLevel(19, Qt.point(map.width / 2.0, map.height / 2.0));
0220             }
0221         }
0222     }
0223 
0224     IndoorMapGateSheet {
0225         id: gateSheet
0226         model: gateModel
0227         parent: root.overlay
0228     }
0229 
0230     FloorLevelChangeModel {
0231         id: floorLevelChangeModel
0232         currentFloorLevel: map.view.floorLevel
0233         floorLevelModel: map.floorLevels
0234     }
0235 
0236     IndoorMapElevatorSheet {
0237         id: elevatorSheet
0238         model: floorLevelChangeModel
0239         parent: root.overlay
0240     }
0241 
0242     LocationQueryOverlayProxyModel {
0243         id: locationModel
0244         sourceModel: PT.LocationQueryModel {
0245             id: locationQuery
0246             manager: LiveDataManager.publicTransportManager
0247         }
0248         mapData: map.mapData
0249     }
0250 
0251     RealtimeEquipmentModel {
0252         id: equipmentModel
0253         mapData: map.mapData
0254         realtimeModel: locationModel.sourceModel
0255     }
0256 
0257     IndoorMapAmenitySheet {
0258         id: amenitySheet
0259         model: AmenityModel {
0260             mapData: map.mapData
0261         }
0262         map: root.map
0263     }
0264 
0265     function queryLiveLocationData()
0266     {
0267         if (rentalVehicleAction.checked || equipmentAction.checked) {
0268             locationQuery.request.latitude = map.mapData.center.y;
0269             locationQuery.request.longitude = map.mapData.center.x;
0270             locationQuery.request.maximumDistance = map.mapData.radius;
0271             locationQuery.request.types =
0272                 (rentalVehicleAction.checked ? (PT.Location.RentedVehicleStation | PT.Location.RentedVehicle) : 0)
0273               | (equipmentAction.checked ? PT.Location.Equipment : 0);
0274         } else {
0275             locationQuery.clear();
0276         }
0277     }
0278 
0279     IndoorMap {
0280         id: map
0281         anchors.fill: parent
0282         overlaySources: [ gateModel, platformModel, locationModel, equipmentModel ]
0283 
0284         IndoorMapScale {
0285             map: map
0286             anchors.left: map.left
0287             anchors.top: map.top
0288             width: 0.3 * map.width
0289         }
0290 
0291         IndoorMapAttributionLabel {
0292             anchors.right: map.right
0293             anchors.bottom: map.bottom
0294         }
0295 
0296         onElementPicked: {
0297             floorLevelChangeModel.element = element;
0298             if (floorLevelChangeModel.hasSingleLevelChange) {
0299                 showPassiveNotification(i18n("Switched to floor %1", floorLevelChangeModel.destinationLevelName), "short");
0300                 map.view.floorLevel = floorLevelChangeModel.destinationLevel;
0301                 return;
0302             } else if (floorLevelChangeModel.hasMultipleLevelChanges) {
0303                 elevatorSheet.open();
0304                 return;
0305             }
0306 
0307             infoModel.element = element;
0308             if (infoModel.name != "" || infoModel.debug) {
0309                 elementDetailsSheet.open();
0310             }
0311         }
0312         onElementLongPressed: {
0313             // this provides info model access for elements with other interactions
0314             infoModel.element = element;
0315             if (infoModel.name != "" || infoModel.debug) {
0316                 elementDetailsSheet.open();
0317             }
0318         }
0319     }
0320 
0321     onCoordinateChanged: map.mapLoader.loadForCoordinate(coordinate.y, coordinate.x);
0322 
0323     Connections {
0324         target: map.mapLoader
0325         function onDone() {
0326             gateModel.setArrivalGate(root.arrivalGateName);
0327             gateModel.setDepartureGate(root.departureGateName);
0328             map.region = root.region;
0329             map.timeZone = root.timeZone;
0330             map.view.beginTime = root.beginTime;
0331             map.view.endTime = root.endTime;
0332             queryLiveLocationData();
0333         }
0334     }
0335 
0336     Components.DoubleFloatingButton {
0337         anchors {
0338             right: parent.right
0339             rightMargin: Kirigami.Units.largeSpacing
0340             bottom: parent.bottom
0341             bottomMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing // to not hide the copyright information
0342         }
0343 
0344         leadingAction: Kirigami.Action {
0345             icon.name: "go-down-symbolic"
0346             text: i18nc("@action:intoolbar Go down one floor", "Floor down")
0347             enabled: map.floorLevels.hasFloorLevelBelow(map.view.floorLevel)
0348             onTriggered: map.view.floorLevel = map.floorLevels.floorLevelBelow(map.view.floorLevel)
0349             visible: map.floorLevels.hasFloorLevels
0350         }
0351 
0352         trailingAction: Kirigami.Action {
0353             icon.name: "go-up-symbolic"
0354             text: i18nc("@action:intoolbar Go up one floor", "Floor up")
0355             enabled: map.floorLevels.hasFloorLevelAbove(map.view.floorLevel)
0356             onTriggered: map.view.floorLevel = map.floorLevels.floorLevelAbove(map.view.floorLevel)
0357             visible: map.floorLevels.hasFloorLevels
0358         }
0359     }
0360 
0361     footer: null
0362 }