Warning, /libraries/kosmindoormap/src/app/indoormap.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 QtCore
0008 import QtQuick
0009 import QtQuick.Layouts
0010 import QtQuick.Controls as QQC2
0011 import QtQuick.Dialogs as Dialogs
0012 import org.kde.kirigami as Kirigami
0013 import org.kde.kpublictransport as PublicTransport
0014 import org.kde.kosmindoormap
0015 import org.kde.kosmindoormap.kpublictransport
0016 import org.kde.osm.editorcontroller
0017 import org.kde.kirigamiaddons.formcard as FormCard
0018 
0019 Kirigami.ApplicationWindow {
0020     globalDrawer: Kirigami.GlobalDrawer {
0021         title: "Indoor Map"
0022         titleIcon: "map-symbolic"
0023         isMenu: true
0024         actions: [
0025             Kirigami.Action {
0026                 text: "Open O5M File"
0027                 icon.name: "document-open-symbolic"
0028                 onTriggered: fileDialog.open()
0029             },
0030             Kirigami.Action {
0031                 text: "Open MapCSS Stylesheet"
0032                 icon.name: "document-open-symbolic"
0033                 onTriggered: mapcssDialog.open()
0034             },
0035             Kirigami.Action {
0036                 text: "Reload Stylesheet"
0037                 icon.name: "view-refresh-symbolic"
0038                 shortcut: "F5"
0039                 onTriggered: {
0040                     var s = page.map.styleSheet;
0041                     page.map.styleSheet = "";
0042                     page.map.styleSheet = s;
0043                 }
0044             },
0045             Kirigami.Action { separator: true },
0046             Kirigami.Action {
0047                 text: "Data Sources"
0048                 icon.name: "help-about-symbolic"
0049                 onTriggered: function() { applicationWindow().pageStack.push(attributionPage); }
0050             },
0051             Kirigami.Action {
0052                 id: aboutAction
0053                 text: "About"
0054                 icon.name: "help-about-symbolic"
0055                 onTriggered: function() { applicationWindow().pageStack.push(aboutPage); }
0056             }
0057         ]
0058     }
0059     contextDrawer: Kirigami.ContextDrawer {
0060         id: contextDrawer
0061     }
0062 
0063     Dialogs.FileDialog {
0064         id: fileDialog
0065         title: "Open OSM File"
0066         fileMode: Dialogs.FileDialog.OpenFile
0067         nameFilters: ["o5m file (*.o5m)", "OSM XML file (*.osm *.xml)", "PBF file (*.osm.pbf)"]
0068         onAccepted: page.map.mapLoader.loadFromFile(fileDialog.selectedFile);
0069     }
0070     Dialogs.FileDialog {
0071         id: mapcssDialog
0072         title: "Open MapCSS Stylesheet"
0073         fileMode: Dialogs.FileDialog.OpenFile
0074         nameFilters: ["MapCSS stylesheet (*.mapcss)"]
0075         onAccepted: page.map.styleSheet = mapcssDialog.selectedFile
0076     }
0077     PublicTransport.Manager { id: ptMgr }
0078     Settings {
0079         id: settings
0080         property alias debugMode: debugAction.checked
0081         property alias stylesheet: page.map.styleSheet
0082         property alias hoverMode: page.mapHoverEnabled
0083     }
0084 
0085     pageStack.initialPage: IndoorMapPage {
0086         id: page
0087         debug: debugAction.checked
0088 
0089         actions: [
0090             Kirigami.Action {
0091                 text: "Select Location"
0092                 icon.name: "search"
0093                 onTriggered: locationSheet.open()
0094             },
0095             Kirigami.Action {
0096                 text: "Light Style"
0097                 onTriggered: page.map.styleSheet = "breeze-light"
0098             },
0099             Kirigami.Action {
0100                 text: "Dark Style"
0101                 onTriggered: page.map.styleSheet = "breeze-dark"
0102             },
0103             Kirigami.Action {
0104                 text: "Diagnostic View"
0105                 onTriggered: page.map.styleSheet = "diagnostic"
0106             },
0107             Kirigami.Action {
0108                 id: debugAction
0109                 text: "Debug Info Model"
0110                 checkable: true
0111                 checked: false
0112             },
0113             Kirigami.Action {
0114                 id: platformAction
0115                 text: "Find Platform"
0116                 onTriggered: platformSheet.open()
0117                 visible: !platformModel.isEmpty
0118             },
0119             Kirigami.Action {
0120                 id: gateAction
0121                 text: "Find Gate"
0122                 onTriggered: gateSheet.open()
0123                 visible: !gateModel.isEmpty
0124             },
0125             Kirigami.Action {
0126                 id: amenityAction
0127                 text: "Find Amenity"
0128                 onTriggered: amenitySheet.open()
0129             },
0130             Kirigami.Action {
0131                 id: equipmentAction
0132                 text: "Show Elevator Status"
0133                 checkable: true
0134                 enabled: !page.map.mapLoader.isLoading
0135                 onTriggered: page.queryLiveLocationData();
0136             },
0137             Kirigami.Action {
0138                 id: rentalVehicleAction
0139                 text: i18n("Show Rental Vehicles")
0140                 checkable: true
0141                 enabled: !page.map.mapLoader.isLoading
0142                 onTriggered: page.queryLiveLocationData();
0143             },
0144             Kirigami.Action {
0145                 text: i18n("Edit with iD")
0146                 icon.name: "document-edit"
0147                 onTriggered: EditorController.editBoundingBox(page.map.view.mapSceneToGeo(page.map.view.viewport), Editor.ID)
0148             },
0149             Kirigami.Action {
0150                 text: i18n("Edit with JOSM")
0151                 icon.name: "org.openstreetmap.josm"
0152                 visible: EditorController.hasEditor(Editor.JOSM)
0153                 onTriggered: EditorController.editBoundingBox(page.map.view.mapSceneToGeo(page.map.view.viewport), Editor.JOSM)
0154             },
0155             Kirigami.Action {
0156                 text: i18n("Edit with Vespucci")
0157                 icon.name: "document-edit"
0158                 visible: EditorController.hasEditor(Editor.Vespucci)
0159                 onTriggered: EditorController.editBoundingBox(page.map.view.mapSceneToGeo(page.map.view.viewport), Editor.Vespucci)
0160             },
0161             Kirigami.Action {
0162                 text: i18n("Enable hover selection")
0163                 icon.name: "followmouse"
0164                 checkable: true
0165                 checked: page.mapHoverEnabled
0166                 onToggled: page.mapHoverEnabled = !page.mapHoverEnabled
0167             }
0168         ]
0169 
0170         function queryLiveLocationData() {
0171             if (rentalVehicleAction.checked || equipmentAction.checked) {
0172                 locationQuery.request.latitude = map.mapData.center.y;
0173                 locationQuery.request.longitude = map.mapData.center.x;
0174                 locationQuery.request.maximumDistance = map.mapData.radius;
0175                 locationQuery.request.types =
0176                     (rentalVehicleAction.checked ? (PublicTransport.Location.RentedVehicleStation | PublicTransport.Location.RentedVehicle) : 0)
0177                 | (equipmentAction.checked ? PublicTransport.Location.Equipment : 0);
0178             } else {
0179                 locationQuery.clear();
0180             }
0181         }
0182 
0183         PlatformModel {
0184             id: platformModel
0185             mapData: page.map.mapData
0186         }
0187 
0188         Component {
0189             id: platformDelegate
0190             QQC2.ItemDelegate {
0191                 property var platform: model
0192                 width: ListView.view.width
0193                 contentItem: Row {
0194                     QQC2.Label { text: platform.lines.length == 0 ? platform.display : (platform.display + " - "); }
0195                     Repeater {
0196                         model: platform.lines
0197                         delegate: Row {
0198                             Kirigami.Icon {
0199                                 id: icon
0200                                 height: Kirigami.Units.iconSizes.small
0201                                 width: implicitWidth
0202                                 visible: source != ""
0203                                 source: {
0204                                     switch (platform.mode) {
0205                                         case Platform.Rail:
0206                                             return PublicTransport.LineMetaData.lookup(modelData, platform.coordinate.y, platform.coordinate.x, PublicTransport.Line.Train, true).logo;
0207                                         case Platform.Tram:
0208                                             return PublicTransport.LineMetaData.lookup(modelData, platform.coordinate.y, platform.coordinate.x, PublicTransport.Line.Tramway, true).logo;
0209                                         case Platform.Subway:
0210                                             return PublicTransport.LineMetaData.lookup(modelData, platform.coordinate.y, platform.coordinate.x, PublicTransport.Line.Metro, true).logo;
0211                                     }
0212                                     return "";
0213                                 }
0214                             }
0215                             QQC2.Label {
0216                                 text: modelData + " "
0217                                 visible: icon.source == ""
0218                             }
0219                         }
0220                     }
0221                 }
0222                 highlighted: false
0223                 onClicked: {
0224                     page.map.view.floorLevel = model.level
0225                     page.map.view.centerOnGeoCoordinate(model.coordinate);
0226                     page.map.view.setZoomLevel(19, Qt.point(page.map.width / 2.0, page.map.height/ 2.0));
0227                     platformSheet.close()
0228                 }
0229             }
0230         }
0231 
0232         Kirigami.OverlaySheet {
0233             id: platformSheet
0234 
0235             header: Kirigami.Heading {
0236                 text: "Find Platform"
0237             }
0238 
0239             ListView {
0240                 model: platformModel
0241                 clip: true
0242                 Layout.preferredWidth: Kirigami.Units.gridUnit * 25
0243 
0244                 section.property: "mode"
0245                 section.delegate: Kirigami.ListSectionHeader {
0246                     label: switch(parseInt(section)) {
0247                         case Platform.Rail: return "Railway";
0248                         case Platform.Subway: return "Subway";
0249                         case Platform.Tram: return "Tramway";
0250                         case Platform.Bus: return "Bus";
0251                         default: console.log(section, Platform.Rail); return section;
0252                     }
0253                     width: ListView.view.width
0254                 }
0255                 section.criteria: ViewSection.FullString
0256 
0257                 delegate: platformDelegate
0258             }
0259         }
0260 
0261         GateModel {
0262             id: gateModel
0263             mapData: page.map.mapData
0264         }
0265 
0266         Kirigami.OverlaySheet {
0267             id: gateSheet
0268 
0269             header: Kirigami.Heading {
0270                 text: "Find Gate"
0271             }
0272 
0273             ListView {
0274                 model: gateModel
0275                 Layout.preferredWidth: Kirigami.Units.gridUnit * 10
0276                 delegate: QQC2.ItemDelegate {
0277                     highlighted: false
0278                     width: ListView.view.width
0279                     contentItem: Kirigami.TitleSubtitle {
0280                         title: model.display
0281                     }
0282                     onClicked: {
0283                         page.map.view.floorLevel = model.level
0284                         page.map.view.centerOnGeoCoordinate(model.coordinate);
0285                         page.map.view.setZoomLevel(18, Qt.point(page.map.width / 2.0, page.map.height/ 2.0));
0286                         gateSheet.close();
0287                     }
0288                 }
0289             }
0290         }
0291 
0292         AmenityModel {
0293             id: amenityModel
0294             mapData: page.map.mapData
0295         }
0296 
0297         Kirigami.OverlaySheet {
0298             id: amenitySheet
0299             header: Kirigami.Heading {
0300                 text: "Find Amenity"
0301             }
0302 
0303             ListView {
0304                 clip: true
0305                 Layout.preferredWidth: Kirigami.Units.gridUnit * 25
0306                 model: AmenitySortFilterProxyModel {
0307                     sourceModel: amenitySheet.visible ? amenityModel : null
0308                     filterCaseSensitivity: Qt.CaseInsensitive
0309                     filterString: amenitySearchField.text
0310                 }
0311 
0312                 delegate: IndoorMapAmenityDelegate {
0313                     id: item
0314                     mapData: page.map.mapData
0315                     required property QtObject model
0316                     onClicked: {
0317                         page.map.view.floorLevel = item.model.level
0318                         page.map.view.centerOnGeoCoordinate(item.model.coordinate);
0319                         page.map.view.setZoomLevel(21, Qt.point(page.map.width / 2.0, page.map.height/ 2.0));
0320                         console.log(item.model.element.url);
0321                         amenitySheet.close();
0322                     }
0323                 }
0324 
0325                 section.property: "groupName"
0326                 section.delegate: Kirigami.ListSectionHeader {
0327                     label: section
0328                     width: ListView.view.width
0329                 }
0330             }
0331 
0332             footer: Kirigami.SearchField {
0333                 id: amenitySearchField
0334                 focus: true
0335             }
0336             onOpened: amenitySearchField.clear()
0337         }
0338 
0339         LocationQueryOverlayProxyModel {
0340             id: locationModel
0341             sourceModel: PublicTransport.LocationQueryModel {
0342                 id: locationQuery
0343                 manager: ptMgr
0344             }
0345             mapData: page.map.mapData
0346         }
0347 
0348         RealtimeEquipmentModel {
0349             id: equipmentModel
0350             mapData: page.map.mapData
0351             realtimeModel: locationModel.sourceModel
0352         }
0353 
0354         SelectLocationSheet {
0355             id: locationSheet
0356             publicTransportManager: ptMgr
0357             onCoordinateSelected: function() {
0358                 page.map.mapLoader.loadForCoordinate(locationSheet.coordinate.y, locationSheet.coordinate.x);
0359                 page.map.view.beginTime = new Date();
0360                 page.map.view.endTime = new Date(page.map.view.beginTime.getTime() + 3600000);
0361                 // TODO timezone
0362 
0363                 settings.setValue("latitude", locationSheet.coordinate.y);
0364                 settings.setValue("longitude", locationSheet.coordinate.x);
0365             }
0366         }
0367 
0368         map.overlaySources: [ gateModel, platformModel, locationModel, equipmentModel ]
0369         map.timeZone: "Europe/Berlin"
0370 
0371         header: RowLayout {
0372             QQC2.Label { text: "Floor Level:" }
0373             QQC2.ComboBox {
0374                 id: floorLevelCombo
0375                 model: page.map.floorLevels
0376                 textRole: "display"
0377                 currentIndex: page.map.floorLevels.rowForLevel(page.map.view.floorLevel);
0378                 onCurrentIndexChanged: if (currentIndex >= 0) { page.map.view.floorLevel = page.map.floorLevels.levelForRow(currentIndex); }
0379                 Layout.fillWidth: true
0380             }
0381             Connections {
0382                 target: page.map.view
0383                 function onFloorLevelChanged() { floorLevelCombo.currentIndex = page.map.floorLevels.rowForLevel(page.map.view.floorLevel); }
0384             }
0385 
0386             QQC2.Slider {
0387                 id: zoomSlider
0388                 from: 14.0
0389                 to: 21.0
0390                 live: true
0391                 Layout.fillWidth: true
0392 
0393                 onValueChanged: {
0394                     page.map.view.setZoomLevel(value, Qt.point(page.map.width / 2.0, page.map.height/ 2.0));
0395                 }
0396             }
0397             Connections {
0398                 target: page.map.view
0399                 function onZoomLevelChanged() { zoomSlider.value = page.map.view.zoomLevel; }
0400             }
0401         }
0402 
0403         coordinate: Qt.point(settings.value("longitude", 11.08196), settings.value("latitude", 49.44572))
0404     }
0405 
0406     Connections {
0407         target: page.map
0408         function onMapDataChanged() {
0409             page.queryLiveLocationData();
0410         }
0411     }
0412 
0413     Component {
0414         id: attributionPage
0415         AttributionPage {
0416             publicTransportManager: ptMgr
0417         }
0418     }
0419 
0420     Component {
0421         id: aboutPage
0422         FormCard.AboutPage {
0423             aboutData: {
0424                 "displayName": "KDE OSM Indoor Map",
0425                 "productName": "org.kde.kosmindoormap",
0426                 "componentName": "org.kde.kosmindoormap",
0427                 "shortDescription": "OSM Indoor Map Demo",
0428                 "homepage": "https://kde.org/",
0429                 "bugAddress": "submit@bugs.kde.org",
0430                 "version": "23.08",
0431                 "licenses": [
0432                     {
0433                         "name": "LGPL 2.0 or later",
0434                         "spdx": "LGPL-2.0-or-later"
0435                     }
0436                 ],
0437                 "copyrightStatement": "© 2020-2023 The KDE Team",
0438                 "desktopFileName": "kosmindoormap"
0439             }
0440         }
0441     }
0442 }