diff --git a/src/map-quick/CMakeLists.txt b/src/map-quick/CMakeLists.txt index a6ad9a3..6b54415 100644 --- a/src/map-quick/CMakeLists.txt +++ b/src/map-quick/CMakeLists.txt @@ -1,25 +1,26 @@ set(kosmindoormapquickplugin_SRC kosmindoormapquickplugin.cpp floorlevelmodel.cpp mapitem.cpp + osmelement.cpp ) set(kosmindoormapquickplugin_qml qmldir IndoorMap.qml ) add_library(kosmindoormapquickplugin ${kosmindoormapquickplugin_SRC}) target_link_libraries(kosmindoormapquickplugin Qt5::Quick KOSMIndoorMap ) # make examples work without installation set_property(TARGET kosmindoormapquickplugin PROPERTY LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/org/kde/kosmindoormap) file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/org/kde/kosmindoormap/) foreach(f IN LISTS kosmindoormapquickplugin_qml) file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/${f} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/org/kde/kosmindoormap/${f} SYMBOLIC) endforeach() # install(TARGETS kosmindoormapquickplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kosmindoormap) # install(FILES ${kosmindoormapquickplugin_qml} ${quick_SRC} DESTINATION ${QML_INSTALL_DIR}/org/kde/kosmindoormap) diff --git a/src/map-quick/IndoorMap.qml b/src/map-quick/IndoorMap.qml index e6be371..244dc74 100644 --- a/src/map-quick/IndoorMap.qml +++ b/src/map-quick/IndoorMap.qml @@ -1,101 +1,118 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import QtQuick 2.12 import QtQuick.Layouts 1.12 import org.kde.kosmindoormap 1.0 import QtQuick.Controls 2.12 as QQC2 /** QML item for displaying a train station or airport map. */ Item { id: mapRoot /** Access to map loading status and progress. */ property alias mapLoader: map.loader /** Path to a MapCSS style sheet used for rendering the map. */ property alias styleSheet: map.styleSheet /** Floor level model. */ property alias floorLevels: map.floorLevels /** Access to the view transformation and floor level selection. */ property alias view: map.view + /** Emitted when a map element has been picked by clicking/tapping on it. */ + signal elementPicked(var element); + MapItemImpl { id: map anchors.fill: parent + } Flickable { id: flickable boundsBehavior: Flickable.StopAtBounds contentX: map.view.panX contentY: map.view.panY contentWidth: map.view.panWidth contentHeight: map.view.panHeight anchors.fill: parent Rectangle { color: "red"; width: 100; height: 100 } Rectangle { color: "green"; width: 100; height: 100; x: flickable.contentWidth - width; y: flickable.contentHeight - height; } onContentXChanged: { if (moving) { map.view.panTopLeft(flickable.contentX, flickable.contentY); map.update(); } } onContentYChanged: { if (moving) { map.view.panTopLeft(flickable.contentX, flickable.contentY); map.update(); } } QQC2.ScrollBar.vertical: QQC2.ScrollBar {} QQC2.ScrollBar.horizontal: QQC2.ScrollBar {} + + TapHandler { + acceptedButtons: Qt.LeftButton + onTapped: { + var root = parent; + while (root.parent) { root = root.parent; } + var localPos = map.mapFromItem(root, eventPoint.scenePosition.x, eventPoint.scenePosition.y); + var element = map.elementAt(localPos.x, localPos.y); + if (!element.isNull) { + elementPicked(element); + } + } + } } Connections { target: map.view onTransformationChanged: { console.log(map.view.panY, flickable.contentY); flickable.contentX = map.view.panX; flickable.contentY = map.view.panY; } } MouseArea { acceptedButtons: Qt.NoButton anchors.fill: parent onWheel: { if (wheel.angleDelta.y > 0) { map.view.zoomIn(Qt.point(wheel.x, wheel.y)); } else { map.view.zoomOut(Qt.point(wheel.x, wheel.y)); } wheel.accepted = true; map.update(); } } PinchArea { anchors.fill: parent } QQC2.BusyIndicator { anchors.centerIn: parent running: map.loader.isLoading } } diff --git a/src/map-quick/kosmindoormapquickplugin.cpp b/src/map-quick/kosmindoormapquickplugin.cpp index 2662b4b..2a6680c 100644 --- a/src/map-quick/kosmindoormapquickplugin.cpp +++ b/src/map-quick/kosmindoormapquickplugin.cpp @@ -1,27 +1,31 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "kosmindoormapquickplugin.h" #include "mapitem.h" +#include "osmelement.h" using namespace KOSMIndoorMap; void KOSMIndoorMapQuickPlugin::registerTypes(const char *uri) { Q_UNUSED(uri); + qRegisterMetaType(); + + qmlRegisterUncreatableType("org.kde.kosmindoormap", 1, 0, "OSMElement", {}); qmlRegisterType("org.kde.kosmindoormap", 1, 0, "MapItemImpl"); } diff --git a/src/map-quick/mapitem.cpp b/src/map-quick/mapitem.cpp index 33273ff..c158532 100644 --- a/src/map-quick/mapitem.cpp +++ b/src/map-quick/mapitem.cpp @@ -1,105 +1,110 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "mapitem.h" #include #include #include using namespace KOSMIndoorMap; MapItem::MapItem(QQuickItem *parent) : QQuickPaintedItem(parent) , m_loader(new MapLoader(this)) , m_view(new View(this)) , m_floorLevelModel(new FloorLevelModel(this)) { connect(m_loader, &MapLoader::done, this, &MapItem::loaderDone); m_view->setScreenSize({100, 100}); // FIXME this breaks view when done too late! m_controller.setView(m_view); connect(m_view, &View::floorLevelChanged, this, [this]() { update(); }); } MapItem::~MapItem() = default; void MapItem::paint(QPainter *painter) { m_controller.updateScene(m_sg); m_renderer.setPainter(painter); m_renderer.render(m_sg, m_view); } MapLoader* MapItem::loader() const { return m_loader; } View* MapItem::view() const { return m_view; } QString MapItem::styleSheetName() const { return m_styleSheetName; } void MapItem::setStylesheetName(const QString &styleSheet) { if (m_styleSheetName == styleSheet) { return; } m_styleSheetName = styleSheet; MapCSSParser cssParser; m_style = cssParser.parse(m_styleSheetName); m_style.compile(m_data.dataSet()); m_controller.setStyleSheet(&m_style); emit styleSheetChanged(); update(); } FloorLevelModel* MapItem::floorLevelModel() const { return m_floorLevelModel; } void MapItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry); m_view->setScreenSize(newGeometry.size().toSize()); qDebug() << newGeometry << m_view->zoomLevel(); } void MapItem::loaderDone() { m_floorLevelModel->setMapData(nullptr); m_sg.clear(); m_data = m_loader->takeData(); m_view->setSceneBoundingBox(m_data.boundingBox()); m_controller.setDataSet(&m_data); m_style.compile(m_data.dataSet()); m_controller.setStyleSheet(&m_style); m_view->setLevel(0); m_floorLevelModel->setMapData(&m_data); m_view->floorLevelChanged(); update(); } + +OSMElement MapItem::elementAt(double x, double y) const +{ + return OSMElement(m_sg.elementAt(m_view->mapScreenToScene(QPointF(x, y)))); +} diff --git a/src/map-quick/mapitem.h b/src/map-quick/mapitem.h index 83bd44d..53a88ca 100644 --- a/src/map-quick/mapitem.h +++ b/src/map-quick/mapitem.h @@ -1,82 +1,85 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KOSMINDOORMAP_MAPITEM_H #define KOSMINDOORMAP_MAPITEM_H #include "floorlevelmodel.h" +#include "osmelement.h" #include #include #include #include #include #include #include #include namespace KOSMIndoorMap { /** Map renderer for the IndoorMap QML item. * @internal Do not use directly! */ class MapItem : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(KOSMIndoorMap::MapLoader* loader READ loader CONSTANT) Q_PROPERTY(KOSMIndoorMap::View* view READ view CONSTANT) Q_PROPERTY(QString styleSheet READ styleSheetName WRITE setStylesheetName NOTIFY styleSheetChanged) Q_PROPERTY(KOSMIndoorMap::FloorLevelModel* floorLevels READ floorLevelModel CONSTANT) public: explicit MapItem(QQuickItem *parent = nullptr); ~MapItem(); void paint(QPainter *painter) override; MapLoader* loader() const; View* view() const; QString styleSheetName() const; void setStylesheetName(const QString &styleSheet); FloorLevelModel *floorLevelModel() const; + Q_INVOKABLE KOSMIndoorMap::OSMElement elementAt(double x, double y) const; + Q_SIGNALS: void styleSheetChanged(); void currentFloorLevelChanged(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; private: void loaderDone(); MapLoader *m_loader = nullptr; MapData m_data; SceneGraph m_sg; View *m_view = nullptr; QString m_styleSheetName; MapCSSStyle m_style; SceneController m_controller; PainterRenderer m_renderer; FloorLevelModel *m_floorLevelModel = nullptr; }; } #endif // KOSMINDOORMAP_MAPITEM_H diff --git a/src/map-quick/kosmindoormapquickplugin.cpp b/src/map-quick/osmelement.cpp similarity index 62% copy from src/map-quick/kosmindoormapquickplugin.cpp copy to src/map-quick/osmelement.cpp index 2662b4b..f442e74 100644 --- a/src/map-quick/kosmindoormapquickplugin.cpp +++ b/src/map-quick/osmelement.cpp @@ -1,27 +1,44 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "kosmindoormapquickplugin.h" -#include "mapitem.h" +#include "osmelement.h" using namespace KOSMIndoorMap; -void KOSMIndoorMapQuickPlugin::registerTypes(const char *uri) +OSMElement::OSMElement() = default; +OSMElement::OSMElement(OSM::Element e) + : m_element(e) { - Q_UNUSED(uri); - qmlRegisterType("org.kde.kosmindoormap", 1, 0, "MapItemImpl"); +} + +OSMElement::~OSMElement() = default; + +bool OSMElement::isNull() const +{ + return m_element.type() == OSM::Type::Null; +} + +QString OSMElement::name() const +{ + // TODO read localized value + return m_element.tagValue("name"); +} + +QString OSMElement::tagValue(const QString &key) const +{ + return m_element.tagValue(key.toUtf8().constData()); } diff --git a/src/map-quick/kosmindoormapquickplugin.cpp b/src/map-quick/osmelement.h similarity index 54% copy from src/map-quick/kosmindoormapquickplugin.cpp copy to src/map-quick/osmelement.h index 2662b4b..a96ba74 100644 --- a/src/map-quick/kosmindoormapquickplugin.cpp +++ b/src/map-quick/osmelement.h @@ -1,27 +1,51 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "kosmindoormapquickplugin.h" -#include "mapitem.h" +#ifndef KOSMINDOORMAP_OSMELEMENT_H +#define KOSMINDOORMAP_OSMELEMENT_H -using namespace KOSMIndoorMap; +#include -void KOSMIndoorMapQuickPlugin::registerTypes(const char *uri) +#include + +namespace KOSMIndoorMap { + +/** QML wrapper around an OSM element. */ +class OSMElement { - Q_UNUSED(uri); - qmlRegisterType("org.kde.kosmindoormap", 1, 0, "MapItemImpl"); + Q_GADGET + Q_PROPERTY(bool isNull READ isNull) + Q_PROPERTY(QString name READ name) +public: + OSMElement(); + explicit OSMElement(OSM::Element e); + ~OSMElement(); + + bool isNull() const; + QString name() const; + + Q_INVOKABLE QString tagValue(const QString &key) const; + +private: + OSM::Element m_element; +}; + } + +Q_DECLARE_METATYPE(KOSMIndoorMap::OSMElement) + +#endif // KOSMINDOORMAP_OSMELEMENT_H diff --git a/src/map/scene/scenegraph.cpp b/src/map/scene/scenegraph.cpp index 703bfb9..ba4b68b 100644 --- a/src/map/scene/scenegraph.cpp +++ b/src/map/scene/scenegraph.cpp @@ -1,177 +1,190 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "scenegraph.h" #include #include #include using namespace KOSMIndoorMap; SceneGraph::SceneGraph() = default; SceneGraph::SceneGraph(SceneGraph&&) = default; SceneGraph::~SceneGraph() = default; SceneGraph& SceneGraph::operator=(SceneGraph &&other) = default; void SceneGraph::clear() { m_items.clear(); m_previousItems.clear(); m_layerOffsets.clear(); m_bgColor = {}; m_floorLevel = 0; m_zoomLevel = 0; } void SceneGraph::addItem(SceneGraphItem &&item) { m_items.push_back(std::move(item)); } void SceneGraph::zSort() { std::stable_sort(m_items.begin(), m_items.end(), SceneGraph::zOrderCompare); recomputeLayerIndex(); } bool SceneGraph::zOrderCompare(const SceneGraphItem &lhs, const SceneGraphItem &rhs) { /* The MapCSS spec says we have to render in the following order: * - Objects with lower layer should always be rendered first. * - Within a layer, first all fills are rendered, then all casings, then all strokes, then all icons and labels. * - Within each of those categories, objects are ordered according to z-index. * - If all of the above are equal, the order is undefined. */ if (lhs.level == rhs.level) { if (lhs.layer == rhs.layer) { return lhs.payload->z < rhs.payload->z; } return lhs.layer < rhs.layer; } return lhs.level < rhs.level; } void SceneGraph::beginSwap() { std::swap(m_items, m_previousItems); m_items.clear(); std::sort(m_previousItems.begin(), m_previousItems.end(), SceneGraph::itemPoolCompare); m_layerOffsets.clear(); } void SceneGraph::endSwap() { m_previousItems.clear(); } int SceneGraph::zoomLevel() const { return m_zoomLevel; } void SceneGraph::setZoomLevel(int zoom) { m_zoomLevel = zoom; } int SceneGraph::currentFloorLevel() const { return m_floorLevel; } void SceneGraph::setCurrentFloorLevel(int level) { m_floorLevel = level; } QColor SceneGraph::backgroundColor() const { return m_bgColor; } void SceneGraph::setBackgroundColor(const QColor &bg) { m_bgColor = bg; } void SceneGraph::recomputeLayerIndex() { m_layerOffsets.clear(); if (m_items.empty()) { return; } auto prevLayer = m_items.front().layer; auto prevIndex = 0; for (auto it = m_items.begin(); it != m_items.end();) { it = std::upper_bound(it, m_items.end(), prevLayer, [](const auto &lhs, const auto &rhs) { return lhs < rhs.layer; }); const auto nextIndex = std::distance(m_items.begin(), it); m_layerOffsets.push_back(std::make_pair(prevIndex, nextIndex)); prevIndex = nextIndex; if (it != m_items.end()) { prevLayer = (*it).layer; } } } -void SceneGraph::itemsAt(QPointF pos) +void SceneGraph::itemsAt(QPointF pos) const { // ### temporary for testing for (const auto &item : m_items) { if (item.payload->inSceneSpace() && item.payload->boundingRect().contains(pos)) { qDebug() << item.element.url(); for (auto it = item.element.tagsBegin(); it != item.element.tagsEnd(); ++it) { qDebug() << " " << (*it).key.name() << (*it).value; } } // TODO HUD space elements } } +OSM::Element SceneGraph::elementAt(QPointF pos) const +{ + for (auto it = m_items.rbegin(); it != m_items.rend(); ++it) { + if ((*it).payload->inSceneSpace() && (*it).payload->boundingRect().contains(pos)) { + // TODO precise bounds check + return (*it).element; + } + // TODO HUD space elements + } + + return {}; +} + const std::vector& SceneGraph::layerOffsets() const { return m_layerOffsets; } SceneGraph::SceneGraphItemIter SceneGraph::itemsBegin(SceneGraph::LayerOffset layer) const { return m_items.begin() + layer.first; } SceneGraph::SceneGraphItemIter SceneGraph::itemsEnd(SceneGraph::LayerOffset layer) const { return m_items.begin() + layer.second; } std::size_t SceneGraph::itemCount() const { return m_items.size(); } bool SceneGraph::itemPoolCompare(const SceneGraphItem &lhs, const SceneGraphItem &rhs) { if (lhs.element.type() == rhs.element.type()) { if (lhs.element.id() == rhs.element.id()) { return lhs.level < rhs.level; } return lhs.element.id() < rhs.element.id(); } return lhs.element.type() < rhs.element.type(); } diff --git a/src/map/scene/scenegraph.h b/src/map/scene/scenegraph.h index 11a7375..d654212 100644 --- a/src/map/scene/scenegraph.h +++ b/src/map/scene/scenegraph.h @@ -1,116 +1,118 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KOSMINDOORMAP_SCENEGRAPH_H #define KOSMINDOORMAP_SCENEGRAPH_H #include "scenegraphitem.h" #include #include #include #include class QPointF; namespace KOSMIndoorMap { class SceneGraphItem; /** Scene graph of the currently displayed level. */ class SceneGraph { public: explicit SceneGraph(); SceneGraph(const SceneGraph&) = delete; SceneGraph(SceneGraph&&); ~SceneGraph(); SceneGraph& operator=(const SceneGraph&) = delete; SceneGraph& operator=(SceneGraph &&other); /** Clears all data from the scene graph. */ void clear(); // scene builder interface void beginSwap(); void addItem(SceneGraphItem &&item); template std::unique_ptr findOrCreatePayload(OSM::Element e, int level); void zSort(); void endSwap(); // dirty state tracking int zoomLevel() const; void setZoomLevel(int zoom); int currentFloorLevel() const; void setCurrentFloorLevel(int level); /** Canvas background color. */ QColor backgroundColor() const; void setBackgroundColor(const QColor &bg); /** Items at scene coordinate @p pos. * TODO this still needs a lot of work to be useful, mostly for debugging atm. */ - void itemsAt(QPointF pos); + void itemsAt(QPointF pos) const; + /** OSM element of the top item at the given scene coordinate. */ + OSM::Element elementAt(QPointF pos) const; // renderer interface typedef std::pair LayerOffset; const std::vector& layerOffsets() const; typedef std::vector::const_iterator SceneGraphItemIter; SceneGraphItemIter itemsBegin(LayerOffset layer) const; SceneGraphItemIter itemsEnd(LayerOffset layer) const; std::size_t itemCount() const; private: void recomputeLayerIndex(); static bool itemPoolCompare(const SceneGraphItem &lhs, const SceneGraphItem &rhs); static bool zOrderCompare(const SceneGraphItem &lhs, const SceneGraphItem &rhs); std::vector m_items; std::vector m_previousItems; std::vector> m_layerOffsets; QColor m_bgColor; int m_zoomLevel = 0; int m_floorLevel = 0; }; template std::unique_ptr SceneGraph::findOrCreatePayload(OSM::Element e, int level) { SceneGraphItem ref; ref.element = e; ref.level = level; auto it = std::lower_bound(m_previousItems.begin(), m_previousItems.end(), ref, SceneGraph::itemPoolCompare); for (;it != m_previousItems.end() && (*it).element.type() == e.type() && (*it).element.id() == e.id() && (*it).level == level && (*it).payload; ++it) { if (dynamic_cast((*it).payload.get())) { return std::move((*it).payload); } } return std::make_unique(); } } #endif // KOSMINDOORMAP_SCENEGRAPH_H diff --git a/tests/indoormap.qml b/tests/indoormap.qml index 9297bc2..9d82654 100644 --- a/tests/indoormap.qml +++ b/tests/indoormap.qml @@ -1,102 +1,122 @@ /* Copyright (C) 2020 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import QtQuick 2.12 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.1 as QQC2 import org.kde.kirigami 2.0 as Kirigami import org.kde.kosmindoormap 1.0 Kirigami.ApplicationWindow { title: "OSM Indoor Map QML Test" pageStack.initialPage: Kirigami.Page { title: "Indoor Map View" 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) } right: Kirigami.Action { iconName: "go-up-symbolic" enabled: map.floorLevels.hasFloorLevelAbove(map.view.floorLevel) onTriggered: map.view.floorLevel = map.floorLevels.floorLevelAbove(map.view.floorLevel) } contextualActions: [ Kirigami.Action { text: "Light Style" onTriggered: map.styleSheet = ":/org.kde.kosmindoormap/assets/css/breeze-light.mapcss" }, Kirigami.Action { text: "Dark Style" onTriggered: map.styleSheet = ":/org.kde.kosmindoormap/assets/css/breeze-dark.mapcss" }, Kirigami.Action { text: "Diagnostic View" onTriggered: map.styleSheet = ":/org.kde.kosmindoormap/assets/css/diagnostic.mapcss" } ] } header: RowLayout { QQC2.Label { text: "Floor Level:" } QQC2.ComboBox { id: floorLevelCombo model: map.floorLevels textRole: "display" Component.onCompleted: currentIndex = map.floorLevels.rowForLevel(map.view.floorLevel); onCurrentIndexChanged: if (currentIndex >= 0) { map.view.floorLevel = map.floorLevels.levelForRow(currentIndex); } } Connections { target: map.view onFloorLevelChanged: floorLevelCombo.currentIndex = map.floorLevels.rowForLevel(map.view.floorLevel); } QQC2.Label { text: "Coordinate:" } QQC2.TextField { id: coordInput placeholderText: "map coordinates" text: "49.44572, 11.08196" } QQC2.Button { text: "x" onClicked: coordInput.text = "" } QQC2.Button { text: ">" onClicked: { var c = coordInput.text.match(/(.*)[,;/ ]+(.*)/); var lat = c[1]; var lon = c[2]; map.mapLoader.loadForCoordinate(lat, lon); } } } + Kirigami.OverlaySheet { + id: elementDetailsSheet + property var element + + header: Kirigami.Heading { + text: elementDetailsSheet.element.name + } + + ColumnLayout { + QQC2.Label { + text: elementDetailsSheet.element.tagValue("description"); + } + } + } + IndoorMap { id: map anchors.fill: parent styleSheet: ":/org.kde.kosmindoormap/assets/css/breeze-light.mapcss" Component.onCompleted: { map.mapLoader.loadForCoordinate(49.44572, 11.08196); } + + onElementPicked: { + elementDetailsSheet.element = element; + elementDetailsSheet.sheetOpen = true; + } } } }