diff options
author | mvglasow <michael -at- vonglasow.com> | 2019-01-31 01:08:22 +0100 |
---|---|---|
committer | mvglasow <michael -at- vonglasow.com> | 2019-01-31 01:08:22 +0100 |
commit | a72e6bce3b93fb70e93a132a3fbca1b4e791ab63 (patch) | |
tree | 4fe24775067884619713bb651147443427d4fd8b | |
parent | 69f4e3e2ec22b8f1382e73c01a63b2bb2ffe9149 (diff) | |
parent | 72fa3c46e4c178bb9a49cb39e719cc465c43509c (diff) | |
download | navit-a72e6bce3b93fb70e93a132a3fbca1b4e791ab63.tar.gz |
Merge branch 'master' into osd-layout
-rw-r--r-- | navit/graphics/qt5/QNavitQuick.cpp | 17 | ||||
-rw-r--r-- | navit/graphics/qt5/QNavitQuick.h | 3 | ||||
-rw-r--r-- | navit/graphics/qt5/QNavitWidget.cpp | 17 | ||||
-rw-r--r-- | navit/graphics/qt5/QNavitWidget.h | 8 | ||||
-rw-r--r-- | navit/graphics/qt5/event_qt5.cpp | 1 | ||||
-rw-r--r-- | navit/graphics/qt5/event_qt5.h | 4 | ||||
-rw-r--r-- | navit/graphics/qt5/graphics_qt5.cpp | 75 | ||||
-rw-r--r-- | navit/graphics/qt5/graphics_qt5.h | 4 | ||||
-rw-r--r-- | navit/gui/internal/gui_internal.c | 47 | ||||
-rw-r--r-- | navit/gui/internal/gui_internal_keyboard.c | 14 | ||||
-rw-r--r-- | navit/gui/internal/gui_internal_menu.c | 257 | ||||
-rw-r--r-- | navit/gui/internal/gui_internal_menu.h | 5 | ||||
-rw-r--r-- | navit/gui/internal/gui_internal_widget.c | 123 | ||||
-rw-r--r-- | navit/gui/internal/gui_internal_widget.h | 11 | ||||
-rw-r--r-- | navit/vehicle/qt5/vehicle_qt5.cpp | 23 |
15 files changed, 472 insertions, 137 deletions
diff --git a/navit/graphics/qt5/QNavitQuick.cpp b/navit/graphics/qt5/QNavitQuick.cpp index 6981f3af7..dcd0d2aa5 100644 --- a/navit/graphics/qt5/QNavitQuick.cpp +++ b/navit/graphics/qt5/QNavitQuick.cpp @@ -16,7 +16,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -//Style with: clang-format -style=WebKit -i #include <glib.h> #ifdef HAVE_UNISTD_H @@ -91,7 +90,10 @@ void QNavitQuick::paint(QPainter* painter) { painter->drawPixmap(graphics_priv->scroll_x, graphics_priv->scroll_y, *graphics_priv->pixmap, boundingRect().x(), boundingRect().y(), boundingRect().width(), boundingRect().height()); - paintOverlays(painter, graphics_priv, &event); + /* disable on root pane disables ALL overlays (for drag of background) */ + if(!(graphics_priv->disable)) { + paintOverlays(painter, graphics_priv, &event); + } } void QNavitQuick::keyPressEvent(QKeyEvent* event) { @@ -171,11 +173,14 @@ void QNavitQuick::geometryChanged(const QRectF& newGeometry, const QRectF& oldGe return; } if (graphics_priv->pixmap != NULL) { - delete graphics_priv->pixmap; - graphics_priv->pixmap = NULL; + if((width() != graphics_priv->pixmap->width()) || (height() != graphics_priv->pixmap->height())) { + delete graphics_priv->pixmap; + graphics_priv->pixmap = NULL; + } + } + if (graphics_priv->pixmap == NULL) { + graphics_priv->pixmap = new QPixmap(width(), height()); } - - graphics_priv->pixmap = new QPixmap(width(), height()); painter = new QPainter(graphics_priv->pixmap); if (painter != NULL) { QBrush brush; diff --git a/navit/graphics/qt5/QNavitQuick.h b/navit/graphics/qt5/QNavitQuick.h index 3679e8127..40c6639ae 100644 --- a/navit/graphics/qt5/QNavitQuick.h +++ b/navit/graphics/qt5/QNavitQuick.h @@ -16,7 +16,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -// style with: clang-format -style=WebKit -i * #ifndef QNAVITQUICK_H #define QNAVITQUICK_H @@ -29,9 +28,9 @@ class QNavitQuick; class QNavitQuick : public QQuickPaintedItem { Q_OBJECT public: + void paint(QPainter* painter); QNavitQuick(QQuickItem* parent = 0); - void paint(QPainter* painter); Q_INVOKABLE void setGraphicContext(GraphicsPriv* gp); diff --git a/navit/graphics/qt5/QNavitWidget.cpp b/navit/graphics/qt5/QNavitWidget.cpp index 9c2b96505..355187b49 100644 --- a/navit/graphics/qt5/QNavitWidget.cpp +++ b/navit/graphics/qt5/QNavitWidget.cpp @@ -16,7 +16,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -// style with: clang-format -style=WebKit -i * #include <glib.h> #ifdef HAVE_UNISTD_H @@ -89,17 +88,23 @@ void QNavitWidget::paintEvent(QPaintEvent* event) { painter.drawPixmap(event->rect().x(), event->rect().y(), *graphics_priv->pixmap, event->rect().x() - graphics_priv->scroll_x, event->rect().y() - graphics_priv->scroll_y, event->rect().width(), event->rect().height()); - paintOverlays(&painter, graphics_priv, event); + /* disable on root pane disables ALL overlays (for drag of background) */ + if(!(graphics_priv->disable)) { + paintOverlays(&painter, graphics_priv, event); + }; } void QNavitWidget::resizeEvent(QResizeEvent* event) { QPainter* painter = NULL; if (graphics_priv->pixmap != NULL) { - delete graphics_priv->pixmap; - graphics_priv->pixmap = NULL; + if((width() != graphics_priv->pixmap->width()) || (height() != graphics_priv->pixmap->height())) { + delete graphics_priv->pixmap; + graphics_priv->pixmap = NULL; + } + } + if (graphics_priv->pixmap == NULL) { + graphics_priv->pixmap = new QPixmap(size()); } - - graphics_priv->pixmap = new QPixmap(size()); painter = new QPainter(graphics_priv->pixmap); if (painter != NULL) { QBrush brush; diff --git a/navit/graphics/qt5/QNavitWidget.h b/navit/graphics/qt5/QNavitWidget.h index 674b69390..40fb88b19 100644 --- a/navit/graphics/qt5/QNavitWidget.h +++ b/navit/graphics/qt5/QNavitWidget.h @@ -16,7 +16,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -// style with: clang-format -style=WebKit -i * #ifndef __QNavitWidget_h #define __QNavitWidget_h @@ -30,10 +29,9 @@ class QNavitWidget; class QNavitWidget : public QWidget { Q_OBJECT -public: - QNavitWidget(struct graphics_priv* my_graphics_priv, - QWidget* parent, - Qt::WindowFlags flags); +public: QNavitWidget(struct graphics_priv* my_graphics_priv, + QWidget* parent, + Qt::WindowFlags flags); protected: virtual bool event(QEvent* event); diff --git a/navit/graphics/qt5/event_qt5.cpp b/navit/graphics/qt5/event_qt5.cpp index 5c7c3ca27..7186534fe 100644 --- a/navit/graphics/qt5/event_qt5.cpp +++ b/navit/graphics/qt5/event_qt5.cpp @@ -16,7 +16,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -// style with: clang-format -style=WebKit -i * #include <glib.h> #include <stdio.h> diff --git a/navit/graphics/qt5/event_qt5.h b/navit/graphics/qt5/event_qt5.h index 892e8fca8..7fe184cd1 100644 --- a/navit/graphics/qt5/event_qt5.h +++ b/navit/graphics/qt5/event_qt5.h @@ -16,15 +16,13 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -// style with: clang-format -style=WebKit -i * #include <QObject> #include <glib.h> class qt5_navit_timer : public QObject { Q_OBJECT -public: - qt5_navit_timer(QObject* parent = 0); +public: qt5_navit_timer(QObject* parent = 0); GHashTable* timer_type; GHashTable* timer_callback; GHashTable* watches; diff --git a/navit/graphics/qt5/graphics_qt5.cpp b/navit/graphics/qt5/graphics_qt5.cpp index c23a4f60f..e7b31c605 100644 --- a/navit/graphics/qt5/graphics_qt5.cpp +++ b/navit/graphics/qt5/graphics_qt5.cpp @@ -16,7 +16,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -// style with: clang-format -style=WebKit -i * #include <glib.h> #ifdef HAVE_UNISTD_H @@ -180,7 +179,8 @@ static const char* fontfamilies[] = { * * Allocates a font handle and returnes filled interface stucture */ -static struct graphics_font_priv* font_new(struct graphics_priv* gr, struct graphics_font_methods* meth, char* font, int size, int flags) { +static struct graphics_font_priv* font_new(struct graphics_priv* gr, struct graphics_font_methods* meth, char* font, + int size, int flags) { int a = 0; struct graphics_font_priv* font_priv; dbg(lvl_debug, "enter (font %s, %d, 0x%x)", font, size, flags); @@ -295,7 +295,8 @@ struct graphics_image_methods image_methods = { image_destroy }; -static struct graphics_image_priv* image_new(struct graphics_priv* gr, struct graphics_image_methods* meth, char* path, int* w, int* h, struct point* hot, int rotation) { +static struct graphics_image_priv* image_new(struct graphics_priv* gr, struct graphics_image_methods* meth, char* path, + int* w, int* h, struct point* hot, int rotation) { struct graphics_image_priv* image_priv; // dbg(lvl_debug,"enter %s, %d %d", path, *w, *h); if (path[0] == 0) { @@ -304,7 +305,11 @@ static struct graphics_image_priv* image_new(struct graphics_priv* gr, struct gr } QString key(path); QString renderer_key(key); - QString extension = key.right(key.lastIndexOf(".")); + int index = key.lastIndexOf("."); + QString extension; + if(index > 0) { + extension = key.right(index); + } QFile imagefile(key); if (!imagefile.exists()) { /* file doesn't exit. Either navit wants us to guess file name by @@ -348,7 +353,7 @@ static struct graphics_image_priv* image_new(struct graphics_priv* gr, struct gr } /* check if we got image */ - if (image_priv->pixmap->isNull()) { + if ((image_priv->pixmap == NULL) || (image_priv->pixmap->isNull())) { g_free(image_priv); return NULL; } else { @@ -444,7 +449,8 @@ static void draw_circle(struct graphics_priv* gr, struct graphics_gc_priv* gc, s * * Renders given text on gr surface. Draws nice contrast outline around text. */ -static void draw_text(struct graphics_priv* gr, struct graphics_gc_priv* fg, struct graphics_gc_priv* bg, struct graphics_font_priv* font, char* text, struct point* p, int dx, int dy) { +static void draw_text(struct graphics_priv* gr, struct graphics_gc_priv* fg, struct graphics_gc_priv* bg, + struct graphics_font_priv* font, char* text, struct point* p, int dx, int dy) { dbg(lvl_debug, "enter gc=%p, fg=%p, bg=%p pos(%d,%d) d(%d, %d) %s", gr, fg, bg, p->x, p->y, dx, dy, text); QPainter* painter = gr->painter; if (painter == NULL) @@ -535,7 +541,8 @@ static void draw_text(struct graphics_priv* gr, struct graphics_gc_priv* fg, str #endif } -static void draw_image(struct graphics_priv* gr, struct graphics_gc_priv* fg, struct point* p, struct graphics_image_priv* img) { +static void draw_image(struct graphics_priv* gr, struct graphics_gc_priv* fg, struct point* p, + struct graphics_image_priv* img) { // dbg(lvl_debug,"enter"); if (gr->painter != NULL) gr->painter->drawPixmap(p->x, p->y, *img->pixmap); @@ -635,7 +642,8 @@ static void draw_mode(struct graphics_priv* gr, enum draw_mode_num mode) { } } -static struct graphics_priv* overlay_new(struct graphics_priv* gr, struct graphics_methods* meth, struct point* p, int w, int h, int wraparound); +static struct graphics_priv* overlay_new(struct graphics_priv* gr, struct graphics_methods* meth, struct point* p, + int w, int h, int wraparound); void resize_callback(struct graphics_priv* gr, int w, int h) { // dbg(lvl_debug,"enter (%d, %d)", w, h); @@ -725,7 +733,8 @@ static void image_free(struct graphics_priv* gr, struct graphics_image_priv* pri * * Calculates the bounding box around the given text. */ -static void get_text_bbox(struct graphics_priv* gr, struct graphics_font_priv* font, char* text, int dx, int dy, struct point* ret, int estimate) { +static void get_text_bbox(struct graphics_priv* gr, struct graphics_font_priv* font, char* text, int dx, int dy, + struct point* ret, int estimate) { int i; struct point pt; QString tmp = QString::fromUtf8(text); @@ -759,29 +768,45 @@ static void get_text_bbox(struct graphics_priv* gr, struct graphics_font_priv* f } static void overlay_disable(struct graphics_priv* gr, int disable) { - GHashTableIter iter; - struct graphics_priv *key, *value; - // dbg(lvl_debug,"enter gr=%p, %d", gr, disable); - - g_hash_table_iter_init(&iter, gr->overlays); - while (g_hash_table_iter_next(&iter, (void**)&key, (void**)&value)) { - /* disable or enable all overlays of this pane */ - value->disable = disable; - } + //dbg(lvl_error,"enter gr=%p, %d", gr, disable); + gr->disable = disable; +#if USE_QWIDGET + /* call repaint on widget */ + if (gr->widget != NULL) + gr->widget->repaint(gr->x, gr->y, gr->pixmap->width(), gr->pixmap->height()); +#endif +#if USE_QML + if (gr->GPriv != NULL) + gr->GPriv->emit_update(); + +#endif } static void overlay_resize(struct graphics_priv* gr, struct point* p, int w, int h, int wraparound) { - // dbg(lvl_debug,"enter"); + // dbg(lvl_debug,"enter %d %d %d %d %d", p->x, p->y, w, h, wraparound); gr->x = p->x; gr->y = p->y; if (gr->painter != NULL) { delete (gr->painter); } - delete (gr->pixmap); - gr->pixmap = new QPixmap(w, h); - gr->pixmap->fill(Qt::transparent); + /* replacing the pixmap clears the content. Only neccesary if size actually changes */ + if((gr->pixmap->height() != h) || (gr->pixmap->width() != w)) { + delete (gr->pixmap); + gr->pixmap = new QPixmap(w, h); + gr->pixmap->fill(Qt::transparent); + } if (gr->painter != NULL) gr->painter = new QPainter(gr->pixmap); +#if USE_QWIDGET + /* call repaint on widget */ + if (gr->widget != NULL) + gr->widget->repaint(gr->x, gr->y, gr->pixmap->width(), gr->pixmap->height()); +#endif +#if USE_QML + if (gr->GPriv != NULL) + gr->GPriv->emit_update(); + +#endif } static struct graphics_methods graphics_methods = { @@ -808,7 +833,8 @@ static struct graphics_methods graphics_methods = { }; /* create new graphics context on given context */ -static struct graphics_priv* overlay_new(struct graphics_priv* gr, struct graphics_methods* meth, struct point* p, int w, int h, int wraparound) { +static struct graphics_priv* overlay_new(struct graphics_priv* gr, struct graphics_methods* meth, struct point* p, + int w, int h, int wraparound) { struct graphics_priv* graphics_priv = NULL; graphics_priv = g_new0(struct graphics_priv, 1); *meth = graphics_methods; @@ -852,7 +878,8 @@ static struct graphics_priv* overlay_new(struct graphics_priv* gr, struct graphi } /* create application and initial graphics context */ -static struct graphics_priv* graphics_qt5_new(struct navit* nav, struct graphics_methods* meth, struct attr** attrs, struct callback_list* cbl) { +static struct graphics_priv* graphics_qt5_new(struct navit* nav, struct graphics_methods* meth, struct attr** attrs, + struct callback_list* cbl) { struct graphics_priv* graphics_priv = NULL; struct attr* event_loop_system = NULL; struct attr* platform = NULL; diff --git a/navit/graphics/qt5/graphics_qt5.h b/navit/graphics/qt5/graphics_qt5.h index f9d19616b..0eed89510 100644 --- a/navit/graphics/qt5/graphics_qt5.h +++ b/navit/graphics/qt5/graphics_qt5.h @@ -16,7 +16,6 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -// style with: clang-format -style=WebKit -i * #ifndef __graphics_qt_h #define __graphics_qt_h @@ -62,8 +61,7 @@ struct graphics_priv; #if USE_QML class GraphicsPriv : public QObject { Q_OBJECT -public: - GraphicsPriv(struct graphics_priv* gp); +public: GraphicsPriv(struct graphics_priv* gp); ~GraphicsPriv(); void emit_update(); diff --git a/navit/gui/internal/gui_internal.c b/navit/gui/internal/gui_internal.c index 39e0b6d18..afae9a9f1 100644 --- a/navit/gui/internal/gui_internal.c +++ b/navit/gui/internal/gui_internal.c @@ -476,7 +476,7 @@ gui_internal_time_help(struct gui_priv *this) { /** * Applies the configuration values to this based on the settings * specified in the configuration file (this->config) and - * the most approriate default profile based on screen resolution. + * the most appropriate default profile based on screen resolution. * * This function should be run after this->root is setup and could * be rerun after the window is resized. @@ -2679,33 +2679,50 @@ static void gui_internal_setup(struct gui_priv *this) { g_free(gui_file); } -//############################################################################################################## -//# Description: -//# Comment: -//# Authors: Martin Schaller (04/2008) -//############################################################################################################## -static void gui_internal_resize(void *data, int w, int h) { +/** + * @brief Callback function invoked when display area is resized + * + * @param data A generic argument structure pointer, here we use it to store the the internal GUI context (this) + * @param wnew The new width of the display area + * @param hnew The new height of the display area + * + * @author Martin Schaller + * @date 2008/04 + */ +static void gui_internal_resize(void *data, int wnew, int hnew) { + GList *l; + struct widget *w; + struct gui_priv *this=data; int changed=0; gui_internal_setup(this); - if (this->root.w != w || this->root.h != h) { - this->root.w=w; - this->root.h=h; - changed=1; - } + changed=gui_internal_menu_needs_resizing(this, &(this->root), wnew, hnew); + /* * If we're drawing behind system bars on Android, watching for actual size changes will not catch * fullscreen toggle events. As a workaround, always assume a size change if padding is supplied. */ if (!changed && this->gra && graphics_get_data(this->gra, "padding")) changed = 1; - dbg(lvl_debug,"w=%d h=%d children=%p", w, h, this->root.children); - navit_handle_resize(this->nav, w, h); + navit_handle_resize(this->nav, wnew, hnew); if (this->root.children) { if (changed) { - gui_internal_html_main_menu(this); + l = g_list_last(this->root.children); + if (l) { + w=l->data; + if (!gui_internal_widget_reload_href(this, + w)) { /* If the foremost widget is a HTML menu, reload & redraw it from its href */ + /* If not, resize the foremost widget */ + dbg(lvl_debug, "Current GUI displayed is not a menu"); + dbg(lvl_debug, "Will call resize with w=%d, h=%d", wnew, hnew) + gui_internal_menu_resize(this, wnew, hnew); + gui_internal_menu_render(this); + } else { + dbg(lvl_debug,"Current GUI displayed is a menu"); + } + } } else { gui_internal_menu_render(this); } diff --git a/navit/gui/internal/gui_internal_keyboard.c b/navit/gui/internal/gui_internal_keyboard.c index 4b2c64cd8..8e758de4f 100644 --- a/navit/gui/internal/gui_internal_keyboard.c +++ b/navit/gui/internal/gui_internal_keyboard.c @@ -133,6 +133,17 @@ struct gui_internal_keyb_mode { -> datai = (mode & VKBD_MASK_7) | ((x) & VKBD_LAYOUT_MASK) #define SWCASE() MODE(gui_internal_keyb_modes[mode/8].case_mode) #define UMLAUT() MODE(gui_internal_keyb_modes[mode/8].umlaut_mode) + + +static void gui_internal_keyboard_topbox_resize(struct gui_priv *this, struct widget *w, void *data, + int neww, int newh) { + struct menu_data *md=gui_internal_menu_data(this); + struct widget *old_wkbdb = md->keyboard; + + dbg(lvl_debug, "resize called for keyboard widget %p with w=%d, h=%d", w, neww, newh); + gui_internal_keyboard_do(this, old_wkbdb, md->keyboard_mode); +} + /** * @brief Creates a new keyboard widget or switches the layout of an existing widget * @@ -167,6 +178,8 @@ gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode) else render=1; gui_internal_widget_children_destroy(this, wkbdb); + gui_internal_widget_reset_pack(this, wkbdb); + gui_internal_widget_pack(this, wkbdb); } else wkbdb=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill); md->keyboard=wkbdb; @@ -176,6 +189,7 @@ gui_internal_keyboard_do(struct gui_priv *this, struct widget *wkbdb, int mode) wkbd->cols=8; wkbd->spx=0; wkbd->spy=0; + wkbd->on_resize=gui_internal_keyboard_topbox_resize; max_w=max_w/8; max_h=max_h/8; // Allows 3 results in the list when searching for Towns wkbd->p.y=max_h*2; diff --git a/navit/gui/internal/gui_internal_menu.c b/navit/gui/internal/gui_internal_menu.c index 9da7f2e4c..6a0d6a52b 100644 --- a/navit/gui/internal/gui_internal_menu.c +++ b/navit/gui/internal/gui_internal_menu.c @@ -17,7 +17,34 @@ extern char *version; -static void gui_internal_menu_destroy(struct gui_priv *this, struct widget *w) { +/** + * @brief Utility function to check if a menu widget is adapted to the display size or needs resizing (if so, the widget dimensions will be set to match those of the display + * + * @param this The GUI instance + * @param w The menu widget (top widget that should spawn over the entire display) + * @param wdisp The width of the display to check the widget against + * @param hdisp The width of the display to check the widget against + * + * @return true if widget w has the same size as the provided display dimensions + */ + +int gui_internal_menu_needs_resizing(struct gui_priv *this, struct widget *w, int wdisp, int hdisp) { + if (w->w != wdisp || w->h != hdisp) { + w->w=wdisp; + w->h=hdisp; + return 1; + } else { + return 0; + } +} + +/** + * @brief destroy a menu widget and perform the associated cleanup in the menu & submenu list + * + * @param this The GUI instance + * @param w The menu widget to destroy + */ +void gui_internal_menu_destroy(struct gui_priv *this, struct widget *w) { struct menu_data *menu_data=w->menu_data; if (menu_data) { if (menu_data->refresh_callback_obj.type) { @@ -36,42 +63,99 @@ static void gui_internal_menu_destroy(struct gui_priv *this, struct widget *w) { this->root.children=g_list_remove(this->root.children, w); } +/** + * @brief Retrieve then html anchor (href) from a menu widger + * + * @param w A widget corresponding to a menu (this widget should be an html menu) + * + * @return the string for the href, or NULL if this menu has no href (or the widget is not a menu) + */ +static char *gui_internal_widget_get_href(struct widget *w) { + if (w && w->menu_data) + return w->menu_data->href; + else + return NULL; +} + +/** + * @brief Reload a menu from its anchor (href) + * + * @param this The internal GUI context + * @param w A widget corresponding to the menu to redraw (this widget should be an html menu, thus it should have a href) + * + * @return 1 in case of success, 0 if no menu could be reloaded + * @note If the widget provided in @p w has no href, we will return 0 + */ +int gui_internal_widget_reload_href(struct gui_priv *this, struct widget *w) { + char *ohref = gui_internal_widget_get_href(w); + if (ohref) { + char *href=g_strdup(ohref); + gui_internal_menu_destroy(this, w); + gui_internal_html_load_href(this, href, 0); + g_free(href); + return 1; + } + return 0; +} + +/** + * @brief Destroy (discard) all menu screens that have been placed after widget @p w + * + * @param this The internal GUI instance + * @param w A widget corresponding to the last menu to keep (all subsequent menus in the list will be destroyed). NULL if all menus should be destroyed. + * @param render whether we should render the menu indicated by widget w (render!=0) or not (render==0) + */ static void gui_internal_prune_menu_do(struct gui_priv *this, struct widget *w, int render) { GList *l; struct widget *wr,*wd; gui_internal_search_idle_end(this); + /* Destroy all menus, backwards, starting from the end until we reach widget w, and redraw widget w */ while ((l = g_list_last(this->root.children))) { wd=l->data; - if (wd == w) { + if (wd == w) { /* This is the widget we want to bring back to display (all subsequent widgets will be destroyed in the loop) */ void (*redisplay)(struct gui_priv *priv, struct widget *widget, void *data); if (!render) return; gui_internal_say(this, w, 0); redisplay=w->menu_data->redisplay; - wr=w->menu_data->redisplay_widget; - if (!w->menu_data->redisplay && !w->menu_data->href) { - gui_internal_widget_render(this, w); - return; - } if (redisplay) { gui_internal_menu_destroy(this, w); + wr=w->menu_data->redisplay_widget; redisplay(this, wr, wr->data); } else { - char *href=g_strdup(w->menu_data->href); - gui_internal_menu_destroy(this, w); - gui_internal_html_load_href(this, href, 0); - g_free(href); + /* Make sure the new menu we are going to display spawns the whole display (in case there was a resize while a submenu was being displayed) */ + w->w=this->root.w; + w->h=this->root.h; + /* If the foremost widget is a HTML menu, reload & redraw it from its href using gui_internal_widget_reload_href() */ + if (!gui_internal_widget_reload_href(this,w)) { + /* If not, resize the foremost widget */ + gui_internal_menu_resize(this, this->root.w, this->root.h); + } + gui_internal_menu_render(this); } return; - } - gui_internal_menu_destroy(this, wd); + } else + gui_internal_menu_destroy(this, wd); } } +/** + * @brief Destroy (discard) all menu screens that have been placed after widget @p w and redraw the display, showing widget @w + * + * @param this The internal GUI instance + * @param w A widget corresponding to the last menu to keep, and to draw (all subsequent menus in the list will be destroyed). NULL if all menus should be destroyed. + */ void gui_internal_prune_menu(struct gui_priv *this, struct widget *w) { gui_internal_prune_menu_do(this, w, 1); } +/** + * @brief Destroy (discard) the last @p count menu screens + * + * @param this The internal GUI instance + * @param count The number of menus to destroy at the tail of the menu/submenu stack (if <=0, no menu will be destroyed) + * @param render whether we should render the new last menu in the stack (render!=0) or not (render==0) + */ void gui_internal_prune_menu_count(struct gui_priv *this, int count, int render) { GList *l=g_list_last(this->root.children); struct widget *w=NULL; @@ -83,9 +167,47 @@ void gui_internal_prune_menu_count(struct gui_priv *this, int count, int render) } } +/** + * @brief Resize the box widget (and its children) corresponding to a menu + * + * Menus are stored in a main box (topbox) that spawn the entire screen, thus, once the topbox has been resized, it will in turn resize its children, + * effectively resizing the whole menu display size + * + * Note: once this function has been run, widget @p w and its children have been resized, a call to gui_internal_box_render() needs to be done by the caller + * + * @param this The internal GUI instance + * @param w A box widget corresponding to the menu widget + * @param data Some data to pass to the box resize handler + * @param neww The new width of the display + * @param newh The new height of the display + */ +void gui_internal_menu_menu_resize(struct gui_priv *this, struct widget *w, void *data, int neww, int newh) { + struct padding *padding = NULL; + + if (w->type != widget_box) { + dbg(lvl_warning, "Called on a non-box widget, ignoring"); + return; + } + if (this->gra) { + padding = graphics_get_data(this->gra, "padding"); + } else + dbg(lvl_warning, "cannot get padding: this->gra is NULL"); + if (padding) { + w->p.x = padding->left; + w->p.y = padding->top; + w->w = neww - padding->left - padding->right; + w->h = newh - padding->top - padding->bottom; + } else { + w->p.x = 0; + w->p.y = 0; + w->w = neww; + w->h = newh; + } + gui_internal_box_resize(this, w, data, w->w, w->h); +} /** - * @brief Initializes a GUI screen + * @brief Initializes a GUI menu screen * * This method initializes the internal GUI's screen on which all other elements (such as HTML menus, * dialogs or others) are displayed. @@ -101,31 +223,15 @@ void gui_internal_prune_menu_count(struct gui_priv *this, int count, int render) struct widget * gui_internal_menu(struct gui_priv *this, const char *label) { struct widget *menu,*w,*w1,*topbox; - struct padding *padding = NULL; - - if (this->gra) { - padding = graphics_get_data(this->gra, "padding"); - } else - dbg(lvl_warning, "cannot get padding: this->gra is NULL"); gui_internal_search_idle_end(this); topbox=gui_internal_box_new_with_label(this, 0, label); - topbox->w=this->root.w; - topbox->h=this->root.h; gui_internal_widget_append(&this->root, topbox); menu=gui_internal_box_new(this, gravity_left_center|orientation_vertical); - - if (padding) { - menu->p.x = padding->left; - menu->p.y = padding->top; - menu->w = topbox->w - padding->left - padding->right; - menu->h = topbox->h - padding->top - padding->bottom; - } else { - menu->p.x = 0; - menu->p.y = 0; - menu->w = topbox->w; - menu->h = topbox->h; - } + menu->on_resize=gui_internal_menu_menu_resize; + topbox->on_resize(this, topbox, NULL, this->root.w, this->root.h); + /* We also have to invoke onresize() handler on menu because it is not (yet) set as a child of topbox */ + menu->on_resize(this, menu, NULL, topbox->w, topbox->h); menu->background=this->background; gui_internal_apply_config(this); topbox->menu_data=g_new0(struct menu_data, 1); @@ -156,17 +262,8 @@ gui_internal_menu(struct gui_priv *this, const char *label) { } if (this->flags & 192) { menu=gui_internal_box_new(this, gravity_left_center|orientation_vertical); - if (padding) { - menu->p.x = padding->left; - menu->p.y = padding->top; - menu->w = topbox->w - padding->left - padding->right; - menu->h = topbox->h - padding->top - padding->bottom; - } else { - menu->p.x = 0; - menu->p.y = 0; - menu->w = topbox->w; - menu->h = topbox->h; - } + menu->on_resize=gui_internal_menu_menu_resize; + menu->on_resize(this, menu, NULL, topbox->w, topbox->h); w1=gui_internal_time_help(this); gui_internal_widget_append(menu, w1); w1=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_expand|flags_fill); @@ -176,19 +273,8 @@ gui_internal_menu(struct gui_priv *this, const char *label) { } gui_internal_widget_pack(this, topbox); gui_internal_widget_reset_pack(this, topbox); - topbox->w=this->root.w; - topbox->h=this->root.h; - if (padding) { - menu->p.x = padding->left; - menu->p.y = padding->top; - menu->w = topbox->w - padding->left - padding->right; - menu->h = topbox->h - padding->top - padding->bottom; - } else { - menu->p.x = 0; - menu->p.y = 0; - menu->w = topbox->w; - menu->h = topbox->h; - } + if (topbox->on_resize) + topbox->on_resize(this, topbox, NULL, this->root.w, this->root.h); return w; } @@ -211,6 +297,14 @@ void gui_internal_menu_reset_pack(struct gui_priv *this) { gui_internal_widget_reset_pack(this, top_box); } +/** + * @brief Renders a menu GUI on the display + * + * @note The whole sequence of menus is kept in this->root.children (when going back one page, we just move to the previous child in the list) + * Thus, only the last child of this->root.children is actually displayed + * + * @param this The internal GUI instance + */ void gui_internal_menu_render(struct gui_priv *this) { GList *l; struct widget *menu; @@ -222,6 +316,52 @@ void gui_internal_menu_render(struct gui_priv *this) { gui_internal_widget_render(this, menu); } +/** + * @brief Resize the currently displayed menu + * + * @param this The internal GUI instance + * @param w The new width of the display + * @param h the new height of the display + */ +void gui_internal_menu_resize(struct gui_priv *this, int w, int h) { + GList *l; + struct widget *menu_topwidget; + + gui_internal_apply_config(this); + l=g_list_last(this->root.children); + menu_topwidget=l->data; + if (menu_topwidget->on_resize) { + dbg(lvl_debug, "Invoking resize handler for menu_topwidget at %p", menu_topwidget); + menu_topwidget->on_resize(this, menu_topwidget, NULL, this->root.w, this->root.h); + } +} + +/** + * @brief Resize a top bar created using gui_internal_top_bar() + * + * @param this The internal GUI instance + * @param data Some data to pass to the box resize handler + * @param neww The new width of the display + * @param newh The new height of the display + */ +static void gui_internal_top_bar_resize(struct gui_priv *this, struct widget *w, void *data, int neww, int newh) { + struct widget *new_top_bar; + + if (w->type != widget_box) { + dbg(lvl_warning, "Called on a non-box widget, ignoring"); + return; + } + new_top_bar=gui_internal_top_bar(this); + gui_internal_widget_move(this, w, new_top_bar); +} + +/** + * @brief Create an GUI top bar (containing the history of GUI menus and submenus) + * + * @param this The internal GUI instance + * + * @return The newly created top bar widget + */ struct widget * gui_internal_top_bar(struct gui_priv *this) { struct widget *w,*wm,*wh,*wc,*wcn; @@ -256,6 +396,7 @@ gui_internal_top_bar(struct gui_priv *this) { w->bt=6; w->bb=6; } + w->on_resize=gui_internal_top_bar_resize; width=this->root.w-w->bl; if (! (this->flags & 2)) { wm=gui_internal_button_new_with_callback(this, NULL, diff --git a/navit/gui/internal/gui_internal_menu.h b/navit/gui/internal/gui_internal_menu.h index 57e37d91c..3906ed23c 100644 --- a/navit/gui/internal/gui_internal_menu.h +++ b/navit/gui/internal/gui_internal_menu.h @@ -2,11 +2,16 @@ struct gui_priv; struct menu_data; struct widget; +int gui_internal_menu_needs_resizing(struct gui_priv *this, struct widget *w, int wdisp, int hdisp); +void gui_internal_menu_destroy(struct gui_priv *this, struct widget *w); +int gui_internal_widget_reload_href(struct gui_priv *this, struct widget *w); void gui_internal_prune_menu(struct gui_priv *this, struct widget *w); void gui_internal_prune_menu_count(struct gui_priv *this, int count, int render); +void gui_internal_menu_menu_resize(struct gui_priv *this, struct widget *w, void *data, int neww, int newh); struct widget *gui_internal_menu(struct gui_priv *this, const char *label); struct menu_data *gui_internal_menu_data(struct gui_priv *this); void gui_internal_menu_reset_pack(struct gui_priv *this); void gui_internal_menu_render(struct gui_priv *this); +void gui_internal_menu_resize(struct gui_priv *this, int w, int h); struct widget *gui_internal_top_bar(struct gui_priv *this); /* end of prototypes */ diff --git a/navit/gui/internal/gui_internal_widget.c b/navit/gui/internal/gui_internal_widget.c index aa4c9eeef..0894be5aa 100644 --- a/navit/gui/internal/gui_internal_widget.c +++ b/navit/gui/internal/gui_internal_widget.c @@ -12,6 +12,63 @@ #include "gui_internal_menu.h" static void gui_internal_scroll_buttons_init(struct gui_priv *this, struct widget *widget, struct scroll_buttons *sb); +void gui_internal_box_pack(struct gui_priv *this, struct widget *w); + +/** + * @brief Transfer the content of one widget into another one (and optionally vice-versa) + * + * @param this The internal GUI instance + * @param[in,out] first The first widget + * @param[in,out] second The second widget + * @param move_only If non nul, transfer only the second widget into the first widget. The second widget is then deallocated and should be be used anymore (this is a move operation) + */ +static void gui_internal_widget_transfer_content(struct gui_priv *this, struct widget *first, struct widget *second, + int move_only) { + struct widget *temp; + + if (!first) { + dbg(lvl_error, "Refusing copy: first argument is NULL"); + return; + } + if (!second) { + dbg(lvl_error, "Refusing copy: second argument is NULL"); + return; + } + temp=g_new0(struct widget, 1); + memcpy(temp, first, sizeof(struct widget)); + memcpy(first, second, sizeof(struct widget)); + if (move_only) { + gui_internal_widget_destroy(this, temp); + /* gui_internal_widget_destroy() will do a g_free(temp), but will also deallocate all children widgets */ + /* Now, we also free the struct widget pointed to by second, so variable second should not be used anymore from this point */ + g_free(second); + } else { + memcpy(second, temp, sizeof(struct widget)); + g_free(temp); + } +} + +/** + * @brief Swap two widgets + * + * @param this The internal GUI instance + * @param[in,out] first The first widget + * @param[in,out] second The second widget + */ +void gui_internal_widget_swap(struct gui_priv *this, struct widget *first, struct widget *second) { + gui_internal_widget_transfer_content(this, first, second, 0); +} + +/** + * @brief Move the content of one widget into another one (the @p src widget is then deallocated and should be be used anymore) + * + * @param this The internal GUI instance + * @param[in,out] dst The destination widget + * @param[in,out] src The source widget + */ +void gui_internal_widget_move(struct gui_priv *this, struct widget *dst, struct widget *src) { + gui_internal_widget_transfer_content(this, dst, src, 1); +} static void gui_internal_background_render(struct gui_priv *this, struct widget *w) { struct point pnt=w->p; @@ -88,6 +145,12 @@ gui_internal_image_new(struct gui_priv *this, struct graphics_image *image) { return widget; } +/** + * @brief Renders an image or icon, preparing it for drawing on the display + * + * @param this The internal GUI instance + * @param w The widget to render + */ static void gui_internal_image_render(struct gui_priv *this, struct widget *w) { struct point pnt; @@ -101,7 +164,7 @@ static void gui_internal_image_render(struct gui_priv *this, struct widget *w) { } /** - * @brief Renders a label. + * @brief Renders a label, preparing it for drawing on the display * * @param this The internal GUI instance * @param w The widget to render @@ -286,6 +349,7 @@ gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, const c widget->text=g_strdup(label); widget->type=widget_box; widget->flags=flags; + widget->on_resize=gui_internal_box_resize; return widget; } @@ -325,14 +389,13 @@ static void gui_internal_box_render(struct gui_priv *this, struct widget *w) { gui_internal_widget_render(this, w->scroll_buttons->button_box); } - /** - * @brief Computes the size and location for the widget. + * @brief Computes the size and location for a box widget * * @param this The internal GUI instance - * @param w The widget to render + * @param w The widget to pack */ -static void gui_internal_box_pack(struct gui_priv *this, struct widget *w) { +void gui_internal_box_pack(struct gui_priv *this, struct widget *w) { struct widget *wc; int x0,x=0,y=0,width=0,height=0,owidth=0,oheight=0,expand=0,expandd=1,count=0,rows=0,cols=w->cols ? w->cols : 0; int hb=w->scroll_buttons?w->scroll_buttons->button_box->h:0; @@ -599,6 +662,46 @@ static void gui_internal_box_pack(struct gui_priv *this, struct widget *w) { } } +/** + * @brief Resize a box widget. + * + * @param this The internal GUI instance + * @param w The widget to resize + * @param wnew The new width of the widget + * @param hnew THe new height of the widget + */ +void gui_internal_box_resize(struct gui_priv *this, struct widget *w, void *data, int wnew, int hnew) { + GList *l; + struct widget *wb; + + w->w = wnew; + w->h = hnew; + + l=w->children; + while (l) { + wb=l->data; + if (wb->on_resize) { + int orientation=w->flags & 0xffff0000; + switch(orientation) { + case orientation_horizontal: + case orientation_vertical: + case orientation_horizontal_vertical: + wb->h = 0; + wb->w = 0; + gui_internal_widget_pack(this, wb); + break; + default: + wb->w = w->w; + wb->h = w->h; + } + wb->on_resize(this, wb, NULL, wb->w, wb->h); + } + l=g_list_next(l); + } + + /* Note: this widget and its children have been resized, a call to gui_internal_box_render() needs to be done by the caller */ +} + void gui_internal_widget_reset_pack(struct gui_priv *this, struct widget *w) { struct widget *wc; GList *l; @@ -717,6 +820,14 @@ void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w) { } +/** + * @brief Renders widgets, preparing it for drawing on the display + * + * The appropriate render function will be called, depending on the type of widget + * + * @param this The internal GUI instance + * @param w The widget to render + */ void gui_internal_widget_render(struct gui_priv *this, struct widget *w) { if(w->p.x > this->root.w || w->p.y > this->root.h || w->state & STATE_INVISIBLE) return; @@ -1344,8 +1455,6 @@ void gui_internal_table_button_next(struct gui_priv * this, struct widget * wm, gui_internal_menu_render(this); } - - /** * @brief Handles the 'previous page' table event. * diff --git a/navit/gui/internal/gui_internal_widget.h b/navit/gui/internal/gui_internal_widget.h index c1cc030f8..cc24cb44e 100644 --- a/navit/gui/internal/gui_internal_widget.h +++ b/navit/gui/internal/gui_internal_widget.h @@ -18,10 +18,15 @@ struct widget { struct graphics_image *img; /** * A function to be invoked on actions. - * @li widget The widget that is receiving the button press. + * @param widget The widget that is receiving the button press. * */ void (*func)(struct gui_priv *priv, struct widget *widget, void *data); + /** + * A function to be invoked on resize or move + * @param widget The widget that is resized + */ + void (*on_resize)(struct gui_priv *priv, struct widget *widget, void *data, int neww, int newh); enum gui_internal_reason reason; int datai; void *data; @@ -151,6 +156,8 @@ struct gui_priv; struct point; struct table_data; struct widget; +void gui_internal_widget_swap(struct gui_priv *this, struct widget *first, struct widget *second); +void gui_internal_widget_move(struct gui_priv *this, struct widget *dst, struct widget *src); struct widget *gui_internal_label_font_new(struct gui_priv *this, const char *text, int font); struct widget *gui_internal_label_new(struct gui_priv *this, const char *text); struct widget *gui_internal_label_new_abbrev(struct gui_priv *this, const char *text, int maxwidth); @@ -170,6 +177,7 @@ void gui_internal_highlight_do(struct gui_priv *this, struct widget *found); void gui_internal_highlight(struct gui_priv *this); struct widget *gui_internal_box_new_with_label(struct gui_priv *this, enum flags flags, const char *label); struct widget *gui_internal_box_new(struct gui_priv *this, enum flags flags); +void gui_internal_box_resize(struct gui_priv *this, struct widget *w, void *data, int wnew, int hnew); void gui_internal_widget_reset_pack(struct gui_priv *this, struct widget *w); void gui_internal_widget_append(struct widget *parent, struct widget *child); void gui_internal_widget_prepend(struct widget *parent, struct widget *child); @@ -177,6 +185,7 @@ void gui_internal_widget_insert_sorted(struct widget *parent, struct widget *chi void gui_internal_widget_children_destroy(struct gui_priv *this, struct widget *w); void gui_internal_widget_destroy(struct gui_priv *this, struct widget *w); void gui_internal_widget_render(struct gui_priv *this, struct widget *w); +void gui_internal_widget_resize(struct gui_priv *this, struct widget *w, int wnew, int hnew); void gui_internal_widget_pack(struct gui_priv *this, struct widget *w); struct widget *gui_internal_button_label(struct gui_priv *this, const char *label, int mode); struct widget *gui_internal_widget_table_new(struct gui_priv *this, enum flags flags, int buttons); diff --git a/navit/vehicle/qt5/vehicle_qt5.cpp b/navit/vehicle/qt5/vehicle_qt5.cpp index 5771f1da7..b855d12b9 100644 --- a/navit/vehicle/qt5/vehicle_qt5.cpp +++ b/navit/vehicle/qt5/vehicle_qt5.cpp @@ -116,7 +116,6 @@ void QNavitGeoReceiver::positionUpdated(const QGeoPositionInfo& info) { dbg(lvl_debug, "Got valid coordinate (lat %f, lon %f)", info.coordinate().latitude(), info.coordinate().longitude()); priv->geo.lat = info.coordinate().latitude(); priv->geo.lng = info.coordinate().longitude(); - priv->have_coords = 1; if (info.coordinate().type() == QGeoCoordinate::Coordinate3D) { dbg(lvl_debug, "Got valid altitude (alt %f)", info.coordinate().altitude()); priv->height = info.coordinate().altitude(); @@ -124,10 +123,17 @@ void QNavitGeoReceiver::positionUpdated(const QGeoPositionInfo& info) { //dbg(lvl_debug, "Time %s", info.timestamp().toUTC().toString().toLatin1().data()); priv->fix_time = info.timestamp().toUTC().toTime_t(); callback_list_call_attr_0(priv->cbl, attr_position_coord_geo); + if(priv->have_coords != attr_position_valid_valid) { + priv->have_coords = attr_position_valid_valid; + callback_list_call_attr_0(priv->cbl, attr_position_valid); + } } else { dbg(lvl_debug, "Got invalid coordinate"); - priv->have_coords = 0; callback_list_call_attr_0(priv->cbl, attr_position_coord_geo); + if(priv->have_coords != attr_position_valid_invalid) { + priv->have_coords = attr_position_valid_invalid; + callback_list_call_attr_0(priv->cbl, attr_position_valid); + } } } @@ -185,7 +191,7 @@ static int vehicle_qt5_position_attr_get(struct vehicle_priv* priv, break; case attr_position_coord_geo: attr->u.coord_geo = &priv->geo; - if (!priv->have_coords) + if (priv->have_coords != attr_position_valid_valid) return 0; break; case attr_position_time_iso8601: @@ -233,7 +239,10 @@ static int vehicle_qt5_set_attr(struct vehicle_priv* priv, struct attr* attr) { break; case attr_position_coord_geo: priv->geo = *attr->u.coord_geo; - priv->have_coords = 1; + if(priv->have_coords != attr_position_valid_valid) { + priv->have_coords = attr_position_valid_valid; + callback_list_call_attr_0(priv->cbl, attr_position_valid); + } break; default: break; @@ -273,8 +282,10 @@ static struct vehicle_priv* vehicle_qt5_new_qt5(struct vehicle_methods* meth, } else { dbg(lvl_debug, "Using %s", ret->source->sourceName().toLatin1().data()); ret->receiver = new QNavitGeoReceiver(NULL, ret); - ret->satellites->setUpdateInterval(1000); - ret->satellites->startUpdates(); + if(ret->satellites != NULL) { + ret->satellites->setUpdateInterval(1000); + ret->satellites->startUpdates(); + } ret->source->setUpdateInterval(500); ret->source->startUpdates(); } |