#include #include "item.h" #include "attr.h" #include "navit.h" #include "xmlconfig.h" // for NAVIT_OBJECT #include "layout.h" #include "map.h" #include "transform.h" #include "vehicle.h" #include "bookmarks.h" #include "backend.h" #include "qml_map.h" #include "qml_poi.h" #include "qml_search.h" #include "mapset.h" #include #include "search.h" extern "C" { #include "proxy.h" } Backend::Backend(QObject * parent):QObject(parent) { set_default_country(); this->search = NULL; _current_town = NULL; _current_street = NULL; } /** * @brief Set some variables and display the main menu * @param struct point *p the point coordinate where we clicked on the screen * @returns nothing */ void Backend::showMenu(struct point *p) { struct coord co; transform_reverse(navit_get_trans(nav), p, &co); dbg(lvl_debug, "Point 0x%x 0x%x", co.x, co.y); dbg(lvl_debug, "Screen coord : %d %d", p->x, p->y); transform_to_geo(transform_get_projection(navit_get_trans(nav)), &co, &(this->g)); dbg(lvl_debug, "%f %f", this->g.lat, this->g.lng); dbg(lvl_debug, "%p %p", nav, &c); this->c.pro = transform_get_projection(navit_get_trans(nav)); this->c.x = co.x; this->c.y = co.y; dbg(lvl_debug, "c : %x %x", this->c.x, this->c.y); // As a test, set the Demo vehicle position to wherever we just clicked navit_set_position(this->nav, &c); navit_block(this->nav, 1); emit displayMenu("MainMenu.qml"); } /** * @brief update the private m_maps list. Expected to be called from QML * @param none * @returns nothing */ void Backend::get_maps() { struct attr attr, description, type, data, active; char * label; bool is_active; struct attr_iter * iter; _maps.clear(); iter = navit_attr_iter_new(NULL); while (navit_get_attr(this->nav, attr_map, &attr, iter)) { if (map_get_attr(attr.u.map, attr_description, &description, NULL)) { label = g_strdup(description.u.str); } else { if (!map_get_attr(attr.u.map, attr_type, &type, NULL)) type.u.str = (char*)""; if (!map_get_attr(attr.u.map, attr_data, &data, NULL)) data.u.str = (char*)""; label = g_strdup_printf("%s:%s", type.u.str, data.u.str); } is_active = false; if (map_get_attr(attr.u.map, attr_active, &active, NULL)) { if (active.u.num == 1) { is_active = true; } } _maps.append(new MapObject(label, is_active)); } emit mapsChanged(); } /** * @brief update the private m_vehicles list. Expected to be called from QML * @param none * @returns nothing */ void Backend::get_vehicles() { struct attr attr,attr2,vattr; struct attr_iter *iter; struct attr active_vehicle; _vehicles.clear(); iter=navit_attr_iter_new(NULL); if (navit_get_attr(this->nav, attr_vehicle, &attr, iter) && !navit_get_attr(this->nav, attr_vehicle, &attr2, iter)) { vehicle_get_attr(attr.u.vehicle, attr_name, &vattr, NULL); navit_attr_iter_destroy(iter); _vehicles.append(new VehicleObject(g_strdup(vattr.u.str), active_vehicle.u.vehicle, attr.u.vehicle)); dbg(lvl_debug, "done"); emit vehiclesChanged(); return; } navit_attr_iter_destroy(iter); if (!navit_get_attr(this->nav, attr_vehicle, &active_vehicle, NULL)) active_vehicle.u.vehicle=NULL; iter=navit_attr_iter_new(NULL); while(navit_get_attr(this->nav, attr_vehicle, &attr, iter)) { vehicle_get_attr(attr.u.vehicle, attr_name, &vattr, NULL); dbg(lvl_debug, "adding vehicle %s", vattr.u.str); _vehicles.append( new VehicleObject( g_strdup(vattr.u.str), attr.u.vehicle == active_vehicle.u.vehicle, attr.u.vehicle ) ); } navit_attr_iter_destroy(iter); emit vehiclesChanged(); } /** * @brief set a pointer to the struct navit * for local use * @param none * @returns nothing */ void Backend::set_navit(struct navit *nav) { this->nav = nav; } /** * @brief set a pointer to the QQmlApplicationEngine * for local use * @param none * @returns nothing */ void Backend::set_engine(QQmlApplicationEngine * engine) { this->engine = engine; } /** * @brief apply search filters on one specific item * @param struct item * the item to filter * @returns 0 if the item should be discarded, 1 otherwise */ int Backend::filter_pois(struct item *item) { enum item_type type=item->type; if (type >= type_line) return 0; return 1; } /** * @brief update the private m_bookmarks list. Expected to be called from QML * @param none * @returns nothing */ void Backend::get_bookmarks() { struct attr attr,mattr; struct item *item; struct coord c; struct pcoord pc; _bookmarks.clear(); pc.pro = transform_get_projection(navit_get_trans(this->nav)); if(navit_get_attr(this->nav, attr_bookmarks, &mattr, NULL) ) { bookmarks_item_rewind(mattr.u.bookmarks); while ((item=bookmarks_get_item(mattr.u.bookmarks))) { if (!item_attr_get(item, attr_label, &attr)) continue; dbg(lvl_debug,"full_label: %s", attr.u.str); if (item_coord_get(item, &c, 1)) { pc.x = c.x; pc.y = c.y; dbg(lvl_debug, "coords : %i x %i", pc.x, pc.y); _bookmarks.append(new BookmarkObject(attr.u.str, pc)); } } } emit bookmarksChanged(); } /** * @brief update the private m_pois list. Expected to be called from QML * @param none * @returns nothing */ void Backend::get_pois() { struct map_selection * sel, * selm; struct coord c, center; struct mapset_handle * h; struct map * m; struct map_rect * mr; struct item * item; enum projection pro = this->c.pro; int idist, dist; _pois.clear(); dist = 10000; sel = map_selection_rect_new(&(this->c), dist * transform_scale(abs(this->c.y) + dist * 1.5), 18); center.x = this->c.x; center.y = this->c.y; dbg(lvl_debug, "center is at %x, %x", center.x, center.y); h = mapset_open(navit_get_mapset(this->nav)); while ((m = mapset_next(h, 1))) { selm = map_selection_dup_pro(sel, pro, map_projection(m)); mr = map_rect_new(m, selm); dbg(lvl_debug, "mr=%p", mr); if (mr) { while ((item = map_rect_get_item(mr))) { if ( filter_pois(item) && item_coord_get_pro(item, &c, 1, pro) && coord_rect_contains(&sel->u.c_rect, &c) && (idist=transform_distance(pro, ¢er, &c)) < dist) { struct attr attr; char * label; char * icon = get_icon(this->nav, item); struct pcoord item_coord; item_coord.pro = transform_get_projection(navit_get_trans(nav)); item_coord.x = c.x; item_coord.y = c.y; idist = transform_distance(pro, ¢er, &c); if (item_attr_get(item, attr_label, &attr)) { label = map_convert_string(item->map, attr.u.str); if (icon) { _pois.append(new PoiObject(label, item_to_name(item->type), idist, icon, item_coord)); } } } } map_rect_destroy(mr); } map_selection_destroy(selm); } map_selection_destroy(sel); mapset_close(h); emit poisChanged(); } /** * @brief get the POIs as a QList * @param none * @returns the pois QList */ QQmlListProperty Backend::getPois() { return QQmlListProperty(this, _pois); } /** * @brief get the Bookmarks as a QList * @param none * @returns the bookmarks QList */ QQmlListProperty Backend::getBookmarks() { return QQmlListProperty(this, _bookmarks); } /** * @brief get the maps as a QList * @param none * @returns the maps QList */ QQmlListProperty Backend::getMaps() { return QQmlListProperty(this, _maps); } /** * @brief get the vehicles as a QList * @param none * @returns the vehicles QList */ QQmlListProperty Backend::getVehicles() { return QQmlListProperty(this, _vehicles); } /** * @brief get the search results as a QList * @param none * @returns the search results QList */ QQmlListProperty Backend::getSearchResults() { return QQmlListProperty(this, _search_results); } /** * @brief get the active POI. Used when displaying the relevant menu * @param none * @returns the active POI */ PoiObject * Backend::activePoi() { dbg(lvl_debug, "name : %s", m_activePoi->name().toUtf8().data()); dbg(lvl_debug, "type : %s", m_activePoi->type().toLatin1().data()); return m_activePoi; } /** * @brief get the current bookmark. Used when displaying the relevant menu * @param none * @returns the current bookmark */ BookmarkObject * Backend::currentBookmark() { return m_currentBookmark; } /** * @brief get the currently selected vehicle. Used when displaying the relevant menu * @param none * @returns the active POI */ VehicleObject * Backend::currentVehicle() { struct attr attr; dbg(lvl_debug, "name : %s", m_currentVehicle->name().toUtf8().data()); if (m_currentVehicle->vehicle()) { if (vehicle_get_attr(m_currentVehicle->vehicle(), attr_position_nmea, &attr, NULL)) dbg(lvl_debug, "NMEA : %s", attr.u.str); } else { dbg(lvl_debug, "m_currentVehicle->v is null"); } return m_currentVehicle; } void Backend::block_draw() { navit_block(this->nav, 1); dbg(lvl_debug, "Draw operations blocked per UI request"); } /** * @brief set the canvas size to use when drawing the map * @param int width * @param int height * @returns nothing */ void Backend::resize(int width, int height) { // If we need to resize the canvas, it means that something (the main map, // or a menu item) wants to display a map. Ensure that draw operations // are not blocked then. navit_block(this->nav, -1); navit_handle_resize(nav, width, height); } /** * @brief set the active POI. Used when clicking on a POI list to display one single POI * @param int index the index of the POI in the m_pois list * @returns nothing */ void Backend::setActivePoi(int index) { struct pcoord c; m_activePoi = (PoiObject *)_pois.at(index); c = m_activePoi->coords(); resize(320, 240); navit_set_center(this->nav, &c, 1); emit activePoiChanged(); } /** * @brief set the current bookmark. Used when clicking on a bookmark list to display one single bookmark * @param int index the index of the bookmark in the m_bookmarks list * @returns nothing */ void Backend::setCurrentBookmark(int index) { struct pcoord c; m_currentBookmark = (BookmarkObject *)_bookmarks.at(index); c = m_currentBookmark->coords(); resize(320, 240); navit_set_center(this->nav, &c, 1); emit currentBookmarkChanged(); } /** * @brief set the current vehicle. Used when clicking on a vehicle list to display one single vehicle * @param int index the index of the vehicle in the m_vehicles list * @returns nothing */ void Backend::setCurrentVehicle(int index) { m_currentVehicle = (VehicleObject *)_vehicles.at(index); emit currentVehicleChanged(); } /** * @brief returns the icon absolute path * @param none * @returns the icon absolute path as a QString */ QString Backend::get_icon_path() { return QString(g_strjoin(NULL,"file://",getenv("NAVIT_SHAREDIR"),"/icons/",NULL)); } /** * @brief set the destination using the currently active POI's coordinates * @param none * @returns nothing */ void Backend::setActivePoiAsDestination() { struct pcoord c; c = m_activePoi->coords(); dbg(lvl_debug, "Destination : %s c=%d:0x%x,0x%x", m_activePoi->name().toUtf8().data(), c.pro, c.x, c.y); navit_set_destination(this->nav, &c, m_activePoi->name().toUtf8().data(), 1); emit hideMenu(); } /** * @brief save the search result for the next search step * @param int index the index of the result in the m_search_results list * @returns nothing */ void Backend::searchValidateResult(int index) { SearchObject * r = (SearchObject *)_search_results.at(index); dbg(lvl_debug, "Saving %s [%i] as search result", r->name().toUtf8().data(), index); if (r->getCoords()) { dbg(lvl_debug, "Item is at %x x %x", r->getCoords()->x, r->getCoords()->y); } if (_search_context == attr_country_all) { _current_country = g_strdup(r->name().toUtf8().data()); _current_town = NULL; _current_street = NULL; } else if (_search_context == attr_town_name) { _current_town = g_strdup(r->name().toUtf8().data()); _current_street = NULL; } else if (_search_context == attr_street_name) { _current_street = g_strdup(r->name().toUtf8().data()); } else { dbg(lvl_error, "Unknown search context for '%s'", r->name().toUtf8().data()); } // navit_set_center(this->nav, r->getCoords(), 1); emit displayMenu("destination_address.qml"); } /** * @brief get the icon that matches the country currently used for searches * @param none * @returns an absolute path for the country icon */ QString Backend::get_country_icon(char * country_iso_code) { // if ( country_iso_code == "" ) { // country_iso_code = _country_iso2; // } return QString(g_strjoin(NULL,"file://",getenv("NAVIT_SHAREDIR"),"/icons/",country_iso_code,".svg",NULL)); } static struct search_param { struct navit *nav; struct mapset *ms; struct search_list *sl; struct attr attr; int partial; void *entry_country, *entry_postal, *entry_city, *entry_district; void *entry_street, *entry_number; } search_param; /** * @brief set the default country * @param none * returns nothing */ void Backend::set_default_country() { _current_country = "Germany"; _country_iso2 = "DE"; } /** * @brief update the current search results according to new inputs. Currently only works to search for towns * @param QString text the text to search for * @returns nothing */ void Backend::updateSearch(QString text) { struct search_list_result *res; struct attr search_attr; if (search == NULL) { search=&search_param; dbg(lvl_debug, "search = %p", search); search->nav=this->nav; search->ms=navit_get_mapset(this->nav); search->sl=search_list_new(search->ms); search->partial = 1; dbg(lvl_debug,"attempting to use country '%s'", _country_iso2); search_attr.type=attr_country_iso2; search_attr.u.str=(char*)_country_iso2; search_list_search(search->sl, &search_attr, 0); while((res=search_list_get_result(search->sl))); } _search_results.clear(); // search->attr.type=attr_country_all; // search->attr.type=attr_town_postal; // search->attr.type=attr_town_name; // search->attr.type=attr_street_name; // search->attr.type=attr_town_name; // search->attr.u.str="Oberhaching"; // search_list_search(search->sl, &search->attr, search->partial); // while((res=search_list_get_result(search->sl))); search->attr.u.str = text.toUtf8().data(); dbg(lvl_error, "searching for %s partial %d", search->attr.u.str, search->partial); search->attr.type = _search_context; search_list_search(search->sl, &search->attr, search->partial); int count = 0; while((res=search_list_get_result(search->sl))) { if ( _search_context == attr_country_all && res->country) { char * label; label = g_strdup(res->country->name); _search_results.append( new SearchObject(label, get_country_icon(res->country->flag), res->c) ); } if ( _search_context == attr_town_name && res->town) { char * label; label = g_strdup(res->town->common.town_name); _search_results.append( new SearchObject(label, "icons/bigcity.png", res->c) ); } if (res->street) { char * label; label = g_strdup(res->street->name); _search_results.append( new SearchObject(label, "icons/smallcity.png", res->c) ); } if (count ++ > 50) { break; } } emit searchResultsChanged(); } void Backend::setSearchContext(QString text) { if (text == "country") { _search_context = attr_country_all; } else if (text == "town") { _search_context = attr_town_name; } else if (text == "street") { _search_context = attr_street_name; } else { dbg(lvl_error, "Unhandled search context '%s'", text.toUtf8().data()); } } QString Backend::currentCountry() { dbg(lvl_debug, "Current country : %s/%s", _country_iso2, _current_country); return QString(_current_country); } QString Backend::currentCountryIso2() { dbg(lvl_debug, "Current country : %s/%s", _country_iso2, _current_country); return QString(_country_iso2); } QString Backend::currentTown() { if (_current_town == NULL) { _current_town = "Enter City"; } dbg(lvl_debug, "Current town : %s", _current_town); return QString(_current_town); } QString Backend::currentStreet() { if (_current_street == NULL) { _current_street = "Enter Street"; } dbg(lvl_debug, "Current street : %s", _current_street); return QString(_current_street); }