4 #include <QtDeclarative>
7 #ifdef HAVE_API_WIN32_BASE
25 #include "transform.h"
31 #include "bookmarks.h"
35 //WORKAOUND for the c/c++ compatibility issues.
36 //range is defined inside of struct attr so it is invisible in c++
47 struct vehicle* currVehicle;
51 int menu_on_map_click;
52 int signal_on_map_click;
60 int lazy; //When TRUE - menu state will not be changed during map/menu switches, FALSE - menu will be always reset to main.qml
63 struct callback_list *cbl;
64 QCoreApplication *app;
68 QWidget *graphicsWidget;
69 QDeclarativeView *guiWidget;
70 QDeclarativeView *prevGuiWidget;
71 QStackedLayout *switcherWidget;
72 struct callback *button_cb;
73 struct callback *motion_cb;
74 struct callback *resize_cb;
75 struct callback *keypress_cb;
76 struct callback *window_closed_cb;
79 class NGQProxyGui* guiProxy;
80 class NGQProxyNavit* navitProxy;
81 class NGQProxyVehicle* vehicleProxy;
82 class NGQProxySearch* searchProxy;
83 class NGQProxyBookmarks* bookmarksProxy;
84 class NGQProxyRoute* routeProxy;
85 class NGQPoint* currentPoint;
90 #include "searchProxy.h"
91 #include "routeProxy.h"
92 #include "bookmarksProxy.h"
93 #include "vehicleProxy.h"
94 #include "navitProxy.h"
97 //Main window class for resizeEvent handling
99 #include <QX11EmbedWidget>
100 class NGQMainWindow : public QX11EmbedWidget
103 class NGQMainWindow : public QWidget
105 #endif /* Q_WS_X11 */
109 NGQMainWindow(struct gui_priv* this_,QWidget *parent) : QX11EmbedWidget(parent) {
111 NGQMainWindow(struct gui_priv* this_,QWidget *parent) : QWidget(parent) {
112 #endif /* Q_WS_X11 */
116 void resizeEvent(QResizeEvent *) {
117 this->object->w=this->width();
118 this->object->h=this->height();
119 //YES, i KNOW about signal/slot thing
120 this->object->guiProxy->setWidth(this->width());
121 this->object->guiProxy->setHeight(this->height());
123 void closeEvent(QCloseEvent* event) {
124 this->object->graphicsWidget->close();
127 struct gui_priv* object;
131 #include "gui_qml.moc"
133 static void gui_qml_dbus_signal(struct gui_priv *this_, struct point *p)
135 struct displaylist_handle *dlh;
136 struct displaylist *display;
137 struct displayitem *di;
139 display=navit_get_displaylist(this_->nav);
140 dlh=graphics_displaylist_open(display);
141 while ((di=graphics_displaylist_next(dlh))) {
142 struct item *item=graphics_displayitem_get_item(di);
143 if (item_is_point(*item) && graphics_displayitem_get_displayed(di) &&
144 graphics_displayitem_within_dist(display, di, p, 10)) {
145 struct map_rect *mr=map_rect_new(item->map, NULL);
146 struct item *itemo=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
148 if (item_attr_get(itemo, attr_data, &attr)) {
149 struct attr cb,*attr_list[2];
154 if (navit_get_attr(this_->nav, attr_callback_list, &cb, NULL))
155 callback_list_call_attr_4(cb.u.callback_list, attr_command, "dbus_send_signal", attr_list, NULL, &valid);
157 map_rect_destroy(mr);
160 graphics_displaylist_close(dlh);
163 static void gui_qml_button(void *data, int pressed, int button, struct point *p)
165 struct gui_priv *this_=(struct gui_priv*)data;
167 // check whether the position of the mouse changed during press/release OR if it is the scrollwheel
168 if (!navit_handle_button(this_->nav, pressed, button, p, NULL)) {
169 dbg(1,"navit has handled button\n");
173 dbg(1,"enter %d %d\n", pressed, button);
174 if (this_->signal_on_map_click) {
175 gui_qml_dbus_signal(this_, p);
179 if ( button == 1 && this_->menu_on_map_click ) {
180 this_->guiProxy->switchToMenu(p);
184 static void gui_qml_motion(void *data, struct point *p)
186 struct gui_priv *this_=(struct gui_priv*)data;
187 navit_handle_motion(this_->nav, p);
190 static void gui_qml_resize(void *data, int w, int h)
192 struct gui_priv *this_=(struct gui_priv*)data;
193 navit_handle_resize(this_->nav, w, h);
196 static void gui_qml_keypress(void *data, char *key)
198 struct gui_priv *this_=(struct gui_priv*) data;
201 transform_get_size(navit_get_trans(this_->nav), &w, &h);
206 navit_set_center_screen(this_->nav, &p, 1);
211 navit_set_center_screen(this_->nav, &p, 1);
216 navit_set_center_screen(this_->nav, &p, 1);
218 case NAVIT_KEY_RIGHT:
221 navit_set_center_screen(this_->nav, &p, 1);
223 case NAVIT_KEY_ZOOM_IN:
224 navit_zoom_in(this_->nav, 2, NULL);
226 case NAVIT_KEY_ZOOM_OUT:
227 navit_zoom_out(this_->nav, 2, NULL);
229 case NAVIT_KEY_RETURN:
233 this_->guiProxy->switchToMenu(&p);
240 gui_qml_window_closed(struct gui_priv *data)
242 struct gui_priv *this_=(struct gui_priv*) data;
243 this_->navitProxy->quit();
245 //GUI interface calls
247 static char *argv[]={(char *)"navit",NULL};
249 static int gui_qml_set_graphics(struct gui_priv *this_, struct graphics *gra)
252 NGQMainWindow* _mainWindow;
257 //Check if we are already in Qt environment
258 if (QApplication::instance()==NULL) {
260 this_->app=new QApplication(argc,argv);
262 this_->app=QApplication::instance();
265 //Link graphics events
266 this_->button_cb=callback_new_attr_1(callback_cast(gui_qml_button), attr_button, this_);
267 graphics_add_callback(gra, this_->button_cb);
268 this_->motion_cb=callback_new_attr_1(callback_cast(gui_qml_motion), attr_motion, this_);
269 graphics_add_callback(gra, this_->motion_cb);
270 this_->resize_cb=callback_new_attr_1(callback_cast(gui_qml_resize), attr_resize, this_);
271 graphics_add_callback(gra, this_->resize_cb);
272 this_->keypress_cb=callback_new_attr_1(callback_cast(gui_qml_keypress), attr_keypress, this_);
273 graphics_add_callback(gra, this_->keypress_cb);
274 this_->window_closed_cb=callback_new_attr_1(callback_cast(gui_qml_window_closed), attr_window_closed, this_);
275 graphics_add_callback(gra, this_->window_closed_cb);
279 this_->switcherWidget = new QStackedLayout();
280 _mainWindow = new NGQMainWindow(this_, NULL);
282 xid=getenv("NAVIT_XID");
283 if (xid.length()>0) {
284 _mainWindow->embedInto(xid.toULong(&ok,0));
286 #endif /* Q_WS_X11 */
287 this_->mainWindow=_mainWindow;
288 if ( this_->w && this_->h ) {
289 this_->mainWindow->resize(this_->w,this_->h);
291 if ( this_->fullscreen ) {
292 this_->mainWindow->showFullScreen();
295 this_->mainWindow->setLayout(this_->switcherWidget);
297 //Create proxy object and bind them to gui widget
298 this_->guiProxy = new NGQProxyGui(this_,this_->mainWindow);
299 this_->navitProxy = new NGQProxyNavit(this_,this_->mainWindow);
300 this_->vehicleProxy = new NGQProxyVehicle(this_,this_->mainWindow);
301 this_->searchProxy = new NGQProxySearch(this_,this_->mainWindow);
302 this_->bookmarksProxy = new NGQProxyBookmarks(this_,this_->mainWindow);
303 this_->routeProxy = new NGQProxyRoute(this_,this_->mainWindow);
305 //Check, if we have compatible graphics
306 this_->graphicsWidget = (QWidget*)graphics_get_data(gra,"qt_widget");
307 if (this_->graphicsWidget == NULL ) {
308 this_->graphicsWidget = new QLabel(QString("Sorry, current graphics type is incompatible with this gui."));
310 this_->switcherWidget->addWidget(this_->graphicsWidget);
312 //Instantiate qml components
313 this_->guiWidget = new QDeclarativeView(NULL);
314 this_->guiWidget->setResizeMode(QDeclarativeView::SizeRootObjectToView);
316 this_->guiWidget->rootContext()->setContextProperty("gui",this_->guiProxy);
317 this_->guiWidget->rootContext()->setContextProperty("navit",this_->navitProxy);
318 this_->guiWidget->rootContext()->setContextProperty("vehicle",this_->vehicleProxy);
319 this_->guiWidget->rootContext()->setContextProperty("search",this_->searchProxy);
320 this_->guiWidget->rootContext()->setContextProperty("bookmarks",this_->bookmarksProxy);
321 this_->guiWidget->rootContext()->setContextProperty("route",this_->routeProxy);
322 this_->guiWidget->rootContext()->setContextProperty("point",this_->currentPoint);
324 this_->guiWidget->setSource(QUrl::fromLocalFile(QString(this_->source)+"/"+this_->skin+"/main.qml"));
325 this_->switcherWidget->addWidget(this_->guiWidget);
328 navit_draw(this_->nav);
329 this_->switcherWidget->setCurrentWidget(this_->graphicsWidget);
331 this_->mainWindow->show();
337 gui_qml_get_attr(struct gui_priv *this_, enum attr_type type, struct attr *attr)
340 case attr_fullscreen:
341 attr->u.num=this_->fullscreen;
344 attr->u.str=this_->skin;
347 attr->u.num=this_->pitch;
350 attr->u.num=this_->radius;
360 gui_qml_set_attr(struct gui_priv *this_, struct attr *attr)
362 switch (attr->type) {
363 case attr_fullscreen:
364 if (!(this_->fullscreen) && (attr->u.num)) {
365 this_->mainWindow->showFullScreen();
367 if ((this_->fullscreen) && !(attr->u.num)) {
368 this_->mainWindow->showNormal();
370 this_->fullscreen=attr->u.num;
373 this_->pitch=attr->u.num;
376 this_->radius=attr->u.num;
379 dbg(0,"unknown attr: %s\n",attr_to_name(attr->type));
384 struct gui_methods gui_qml_methods = {
387 gui_qml_set_graphics,
398 gui_qml_command(struct gui_priv *this_, char *function, struct attr **in, struct attr ***out, int *valid) {
399 this_->guiProxy->processCommand(function);
402 static struct command_table commands[] = {
403 {"*",command_cast(gui_qml_command)},
406 static struct gui_priv * gui_qml_new(struct navit *nav, struct gui_methods *meth, struct attr **attrs, struct gui *gui)
408 struct gui_priv *this_;
410 *meth=gui_qml_methods;
411 this_=g_new0(struct gui_priv, 1);
416 this_->self.type=attr_gui;
417 this_->self.u.gui=gui;
419 navit_ignore_graphics_events(this_->nav, 1);
421 this_->fullscreen = 0; //NO by default
422 if( (attr=attr_search(attrs,NULL,attr_fullscreen)))
423 this_->fullscreen=attr->u.num;
424 this_->menu_on_map_click = 1; //YES by default;
425 if( (attr=attr_search(attrs,NULL,attr_menu_on_map_click)))
426 this_->menu_on_map_click=attr->u.num;
427 this_->signal_on_map_click = 0; //YES by default;
428 if( (attr=attr_search(attrs,NULL,attr_signal_on_map_click)))
429 this_->signal_on_map_click=attr->u.num;
430 this_->radius = 10; //Default value
431 if( (attr=attr_search(attrs,NULL,attr_radius)))
432 this_->radius=attr->u.num;
433 this_->pitch = 20; //Default value
434 if( (attr=attr_search(attrs,NULL,attr_pitch)))
435 this_->pitch=attr->u.num;
436 this_->lazy = 1; //YES by default
437 if( (attr=attr_search(attrs,NULL,attr_lazy)))
438 this_->lazy=attr->u.num;
439 this_->w=800; //Default value
440 if( (attr=attr_search(attrs,NULL,attr_width)))
441 this_->w=attr->u.num;
442 this_->h=600; //Default value
443 if( (attr=attr_search(attrs,NULL,attr_height)))
444 this_->h=attr->u.num;
445 if( (attr=attr_search(attrs,NULL,attr_source)))
446 this_->source=attr->u.str;
447 if( (attr=attr_search(attrs,NULL,attr_skin)))
448 this_->skin=attr->u.str;
449 if( (attr=attr_search(attrs,NULL,attr_icon_src)))
450 this_->icon_src=attr->u.str;
452 if ( this_->source==NULL ) {
453 this_->source=g_strjoin(NULL,getenv("NAVIT_SHAREDIR"),"/gui/qml/skins",NULL);
455 if ( this_->skin==NULL ) {
456 this_->skin=g_strdup("navit");
458 if ( this_->icon_src==NULL ) {
459 this_->icon_src=g_strjoin(NULL,getenv("NAVIT_SHAREDIR"),"/xpm/",NULL);
462 if ((attr=attr_search(attrs, NULL, attr_callback_list))) {
463 command_add_table(attr->u.callback_list, commands, sizeof(commands)/sizeof(struct command_table), this_);
466 this_->cbl=callback_list_new();
471 void plugin_init(void) {
472 plugin_register_gui_type("qml",gui_qml_new);