diff options
author | wanglu <wang_lu@dl.cn.nexty-ele.com> | 2019-03-25 09:42:49 +0800 |
---|---|---|
committer | wanglu <wang_lu@dl.cn.nexty-ele.com> | 2019-03-25 09:52:02 +0800 |
commit | 4a8b7a6301e4b093c99329d0a16fbee6c535f312 (patch) | |
tree | fe9f589e1723e8f173b50dfa617374042f4cf7a7 /app | |
parent | fb539bbd9f7b36d26cd56fe09b804e18b3b3d984 (diff) |
This is a application for display turn by run navigation information.halibut_8.0.0halibut_7.99.3halibut_7.99.2halibut_7.99.1halibut/8.0.0halibut/7.99.3halibut/7.99.2halibut/7.99.18.0.07.99.37.99.27.99.1
Change-Id: I0866a7d9ffa347c0935b4d00259ad1a74cd00d6e
Signed-off-by: wanglu <wang_lu@dl.cn.nexty-ele.com>
Diffstat (limited to 'app')
47 files changed, 1283 insertions, 0 deletions
diff --git a/app/app.pri b/app/app.pri new file mode 100644 index 0000000..a1f6562 --- /dev/null +++ b/app/app.pri @@ -0,0 +1,18 @@ +load(configure) + +qtCompileTest(libhomescreen) +qtCompileTest(qlibwindowmanager) + +config_libhomescreen { + CONFIG += link_pkgconfig + PKGCONFIG += libhomescreen + DEFINES += HAVE_LIBHOMESCREEN +} + +config_qlibwindowmanager { + CONFIG += link_pkgconfig + PKGCONFIG += qlibwindowmanager + DEFINES += HAVE_QLIBWINDOWMANAGER +} + +DESTDIR = $${OUT_PWD}/../package/root/bin diff --git a/app/app.pro b/app/app.pro new file mode 100644 index 0000000..594eca3 --- /dev/null +++ b/app/app.pro @@ -0,0 +1,36 @@ +TARGET = tbtnavi +TEMPLATE = app + +QT += qml network quick positioning location sql widgets dbus + +CONFIG += c++14 + +include(app.pri) + +ios|android { + QT -= widgets +} + +SOURCES += \ + main.cpp \ + qcheapruler.cpp \ + dbus_client.cpp \ + file_operation.cpp + +HEADERS += \ + qcheapruler.hpp \ + dbus_client.h \ + file_operation.h + +INCLUDEPATH += \ + ../include + +OTHER_FILES += \ + qmapboxlgapp.qml + +RESOURCES += \ + images/images.qrc \ + app.qrc + +DBUS_ADAPTORS += org.agl.naviapi.xml +DBUS_INTERFACES += org.agl.naviapi.xml diff --git a/app/app.qrc b/app/app.qrc new file mode 100644 index 0000000..7ffb6e2 --- /dev/null +++ b/app/app.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>qml/qmldir</file> + <file>qml/Main.qml</file> + <file>qml/MapWindow.qml</file> + <file>qml/TbtBoard.qml</file> + </qresource> +</RCC> diff --git a/app/config.tests/libhomescreen/.qmake.stash b/app/config.tests/libhomescreen/.qmake.stash new file mode 100644 index 0000000..d0807e7 --- /dev/null +++ b/app/config.tests/libhomescreen/.qmake.stash @@ -0,0 +1,24 @@ +QMAKE_CXX.INCDIRS = \ + /usr/include/c++/5 \ + /usr/include/x86_64-linux-gnu/c++/5 \ + /usr/include/c++/5/backward \ + /usr/lib/gcc/x86_64-linux-gnu/5/include \ + /usr/local/include \ + /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed \ + /usr/include/x86_64-linux-gnu \ + /usr/include +QMAKE_CXX.LIBDIRS = \ + /usr/lib/gcc/x86_64-linux-gnu/5 \ + /usr/lib/x86_64-linux-gnu \ + /usr/lib \ + /lib/x86_64-linux-gnu \ + /lib +QMAKE_CXX.QT_COMPILER_STDCXX = 199711L +QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 5 +QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 4 +QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 0 +QMAKE_CXX.COMPILER_MACROS = \ + QT_COMPILER_STDCXX \ + QMAKE_GCC_MAJOR_VERSION \ + QMAKE_GCC_MINOR_VERSION \ + QMAKE_GCC_PATCH_VERSION diff --git a/app/config.tests/libhomescreen/libhomescreen.cpp b/app/config.tests/libhomescreen/libhomescreen.cpp new file mode 100644 index 0000000..d698b05 --- /dev/null +++ b/app/config.tests/libhomescreen/libhomescreen.cpp @@ -0,0 +1,8 @@ +#include <libhomescreen.hpp> + +int main(int argc,char **argv) +{ + LibHomeScreen libHomeScreen; + return 0; +} + diff --git a/app/config.tests/libhomescreen/libhomescreen.pro b/app/config.tests/libhomescreen/libhomescreen.pro new file mode 100644 index 0000000..7d43112 --- /dev/null +++ b/app/config.tests/libhomescreen/libhomescreen.pro @@ -0,0 +1,5 @@ +SOURCES = libhomescreen.cpp + +CONFIG -= qt +CONFIG += link_pkgconfig +PKGCONFIG += libhomescreen diff --git a/app/config.tests/qlibwindowmanager/.qmake.stash b/app/config.tests/qlibwindowmanager/.qmake.stash new file mode 100644 index 0000000..d0807e7 --- /dev/null +++ b/app/config.tests/qlibwindowmanager/.qmake.stash @@ -0,0 +1,24 @@ +QMAKE_CXX.INCDIRS = \ + /usr/include/c++/5 \ + /usr/include/x86_64-linux-gnu/c++/5 \ + /usr/include/c++/5/backward \ + /usr/lib/gcc/x86_64-linux-gnu/5/include \ + /usr/local/include \ + /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed \ + /usr/include/x86_64-linux-gnu \ + /usr/include +QMAKE_CXX.LIBDIRS = \ + /usr/lib/gcc/x86_64-linux-gnu/5 \ + /usr/lib/x86_64-linux-gnu \ + /usr/lib \ + /lib/x86_64-linux-gnu \ + /lib +QMAKE_CXX.QT_COMPILER_STDCXX = 199711L +QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 5 +QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 4 +QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 0 +QMAKE_CXX.COMPILER_MACROS = \ + QT_COMPILER_STDCXX \ + QMAKE_GCC_MAJOR_VERSION \ + QMAKE_GCC_MINOR_VERSION \ + QMAKE_GCC_PATCH_VERSION diff --git a/app/config.tests/qlibwindowmanager/qlibwindowmanager.cpp b/app/config.tests/qlibwindowmanager/qlibwindowmanager.cpp new file mode 100644 index 0000000..bb95c93 --- /dev/null +++ b/app/config.tests/qlibwindowmanager/qlibwindowmanager.cpp @@ -0,0 +1,8 @@ +#include <qlibwindowmanager.h> + +int main(int argc,char **argv) +{ + QLibWindowmanager qwm; + return 0; +} + diff --git a/app/config.tests/qlibwindowmanager/qlibwindowmanager.pro b/app/config.tests/qlibwindowmanager/qlibwindowmanager.pro new file mode 100644 index 0000000..cb51d98 --- /dev/null +++ b/app/config.tests/qlibwindowmanager/qlibwindowmanager.pro @@ -0,0 +1,5 @@ +SOURCES = qlibwindowmanager.cpp + +CONFIG += qt +CONFIG += link_pkgconfig +PKGCONFIG += qlibwindowmanager diff --git a/app/dbus_client.cpp b/app/dbus_client.cpp new file mode 100644 index 0000000..6b5b5fb --- /dev/null +++ b/app/dbus_client.cpp @@ -0,0 +1,116 @@ +#include "dbus_client.h" + +dbus_client::dbus_client(const QString &pathName, + const QString &objName, + const QString &serverName, + QObject *parent) : + m_serverName(serverName), + m_pathName(pathName + serverName), + m_objName(objName + serverName) +{ + //DBus & api ini + initDBus(); + initAPIs(parent); +} + +dbus_client::~dbus_client(){} + +void dbus_client::initDBus(){ + + new NaviapiAdaptor(this); + + //make a connect session to navigation service(add route info) + if (!QDBusConnection::sessionBus().connect( + QString(), + QString(), + m_pathName, + "signalRouteInfo", + this, + SLOT(addRoutePointsSlot(double, double, double, double)))) { //slot + qDebug() << m_serverName << "sessionBus.connect(): signalRouteInfo failed"; + } + + //make a connect session to navigation service(current postion info) + if (!QDBusConnection::sessionBus().connect( + QString(), + QString(), + m_pathName, + "signalPosInfo", + this, + SLOT(positionSlot(double, double, double, double)))) { //slot + qDebug() << m_serverName << "sessionBus.connect(): signalPosInfo failed"; + } + + //make a connect session to navigation service(when demo stopped) + if (!QDBusConnection::sessionBus().connect( + QString(), + QString(), + m_pathName, + "signalStopDemo", + this, + SLOT(stopdemoSlot()))) { //slot + qDebug() << m_serverName << "sessionBus.connect(): signalStopDemo failed"; + } + + //make a connect session to navigation service(when arrived destination) + if (!QDBusConnection::sessionBus().connect( + QString(), + QString(), + m_pathName, + "signalArrvied", + this, + SLOT(arrivedestSlot()))) { //slot + qDebug() << m_serverName << "sessionBus.connect(): signalArrvied failed"; + } +} + +void dbus_client::initAPIs(QObject *parent){ + //connect the signal to qml inside function(addRoutePointsQml -> do_addRoutePoint) + if(!QObject::connect(this, SIGNAL(addRoutePointsQml(QVariant, QVariant, QVariant, QVariant)), + parent, SLOT(do_addRoutePoint(QVariant, QVariant, QVariant, QVariant)))) { + qDebug() << m_serverName << "SIGNAL:addRoutePointsQml to qmlSLOT:do_addRoutePoint connect is failed"; + } + + //connect the signal to qml inside function(positionQml -> do_setCoordinate) + if(!QObject::connect(this, SIGNAL(positionQml(QVariant, QVariant,QVariant, QVariant)), + parent, SLOT(do_setCoordinate(QVariant, QVariant,QVariant, QVariant)))) { + qDebug() << m_serverName << "SIGNAL:positionQml to qmlSLOT:do_setCoordinate connect is failed"; + } + + //connect the signal to qml inside function(stopdemoQml -> do_stopnavidemo) + if(!QObject::connect(this, SIGNAL(stopdemoQml()), + parent, SLOT(do_stopnavidemo()))) { + qDebug() << m_serverName << "SIGNAL:stopdemoQml to qmlSLOT:do_stopnavidemo connect is failed"; + } + + //connect the signal to qml inside function(arrivedestQml -> do_arrivedest) + if(!QObject::connect(this, SIGNAL(arrivedestQml()), + parent, SLOT(do_arrivedest()))) { + qDebug() << m_serverName << "SIGNAL:arrivedestQml to qmlSLOT:do_arrivedest connect is failed"; + } +} + +//Signal&&Method +//addRoutePointsSlot -> addRoutePointsQml(use for qml) +void dbus_client::addRoutePointsSlot(double route_Lat_s, double route_Lon_s, double route_Lat_e, double route_Lon_e) +{ + emit addRoutePointsQml(route_Lat_s, route_Lon_s, route_Lat_e, route_Lon_e); +} + +//positionSlot -> positionQml(use for qml) +void dbus_client::positionSlot(double cur_Lat_p, double cur_Lon_p,double cur_direction, double cur_distance) +{ + emit positionQml(cur_Lat_p, cur_Lon_p,cur_direction,cur_distance); +} + +//stopdemoSlot -> stopdemoQml(use for qml) +void dbus_client::stopdemoSlot() +{ + emit stopdemoQml(); +} + +//arrivedestSlot -> arrivedestQml(use for qml) +void dbus_client::arrivedestSlot() +{ + emit arrivedestQml(); +} diff --git a/app/dbus_client.h b/app/dbus_client.h new file mode 100644 index 0000000..0abae31 --- /dev/null +++ b/app/dbus_client.h @@ -0,0 +1,46 @@ +#ifndef DBUS_CLIENT_H +#define DBUS_CLIENT_H + +#include "naviapi_interface.h" +#include "naviapi_adaptor.h" +#include <QtQml/QQmlApplicationEngine> + +class dbus_client : public QObject{ + Q_OBJECT + QString m_serverName; + QString m_pathName; + QString m_objName; + +public: + dbus_client(const QString &pathName, + const QString &objName, + const QString &serverName, + QObject *parent = nullptr); + ~dbus_client(); + +private: + //DBus & API init + void initDBus(); + void initAPIs(QObject*); + +signals: + //notify add routepoints signal to qml + void addRoutePointsQml(QVariant, QVariant, QVariant, QVariant); + //notify current position signal to qml + void positionQml(QVariant, QVariant,QVariant, QVariant); + //notify stop demo signal to qml + void stopdemoQml(); + //notify arrive destination signal to qml + void arrivedestQml(); + +private slots: + //receive add routepoints notify from navigation service + void addRoutePointsSlot(double route_Lat_s, double route_Lon_s, double route_Lat_e, double route_Lon_e); + //receive current position notify from navigation service + void positionSlot(double cur_Lat_p, double cur_Lon_p,double cur_direction, double cur_distance); + //receive stop demo notify from navigation service + void stopdemoSlot(); + //receive arrive destination notify from navigation service + void arrivedestSlot(); +}; +#endif // DBUS_CLIENT_H diff --git a/app/file_operation.cpp b/app/file_operation.cpp new file mode 100644 index 0000000..a191c76 --- /dev/null +++ b/app/file_operation.cpp @@ -0,0 +1,92 @@ +#include "file_operation.h" + +File_Operation::File_Operation(){ + initFileOperation(); +} + +File_Operation::~File_Operation(){ + +} + +void File_Operation::initFileOperation(){ + + m_mapAccessToken = ""; + m_car_speed = 60; // set default Km/h + m_update_interval = 100; // set default millisecond + m_start_latitude = 35.692396; // set default coordinate Tokyo Hilton + m_start_longitute = 139.691102; + + QFile file(NAVI_CONFIG_FILEPATH); + if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ + fprintf(stderr,"Failed to open mapAccessToken file \"%s\": %m", qPrintable(NAVI_CONFIG_FILEPATH)); + return; + } + + QByteArray data = file.readAll(); + QJsonDocument jsonDoc(QJsonDocument::fromJson(data)); + QJsonObject jsonObj(jsonDoc.object()); + + if(jsonObj.contains("mapAccessToken")){ + m_mapAccessToken = jsonObj["mapAccessToken"].toString(); + }else{ + fprintf(stderr,"Failed to find mapAccessToken data \"%s\": %m", qPrintable(NAVI_CONFIG_FILEPATH)); + return; + } + if(jsonObj.contains("mapStyle")){ + m_mapStyle = jsonObj["mapStyle"].toString(); + }else{ + fprintf(stderr,"Failed to find mapStyle data \"%s\": %m", qPrintable(NAVI_CONFIG_FILEPATH)); + return; + } + + if(jsonObj.contains("speed")){ + m_car_speed = jsonObj["speed"].toDouble(); + }else{ + fprintf(stderr,"Failed to find speed data \"%s\": %m", qPrintable(NAVI_CONFIG_FILEPATH)); + return; + } + + if(jsonObj.contains("interval")){ + m_update_interval = jsonObj["interval"].toInt(); + }else{ + fprintf(stderr,"Failed to find interval data \"%s\": %m", qPrintable(NAVI_CONFIG_FILEPATH)); + return; + } + + if(jsonObj.contains("latitude")){ + m_start_latitude = jsonObj["latitude"].toDouble(); + }else{ + fprintf(stderr,"Failed to find latitude data \"%s\": %m", qPrintable(NAVI_CONFIG_FILEPATH)); + return; + } + + if(jsonObj.contains("longitute")){ + m_start_longitute = jsonObj["longitute"].toDouble(); + }else{ + fprintf(stderr,"Failed to find longitute data \"%s\": %m", qPrintable(NAVI_CONFIG_FILEPATH)); + return; + } + + file.close(); + + return; +} + +QString File_Operation::getMapAccessToken() { + return m_mapAccessToken; +} +QString File_Operation::getMapStyle() { + return m_mapStyle; +} +double File_Operation::getCarSpeed(){ + return m_car_speed; +} +int File_Operation::getUpdateInterval(){ + return m_update_interval; +} +double File_Operation::getStartLatitude(){ + return m_start_latitude; +} +double File_Operation::getStartLongitute(){ + return m_start_longitute; +} diff --git a/app/file_operation.h b/app/file_operation.h new file mode 100644 index 0000000..65df54a --- /dev/null +++ b/app/file_operation.h @@ -0,0 +1,40 @@ +#ifndef FILE_OPERATION_H +#define FILE_OPERATION_H +#include <QObject> +#include <QString> +#include <QFile> +#include <QJsonObject> +#include <QJsonDocument> + +/****************************************************** + * Write navigation config in /etc/naviconfig.ini + ******************************************************/ +#define NAVI_CONFIG_FILEPATH "/etc/naviconfig.ini" + +class File_Operation: public QObject{ + + Q_OBJECT + + QString m_mapAccessToken; + QString m_mapStyle; + double m_car_speed; // set Km/h + int m_update_interval; // set millisecond + double m_start_latitude; + double m_start_longitute; + +public: + File_Operation(); + ~File_Operation(); + + Q_INVOKABLE QString getMapAccessToken(); + Q_INVOKABLE QString getMapStyle(); + Q_INVOKABLE double getCarSpeed(); + Q_INVOKABLE int getUpdateInterval(); + Q_INVOKABLE double getStartLatitude(); + Q_INVOKABLE double getStartLongitute(); + +private: + void initFileOperation(); +}; + +#endif // FILE_OPERATION_H diff --git a/app/images/Thumbs.db b/app/images/Thumbs.db Binary files differnew file mode 100644 index 0000000..3ac30c1 --- /dev/null +++ b/app/images/Thumbs.db diff --git a/app/images/arrow-0-large.png b/app/images/arrow-0-large.png Binary files differnew file mode 100644 index 0000000..124b896 --- /dev/null +++ b/app/images/arrow-0-large.png diff --git a/app/images/arrow-l-180-full.png b/app/images/arrow-l-180-full.png Binary files differnew file mode 100644 index 0000000..0c71027 --- /dev/null +++ b/app/images/arrow-l-180-full.png diff --git a/app/images/arrow-l-180-large.png b/app/images/arrow-l-180-large.png Binary files differnew file mode 100644 index 0000000..cb4ff22 --- /dev/null +++ b/app/images/arrow-l-180-large.png diff --git a/app/images/arrow-l-30-full.png b/app/images/arrow-l-30-full.png Binary files differnew file mode 100644 index 0000000..de799ac --- /dev/null +++ b/app/images/arrow-l-30-full.png diff --git a/app/images/arrow-l-30-large.png b/app/images/arrow-l-30-large.png Binary files differnew file mode 100644 index 0000000..b660a71 --- /dev/null +++ b/app/images/arrow-l-30-large.png diff --git a/app/images/arrow-l-45-full.png b/app/images/arrow-l-45-full.png Binary files differnew file mode 100644 index 0000000..a3d8354 --- /dev/null +++ b/app/images/arrow-l-45-full.png diff --git a/app/images/arrow-l-45-large.png b/app/images/arrow-l-45-large.png Binary files differnew file mode 100644 index 0000000..6050cf7 --- /dev/null +++ b/app/images/arrow-l-45-large.png diff --git a/app/images/arrow-l-75-full.png b/app/images/arrow-l-75-full.png Binary files differnew file mode 100644 index 0000000..cd92e2d --- /dev/null +++ b/app/images/arrow-l-75-full.png diff --git a/app/images/arrow-l-75-large.png b/app/images/arrow-l-75-large.png Binary files differnew file mode 100644 index 0000000..5edd0b4 --- /dev/null +++ b/app/images/arrow-l-75-large.png diff --git a/app/images/arrow-r-180-full.png b/app/images/arrow-r-180-full.png Binary files differnew file mode 100644 index 0000000..d761b48 --- /dev/null +++ b/app/images/arrow-r-180-full.png diff --git a/app/images/arrow-r-180-large.png b/app/images/arrow-r-180-large.png Binary files differnew file mode 100644 index 0000000..22e8c9f --- /dev/null +++ b/app/images/arrow-r-180-large.png diff --git a/app/images/arrow-r-30-full.png b/app/images/arrow-r-30-full.png Binary files differnew file mode 100644 index 0000000..0bebfb9 --- /dev/null +++ b/app/images/arrow-r-30-full.png diff --git a/app/images/arrow-r-30-large.png b/app/images/arrow-r-30-large.png Binary files differnew file mode 100644 index 0000000..47bd445 --- /dev/null +++ b/app/images/arrow-r-30-large.png diff --git a/app/images/arrow-r-45-full.png b/app/images/arrow-r-45-full.png Binary files differnew file mode 100644 index 0000000..fa170f0 --- /dev/null +++ b/app/images/arrow-r-45-full.png diff --git a/app/images/arrow-r-45-large.png b/app/images/arrow-r-45-large.png Binary files differnew file mode 100644 index 0000000..b69a9e8 --- /dev/null +++ b/app/images/arrow-r-45-large.png diff --git a/app/images/arrow-r-75-full.png b/app/images/arrow-r-75-full.png Binary files differnew file mode 100644 index 0000000..08dc143 --- /dev/null +++ b/app/images/arrow-r-75-full.png diff --git a/app/images/arrow-r-75-large.png b/app/images/arrow-r-75-large.png Binary files differnew file mode 100644 index 0000000..537fd0b --- /dev/null +++ b/app/images/arrow-r-75-large.png diff --git a/app/images/car-marker.png b/app/images/car-marker.png Binary files differnew file mode 100644 index 0000000..34bab94 --- /dev/null +++ b/app/images/car-marker.png diff --git a/app/images/destination.png b/app/images/destination.png Binary files differnew file mode 100644 index 0000000..2d92322 --- /dev/null +++ b/app/images/destination.png diff --git a/app/images/destination_full.png b/app/images/destination_full.png Binary files differnew file mode 100644 index 0000000..e5c79d9 --- /dev/null +++ b/app/images/destination_full.png diff --git a/app/images/images.qrc b/app/images/images.qrc new file mode 100644 index 0000000..fc51ad3 --- /dev/null +++ b/app/images/images.qrc @@ -0,0 +1,28 @@ +<RCC> + <qresource prefix="/"> + <file>car-marker.png</file> + <file>marker-green.png</file> + <file>marker-end.png</file> + <file>simple-bottom-background-black.png</file> + <file>arrow-l-30-full.png</file> + <file>arrow-l-45-full.png</file> + <file>arrow-l-75-full.png</file> + <file>arrow-l-180-full.png</file> + <file>arrow-r-30-full.png</file> + <file>arrow-r-45-full.png</file> + <file>arrow-r-75-full.png</file> + <file>arrow-r-180-full.png</file> + <file>arrow-0-large.png</file> + <file>arrow-l-30-large.png</file> + <file>arrow-l-45-large.png</file> + <file>arrow-l-75-large.png</file> + <file>arrow-l-180-large.png</file> + <file>arrow-r-30-large.png</file> + <file>arrow-r-45-large.png</file> + <file>arrow-r-75-large.png</file> + <file>arrow-r-180-large.png</file> + <file>simple-background-white.png</file> + <file>destination.png</file> + <file>destination_full.png</file> + </qresource> +</RCC> diff --git a/app/images/marker-end.png b/app/images/marker-end.png Binary files differnew file mode 100644 index 0000000..2763c39 --- /dev/null +++ b/app/images/marker-end.png diff --git a/app/images/marker-green.png b/app/images/marker-green.png Binary files differnew file mode 100644 index 0000000..e2f2078 --- /dev/null +++ b/app/images/marker-green.png diff --git a/app/images/simple-background-white.png b/app/images/simple-background-white.png Binary files differnew file mode 100644 index 0000000..df9c2a0 --- /dev/null +++ b/app/images/simple-background-white.png diff --git a/app/images/simple-bottom-background-black.png b/app/images/simple-bottom-background-black.png Binary files differnew file mode 100644 index 0000000..5c70f5f --- /dev/null +++ b/app/images/simple-bottom-background-black.png diff --git a/app/main.cpp b/app/main.cpp new file mode 100644 index 0000000..6194c25 --- /dev/null +++ b/app/main.cpp @@ -0,0 +1,126 @@ +#include <QQmlApplicationEngine> + +#include <QtCore/QDebug> +#include <QtCore/QCommandLineParser> +#include <QtCore/QUrlQuery> +#include <QtGui/QGuiApplication> +#include <QtQml/QQmlContext> +#include <QtQuick/QQuickWindow> +#include <QtDBus/QDBusConnection> + +#include "qcheapruler.hpp" +#include "dbus_client.h" +#include "file_operation.h" + +#ifdef HAVE_LIBHOMESCREEN +#include <libhomescreen.hpp> +#endif +#ifdef HAVE_QLIBWINDOWMANAGER +#include <qlibwindowmanager.h> +#endif + +int main(int argc, char *argv[]) +{ + if (!QDBusConnection::sessionBus().isConnected()) { + qWarning("Cannot connect to the D-Bus session bus.\n" + "Please check your system settings and try again.\n"); + return 1; + } + + QString myname = QString("tbtnavi"); + + QGuiApplication app(argc, argv); + app.setApplicationName(myname); + app.setApplicationVersion(QStringLiteral("0.1.0")); + app.setOrganizationDomain(QStringLiteral("automotivelinux.org")); + app.setOrganizationName(QStringLiteral("AutomotiveGradeLinux")); + + QCommandLineParser parser; + parser.addPositionalArgument("port", app.translate("main", "port for binding")); + parser.addPositionalArgument("secret", app.translate("main", "secret for binding")); + parser.addHelpOption(); + parser.addVersionOption(); + parser.process(app); + QStringList positionalArguments = parser.positionalArguments(); + + QQmlApplicationEngine engine; + int port = 0; + QString secret; + if (positionalArguments.length() == 2) { + port = positionalArguments.takeFirst().toInt(); + secret = positionalArguments.takeFirst(); + } + +#ifdef HAVE_QLIBWINDOWMANAGER + // WindowManager + QLibWindowmanager* qwm = new QLibWindowmanager(); + if(qwm->init(port,secret) != 0){ + exit(EXIT_FAILURE); + } + // Request a surface as described in layers.json windowmanager’s file + if(qwm->requestSurface(myname) != 0){ + exit(EXIT_FAILURE); + } +#endif + +#ifdef HAVE_LIBHOMESCREEN + // HomeScreen + LibHomeScreen* hs = new LibHomeScreen(); + std::string token = secret.toStdString(); + hs->init(port, token.c_str()); + // Set the event handler for Event_TapShortcut which will activate the surface for windowmanager + hs->set_event_handler(LibHomeScreen::Event_TapShortcut, [qwm, myname](json_object *object){ + + json_object *appnameJ = nullptr; + if(json_object_object_get_ex(object, "application_name", &appnameJ)) + { + const char *appname = json_object_get_string(appnameJ); + if(QString::compare(myname, appname, Qt::CaseInsensitive) == 0) + { + qDebug("Surface %s got tapShortcut\n", appname); + json_object *para, *area; + json_object_object_get_ex(object, "parameter", ¶); + json_object_object_get_ex(para, "area", &area); + const char *displayArea = json_object_get_string(area); + qDebug("Surface %s got tapShortcut area\n", displayArea); +// qwm->activateWindow(myname, QString(QLatin1String(displayArea))); + qwm->activateWindow(myname, "master.split.sub"); + } + } + }); +#endif + qmlRegisterType<QCheapRuler>("com.mapbox.cheap_ruler", 1, 0, "CheapRuler"); + + File_Operation file; + engine.rootContext()->setContextProperty("fileOperation", &file); + + engine.load(QUrl(QStringLiteral("qrc:qml/Main.qml"))); + + QObject *root = engine.rootObjects().first(); + QQuickWindow *window = qobject_cast<QQuickWindow *>(root); + + //make the DBus connection info + QString pathBase = "org.agl."; + QString objBase = "/org/agl/"; + QString serverName = "naviapi"; + QObject *mapWindow = root->findChild<QObject*>("mapwindow"); + dbus_client dbus(pathBase, objBase, serverName, mapWindow); + +#ifdef HAVE_QLIBWINDOWMANAGER +// QObject::connect(window, SIGNAL(frameSwapped()), qwm, SLOT(slotActivateSurface())); + // Create an event callback against an event type. Here a lambda is called when SyncDraw event occurs + qwm->set_event_handler(QLibWindowmanager::Event_SyncDraw, [root, qwm, myname](json_object *object) { + fprintf(stderr, "Surface got syncDraw!\n"); + qwm->endDraw(myname); + }); + // Create an event callback against an event type. Here a lambda is called when SyncDraw event occurs + qwm->set_event_handler(QLibWindowmanager::Event_Active, [root](json_object *object) { + fprintf(stderr, "Surface got Event_Active!\n"); + }); +#else + window->resize(1024, 768); + window->setVisible(true); +#endif + + return app.exec(); +} diff --git a/app/org.agl.naviapi.xml b/app/org.agl.naviapi.xml new file mode 100644 index 0000000..d1538e7 --- /dev/null +++ b/app/org.agl.naviapi.xml @@ -0,0 +1,28 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.agl.naviapi"> + <!-- void signalRouteInfo() --> + <signal name="signalRouteInfo"> + <arg name="start_latitude" type="d" direction="out"/> + <arg name="start_longitude" type="d" direction="out"/> + <arg name="end_latitude" type="d" direction="out"/> + <arg name="end_longitude" type="d" direction="out"/> + </signal> + <!-- void signalPosInfo() --> + <signal name="signalPosInfo"> + <arg name="latitude" type="d" direction="out"/> + <arg name="longitude" type="d" direction="out"/> + <arg name="direction" type="d" direction="out"/> + <arg name="distance" type="d" direction="out"/> + </signal> + <!-- void signalStopDemo() --> + <signal name="signalStopDemo"> + </signal> + <!-- void signalArrvied() --> + <signal name="signalArrvied"> + </signal> + <!-- void getRouteInfo() --> + <signal name="getRouteInfo"> + </signal> + </interface> +</node> diff --git a/app/qcheapruler.cpp b/app/qcheapruler.cpp new file mode 100644 index 0000000..890fd63 --- /dev/null +++ b/app/qcheapruler.cpp @@ -0,0 +1,117 @@ +#include "qcheapruler.hpp" +#include "naviapi_adaptor.h" + +#include <QString> + +QCheapRuler::QCheapRuler() +{ + //set the default current position + // m_currentPosition = QGeoCoordinate(36.136261, -115.151254); + m_currentPosition = QGeoCoordinate(35.692396, 139.691102); +} + +QCheapRuler::~QCheapRuler() +{ +} + +//get route distance +double QCheapRuler::distance() const +{ + return m_distance; +} + +//get current distance along the route +double QCheapRuler::currentDistance() const +{ + return m_currentDistance; +} + +//set current position below the coordinate info from navigation service +void QCheapRuler::setCurrentPosition(double latitude, double longitude) +{ + //set coordinate info and notify the changes when latitude or longitude info has changed + if((m_currentPosition.latitude() != latitude) + ||(m_currentPosition.longitude() != longitude)) + { + m_currentPosition.setLatitude(latitude); + m_currentPosition.setLongitude(longitude); + emit currentPositionChanged(); + } +} + +void QCheapRuler::setCurrentDistance(double distance) +{ + //set current distance info and notify the changes when the info has changed + //but it will not send notify when it start or stop demo + if((m_currentDistance != distance) + &&(distance != 0.0)) + { + m_currentDistance = distance; + emit currentDistanceChanged(); + } +} + +//get current position(coordinate) +QGeoCoordinate QCheapRuler::currentPosition() const +{ + return m_currentPosition; +} + +QJSValue QCheapRuler::path() const +{ + // Should neveer be called. + return QJSValue(); +} + +//set route path and get the total distance +void QCheapRuler::setPath(const QJSValue &value) +{ + if (!value.isArray()) + return; + + m_path.clear(); + quint32 length = value.property(QStringLiteral("length")).toUInt(); + + //push back the coordinate info along the route + for (unsigned i = 0; i < length; ++i) { + auto property = value.property(i); + cr::point coordinate = { 0., 0. }; + + if (property.hasProperty(QStringLiteral("latitude"))) + coordinate.y = property.property(QStringLiteral("latitude")).toNumber(); + + if (property.hasProperty(QStringLiteral("longitude"))) + coordinate.x = property.property(QStringLiteral("longitude")).toNumber(); + + m_path.push_back(coordinate); + } + + //count the total distance along the route + double distance = ruler().lineDistance(m_path); + if (m_distance != distance) { + m_distance = distance; + } + + emit pathChanged(); +} + +//init the route and postion info when start in the first time.(can be called by qml) +void QCheapRuler::initRouteInfo() +{ + //send "getRouteInfo" message to the navigation service + QDBusMessage message = QDBusMessage::createSignal("/", "org.agl.naviapi", "getRouteInfo"); + if(!QDBusConnection::sessionBus().send(message)) + { + qDebug() << "initRouteInfo" << "sessionBus.send(): getRouteInfo failed"; + } +} + +//init the CheapRuler class +cr::CheapRuler QCheapRuler::ruler() const +{ + if (m_path.empty()) { + return cr::CheapRuler(0., cr::CheapRuler::Kilometers); + } else { + return cr::CheapRuler(m_currentPosition.latitude(), cr::CheapRuler::Kilometers); + } +} diff --git a/app/qcheapruler.hpp b/app/qcheapruler.hpp new file mode 100644 index 0000000..9e9c664 --- /dev/null +++ b/app/qcheapruler.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include <QGeoCoordinate> +#include <QJSValue> +#include <QObject> +#include <QtCore> + +#include <mapbox/cheap_ruler.hpp> /* BSD3 LICENSE */ + +namespace cr = mapbox::cheap_ruler; + +class QCheapRuler : public QObject{ + Q_OBJECT + //registy the read write¬ify function for qml + //the distance from start point to end point(read only) + Q_PROPERTY(double distance READ distance) + //the distance from start point to current postion along the route(read notify) + Q_PROPERTY(double currentDistance READ currentDistance NOTIFY currentDistanceChanged) + //the coordinate info of current postion(read) + Q_PROPERTY(QGeoCoordinate currentPosition READ currentPosition NOTIFY currentPositionChanged) + //the route path info postion(read write¬ify) + Q_PROPERTY(QJSValue path READ path WRITE setPath NOTIFY pathChanged) + +public: + QCheapRuler(); + ~QCheapRuler(); + + //read write¬ify function for qml + double distance() const; + double currentDistance() const; + QGeoCoordinate currentPosition() const; + QJSValue path() const; + void setPath(const QJSValue &value); + + //functions that can called by qml(Q_INVOKABLE) + Q_INVOKABLE void initRouteInfo(); + Q_INVOKABLE void setCurrentPosition(double, double); + Q_INVOKABLE void setCurrentDistance(double); + +signals: + //notify signals to qml + //notify signal when the distance from start point to current postion changed + void currentDistanceChanged(); + //notify signal when currentPosition changed + void currentPositionChanged(); + //notify signal when the distance from start point to current postion changed + void pathChanged(); + +private: + cr::CheapRuler ruler() const; + + double m_distance = 0.; + double m_currentDistance = 0.; + QGeoCoordinate m_currentPosition; + + cr::line_string m_path; +}; diff --git a/app/qml/Main.qml b/app/qml/Main.qml new file mode 100644 index 0000000..4139cb9 --- /dev/null +++ b/app/qml/Main.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.2 + +import "qrc:/qml" + +ApplicationWindow { + id: window + + title: "Turn By Turn Navigation Demo" + height: 720 + width: 640 + visible: true + + Item { + anchors.centerIn: parent + width: parent.width + height: parent.height + + MapWindow { + id:mapwindow + anchors.fill: parent + objectName: "mapwindow" + } + } +} diff --git a/app/qml/MapWindow.qml b/app/qml/MapWindow.qml new file mode 100644 index 0000000..8a41390 --- /dev/null +++ b/app/qml/MapWindow.qml @@ -0,0 +1,283 @@ +import QtLocation 5.9 +import QtPositioning 5.0 +import QtQuick 2.0 + +import com.mapbox.cheap_ruler 1.0 + +Item { + id: mapWindow + + property int disOffset: 70 + property real rotateAngle: 0 + property var startPoint + property var endPoint + + //turn by turn board view + TbtBoard { + id: tbt_board + z: 1 + visible: false + anchors.fill: parent + } + + //mapview and route views + Map { + id: map + anchors.fill: parent + + plugin: Plugin { + name: "mapboxgl" + + PluginParameter { + name: "mapboxgl.mapping.items.insert_before" + value: "road-label-small" + } + + PluginParameter { + name: "mapboxgl.mapping.additional_style_urls" + value: "mapbox://styles/mapbox/streets-v9" + } + + PluginParameter { + name: "mapboxgl.access_token" + value: fileOperation.getMapAccessToken() + } + + PluginParameter { + name: "mapboxgl.mapping.cache.directory" + value: "/home/0/app-data/navigation/" + } + } + + center: ruler.currentPosition + zoomLevel: 20 + tilt: 60 + gesture.acceptedGestures:MapGestureArea.NoGesture + copyrightsVisible: false + + RotationAnimation on bearing { + id: bearingAnimation + + duration: 250 + alwaysRunToEnd: false + direction: RotationAnimation.Shortest + running: true + } + + Location { + id: previousLocation + coordinate: QtPositioning.coordinate(0, 0); + } + + onCenterChanged: { + if (previousLocation.coordinate === center) + return; + + bearingAnimation.to = previousLocation.coordinate.azimuthTo(center); + bearingAnimation.start(); + + previousLocation.coordinate = center; + } + + MapQuickItem { + id: startMarker + + sourceItem: Image { + id: greenMarker + source: "qrc:///marker-green.png" + } + anchorPoint.x: greenMarker.width / 2 + anchorPoint.y: greenMarker.height / 2 + } + + MapQuickItem { + id: endMarker + + sourceItem: Image { + id: redMarker + source: "qrc:///marker-end.png" + } + anchorPoint.x: redMarker.width / 2 + anchorPoint.y: redMarker.height / 2 + } + + MapItemView { + model: routeModel + + delegate: MapRoute { + route: routeData + line.color: "#6b43a1" + line.width: map.zoomLevel - 5 + opacity: (index == 0) ? 1.0 : 0.3 + + onRouteChanged: { + ruler.path = routeData.path; + } + } + } + + MapQuickItem { + zoomLevel: map.zoomLevel + + sourceItem: Image { + id: carMarker + source: "qrc:///car-marker.png" + transform: Rotation { + origin.x: carMarker.width / 2; + origin.y: carMarker.height / 2; + angle: rotateAngle + } + } + + coordinate: ruler.currentPosition + anchorPoint.x: carMarker.width / 2 + anchorPoint.y: carMarker.height / 2 + + Location { + id: previousCarLocation + coordinate: QtPositioning.coordinate(0, 0); + } + + onCoordinateChanged: { + if(coordinate === mapWindow.startPoint) + return; + rotateAngle = previousCarLocation.coordinate.azimuthTo(coordinate); + previousCarLocation.coordinate = coordinate; + } + } + + //add route view in the map + function updateRoute() { + routeQuery.clearWaypoints(); + routeQuery.addWaypoint(startMarker.coordinate); + routeQuery.addWaypoint(endMarker.coordinate); + map.addMapItem(startMarker) + map.addMapItem(endMarker) + } + + //clear route view in the map + function clearRoute() { + routeQuery.clearWaypoints(); + routeModel.reset(); + map.removeMapItem(startMarker) + map.removeMapItem(endMarker) + } + + CheapRuler { + id: ruler + + onCurrentDistanceChanged: { + var total = 0; + var i = 0; + var alldistance = ruler.distance * 1000; + + if((routeModel.status === RouteModel.Ready) + && (routeModel.count === 1)) + { + // XXX: Use car speed in meters to pre-warn the turn instruction + while (total < ruler.currentDistance && i < routeModel.get(0).segments.length) + { + total += routeModel.get(0).segments[i++].maneuver.distanceToNextInstruction; + } + + //show the tbt board(it will be always show when demo start) + tbt_board.visible = true + + // Set turn instruction + tbt_board.do_setTurnInstructions(routeModel.get(0).segments[i].maneuver.instructionText) + tbt_board.state = routeModel.get(0).segments[i].maneuver.direction + + //when goto the last instruction,set the states to "arriveDest" + if(i >= (routeModel.get(0).segments.length-1)) + { + total = alldistance; + tbt_board.state = "arriveDest"; + } + + var dis = (total - ruler.currentDistance).toFixed(1); + + // Set distance + tbt_board.do_setDistance(dis) + + // Set board status + if(dis < mapWindow.disOffset && i < routeModel.get(0).segments.length) + { + //show the tbt board(the big one) + tbt_board.do_showTbtboard(true) + } + else + { + //disvisible the tbt board(the big one) + tbt_board.do_showTbtboard(false) + } + } + } + } + } + + //the route view display by RouteModel + RouteModel { + id: routeModel + + autoUpdate: true + query: routeQuery + + plugin: Plugin { + name: "mapbox" + + // Development access token, do not use in production. + PluginParameter { + name: "mapbox.access_token" + value: fileOperation.getMapAccessToken() + } + } + } + + RouteQuery { + id: routeQuery + } + + Component.onCompleted: { + //request the route info when map load finish + if (ruler) { + ruler.initRouteInfo(); + ruler.setCurrentPosition(fileOperation.getStartLatitude(), fileOperation.getStartLongitute()); + } + } + + //the functions can be called by outside + //add route signal function + function do_addRoutePoint(poi_Lat_s, poi_Lon_s, poi_Lat_e, poi_Lon_e) { + //set the startPoint and endPoint + startPoint= QtPositioning.coordinate(poi_Lat_s,poi_Lon_s); + endPoint = QtPositioning.coordinate(poi_Lat_e,poi_Lon_e); + startMarker.coordinate = startPoint; + endMarker.coordinate = endPoint; + //update the route view + if (map) { + map.updateRoute(); + } + } + + //set the current position + function do_setCoordinate(latitude,longitude,direction,distance) { + ruler.setCurrentPosition(latitude, longitude); + ruler.setCurrentDistance(distance); + } + + //stop navidemo signal + function do_stopnavidemo() { + //disvisible the tbt board + tbt_board.visible = false + //clear the routeview + if (map) { + map.clearRoute(); + } + } + + //arrvice the destination signal + function do_arrivedest(){ + //disvisible the tbt board + tbt_board.visible = false + } +} diff --git a/app/qml/TbtBoard.qml b/app/qml/TbtBoard.qml new file mode 100644 index 0000000..cf6f537 --- /dev/null +++ b/app/qml/TbtBoard.qml @@ -0,0 +1,187 @@ +import QtQuick 2.0 + +//turn by turn board view +Item { + id: tbt_board + + property bool showboard: false + + // the backgroud image(the small one) + Image { + id: whitebackgroud + visible: !showboard + anchors.top: parent.top + width:turnDirection.width + height:turnDirection.height + distance.height + source: "qrc:simple-background-white.png" + z: 1 + } + + // turn direction arrow board image(the small one) + Image { + id: turnDirection + visible: !showboard + anchors.top: parent.top + z: 3 + } + + // the distance to the next crossing road(textview)(the small one) + Text { + id: distance + visible: !showboard + anchors.top: turnDirection.bottom + z: 3 + font.pixelSize: 23 + width:turnDirection.width + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.weight: Font.Light + color: "#000000" + } + + // the backgroud image + Image { + id: backgroudBoard + visible: showboard + anchors.fill: parent + source: "qrc:simple-bottom-background-black.png" + z: 1 + } + + // turn direction arrow board image + Image { + id: turnDirectionBoard + visible: showboard + width : parent.height - turnInstructionsBoard.height - distanceBoard.height + height: parent.height - turnInstructionsBoard.height - distanceBoard.height + anchors.centerIn: parent + z: 3 + } + + // the distance to the next crossing road(textview) + Text { + id: distanceBoard + visible: showboard + anchors.bottom: turnInstructionsBoard.top + z: 3 + font.pixelSize: 45 + width:tbt_board.width + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.weight: Font.Light + color: "#FFFFFF" + } + + // the description of the next crossing road(textview) + Text { + id: turnInstructionsBoard + visible: showboard + anchors.bottom: parent.bottom + z: 3 + font.pixelSize: 30 + width:tbt_board.width + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.weight: Font.Light + color: "#FFFFFF" + } + + // the cases of direction arrow board + states: [ + State { + name: "arriveDest" //arrive the destination + PropertyChanges { target: turnDirectionBoard; source: "qrc:destination_full.png" } + PropertyChanges { target: turnDirection; source: "qrc:destination.png" } + }, + State { + name: "0" // NoDirection + PropertyChanges { target: turnDirectionBoard; source: "" } + PropertyChanges { target: turnDirection; source: "" } + }, + State { + name: "1" // DirectionForward + PropertyChanges { target: turnDirectionBoard; source: "" } + PropertyChanges { target: turnDirection; source: "" } + }, + State { + name: "2" // DirectionBearRight + PropertyChanges { target: turnDirectionBoard; source: "" } + PropertyChanges { target: turnDirection; source: "" } + }, + State { + name: "3" // DirectionLightRight + PropertyChanges { target: turnDirectionBoard; source: "qrc:arrow-r-30-full.png" } + PropertyChanges { target: turnDirection; source: "qrc:arrow-r-30-large.png" } + }, + State { + name: "4" // DirectionRight + PropertyChanges { target: turnDirectionBoard; source: "qrc:arrow-r-45-full.png" } + PropertyChanges { target: turnDirection; source: "qrc:arrow-r-45-large.png" } + }, + State { + name: "5" // DirectionHardRight + PropertyChanges { target: turnDirectionBoard; source: "qrc:arrow-r-75-full.png" } + PropertyChanges { target: turnDirection; source: "qrc:arrow-r-75-large.png" } + }, + State { + name: "6" // DirectionUTurnRight + //TODO modify qtlocation U-Turn best.For test, change app source. + PropertyChanges { target: turnDirectionBoard; source: "qrc:arrow-l-180-full.png" } + PropertyChanges { target: turnDirection; source: "qrc:arrow-l-180-large.png" } + }, + State { + name: "7" // DirectionUTurnLeft + //TODO modify qtlocation U-Turn best.For test, change app source. + PropertyChanges { target: turnDirectionBoard; source: "qrc:arrow-r-180-full.png" } + PropertyChanges { target: turnDirection; source: "qrc:arrow-r-180-large.png" } + }, + State { + name: "8" // DirectionHardLeft + PropertyChanges { target: turnDirectionBoard; source: "qrc:arrow-l-75-full.png" } + PropertyChanges { target: turnDirection; source: "qrc:arrow-l-75-large.png" } + }, + State { + name: "9" // DirectionLeft + PropertyChanges { target: turnDirectionBoard; source: "qrc:arrow-l-45-full.png" } + PropertyChanges { target: turnDirection; source: "qrc:arrow-l-45-large.png" } + }, + State { + name: "10" // DirectionLightLeft + PropertyChanges { target: turnDirectionBoard; source: "qrc:arrow-l-30-full.png" } + PropertyChanges { target: turnDirection; source: "qrc:arrow-l-30-large.png" } + }, + State { + name: "11" // DirectionBearLeft + PropertyChanges { target: turnDirectionBoard; source: "" } + PropertyChanges { target: turnDirection; source: "" } + } + ] + + // Set distance + function do_setDistance(dis) { + if(dis > 1000) + { + distanceBoard.text = (dis / 1000).toFixed(1) + " km" + } + else + { + distanceBoard.text = dis + " m" + } + + distance.text = (((dis/100).toFixed(0))*100) +"m" + } + + //set turnInstructions + function do_setTurnInstructions(turnInstructions) { + turnInstructionsBoard.text = turnInstructions + } + + //show the tbt board(the big one) + function do_showTbtboard(mvisible) { + showboard = mvisible + } +} diff --git a/app/qml/qmldir b/app/qml/qmldir new file mode 100644 index 0000000..7bbd751 --- /dev/null +++ b/app/qml/qmldir @@ -0,0 +1,2 @@ +MapWindow 1.0 MapWindow.qml +TbtBoard 1.0 TbtBoard.qml |