File indexing completed on 2024-04-28 04:41:02
0001 /* 0002 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include <KOSMIndoorMap/FloorLevelModel> 0008 #include <KOSMIndoorMap/HitDetector> 0009 #include <KOSMIndoorMap/MapCSSParser> 0010 #include <KOSMIndoorMap/MapCSSStyle> 0011 #include <KOSMIndoorMap/MapData> 0012 #include <KOSMIndoorMap/MapLoader> 0013 #include <KOSMIndoorMap/PainterRenderer> 0014 #include <KOSMIndoorMap/SceneController> 0015 #include <KOSMIndoorMap/SceneGraph> 0016 #include <KOSMIndoorMap/View> 0017 0018 #include <QApplication> 0019 #include <QCommandLineParser> 0020 #include <QMouseEvent> 0021 #include <QComboBox> 0022 #include <QHBoxLayout> 0023 #include <QPainter> 0024 #include <QRegularExpression> 0025 #include <QtPlugin> 0026 0027 #if HAVE_OSM_PBF_SUPPORT 0028 Q_IMPORT_PLUGIN(OSM_PbfIOPlugin) 0029 #endif 0030 Q_IMPORT_PLUGIN(OSM_XmlIOPlugin) 0031 0032 using namespace KOSMIndoorMap; 0033 0034 static QString cssPath(const QString &styleName) 0035 { 0036 return QLatin1String(SOURCE_DIR "/../src/map/assets/css/") + styleName + QLatin1String(".mapcss"); 0037 // return QLatin1String(":/org.kde.kosmindoormap/assets/css/") + styleName + QLatin1String(".mapcss"); 0038 } 0039 0040 class MapWidget : public QWidget 0041 { 0042 public: 0043 explicit MapWidget(QWidget *parent = nullptr); 0044 void paintEvent(QPaintEvent *event) override; 0045 void resizeEvent(QResizeEvent *event) override; 0046 void mousePressEvent(QMouseEvent *event) override; 0047 void mouseMoveEvent(QMouseEvent *event) override; 0048 void mouseReleaseEvent(QMouseEvent *event) override; 0049 void wheelEvent(QWheelEvent *event) override; 0050 void setMapData(MapData &&data); 0051 void setStyleSheet(const QString &styleName); 0052 0053 MapData m_data; 0054 SceneGraph m_sg; 0055 MapCSSStyle m_style; 0056 SceneController m_controller; 0057 PainterRenderer m_renderer; 0058 View m_view; 0059 QPoint m_lastPanPoint; 0060 }; 0061 0062 MapWidget::MapWidget(QWidget* parent) 0063 : QWidget(parent) 0064 { 0065 m_view.setScreenSize(size()); 0066 m_controller.setView(&m_view); 0067 } 0068 0069 void MapWidget::paintEvent(QPaintEvent *event) 0070 { 0071 m_controller.updateScene(m_sg); 0072 QPainter p(this); 0073 m_renderer.setPainter(&p); 0074 m_renderer.render(m_sg, &m_view); 0075 return QWidget::paintEvent(event); 0076 } 0077 0078 void MapWidget::resizeEvent(QResizeEvent *event) 0079 { 0080 QWidget::resizeEvent(event); 0081 m_view.setScreenSize(size()); 0082 } 0083 0084 void MapWidget::mousePressEvent(QMouseEvent *event) 0085 { 0086 m_lastPanPoint = event->pos(); 0087 QWidget::mousePressEvent(event); 0088 } 0089 0090 void MapWidget::mouseMoveEvent(QMouseEvent *event) 0091 { 0092 m_view.panScreenSpace(m_lastPanPoint - event->pos()); 0093 m_lastPanPoint = event->pos(); 0094 QWidget::mouseMoveEvent(event); 0095 update(); 0096 } 0097 0098 void MapWidget::mouseReleaseEvent(QMouseEvent *event) 0099 { 0100 if (event->button() == Qt::RightButton) { 0101 HitDetector detector; 0102 const auto items = detector.itemsAt(event->pos(), m_sg, &m_view); 0103 for (const auto item : items) { 0104 qDebug() << item->element.url(); 0105 for (auto it = item->element.tagsBegin(); it != item->element.tagsEnd(); ++it) { 0106 qDebug() << " " << (*it).key.name() << (*it).value; 0107 } 0108 switch (item->element.type()) { 0109 case OSM::Type::Null: 0110 case OSM::Type::Node: 0111 break; 0112 case OSM::Type::Way: 0113 for (const auto &node : item->element.way()->nodes) { 0114 qDebug() << " " << node; 0115 } 0116 break; 0117 case OSM::Type::Relation: 0118 for (const auto &mem : item->element.relation()->members) { 0119 qDebug() << " " << mem.role().name() << (int)mem.type() << mem.id; 0120 } 0121 break; 0122 } 0123 } 0124 } 0125 } 0126 0127 void MapWidget::wheelEvent(QWheelEvent *event) 0128 { 0129 if (event->angleDelta().y() > 0) { 0130 m_view.zoomIn(event->position()); 0131 } else { 0132 m_view.zoomOut(event->position()); 0133 } 0134 QWidget::wheelEvent(event); 0135 update(); 0136 } 0137 0138 void MapWidget::setMapData(MapData &&data) 0139 { 0140 m_data = std::move(data); 0141 m_controller.setMapData(m_data); 0142 m_view.setSceneBoundingBox(m_data.boundingBox()); 0143 m_style.compile(m_data.dataSet()); 0144 m_controller.setStyleSheet(&m_style); 0145 update(); 0146 } 0147 0148 void MapWidget::setStyleSheet(const QString &styleName) 0149 { 0150 MapCSSParser cssParser; 0151 m_style = cssParser.parse(cssPath(styleName)); 0152 m_style.compile(m_data.dataSet()); 0153 m_controller.setStyleSheet(&m_style); 0154 } 0155 0156 0157 int main(int argc, char **argv) 0158 { 0159 QApplication app(argc, argv); 0160 QCommandLineParser parser; 0161 QCommandLineOption coordOpt({QStringLiteral("coordinate"), QStringLiteral("c")}, QStringLiteral("coordinate of the location to load"), QStringLiteral("lat,lon")); 0162 parser.addOption(coordOpt); 0163 QCommandLineOption fileOpt({QStringLiteral("file"), QStringLiteral("f")}, QStringLiteral("O5M or OSM PBF file to load"), QStringLiteral("file")); 0164 parser.addOption(fileOpt); 0165 parser.addHelpOption(); 0166 parser.addVersionOption(); 0167 parser.process(app); 0168 0169 MapWidget widget; 0170 widget.resize(480, 720); 0171 widget.setStyleSheet(QStringLiteral("breeze-light")); 0172 0173 auto layout = new QHBoxLayout(&widget); 0174 layout->setAlignment(Qt::AlignTop); 0175 0176 FloorLevelModel floorModel; 0177 auto levelBox = new QComboBox; 0178 levelBox->setModel(&floorModel); 0179 layout->addWidget(levelBox); 0180 QObject::connect(levelBox, &QComboBox::currentTextChanged, &app, [&]() { 0181 widget.m_view.setLevel(levelBox->currentData().value<MapLevel>().numericLevel()); 0182 widget.update(); 0183 }); 0184 0185 auto styleBox = new QComboBox; 0186 layout->addWidget(styleBox); 0187 styleBox->addItems({QStringLiteral("breeze-light"), QStringLiteral("breeze-dark"), QStringLiteral("diagnostic")}); 0188 QObject::connect(styleBox, &QComboBox::currentTextChanged, &app, [&](const QString &styleName) { 0189 widget.setStyleSheet(styleName); 0190 widget.update(); 0191 }); 0192 0193 widget.show(); 0194 0195 MapLoader loader; 0196 QObject::connect(&loader, &MapLoader::done, &app, [&]() { 0197 widget.setMapData(loader.takeData()); 0198 floorModel.setMapData(&widget.m_data); 0199 levelBox->setCurrentText(QLatin1String("0")); 0200 }); 0201 0202 if (parser.isSet(fileOpt)) { 0203 loader.loadFromFile(parser.value(fileOpt)); 0204 } else if (parser.isSet(coordOpt)) { 0205 const auto s = parser.value(coordOpt).split(QRegularExpression(QStringLiteral("[,/;]"))); 0206 loader.loadForCoordinate(s.at(0).toDouble(), s.at(1).toDouble()); 0207 } 0208 0209 return app.exec(); 0210 }