diff options
author | Stefan Wildemann <metalstrolch@users.noreply.github.com> | 2017-05-05 05:04:00 +0200 |
---|---|---|
committer | Pierre GRANDIN <pgrandin@users.noreply.github.com> | 2017-05-04 20:04:00 -0700 |
commit | 585305d57ce8e1c5a3db978086102604f55cb006 (patch) | |
tree | 729b8e85769c9122f0a84e241d369373408e744a | |
parent | a5b607303d83e2b46950e2aef63eb5787f3098fb (diff) | |
download | navit-585305d57ce8e1c5a3db978086102604f55cb006.tar.gz |
Add Qt5 qml gui skeleton (#236)R7461
* Initial parts of qt5 qml graphics based on graphics/qt5_qml
* Qt5 QML gui: working handover
The hand over of the QML engine between the graphics and the gui part is
working now. The gui can load it's own QML component and embed the navit
widget inside other QML code.
* Remove unneeded moc include
* Fix: Apply coding style
* Fix:extern "C" the navit includes in graphics qt5
Seems the navit includes are not fully "c++" aware, so extern "C" them in the
c++ parts.
-rwxr-xr-x | CMakeLists.txt | 4 | ||||
-rw-r--r-- | navit/graphics/qt5/QNavitQuick.cpp | 5 | ||||
-rw-r--r-- | navit/graphics/qt5/QNavitWidget.cpp | 5 | ||||
-rw-r--r-- | navit/graphics/qt5/event_qt5.cpp | 5 | ||||
-rw-r--r-- | navit/graphics/qt5/graphics_qt5.cpp | 27 | ||||
-rw-r--r-- | navit/graphics/qt5/graphics_qt5.h | 4 | ||||
-rw-r--r-- | navit/graphics/qt5/graphics_qt5.qml | 17 | ||||
-rw-r--r-- | navit/graphics/qt5/graphics_qt5.qrc | 1 | ||||
-rw-r--r-- | navit/graphics/qt5/loader.qml | 20 | ||||
-rw-r--r-- | navit/gui/qt5_qml/CMakeLists.txt | 7 | ||||
-rw-r--r-- | navit/gui/qt5_qml/gui_qt5_qml.cpp | 254 | ||||
-rw-r--r-- | navit/gui/qt5_qml/gui_qt5_qml.qml | 23 | ||||
-rw-r--r-- | navit/gui/qt5_qml/gui_qt5_qml.qrc | 5 |
13 files changed, 355 insertions, 22 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e4e5ed7aa..8804c0184 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,6 +96,7 @@ add_module(graphics/egl "Required library not found" FALSE) add_module(graphics/qt_qpainter "Qt libraries not found" FALSE) add_module(graphics/qt5 "Qt5 libraries not found" FALSE) add_module(gui/qml "Qt Declarative not found" FALSE) +add_module(gui/qt5_qml "Qt5 Declarative not found" FALSE) add_module(gui/gtk "GTK libs not found" FALSE) add_module(vehicle/gpsd "gpsd lib not found" FALSE) add_module(vehicle/gypsy "gypsy lib not found" FALSE) @@ -339,6 +340,9 @@ if (Qt5Widgets_FOUND OR Qt5Quick_FOUND) if(USE_QML) set(Qt5_ADDITIONAL_LIBRARIES ${Qt5_ADDITIONAL_LIBRARIES} ${Qt5Quick_LIBRARIES}) endif() + set_with_reason(gui/qt5_qml "Qt5 found" TRUE + ${Qt5Quick_LIBRARIES}) + endif() set_with_reason(graphics/qt5 "Qt5 found" TRUE ${Qt5_ADDITIONAL_LIBRARIES} diff --git a/navit/graphics/qt5/QNavitQuick.cpp b/navit/graphics/qt5/QNavitQuick.cpp index d2664be27..798415f2c 100644 --- a/navit/graphics/qt5/QNavitQuick.cpp +++ b/navit/graphics/qt5/QNavitQuick.cpp @@ -18,10 +18,12 @@ */ #include <glib.h> -#include "config.h" #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +extern"C" { +#include "config.h" + #include "item.h" #include "point.h" #include "graphics.h" @@ -32,6 +34,7 @@ #include "window.h" #include "callback.h" #include "keys.h" +} #if defined(WINDOWS) || defined(WIN32) || defined (HAVE_API_WIN32_CE) #include <windows.h> #endif diff --git a/navit/graphics/qt5/QNavitWidget.cpp b/navit/graphics/qt5/QNavitWidget.cpp index d58f835a6..20b1d852f 100644 --- a/navit/graphics/qt5/QNavitWidget.cpp +++ b/navit/graphics/qt5/QNavitWidget.cpp @@ -18,10 +18,12 @@ */ #include <glib.h> -#include "config.h" #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +extern "C" { +#include "config.h" + #include "item.h" #include "point.h" #include "graphics.h" @@ -32,6 +34,7 @@ #include "window.h" #include "callback.h" #include "keys.h" +} #if defined(WINDOWS) || defined(WIN32) || defined (HAVE_API_WIN32_CE) #include <windows.h> #endif diff --git a/navit/graphics/qt5/event_qt5.cpp b/navit/graphics/qt5/event_qt5.cpp index 9cea3d921..729e3903b 100644 --- a/navit/graphics/qt5/event_qt5.cpp +++ b/navit/graphics/qt5/event_qt5.cpp @@ -20,7 +20,10 @@ #include <glib.h> #include <stdio.h> #include <stdlib.h> + +extern "C" { #include "config.h" + #include "navit/point.h" #include "navit/item.h" #include "navit/graphics.h" @@ -32,6 +35,8 @@ #include "navit/window.h" #include "navit/keys.h" #include "navit/navit.h" +} + #if defined(WINDOWS) || defined(WIN32) || defined (HAVE_API_WIN32_CE) #include <windows.h> #endif diff --git a/navit/graphics/qt5/graphics_qt5.cpp b/navit/graphics/qt5/graphics_qt5.cpp index 37fda3d66..f03ad36e0 100644 --- a/navit/graphics/qt5/graphics_qt5.cpp +++ b/navit/graphics/qt5/graphics_qt5.cpp @@ -18,10 +18,12 @@ */ #include <glib.h> -#include "config.h" #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +extern "C" { +#include "config.h" + #include "item.h" #include "point.h" #include "graphics.h" @@ -31,9 +33,8 @@ #include "debug.h" #include "window.h" #include "callback.h" -#if defined(WINDOWS) || defined(WIN32) || defined (HAVE_API_WIN32_CE) -#include <windows.h> -#endif +} + #include "graphics_qt5.h" #include "event_qt5.h" #include <QGuiApplication> @@ -55,6 +56,9 @@ #include <QApplication> #include "QNavitWidget.h" #endif +#if defined(WINDOWS) || defined(WIN32) || defined (HAVE_API_WIN32_CE) +#include <windows.h> +#endif #if USE_QML GraphicsPriv::GraphicsPriv(struct graphics_priv * gp) @@ -665,6 +669,10 @@ get_data(struct graphics_priv *this_priv, char const *type) resize_callback(this_priv, this_priv->pixmap->width(),this_priv->pixmap->height()); return win; } + if (strcmp(type, "engine") == 0) { + dbg(lvl_debug, "Hand over QQmlApplicationEngine\n"); + return(this_priv->engine); + } return NULL; } @@ -893,6 +901,7 @@ graphics_qt5_new(struct navit *nav, struct graphics_methods *meth, struct attr * graphics_priv->y = 0; graphics_priv->disable = 0; #if USE_QML + graphics_priv->engine = NULL; graphics_priv->window = NULL; graphics_priv->GPriv = NULL; if(use_qml) @@ -901,15 +910,15 @@ graphics_qt5_new(struct navit *nav, struct graphics_methods *meth, struct attr * qmlRegisterType<QNavitQuick>("com.navit.graphics_qt5", 1, 0, "QNavitQuick"); /* get our qml application from embedded resources. May be replaced by the * QtQuick gui component if enabled */ - QQmlApplicationEngine * engine = new QQmlApplicationEngine(); - if(engine != NULL) + graphics_priv->engine = new QQmlApplicationEngine(); + if(graphics_priv->engine != NULL) { graphics_priv->GPriv = new GraphicsPriv(graphics_priv); - QQmlContext *context = engine->rootContext(); + QQmlContext *context = graphics_priv->engine->rootContext(); context->setContextProperty("graphics_qt5_context", graphics_priv->GPriv); - engine->load(QUrl("qrc:///graphics_qt5.qml")); + graphics_priv->engine->load(QUrl("qrc:///loader.qml")); /* Get the engine's root window (for resizing) */ - QObject *toplevel = engine->rootObjects().value(0); + QObject *toplevel = graphics_priv->engine->rootObjects().value(0); graphics_priv->window = qobject_cast<QQuickWindow *> (toplevel); } } diff --git a/navit/graphics/qt5/graphics_qt5.h b/navit/graphics/qt5/graphics_qt5.h index 2e3f7b85e..fad818773 100644 --- a/navit/graphics/qt5/graphics_qt5.h +++ b/navit/graphics/qt5/graphics_qt5.h @@ -16,6 +16,7 @@ #include <QPen> #include <QBrush> #if USE_QML +#include <QQmlApplicationEngine> #include <QQuickWindow> #include <QObject> #endif @@ -57,7 +58,8 @@ signals: struct graphics_priv { #if USE_QML - GraphicsPriv * GPriv; + QQmlApplicationEngine * engine; + GraphicsPriv * GPriv; QQuickWindow * window; #endif #if USE_QWIDGET diff --git a/navit/graphics/qt5/graphics_qt5.qml b/navit/graphics/qt5/graphics_qt5.qml index a797c8eb9..5f6056b26 100644 --- a/navit/graphics/qt5/graphics_qt5.qml +++ b/navit/graphics/qt5/graphics_qt5.qml @@ -2,14 +2,11 @@ import com.navit.graphics_qt5 1.0 import QtQuick 2.2 import QtQuick.Window 2.0 -Window { - width: 200; height: 200 - QNavitQuick { - id: navit1 - anchors.fill: parent - focus: true - Component.onCompleted: { - navit1.setGraphicContext(graphics_qt5_context) - } - } +QNavitQuick { + id: navit1 + anchors.fill: parent + focus: true + Component.onCompleted: { + navit1.setGraphicContext(graphics_qt5_context) + } } diff --git a/navit/graphics/qt5/graphics_qt5.qrc b/navit/graphics/qt5/graphics_qt5.qrc index 4c82492ee..6a161f621 100644 --- a/navit/graphics/qt5/graphics_qt5.qrc +++ b/navit/graphics/qt5/graphics_qt5.qrc @@ -1,5 +1,6 @@ <RCC> <qresource prefix="/"> + <file>loader.qml</file> <file>graphics_qt5.qml</file> </qresource> </RCC> diff --git a/navit/graphics/qt5/loader.qml b/navit/graphics/qt5/loader.qml new file mode 100644 index 000000000..6901c2c6f --- /dev/null +++ b/navit/graphics/qt5/loader.qml @@ -0,0 +1,20 @@ +import com.navit.graphics_qt5 1.0 +import QtQuick 2.2 +import QtQuick.Window 2.0 + +Window { + width: 200; height: 200 + + Loader { + id: navit_loader + focus: true + source: "graphics_qt5.qml" + anchors.fill: parent + objectName: "navit_loader" + } + + Item { + id: root_item + anchors.fill: parent + } +} diff --git a/navit/gui/qt5_qml/CMakeLists.txt b/navit/gui/qt5_qml/CMakeLists.txt new file mode 100644 index 000000000..a191c9d69 --- /dev/null +++ b/navit/gui/qt5_qml/CMakeLists.txt @@ -0,0 +1,7 @@ +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) + +qt5_add_resources(GUI_QT5_QML_QRC "gui_qt5_qml.qrc") +module_add_library(gui_qt5_qml gui_qt5_qml.cpp ${GUI_QT5_QML_QRC}) diff --git a/navit/gui/qt5_qml/gui_qt5_qml.cpp b/navit/gui/qt5_qml/gui_qt5_qml.cpp new file mode 100644 index 000000000..a8689843f --- /dev/null +++ b/navit/gui/qt5_qml/gui_qt5_qml.cpp @@ -0,0 +1,254 @@ +/** + * Navit, a modular navigation system. + * Copyright (C) 2005-2010 Navit Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +// style with: clang-format -style=WebKit -i * + +#include <QQmlApplicationEngine> +#include <glib.h> + +extern "C" { +#include "item.h" /* needs to be first, as attr.h depends on it */ + +#include "attr.h" +#include "bookmarks.h" +#include "callback.h" +#include "color.h" +#include "command.h" +#include "config.h" +#include "coord.h" +#include "coord.h" +#include "country.h" +#include "debug.h" +#include "event.h" + +#include "point.h" /* needs to be before graphics.h */ + +#include "graphics.h" +#include "gui.h" +#include "keys.h" +#include "map.h" +#include "mapset.h" +#include "navit.h" +#include "plugin.h" +#include "route.h" +#include "search.h" +#include "track.h" +#include "transform.h" +#include "vehicle.h" +#include "xmlconfig.h" + +#include "layout.h" +} + +struct gui_priv { + /* navit internal handle */ + struct navit* nav; + /* gui handle */ + struct gui* gui; + + /* attributes given to us */ + struct attr attributes; + + /* list of callbacks to navit */ + struct callback_list* callbacks; + /* own callbacks * + * TODO: Why do we need them as members? */ + struct callback* button_cb; + struct callback* motion_cb; + struct callback* resize_cb; + struct callback* keypress_cb; + struct callback* window_closed_cb; + + /* current graphics */ + struct graphics* gra; + /* root window */ + struct window* win; + /* navit root widget dimesnions*/ + int w; + int h; + + /* Qt application instance */ + QQmlApplicationEngine* engine; + QObject* loader; /* Loader QML component to load our QML parts to the QML engine */ + + /* configuration */ + int menu_on_map_click; +}; + +static void gui_qt5_qml_button(void* data, int pressed, int button, struct point* p) +{ + struct gui_priv* gui_priv = (struct gui_priv*)data; + + /* check if navit wants to handle this */ + if (!navit_handle_button(gui_priv->nav, pressed, button, p, NULL)) { + dbg(lvl_debug, "navit has handled button\n"); + return; + } + dbg(lvl_debug, "enter %d %d\n", pressed, button); + + /* check if user requested menu */ + if (button == 1 && gui_priv->menu_on_map_click) { + dbg(lvl_debug, "navit wants us to enter menu\n"); + /*TODO: want to emit a signal somewhere? */ + } +} + +static void gui_qt5_qml_motion(void* data, struct point* p) +{ + struct gui_priv* gui_priv = (struct gui_priv*)data; + dbg(lvl_debug, "enter (%d, %d)\n", p->x, p->y); + /* forward this to navit */ + navit_handle_motion(gui_priv->nav, p); +} + +static void gui_qt5_qml_resize(void* data, int w, int h) +{ + struct gui_priv* gui_priv = (struct gui_priv*)data; + dbg(lvl_debug, "enter\n"); + /* forward this to navit */ + navit_handle_resize(gui_priv->nav, w, h); +} + +static int gui_qt5_qml_set_graphics(struct gui_priv* gui_priv, struct graphics* gra) +{ + struct transformation* trans; + dbg(lvl_debug, "enter\n"); + + /* get navit transition */ + trans = navit_get_trans(gui_priv->nav); + + /* Tell navit to ignore events from graphics. We will hook the ones being supported.*/ + navit_ignore_graphics_events(gui_priv->nav, 1); + + /* remeber graphics */ + gui_priv->gra = gra; + + /* hook button callback */ + gui_priv->button_cb = callback_new_attr_1(callback_cast(gui_qt5_qml_button), attr_button, gui_priv); + graphics_add_callback(gra, gui_priv->button_cb); + + /* hook motion callback */ + gui_priv->motion_cb = callback_new_attr_1(callback_cast(gui_qt5_qml_motion), attr_motion, gui_priv); + graphics_add_callback(gra, gui_priv->motion_cb); + + /* hook resize callback. Will be called imediately!*/ + gui_priv->resize_cb = callback_new_attr_1(callback_cast(gui_qt5_qml_resize), attr_resize, gui_priv); + graphics_add_callback(gra, gui_priv->resize_cb); + + /* get main navit window */ + gui_priv->win = (struct window*)graphics_get_data(gra, "window"); + if (!gui_priv->win) { + dbg(lvl_error, "failed to obtain window from graphics plugin, cannot set graphics\n"); + return 1; + } + + /* expect to have qt5 graphics. So get the qml engine prepared by graphics */ + gui_priv->engine = (QQmlApplicationEngine*)graphics_get_data(gra, "engine"); + if (gui_priv->engine == NULL) { + dbg(lvl_error, "Graphics doesn't seem to be qt5, or doesn't have QML. Cannot set graphics\n"); + return 1; + } + + /* find the loader component */ + gui_priv->loader = gui_priv->engine->rootObjects().value(0)->findChild<QObject*>("navit_loader"); + if (gui_priv->loader != NULL) { + dbg(lvl_debug, "navit_loader found\n"); + /* load our root window into the loader component */ + gui_priv->loader->setProperty("source", "qrc:///gui_qt5_qml.qml"); + } + + transform_get_size(trans, &gui_priv->w, &gui_priv->h); + dbg(lvl_debug, "navit provided geometry: (%d, %d)\n", gui_priv->w, gui_priv->h); + + /* Was resize callback already issued? */ + // if (navit_get_ready(gui_priv->nav) & 2) + // gui_internal_setup(this); + + /* allow navit to draw */ + navit_draw(gui_priv->nav); + return 0; +} + +static int +gui_qt5_qml_get_attr(struct gui_priv* gui_priv, enum attr_type type, struct attr* attr) +{ + dbg(lvl_debug, "enter\n"); + return 1; +} + +static int +gui_qt5_qml_set_attr(struct gui_priv* gui_priv, struct attr* attr) +{ + dbg(lvl_debug, "enter\n"); + return 1; +} + +struct gui_methods gui_qt5_qml_methods = { + NULL, + NULL, + gui_qt5_qml_set_graphics, + NULL, + NULL, + NULL, + NULL, + gui_qt5_qml_get_attr, + NULL, + gui_qt5_qml_set_attr, +}; + +static struct gui_priv* gui_qt5_qml_new(struct navit* nav, struct gui_methods* meth, struct attr** attrs, struct gui* gui) +{ + struct gui_priv* gui_priv; + struct attr* attr; + + dbg(lvl_debug, "enter\n"); + + /* tell navit our methods */ + *meth = gui_qt5_qml_methods; + + /* allocate gui private structure */ + gui_priv = g_new0(struct gui_priv, 1); + + /* default config */ + gui_priv->menu_on_map_click = 1; + + /* read config */ + if ((attr = attr_search(attrs, NULL, attr_menu_on_map_click))) + gui_priv->menu_on_map_click = attr->u.num; + + /* remember navit internal handle */ + gui_priv->nav = nav; + /* remember our gui handle */ + gui_priv->gui = gui; + + /* remember the attributes given to us */ + gui_priv->attributes.type = attr_gui; + gui_priv->attributes.u.gui = gui; + + /* create new callbacks */ + gui_priv->callbacks = callback_list_new(); + + /* return self */ + return gui_priv; +} + +void plugin_init(void) +{ + Q_INIT_RESOURCE(gui_qt5_qml); + plugin_register_category_gui("qt5_qml", gui_qt5_qml_new); +} diff --git a/navit/gui/qt5_qml/gui_qt5_qml.qml b/navit/gui/qt5_qml/gui_qt5_qml.qml new file mode 100644 index 000000000..679013319 --- /dev/null +++ b/navit/gui/qt5_qml/gui_qt5_qml.qml @@ -0,0 +1,23 @@ +import com.navit.graphics_qt5 1.0 +import QtQuick 2.2 +import QtQuick.Window 2.0 + +Rectangle { + width: 200 + height: 100 + color: "red" + + Text { + anchors.centerIn: parent + text: "Hello, World!" + } + QNavitQuick { + id: navit1 + width: 300 + height: 300 + focus: true + Component.onCompleted: { + navit1.setGraphicContext(graphics_qt5_context) + } + } +} diff --git a/navit/gui/qt5_qml/gui_qt5_qml.qrc b/navit/gui/qt5_qml/gui_qt5_qml.qrc new file mode 100644 index 000000000..51fa8af88 --- /dev/null +++ b/navit/gui/qt5_qml/gui_qt5_qml.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>gui_qt5_qml.qml</file> + </qresource> +</RCC> |