#include <bluetooth/hci_lib.h>
#include <bluetooth/rfcomm.h>
+#include <sqlite.h>
+
/****************************************************************************
* BELOW: DEFINES ***********************************************************
****************************************************************************/
/* Pans are done two "grids" at a time, or 64 pixels. */
#define PAN_UNITS (grid2unit(2))
-#define INITIAL_DOWNLOAD_RETRIES (2)
-
-#define UNITS_KM _("km")
-#define UNITS_MI _("mi.")
-#define UNITS_NM _("n.m.")
+#define INITIAL_DOWNLOAD_RETRIES (3)
#define GCONF_KEY_PREFIX "/apps/maemo/maemo-mapper"
#define GCONF_KEY_RCVR_MAC GCONF_KEY_PREFIX"/receiver_mac"
#define GCONF_KEY_VOICE_PITCH GCONF_KEY_PREFIX"/voice_pitch"
#define GCONF_KEY_ALWAYS_KEEP_ON GCONF_KEY_PREFIX"/always_keep_on"
#define GCONF_KEY_UNITS GCONF_KEY_PREFIX"/units"
+#define GCONF_KEY_ESCAPE_KEY GCONF_KEY_PREFIX"/escape_key"
+
+#define GCONF_KEY_POI_DB GCONF_KEY_PREFIX"/poi_db"
+#define GCONF_KEY_POI_ZOOM GCONF_KEY_PREFIX"/poi_zoom"
#define GCONF_KEY_COLOR_MARK GCONF_KEY_PREFIX"/color_mark"
#define GCONF_KEY_COLOR_MARK_VELOCITY GCONF_KEY_PREFIX"/color_mark_velocity"
#define GCONF_KEY_COLOR_ROUTE GCONF_KEY_PREFIX"/color_route"
#define GCONF_KEY_COLOR_ROUTE_WAY GCONF_KEY_PREFIX"/color_route_way"
#define GCONF_KEY_COLOR_ROUTE_NEXTWAY GCONF_KEY_PREFIX"/color_route_nextway"
+#define GCONF_KEY_COLOR_POI GCONF_KEY_PREFIX"/color_poi"
#define GCONF_KEY_AUTOCENTER_MODE GCONF_KEY_PREFIX"/autocenter_mode"
#define GCONF_KEY_LEAD_AMOUNT GCONF_KEY_PREFIX"/lead_amount"
#define GCONF_KEY_SHOWVELVEC GCONF_KEY_PREFIX"/show_velocity_vector"
#define GCONF_KEY_ENABLE_GPS GCONF_KEY_PREFIX"/enable_gps"
#define GCONF_KEY_ROUTE_LOCATIONS GCONF_KEY_PREFIX"/route_locations"
+#define GCONF_KEY_REPOSITORIES GCONF_KEY_PREFIX"/repositories"
+#define GCONF_KEY_CURRREPO GCONF_KEY_PREFIX"/curr_repo"
+#define GCONF_KEY_GPS_INFO GCONF_KEY_PREFIX"/gps_info"
+
#define XML_DATE_FORMAT "%FT%T"
} \
};
-#define EARTH_RADIUS_KM (6371.f)
-#define EARTH_RADIUS_MI (3958.75587f)
-#define EARTH_RADIUS_NM (3440.06479f)
-
#define MERCATOR_SPAN (-6.28318377773622f)
#define MERCATOR_TOP (3.14159188886811f)
#define latlon2unit(lat, lon, unitx, unity) { \
ERROR,
} SaxState;
+/** POI dialog action **/
+typedef enum
+{
+ ACTION_ADD_POI,
+ ACTION_EDIT_POI,
+} POIAction;
+
+/** Category list **/
+typedef enum
+{
+ CAT_ID,
+ CAT_ENABLED,
+ CAT_LABEL,
+ CAT_DESCRIPTION,
+ CAT_NUM_COLUMNS
+} CategoryList;
+
+/** POI list **/
+typedef enum
+{
+ POI_INDEX,
+ POI_LATITUDE,
+ POI_LONGITUDE,
+ POI_LABEL,
+ POI_CATEGORY,
+ POI_NUM_COLUMNS
+} POIList;
+
+/** This enum defines the possible units we can use. */
+typedef enum
+{
+ UNITS_KM,
+#define UNITS_KM_TEXT _("km")
+ UNITS_MI,
+#define UNITS_MI_TEXT _("mi.")
+ UNITS_NM,
+#define UNITS_NM_TEXT _("n.m.")
+} UnitType;
+gchar *UNITS_TEXT[3];
+#define EARTH_RADIUS (3440.06479f)
+gfloat UNITS_CONVERT[] =
+{
+ 1.85200,
+ 1.15077945,
+ 1.f,
+};
+
+typedef enum
+{
+ ESCAPE_KEY_TOGGLE_TRACKS,
+#define ESCAPE_KEY_TOGGLE_TRACKS_TEXT _("Toggle Tracks")
+ ESCAPE_KEY_CHANGE_REPO,
+#define ESCAPE_KEY_CHANGE_REPO_TEXT _("Next Repository")
+ ESCAPE_KEY_RESET_BLUETOOTH,
+#define ESCAPE_KEY_RESET_BLUETOOTH_TEXT _("Reset Bluetooth")
+} EscapeKeyAction;
+gchar *ESCAPE_KEY_TEXT[3];
+
+
/** A general definition of a point in the Maemo Mapper unit system. */
typedef struct _Point Point;
struct _Point {
GString *chars;
};
+/** Data used during action: add or edit category/poi **/
+typedef struct _DeletePOI DeletePOI;
+struct _DeletePOI {
+ GtkWidget *dialog;
+ gchar *txt_label;
+ guint id;
+};
+
/** Data used during the asynchronous progress update phase of automatic map
* downloading. */
typedef struct _ProgressUpdateInfo ProgressUpdateInfo;
GList *src_list;
GList *dest_list;
guint tilex, tiley, zoom; /* for refresh. */
- gint retries_left;
+ gint retries_left; /* if equal to zero, it means we're DELETING maps. */
guint hash;
};
guint bytes_maxsize;
};
+/** Data regarding a map repository. */
+typedef struct _RepoData RepoData;
+struct _RepoData {
+ gchar *name;
+ gchar *url;
+ gchar *cache_dir;
+ guint dl_zoom_steps;
+ guint view_zoom_steps;
+ GtkWidget *menu_item;
+};
+
+/** GPS Data and Satellite **/
+typedef struct _GpsData GpsData;
+struct _GpsData {
+ guint fix;
+ guint fixquality;
+ struct tm time; /* gps fix time */
+ struct tm timeloc; /* local time */
+ gfloat latitude;
+ gfloat longitude;
+ gchar slatitude[15];
+ gchar slongitude[15];
+ gfloat speed; /* in knots */
+ gfloat maxspeed; /* in knots */
+ guint altitude; /* in meters */
+ gfloat heading;
+ gfloat hdop;
+ gfloat pdop;
+ gfloat vdop;
+ guint satinview;
+ guint satinuse;
+ guint satforfix[12];
+};
+
+typedef struct _GpsSatelliteData GpsSatelliteData;
+struct _GpsSatelliteData {
+ guint prn;
+ guint elevation;
+ guint azimuth;
+ guint snr;
+};
/****************************************************************************
* ABOVE: TYPEDEFS **********************************************************
****************************************************************************/
-
-
/****************************************************************************
* BELOW: DATA **************************************************************
****************************************************************************/
/** The backing pixmap of _map_widget. */
static GdkPixmap *_map_pixmap = NULL;
+static GtkWidget *_gps_widget = NULL;
+static GtkWidget *_text_lat = NULL;
+static GtkWidget *_text_lon = NULL;
+static GtkWidget *_text_speed = NULL;
+static GtkWidget *_text_alt = NULL;
+static GtkWidget *_sat_panel = NULL;
+static GtkWidget *_text_time = NULL;
+static GtkWidget *_heading_panel = NULL;
+
+static GtkWidget *_sat_details_panel = NULL;
+static GtkWidget *_sdi_lat = NULL;
+static GtkWidget *_sdi_lon = NULL;
+static GtkWidget *_sdi_spd = NULL;
+static GtkWidget *_sdi_alt = NULL;
+static GtkWidget *_sdi_hea = NULL;
+static GtkWidget *_sdi_tim = NULL;
+static GtkWidget *_sdi_vie = NULL;
+static GtkWidget *_sdi_use = NULL;
+static GtkWidget *_sdi_fix = NULL;
+static GtkWidget *_sdi_fqu = NULL;
+static GtkWidget *_sdi_msp = NULL;
/** The file descriptor of our connection with the GPS receiver. */
static gint _fd = -1;
+static gchar _gps_read_buf[256];
+static guint _gps_read_buf_pos = 0;
/** The GIOChannel through which communication with the GPS receiver is
* performed. */
static gint _vel_offsetx = 0;
static gint _vel_offsety = 0;
+static GpsData _gps;
+static GpsSatelliteData _gps_sat[12];
+gboolean _satdetails_on = FALSE;
/** The current connection state. */
static ConnState _conn_state = RCVR_OFF;
static GdkGC *_gc_route = NULL;
static GdkGC *_gc_route_way = NULL;
static GdkGC *_gc_route_nextway = NULL;
+static GdkGC *_gc_poi = NULL;
static GdkColor _color_mark = {0, 0, 0, 0};
static GdkColor _color_mark_velocity = {0, 0, 0, 0};
static GdkColor _color_mark_old = {0, 0, 0, 0};
static GdkColor _color_route = {0, 0, 0, 0};
static GdkColor _color_route_way = {0, 0, 0, 0};
static GdkColor _color_route_nextway = {0, 0, 0, 0};
+static GdkColor _color_poi = {0, 0, 0, 0};
static GdkColor DEFAULT_COLOR_MARK = {0, 0x0000, 0x0000, 0xc000};
static GdkColor DEFAULT_COLOR_MARK_VELOCITY = {0, 0x6000, 0x6000, 0xf800};
static GdkColor DEFAULT_COLOR_MARK_OLD = {0, 0x8000, 0x8000, 0x8000};
static GdkColor DEFAULT_COLOR_ROUTE = {0, 0x0000, 0xa000, 0x0000};
static GdkColor DEFAULT_COLOR_ROUTE_WAY = {0, 0x0000, 0x8000, 0x0000};
static GdkColor DEFAULT_COLOR_ROUTE_NEXTWAY = {0, 0x0000, 0x6000, 0x0000};
+static GdkColor DEFAULT_COLOR_POI = {0, 0xa000, 0x0000, 0xa000};
/** MAIN MENU ITEMS. */
static GtkWidget *_menu_route_download_item = NULL;
static GtkWidget *_menu_track_save_item = NULL;
static GtkWidget *_menu_track_mark_way_item = NULL;
static GtkWidget *_menu_track_clear_item = NULL;
-static GtkWidget *_menu_maps_dlroute_item = NULL;
-static GtkWidget *_menu_maps_dlarea_item = NULL;
+static GtkWidget *_menu_maps_submenu = NULL;
+static GtkWidget *_menu_maps_mapman_item = NULL;
+static GtkWidget *_menu_maps_repoman_item = NULL;
static GtkWidget *_menu_auto_download_item = NULL;
static GtkWidget *_menu_show_tracks_item = NULL;
static GtkWidget *_menu_show_routes_item = NULL;
static GtkWidget *_menu_ac_none_item = NULL;
static GtkWidget *_menu_fullscreen_item = NULL;
static GtkWidget *_menu_enable_gps_item = NULL;
+static GtkWidget *_menu_gps_show_info_item = NULL;
+static GtkWidget *_menu_gps_details_item = NULL;
+static GtkWidget *_menu_gps_reset_item = NULL;
static GtkWidget *_menu_settings_item = NULL;
+static GtkWidget *_menu_poi_item = NULL;
static GtkWidget *_menu_help_item = NULL;
static GtkWidget *_menu_close_item = NULL;
static GtkWidget *_cmenu_loc_clip_latlon_item = NULL;
static GtkWidget *_cmenu_loc_route_to_item = NULL;
static GtkWidget *_cmenu_loc_distance_to_item = NULL;
+static GtkWidget *_cmenu_add_poi = NULL;
+static GtkWidget *_cmenu_edit_poi = NULL;
static GtkWidget *_cmenu_way_show_latlon_item = NULL;
static GtkWidget *_cmenu_way_show_desc_item = NULL;
/** CONFIGURATION INFORMATION. */
static struct sockaddr_rc _rcvr_addr = { 0 };
static gchar *_rcvr_mac = NULL;
-static gchar *_map_dir_name = NULL;
-static gchar *_map_uri_format = NULL;
static gchar *_route_dir_uri = NULL;
static gchar *_track_file_uri = NULL;
static CenterMode _center_mode = CENTER_LEAD;
static gboolean _fullscreen = FALSE;
static gboolean _enable_gps = FALSE;
+static gboolean _gps_info = FALSE;
static gint _show_tracks = 0;
static gboolean _show_velvec = TRUE;
static gboolean _auto_download = FALSE;
-static guint _zoom_steps = 2;
static guint _lead_ratio = 5;
static guint _center_ratio = 7;
static guint _draw_line_width = 5;
-static guint _announce_notice_ratio = 6;
+static guint _announce_notice_ratio = 8;
static gboolean _enable_voice = TRUE;
static gboolean _always_keep_on = FALSE;
static gdouble _voice_speed = 1.0;
static gint _voice_pitch = 0;
static GSList *_loc_list;
static GtkListStore *_loc_model;
-static gchar *_units = NULL;
+static UnitType _units = UNITS_KM;
+static EscapeKeyAction _escape_key = ESCAPE_KEY_TOGGLE_TRACKS;
+
+static GList *_repo_list = NULL;
+static RepoData *_curr_repo = NULL;
+
+/** POI */
+static gchar *_poi_db = NULL;
+static sqlite *_db = NULL;
+static guint _poi_zoom = 6;
+static gboolean _dbconn = FALSE;
/** The singleton auto-route-download data. */
static AutoRouteDownloadData _autoroute_data;
static gchar XML_TZONE[7];
+static gint _gmtoffset = 0;
/****************************************************************************
* ABOVE: DATA **************************************************************
map_cb_button_press(GtkWidget *widget, GdkEventButton *event);
static gboolean
map_cb_button_release(GtkWidget *widget, GdkEventButton *event);
+static gboolean
+heading_panel_expose(GtkWidget *widget, GdkEventExpose *event);
+static gboolean
+sat_panel_expose(GtkWidget *widget, GdkEventExpose *event);
+static gboolean
+sat_details_panel_expose(GtkWidget *widget, GdkEventExpose *event);
static gboolean
channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data);
menu_cb_show_routes(GtkAction *action);
static gboolean
menu_cb_show_velvec(GtkAction *action);
+static gboolean
+menu_cb_category(GtkAction *action);
+
+static gboolean
+menu_cb_maps_select(GtkAction *action, gpointer new_repo);
static gboolean
-menu_cb_maps_dlroute(GtkAction *action);
+menu_cb_mapman(GtkAction *action);
static gboolean
-menu_cb_maps_dlarea(GtkAction *action);
+menu_cb_maps_repoman(GtkAction *action);
static gboolean
menu_cb_auto_download(GtkAction *action);
cmenu_cb_loc_route_to(GtkAction *action);
static gboolean
cmenu_cb_loc_distance_to(GtkAction *action);
+static gboolean
+cmenu_cb_add_poi(GtkAction *action);
+static gboolean
+cmenu_cb_edit_poi(GtkAction *action);
static gboolean
cmenu_cb_way_show_latlon(GtkAction *action);
menu_cb_fullscreen(GtkAction *action);
static gboolean
menu_cb_enable_gps(GtkAction *action);
+static gboolean
+menu_cb_gps_show_info(GtkAction *action);
+static gboolean
+menu_cb_gps_details(GtkAction *action);
+static gboolean
+menu_cb_gps_reset(GtkAction *action);
static gboolean
menu_cb_settings(GtkAction *action);
* BELOW: ROUTINES **********************************************************
****************************************************************************/
-static gfloat
-calculate_distance(gfloat lat1, gfloat lon1, gfloat lat2, gfloat lon2)
+static gboolean
+gps_display_details(void)
{
- gfloat dlat, dlon, slat, slon, a;
+ gchar *buffer, strtime[15];
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Convert to radians. */
- lat1 *= (PI / 180.f);
- lon1 *= (PI / 180.f);
- lat2 *= (PI / 180.f);
- lon2 *= (PI / 180.f);
+ if(_gps.fix < 2)
+ {
+ /* no fix no fun */
+ gtk_label_set_label(GTK_LABEL(_sdi_lat), " --- ");
+ gtk_label_set_label(GTK_LABEL(_sdi_lon), " --- ");
+ gtk_label_set_label(GTK_LABEL(_sdi_spd), " --- ");
+ gtk_label_set_label(GTK_LABEL(_sdi_alt), " --- ");
+ gtk_label_set_label(GTK_LABEL(_sdi_hea), " --- ");
+ gtk_label_set_label(GTK_LABEL(_sdi_tim), " --:--:-- ");
+ }
+ else
+ {
+ gfloat speed = _gps.speed * UNITS_CONVERT[_units];
- dlat = lat2 - lat1;
- dlon = lon2 - lon1;
-
- slat = sinf(dlat / 2.f);
- slon = sinf(dlon / 2.f);
- a = (slat * slat) + (cosf(lat1) * cosf(lat2) * slon * slon);
+ /* latitude */
+ gtk_label_set_label(GTK_LABEL(_sdi_lat), _gps.slatitude);
+
+ /* longitude */
+ gtk_label_set_label(GTK_LABEL(_sdi_lon), _gps.slongitude);
+
+ /* speed */
+ switch(_units)
+ {
+ case UNITS_MI:
+ buffer = g_strdup_printf("%.1f mph", speed);
+ break;
+ case UNITS_NM:
+ buffer = g_strdup_printf("%.1f kn", speed);
+ break;
+ default:
+ buffer = g_strdup_printf("%.1f km/h", speed);
+ break;
+ }
+ gtk_label_set_label(GTK_LABEL(_sdi_spd), buffer);
+ g_free(buffer);
+
+ /* altitude */
+ switch(_units)
+ {
+ case UNITS_MI:
+ case UNITS_NM:
+ buffer = g_strdup_printf("%d ft",
+ (guint)(_gps.altitude * 3.2808399f));
+ break;
+ default:
+ buffer = g_strdup_printf("%d m", _gps.altitude);
+ break;
+ }
+ gtk_label_set_label(GTK_LABEL(_sdi_alt), buffer);
+ g_free(buffer);
+
+ /* heading */
+ buffer = g_strdup_printf("%0.0f\u00b0", _gps.heading);
+ gtk_label_set_label(GTK_LABEL(_sdi_hea), buffer);
+ g_free(buffer);
+
+ /* local time */
+ strftime(strtime, 15, "%X", &_gps.timeloc);
+ gtk_label_set_label(GTK_LABEL(_sdi_tim), strtime);
+ }
+
+ /* Sat in view */
+ buffer = g_strdup_printf("%d", _gps.satinview);
+ gtk_label_set_label(GTK_LABEL(_sdi_vie), buffer);
+ g_free(buffer);
+
+ /* Sat in use */
+ buffer = g_strdup_printf("%d", _gps.satinuse);
+ gtk_label_set_label(GTK_LABEL(_sdi_use), buffer);
+ g_free(buffer);
+
+ /* fix */
+ switch(_gps.fix)
+ {
+ case 2:
+ case 3: buffer = g_strdup_printf("%dD fix", _gps.fix); break;
+ default: buffer = g_strdup_printf("nofix"); break;
+ }
+ gtk_label_set_label(GTK_LABEL(_sdi_fix), buffer);
+ g_free(buffer);
+
+ if(_gps.fix == 1)
+ buffer = g_strdup("none");
+ else
+ {
+ switch (_gps.fixquality)
+ {
+ case 1 : buffer = g_strdup_printf(_("SPS")); break;
+ case 2 : buffer = g_strdup_printf(_("DGPS")); break;
+ case 3 : buffer = g_strdup_printf(_("PPS")); break;
+ case 4 : buffer = g_strdup_printf(_("Real Time Kinematic")); break;
+ case 5 : buffer = g_strdup_printf(_("Float RTK")); break;
+ case 6 : buffer = g_strdup_printf(_("Estimated")); break;
+ case 7 : buffer = g_strdup_printf(_("Manual)")); break;
+ case 8 : buffer = g_strdup_printf(_("Simulation")); break;
+ default : buffer = g_strdup_printf(_("none")); break;
+ }
+ }
+ gtk_label_set_label(GTK_LABEL(_sdi_fqu), buffer);
+ g_free(buffer);
+
+ /* max speed */
+ {
+ gfloat maxspeed = _gps.maxspeed * UNITS_CONVERT[_units];
- return (2.f * atan2f(sqrtf(a), sqrtf(1.f - a))) *
- (!strcmp(_units, UNITS_MI) ? EARTH_RADIUS_MI :
- !strcmp(_units, UNITS_NM) ? EARTH_RADIUS_NM :
- EARTH_RADIUS_KM);
+ /* speed */
+ switch(_units)
+ {
+ case UNITS_MI:
+ buffer = g_strdup_printf("%.1f mph", maxspeed);
+ break;
+ case UNITS_NM:
+ buffer = g_strdup_printf("%.1f kn", maxspeed);
+ break;
+ default:
+ buffer = g_strdup_printf("%.1f km/h", maxspeed);
+ break;
+ }
+ gtk_label_set_label(GTK_LABEL(_sdi_msp), buffer);
+ g_free(buffer);
+ }
+
+ /* refresh sat panel */
+ gtk_widget_queue_draw_area(GTK_WIDGET(_sat_details_panel),
+ 0, 0,
+ _sat_details_panel->allocation.width,
+ _sat_details_panel->allocation.height);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
-/**
- * Pop up a modal dialog box with simple error information in it.
- */
static void
-popup_error(GtkWidget *window, const gchar *error)
+gps_display_data(void)
{
- GtkWidget *dialog;
- printf("%s(\"%s\")\n", __PRETTY_FUNCTION__, error);
+ gchar *buffer, strtime[15];
+ printf("%s()\n", __PRETTY_FUNCTION__);
- dialog = hildon_note_new_information(GTK_WINDOW(window), error);
+ if(_gps.fix < 2)
+ {
+ /* no fix no fun */
+ gtk_label_set_label(GTK_LABEL(_text_lat), " --- ");
+ gtk_label_set_label(GTK_LABEL(_text_lon), " --- ");
+ gtk_label_set_label(GTK_LABEL(_text_speed), " --- ");
+ gtk_label_set_label(GTK_LABEL(_text_alt), " --- ");
+ gtk_label_set_label(GTK_LABEL(_text_time), " --:--:-- ");
+ }
+ else
+ {
+ gfloat speed = _gps.speed * UNITS_CONVERT[_units];
- gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(dialog);
+ /* latitude */
+ gtk_label_set_label(GTK_LABEL(_text_lat), _gps.slatitude);
+
+ /* longitude */
+ gtk_label_set_label(GTK_LABEL(_text_lon), _gps.slongitude);
+
+ /* speed */
+ switch(_units)
+ {
+ case UNITS_MI:
+ buffer = g_strdup_printf("Spd: %.1f mph", speed);
+ break;
+ case UNITS_NM:
+ buffer = g_strdup_printf("Spd: %.1f kn", speed);
+ break;
+ default:
+ buffer = g_strdup_printf("Spd: %.1f km/h", speed);
+ break;
+ }
+ gtk_label_set_label(GTK_LABEL(_text_speed), buffer);
+ g_free(buffer);
+
+ /* altitude */
+ switch(_units)
+ {
+ case UNITS_MI:
+ case UNITS_NM:
+ buffer = g_strdup_printf("Alt: %d ft",
+ (guint)(_gps.altitude * 3.2808399f));
+ break;
+ default:
+ buffer = g_strdup_printf("Alt: %d m", _gps.altitude);
+ }
+ gtk_label_set_label(GTK_LABEL(_text_alt), buffer);
+ g_free(buffer);
+
+ /* local time */
+ strftime(strtime, 15, "%X", &_gps.timeloc);
+ gtk_label_set_label(GTK_LABEL(_sdi_tim), strtime);
+ }
+
+ /* refresh sat panel */
+ gtk_widget_queue_draw_area(GTK_WIDGET(_sat_panel),
+ 0, 0,
+ _sat_panel->allocation.width,
+ _sat_panel->allocation.height);
+
+ /* refresh heading panel*/
+ gtk_widget_queue_draw_area(GTK_WIDGET(_heading_panel),
+ 0, 0,
+ _heading_panel->allocation.width,
+ _heading_panel->allocation.height);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return;
}
-/**
- * Set the connection state. This function controls all connection-related
- * banners.
- */
static void
-set_conn_state(ConnState new_conn_state)
+gps_hide_text(void)
{
- printf("%s(%d)\n", __PRETTY_FUNCTION__, new_conn_state);
+ printf("%s()\n", __PRETTY_FUNCTION__);
- switch(_conn_state = new_conn_state)
+ /* Clear gps data */
+ _gps.fix = 1;
+ _gps.satinuse = 0;
+ _gps.satinview = 0;
+
+ if(_gps_info)
+ gps_display_data();
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+static void
+gps_show_info(void)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ if(_gps_info && _enable_gps)
+ gtk_widget_show_all(GTK_WIDGET(_gps_widget));
+ else
{
- case RCVR_OFF:
- case RCVR_FIXED:
- if(_connect_banner)
- {
- gtk_widget_destroy(_connect_banner);
- _connect_banner = NULL;
- }
- if(_fix_banner)
- {
- gtk_widget_destroy(_fix_banner);
- _fix_banner = NULL;
- }
- break;
- case RCVR_DOWN:
- if(_fix_banner)
- {
- gtk_widget_destroy(_fix_banner);
- _fix_banner = NULL;
- }
- if(!_connect_banner)
- _connect_banner = hildon_banner_show_animation(
- _window, NULL, _("Searching for GPS receiver"));
- break;
- case RCVR_UP:
- if(_connect_banner)
- {
- gtk_widget_destroy(_connect_banner);
- _connect_banner = NULL;
- }
- if(!_fix_banner)
- _fix_banner = hildon_banner_show_progress(
- _window, NULL, _("Establishing GPS fix"));
- break;
- default: ; /* to quell warning. */
+ gps_hide_text();
+ gtk_widget_hide_all(GTK_WIDGET(_gps_widget));
}
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * Updates _near_point, _next_way, and _next_wpt. If quick is FALSE (as
- * it is when this function is called from route_find_nearest_point), then
- * the entire list (starting from _near_point) is searched. Otherwise, we
- * stop searching when we find a point that is farther away.
- */
-static gboolean
-route_update_nears(gboolean quick)
+static void
+draw_sat_info(GtkWidget *widget, guint x0, guint y0,
+ guint width, guint height, gboolean showsnr)
{
- gboolean ret = FALSE;
- Point *curr, *near;
- WayPoint *wcurr, *wnext;
- guint near_dist_rough;
- printf("%s(%d)\n", __PRETTY_FUNCTION__, quick);
-
- /* If we have waypoints (_next_way != NULL), then determine the "next
- * waypoint", which is defined as the waypoint after the nearest point,
- * UNLESS we've passed that waypoint, in which case the waypoint after
- * that waypoint becomes the "next" waypoint. */
- if(_next_way)
+ PangoContext *context = NULL;
+ PangoLayout *layout = NULL;
+ PangoFontDescription *fontdesc = NULL;
+ GdkColor color;
+ GdkGC *gc1, *gc2, *gc;
+ guint step, i, j, snr_height, bymargin, xoffset, yoffset;
+ guint x, y, x1, y1;
+ gchar *tmp = NULL;
+
+ xoffset = x0;
+ yoffset = y0;
+ /* Bootom margin - 12% */
+ bymargin = height * 0.88f;
+
+ /* Bottom line */
+ gdk_draw_line(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ xoffset + 5, yoffset + bymargin,
+ xoffset + width - 10 - 2, yoffset + bymargin);
+ gdk_draw_line(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ xoffset + 5, yoffset + bymargin - 1,
+ xoffset + width - 10 - 2, yoffset + bymargin - 1);
+
+ context = gtk_widget_get_pango_context(widget);
+ layout = pango_layout_new(context);
+ fontdesc = pango_font_description_new();
+
+ pango_font_description_set_family(fontdesc,"Sans Serif");
+
+ if(_gps.satinview > 0 )
{
- /* First, set near_dist_rough with the new distance from _near_point. */
- near = _near_point;
- near_dist_rough = DISTANCE_ROUGH(_pos, *near);
+ pango_font_description_set_size(fontdesc, 8*PANGO_SCALE);
- /* Now, search _route for a closer point. If quick is TRUE, then we'll
- * only search forward, only as long as we keep finding closer points.
- */
- for(curr = _near_point; curr++ != _route.tail; )
+ pango_layout_set_font_description (layout, fontdesc);
+ pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+
+ /* Left margin - 5pix, Right margin - 5pix */
+ step = (width - 10) / _gps.satinview;
+
+ color.red = 0;
+ color.green = 0;
+ color.blue = 0;
+ gc1 = gdk_gc_new (widget->window);
+ gdk_gc_set_rgb_fg_color (gc1, &color);
+
+ color.red = 0;
+ color.green = 0;
+ color.blue = 0xffff;
+ gc2 = gdk_gc_new (widget->window);
+ gdk_gc_set_rgb_fg_color (gc2, &color);
+
+ for(i = 0; i < _gps.satinview; i++)
{
- if(curr->unity)
+ /* Sat used or not */
+ gc = gc1;
+ for(j = 0; j < _gps.satinuse ; j++)
{
- guint dist_rough = DISTANCE_ROUGH(_pos, *curr);
- if(dist_rough <= near_dist_rough)
+ if(_gps.satforfix[j] == _gps_sat[i].prn)
{
- near = curr;
- near_dist_rough = dist_rough;
- }
- else if(quick)
+ gc = gc2;
break;
+ }
}
- }
- /* Update _near_point. */
- _near_point = near;
- _near_point_dist_rough = near_dist_rough;
+ x = 5 + i * step;
+ snr_height = _gps_sat[i].snr * height * 0.78f / 100;
+ y = height * 0.1f + (height * 0.78f - snr_height);
- for(wnext = wcurr = _next_way; wcurr != _route.wtail; wcurr++)
- {
- if(wcurr->point < near
- /* Okay, this else if expression warrants explanation. If the
- * nearest track point happens to be a waypoint, then we want to
- * check if we have "passed" that waypoint. To check this, we
- * test the distance from _pos to the waypoint and from _pos to
- * _next_wpt, and if the former is increasing and the latter is
- * decreasing, then we have passed the waypoint, and thus we
- * should skip it. Note that if there is no _next_wpt, then
- * there is no next waypoint, so we do not skip it in that case. */
- || (wcurr->point == near && quick
- && (_next_wpt
- && (DISTANCE_ROUGH(_pos, *near) > _next_way_dist_rough
- && DISTANCE_ROUGH(_pos, *_next_wpt)
- < _next_wpt_dist_rough))))
- wnext = wcurr + 1;
- else
- break;
- }
+ /* draw sat rectangle... */
+ gdk_draw_rectangle(widget->window,
+ gc,
+ TRUE,
+ xoffset + x,
+ yoffset + y,
+ step - 2,
+ snr_height);
- if(wnext == _route.wtail && (wnext->point < near
- || (wnext->point == near && quick
- && (!_next_wpt
- || (DISTANCE_ROUGH(_pos, *near) > _next_way_dist_rough
- &&DISTANCE_ROUGH(_pos, *_next_wpt)
- < _next_wpt_dist_rough)))))
- {
- _next_way = NULL;
- _next_wpt = NULL;
- _next_way_dist_rough = -1;
- _next_wpt_dist_rough = -1;
- ret = TRUE;
- }
- /* Only update _next_way (and consequently _next_wpt) if _next_way is
- * different, and record that fact for return. */
- else
- {
- if(!quick || _next_way != wnext)
+ if(showsnr && _gps_sat[i].snr > 0)
{
- _next_way = wnext;
- _next_wpt = wnext->point;
- if(_next_wpt == _route.tail)
- _next_wpt = NULL;
- else
- {
- while(!(++_next_wpt)->unity)
- {
- if(_next_wpt == _route.tail)
- {
- _next_wpt = NULL;
- break;
- }
- }
- }
- ret = TRUE;
+ /* ...snr.. */
+ tmp = g_strdup_printf("%02d", _gps_sat[i].snr);
+ pango_layout_set_text(layout, tmp, 2);
+ pango_layout_get_pixel_size(layout, &x1, &y1);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ xoffset + x + ((step - 2) - x1)/2,
+ yoffset + y - 15,
+ layout);
+ g_free(tmp);
}
- _next_way_dist_rough = DISTANCE_ROUGH(_pos, *wnext->point);
- if(_next_wpt)
- _next_wpt_dist_rough = DISTANCE_ROUGH(_pos, *_next_wpt);
+
+ /* ...and sat number */
+ tmp = g_strdup_printf("%02d", _gps_sat[i].prn);
+ pango_layout_set_text(layout, tmp, 2);
+ pango_layout_get_pixel_size(layout, &x1, &y1);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ xoffset + x + ((step - 2) - x1)/2 ,
+ yoffset + bymargin + 1,
+ layout);
+ g_free(tmp);
}
+ g_object_unref (gc1);
+ g_object_unref (gc2);
}
- vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, ret);
- return ret;
-}
-
-/**
- * Reset the _near_point data by searching the entire route for the nearest
- * route point and waypoint.
- */
-static void
-route_find_nearest_point()
-{
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- /* Initialize _near_point. */
- _near_point = _route.head;
- while(!_near_point->unity && _near_point != _route.tail)
- _near_point++;
-
- /* Initialize _next_way. */
- if(_route.wtail == _route.whead - 1
- || (_autoroute_data.enabled && _route.wtail == _route.whead))
- _next_way = NULL;
- else
- /* We have at least one waypoint. */
- _next_way = (_autoroute_data.enabled ? _route.whead + 1 : _route.whead);
- _next_way_dist_rough = -1;
-
- /* Initialize _next_wpt. */
- _next_wpt = NULL;
- _next_wpt_dist_rough = -1;
-
- route_update_nears(FALSE);
+ pango_font_description_free (fontdesc);
+ g_object_unref (layout);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return;
}
-/**
- * Render a single track line to _map_pixmap. If either point on the line
- * is a break (defined as unity == 0), a circle is drawn at the other point.
- * IT IS AN ERROR FOR BOTH POINTS TO INDICATE A BREAK.
- */
static void
-map_render_segment(GdkGC *gc_norm, GdkGC *gc_alt,
- guint unitx1, guint unity1, guint unitx2, guint unity2)
+draw_sat_details(GtkWidget *widget, guint x0, guint y0,
+ guint width, guint height)
{
- vprintf("%s()\n", __PRETTY_FUNCTION__);
-
- if(!unity1)
- {
- guint x2, y2;
- x2 = unit2bufx(unitx2);
- y2 = unit2bufy(unity2);
- /* Make sure this circle will be visible. */
- if((x2 < BUF_WIDTH_PIXELS)
- && (y2 < BUF_HEIGHT_PIXELS))
- gdk_draw_arc(_map_pixmap, gc_alt,
- FALSE, /* FALSE: not filled. */
- x2 - _draw_line_width,
- y2 - _draw_line_width,
- 2 * _draw_line_width,
- 2 * _draw_line_width,
- 0, /* start at 0 degrees. */
- 360 * 64);
- }
- else if(!unity2)
+ guint i, j, x, y, size, halfsize, xoffset, yoffset;
+ guint x1, y1;
+ gfloat tmp;
+ GdkColor color;
+ GdkGC *gc1, *gc2, *gc3, *gc;
+ PangoContext *context = NULL;
+ PangoLayout *layout = NULL;
+ PangoFontDescription *fontdesc = NULL;
+ gchar *buffer = NULL;
+
+ size = MIN(width, height);
+ halfsize = size/2;
+ if(width > height)
{
- guint x1, y1;
- x1 = unit2bufx(unitx1);
- y1 = unit2bufy(unity1);
- /* Make sure this circle will be visible. */
- if((x1 < BUF_WIDTH_PIXELS)
- && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
- gdk_draw_arc(_map_pixmap, gc_alt,
- FALSE, /* FALSE: not filled. */
- x1 - _draw_line_width,
- y1 - _draw_line_width,
- 2 * _draw_line_width,
- 2 * _draw_line_width,
- 0, /* start at 0 degrees. */
- 360 * 64);
+ xoffset = x0 + (width - height - 10) / 2;
+ yoffset = y0 + 5;
}
else
{
- gint x1, y1, x2, y2;
- x1 = unit2bufx(unitx1);
- y1 = unit2bufy(unity1);
- x2 = unit2bufx(unitx2);
- y2 = unit2bufy(unity2);
- /* Make sure this line could possibly be visible. */
- if(!((x1 > BUF_WIDTH_PIXELS && x2 > BUF_WIDTH_PIXELS)
- || (x1 < 0 && x2 < 0)
- || (y1 > BUF_HEIGHT_PIXELS && y2 > BUF_HEIGHT_PIXELS)
- || (y1 < 0 && y2 < 0)))
- gdk_draw_line(_map_pixmap, gc_norm, x1, y1, x2, y2);
+ xoffset = x0 + 5;
+ yoffset = y0 + (height - width - 10) / 2;
+ }
+
+ context = gtk_widget_get_pango_context(widget);
+ layout = pango_layout_new(context);
+ fontdesc = pango_font_description_new();
+
+ pango_font_description_set_family(fontdesc,"Sans Serif");
+ pango_font_description_set_size(fontdesc, 10*PANGO_SCALE);
+ pango_layout_set_font_description (layout, fontdesc);
+ pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+
+ /* 90 */
+ gdk_draw_arc(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ FALSE,
+ xoffset + 2, yoffset + 2, size - 4, size - 4,
+ 0, 64 * 360);
+
+ /* 60 */
+ gdk_draw_arc(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ FALSE,
+ xoffset + size/6, yoffset + size/6,
+ size/6*4, size/6*4,
+ 0, 64 * 360);
+
+ /* 30 */
+ gdk_draw_arc(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ FALSE,
+ xoffset + size/6*2, yoffset + size/6*2,
+ size/6*2, size/6*2,
+ 0, 64 * 360);
+
+ guint line[12] = {0,30,60,90,120,150,180,210,240,270,300,330};
+
+ for(i = 0; i < 6; i++)
+ {
+ /* line */
+ tmp = (line[i] * (1.f / 180.f)) * PI;
+ gdk_draw_line(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ xoffset + halfsize + (halfsize -2) * sinf(tmp),
+ yoffset + halfsize - (halfsize -2) * cosf(tmp),
+ xoffset + halfsize - (halfsize -2) * sinf(tmp),
+ yoffset + halfsize + (halfsize -2) * cosf(tmp));
}
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
-
-/**
- * Render all track data onto the _map_pixmap. Note that this does not
- * clear the pixmap of previous track data (use map_force_redraw() for
- * that), and also note that this method does not queue any redraws, so it
- * is up to the caller to decide which part of the track really needs to be
- * redrawn.
- */
-static void
-map_render_track()
-{
- TrackPoint *curr;
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- for(curr = _track.head; curr != _track.tail; curr++)
- map_render_segment(_gc_track, _gc_track_break,
- curr->point.unitx, curr->point.unity,
- curr[1].point.unitx, curr[1].point.unity);
-
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
-
-/**
- * Render all track data onto the _map_pixmap. Note that this does not
- * clear the pixmap of previous track data (use map_force_redraw() for
- * that), and also note that this method does not queue any redraws, so it
- * is up to the caller to decide which part of the track really needs to be
- * redrawn.
- */
-static void
-map_render_route()
-{
- Point *curr;
- WayPoint *wcurr;
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- _visible_way_first = _visible_way_last = NULL;
- for(curr = _route.head, wcurr = _route.whead; curr != _route.tail; curr++)
+ for(i = 0; i < 12; i++)
{
- if(wcurr <= _route.wtail && curr == wcurr->point)
- {
- guint x1 = unit2bufx(wcurr->point->unitx);
- guint y1 = unit2bufy(wcurr->point->unity);
- if((x1 < BUF_WIDTH_PIXELS)
- && (y1 < BUF_HEIGHT_PIXELS))
- {
- gdk_draw_arc(_map_pixmap,
- (wcurr==_next_way ? _gc_route_nextway : _gc_route_way),
- FALSE, /* FALSE: not filled. */
- x1 - _draw_line_width,
- y1 - _draw_line_width,
- 2 * _draw_line_width,
- 2 * _draw_line_width,
- 0, /* start at 0 degrees. */
- 360 * 64);
- if(!_visible_way_first)
- _visible_way_first = wcurr;
- _visible_way_last = wcurr;
- }
- wcurr++;
- if(!curr[1].unity)
- continue;
- }
- map_render_segment(_gc_route, _gc_route_way,
- curr->unitx, curr->unity, curr[1].unitx, curr[1].unity);
+ tmp = (line[i] * (1.f / 180.f)) * PI;
+ /* azimuth */
+ if(line[i] == 0)
+ buffer = g_strdup_printf("N");
+ else
+ buffer = g_strdup_printf("%d\u00b0", line[i]);
+ pango_layout_set_text(layout, buffer, strlen(buffer));
+ pango_layout_get_pixel_size(layout, &x, &y);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ (xoffset + halfsize + (halfsize - size/12) * sinf(tmp)) - x/2,
+ (yoffset + halfsize - (halfsize - size/12) * cosf(tmp)) - y/2,
+ layout);
+ g_free(buffer);
}
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
-
-static void
-map_render_paths()
-{
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- if((_show_tracks & ROUTES_MASK) && _route.head)
+ /* elevation 30 */
+ tmp = (30 * (1.f / 180.f)) * PI;
+ buffer = g_strdup_printf("30\u00b0");
+ pango_layout_set_text(layout, buffer, strlen(buffer));
+ pango_layout_get_pixel_size(layout, &x, &y);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ (xoffset + halfsize + size/6*2 * sinf(tmp)) - x/2,
+ (yoffset + halfsize - size/6*2 * cosf(tmp)) - y/2,
+ layout);
+ g_free(buffer);
+
+ /* elevation 60 */
+ tmp = (30 * (1.f / 180.f)) * PI;
+ buffer = g_strdup_printf("60\u00b0");
+ pango_layout_set_text(layout, buffer, strlen(buffer));
+ pango_layout_get_pixel_size(layout, &x, &y);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ (xoffset + halfsize + size/6 * sinf(tmp)) - x/2,
+ (yoffset + halfsize - size/6 * cosf(tmp)) - y/2,
+ layout);
+ g_free(buffer);
+
+ color.red = 0;
+ color.green = 0;
+ color.blue = 0;
+ gc1 = gdk_gc_new (widget->window);
+ gdk_gc_set_rgb_fg_color (gc1, &color);
+
+ color.red = 0;
+ color.green = 0;
+ color.blue = 0xffff;
+ gc2 = gdk_gc_new (widget->window);
+ gdk_gc_set_rgb_fg_color (gc2, &color);
+
+ color.red = 0xffff;
+ color.green = 0xffff;
+ color.blue = 0xffff;
+ gc3 = gdk_gc_new (widget->window);
+ gdk_gc_set_rgb_fg_color (gc3, &color);
+
+ for(i = 0; i < _gps.satinview; i++)
{
- map_render_route();
- if(_next_way == NULL)
+ /* satellite track */
+ tmp = (_gps_sat[i].azimuth * (1.f / 180.f)) * PI;
+ x = xoffset + halfsize + (90 - _gps_sat[i].elevation)
+ * halfsize / 90 * sinf(tmp);
+ y = yoffset + halfsize - (90 - _gps_sat[i].elevation)
+ * halfsize/90 * cosf(tmp);
+ gdk_draw_point (widget->window, gc2, x, y);
+
+ /* Sat used or not */
+ gc = gc1;
+ for(j = 0; j < _gps.satinuse ; j++)
{
- guint x1 = unit2bufx(_route.tail[-1].unitx);
- guint y1 = unit2bufy(_route.tail[-1].unity);
- if((x1 < BUF_WIDTH_PIXELS)
- && (y1 < BUF_HEIGHT_PIXELS))
+ if(_gps.satforfix[j] == _gps_sat[i].prn)
{
- gdk_draw_arc(_map_pixmap,
- _gc_route_nextway,
- FALSE, /* FALSE: not filled. */
- x1 - _draw_line_width,
- y1 - _draw_line_width,
- 2 * _draw_line_width,
- 2 * _draw_line_width,
- 0, /* start at 0 degrees. */
- 360 * 64);
+ gc = gc2;
+ break;
}
}
+
+ tmp = (_gps_sat[i].azimuth * (1.f / 180.f)) * PI;
+ x = xoffset + halfsize
+ + (90 - _gps_sat[i].elevation)*halfsize/90 * sinf(tmp);
+ y = yoffset + halfsize
+ - (90 - _gps_sat[i].elevation)*halfsize/90 * cosf(tmp);
+
+ gdk_draw_arc (widget->window,
+ gc, TRUE,
+ x - 10, y - 10, 20, 20,
+ 0, 64 * 360);
+
+ buffer = g_strdup_printf("%02d", _gps_sat[i].prn);
+ pango_layout_set_text(layout, buffer, strlen(buffer));
+ pango_layout_get_pixel_size(layout, &x1, &y1);
+ gdk_draw_layout(widget->window,
+ gc3,
+ x - x1/2,
+ y - y1/2,
+ layout);
+ g_free(buffer);
}
- if(_show_tracks & TRACKS_MASK)
- map_render_track();
+ g_object_unref (gc1);
+ g_object_unref (gc2);
+ g_object_unref (gc3);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ pango_font_description_free (fontdesc);
+ g_object_unref (layout);
+
+ return;
}
-static void
-track_resize(Track *track, guint size)
-{
- printf("%s()\n", __PRETTY_FUNCTION__);
- if(track->head + size != track->cap)
- {
- TrackPoint *old_head = track->head;
- track->head = g_renew(TrackPoint, old_head, size);
- track->cap = track->head + size;
- if(track->head != old_head)
- track->tail = track->head + (track->tail - old_head);
- }
+static gboolean
+sat_details_panel_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+ guint width, height, x, y;
+ PangoContext *context = NULL;
+ PangoLayout *layout = NULL;
+ PangoFontDescription *fontdesc = NULL;
+ gchar *buffer = NULL;
+
+ width = widget->allocation.width;
+ height = widget->allocation.height * 0.9;
+
+ draw_sat_info(widget, 0, 0, width/2, height, TRUE);
+ draw_sat_details(widget, width/2, 0, width/2, height);
+
+ context = gtk_widget_get_pango_context(widget);
+ layout = pango_layout_new(context);
+ fontdesc = pango_font_description_new();
+
+ pango_font_description_set_family(fontdesc,"Sans Serif");
+ pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+ pango_font_description_set_size(fontdesc, 14*PANGO_SCALE);
+ pango_layout_set_font_description (layout, fontdesc);
+
+ buffer = g_strdup_printf(
+ _("Satellites in view: %d; in use: %d"),
+ _gps.satinview,
+ _gps.satinuse);
+ pango_layout_set_text(layout, buffer, strlen(buffer));
+ pango_layout_get_pixel_size(layout, &x, &y);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ 10,
+ height*0.9 + 10,
+ layout);
+ g_free(buffer);
+
+ buffer = g_strdup_printf(_("HDOP: %.01f"), _gps.hdop);
+ pango_layout_set_text(layout, buffer, strlen(buffer));
+ pango_layout_get_pixel_size(layout, &x, &y);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ (width/8) - x/2,
+ (height/6) - y/2,
+ layout);
+ g_free(buffer);
+ buffer = g_strdup_printf(_("PDOP: %.01f"), _gps.pdop);
+ pango_layout_set_text(layout, buffer, strlen(buffer));
+ pango_layout_get_pixel_size(layout, &x, &y);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ (width/8) - x/2,
+ (height/6) - y/2 + 20,
+ layout);
+ g_free(buffer);
+ buffer = g_strdup_printf(_("VDOP: %.01f"), _gps.vdop);
+ pango_layout_set_text(layout, buffer, strlen(buffer));
+ pango_layout_get_pixel_size(layout, &x, &y);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ (width/8) - x/2,
+ (height/6) - y/2 + 40,
+ layout);
+ g_free(buffer);
+
+ pango_font_description_free (fontdesc);
+ g_object_unref (layout);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
static void
-route_resize(Route *route, guint size)
+gps_details(void)
{
+ GtkWidget *dialog;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *notebook;
printf("%s()\n", __PRETTY_FUNCTION__);
- if(route->head + size != route->cap)
- {
- Point *old_head = route->head;
- WayPoint *curr;
- route->head = g_renew(Point, old_head, size);
- route->cap = route->head + size;
- if(route->head != old_head)
- {
- route->tail = route->head + (route->tail - old_head);
+ dialog = gtk_dialog_new_with_buttons(_("GPS Details"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
- /* Adjust all of the waypoints. */
- for(curr = route->whead - 1; curr++ != route->wtail; )
- curr->point = route->head + (curr->point - old_head);
- }
- }
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 600, 300);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ notebook = gtk_notebook_new(), TRUE, TRUE, 0);
-static void
-route_wresize(Route *route, guint wsize)
-{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ /* textual info */
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ table = gtk_table_new(4, 6, FALSE),
+ label = gtk_label_new(_("GPS Information")));
- if(route->whead + wsize != route->wcap)
+ _sat_details_panel = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (_sat_details_panel, 300, 300);
+ /* sat details info */
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ _sat_details_panel,
+ label = gtk_label_new(_("Satellites details")));
+ g_signal_connect (G_OBJECT (_sat_details_panel), "expose_event",
+ G_CALLBACK (sat_details_panel_expose), NULL);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Latitude")),
+ 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_lat = gtk_label_new(" --- "),
+ 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_lat), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Longitude")),
+ 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_lon = gtk_label_new(" --- "),
+ 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_lon), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Speed")),
+ 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_spd = gtk_label_new(" --- "),
+ 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_spd), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Altitude")),
+ 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_alt = gtk_label_new(" --- "),
+ 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_alt), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Heading")),
+ 0, 1, 4, 5, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_hea = gtk_label_new(" --- "),
+ 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_hea), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Local time")),
+ 0, 1, 5, 6, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_tim = gtk_label_new(_(" --:--:-- ")),
+ 1, 2, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_tim), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Sat in view")),
+ 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_vie = gtk_label_new("0"),
+ 3, 4, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_vie), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Sat in use")),
+ 2, 3, 1, 2, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_use = gtk_label_new("0"),
+ 3, 4, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_use), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Fix")),
+ 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_fix = gtk_label_new(_("nofix")),
+ 3, 4, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_fix), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Fix Quality")),
+ 2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_fqu = gtk_label_new(_("none")),
+ 3, 4, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_fix), 0.f, 0.5f);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Max speed")),
+ 2, 3, 5, 6, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ _sdi_msp = gtk_label_new(" --- "),
+ 3, 4, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(_sdi_msp), 0.f, 0.5f);
+
+ gtk_widget_show_all(dialog);
+ _satdetails_on = TRUE;
+ gps_display_details();
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
{
- WayPoint *old_whead = route->whead;
- route->whead = g_renew(WayPoint, old_whead, wsize);
- route->wtail = route->whead + (route->wtail - old_whead);
- route->wcap = route->whead + wsize;
+ _satdetails_on = FALSE;
+ break;
}
+ gtk_widget_destroy(dialog);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-#define MACRO_TRACK_INCREMENT_TAIL(track) { \
- if(++(track).tail == (track).cap) \
- track_resize(&(track), (track).cap - (track).head + ARRAY_CHUNK_SIZE); \
-}
+static gfloat
+calculate_distance(gfloat lat1, gfloat lon1, gfloat lat2, gfloat lon2)
+{
+ gfloat dlat, dlon, slat, slon, a;
-#define MACRO_ROUTE_INCREMENT_TAIL(route) { \
- if(++(route).tail == (route).cap) \
- route_resize(&(route), (route).cap - (route).head + ARRAY_CHUNK_SIZE); \
-}
+ /* Convert to radians. */
+ lat1 *= (PI / 180.f);
+ lon1 *= (PI / 180.f);
+ lat2 *= (PI / 180.f);
+ lon2 *= (PI / 180.f);
-#define MACRO_ROUTE_INCREMENT_WTAIL(route) { \
- if(++(route).wtail == (route).wcap) \
- route_wresize(&(route), \
- (route).wcap - (route).whead + ARRAY_CHUNK_SIZE); \
+ dlat = lat2 - lat1;
+ dlon = lon2 - lon1;
+
+ slat = sinf(dlat / 2.f);
+ slon = sinf(dlon / 2.f);
+ a = (slat * slat) + (cosf(lat1) * cosf(lat2) * slon * slon);
+
+ return ((2.f * atan2f(sqrtf(a), sqrtf(1.f - a))) * EARTH_RADIUS)
+ * UNITS_CONVERT[_units];
}
/**
- * Add a point to the _track list. This function is slightly overloaded,
- * since it is what houses the check for "have we moved
- * significantly": it also initiates the re-calculation of the _near_point
- * data, as well as calling osso_display_state_on() when we have the focus.
- *
- * If a non-zero time is given, then the current position (as taken from the
- * _pos variable) is appended to _track with the given time. If time is zero,
- * then _pos_null is appended to _track with time zero (this produces a "break"
- * in the track).
+ * Pop up a modal dialog box with simple error information in it.
*/
static void
-track_add(time_t time, gboolean newly_fixed)
+popup_error(GtkWidget *window, const gchar *error)
{
- Point pos = (time == 0 ? _pos_null : _pos);
- printf("%s(%u, %u)\n", __PRETTY_FUNCTION__, pos.unitx, pos.unity);
-
- if(abs((gint)pos.unitx - _track.tail->point.unitx) > _draw_line_width
- || abs((gint)pos.unity - _track.tail->point.unity) > _draw_line_width)
- {
- if(time && _route.head
- && (newly_fixed ? (route_find_nearest_point(), TRUE)
- : route_update_nears(TRUE)))
- {
- map_render_paths();
- MACRO_QUEUE_DRAW_AREA();
- }
- if(_show_tracks & TRACKS_MASK)
- {
- /* Instead of calling map_render_paths(), we'll draw the new line
- * ourselves and call gtk_widget_queue_draw_area(). */
- gint tx1, ty1, tx2, ty2;
- map_render_segment(_gc_track, _gc_track_break,
- _track.tail->point.unitx, _track.tail->point.unity,
- pos.unitx, pos.unity);
- if(time && _track.tail->point.unity)
- {
- tx1 = unit2x(_track.tail->point.unitx);
- ty1 = unit2y(_track.tail->point.unity);
- tx2 = unit2x(pos.unitx);
- ty2 = unit2y(pos.unity);
- gtk_widget_queue_draw_area(_map_widget,
- MIN(tx1, tx2) - _draw_line_width,
- MIN(ty1, ty2) - _draw_line_width,
- abs(tx1 - tx2) + (2 * _draw_line_width),
- abs(ty1 - ty2) + (2 * _draw_line_width));
- }
- }
- MACRO_TRACK_INCREMENT_TAIL(_track);
-
- _track.tail->point = pos;
- _track.tail->time = time;
-
- if(_autoroute_data.enabled && !_autoroute_data.in_progress
- && _near_point_dist_rough > 400)
- {
- _autoroute_data.in_progress = TRUE;
- g_idle_add((GSourceFunc)auto_route_dl_idle, NULL);
- }
+ GtkWidget *dialog;
+ printf("%s(\"%s\")\n", __PRETTY_FUNCTION__, error);
- /* Keep the display on. */
- KEEP_DISPLAY_ON();
- }
+ dialog = hildon_note_new_information(GTK_WINDOW(window), error);
- /* Check if we should announce upcoming waypoints. */
- if(time && _next_way_dist_rough
- < (10 + (guint)_speed) * _announce_notice_ratio * 5)
- {
- if(_enable_voice && strcmp(_next_way->desc, _last_spoken_phrase))
- {
- g_free(_last_spoken_phrase);
- _last_spoken_phrase = g_strdup(_next_way->desc);
- printf("Sending to flite: %s\n", _last_spoken_phrase);
- hildon_play_system_sound(
- "/usr/share/sounds/ui-information_note.wav");
- osso_rpc_async_run(_osso,
- "com.nokia.flite",
- "/com/nokia/flite",
- "com.nokia.flite",
- "flite_tts",
- NULL,
- NULL,
- DBUS_TYPE_UINT32,
- getpid(),
- DBUS_TYPE_STRING,
- _last_spoken_phrase,
- DBUS_TYPE_UINT32,
- 18,
- DBUS_TYPE_DOUBLE,
- _voice_speed,
- DBUS_TYPE_DOUBLE,
- _voice_pitch,
- DBUS_TYPE_STRING,
- g_strdup("cmu_us_kal"),
- DBUS_TYPE_INVALID);
- }
- hildon_banner_show_information(_window, NULL, _next_way->desc);
- }
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * Disconnect from the receiver. This method cleans up any and everything
- * that might be associated with the receiver.
- */
static void
-rcvr_disconnect()
+db_connect()
{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ gchar buffer[100];
+ gchar *perror;
+ gchar **pszResult;
+ guint nRow, nColumn;
- /* Remove watches. */
- if(_clater_sid)
- {
- g_source_remove(_clater_sid);
- _clater_sid = 0;
- }
- if(_error_sid)
- {
- g_source_remove(_error_sid);
- _error_sid = 0;
- }
- if(_connect_sid)
- {
- g_source_remove(_connect_sid);
- _connect_sid = 0;
- }
- if(_input_sid)
- {
- g_source_remove(_input_sid);
- _input_sid = 0;
- }
+ _dbconn = FALSE;
- /* Destroy the GIOChannel object. */
- if(_channel)
+ if(!_poi_db)
+ return;
+
+ if((_db = sqlite_open(_poi_db, 0666, &perror)) == NULL)
{
- g_io_channel_shutdown(_channel, FALSE, NULL);
- g_io_channel_unref(_channel);
- _channel = NULL;
+ gchar buffer2[200];
+ sprintf(buffer2, "%s: %s", _("Problem with POI database"), perror);
+ popup_error(_window, buffer2);
+ g_free(perror);
+ return;
}
- /* Close the file descriptor. */
- if(_fd != -1)
+ if(sqlite_get_table(_db, "select label from poi limit 1",
+ &pszResult, &nRow, &nColumn, NULL) != SQLITE_OK)
{
- close(_fd);
- _fd = -1;
+ if(SQLITE_OK != sqlite_exec(_db,
+ "create table poi (poi_id integer PRIMARY KEY, lat real, "
+ "lon real, label text, desc text, cat_id integer);"
+ "create table category (cat_id integer PRIMARY KEY,"
+ "label text, desc text, enabled integer);"
+ "insert into category (label, desc, enabled) "
+ "values ('Fuel',"
+ "'Stations for purchasing fuel for vehicles.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Residence', "
+ "'Houses, apartments, or other residences of import.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Dining', "
+ "'Places to eat or drink.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Shopping/Services', "
+ "'Places to shop or acquire services.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Recreation', "
+ "'Indoor or Outdoor places to have fun.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Transportation', "
+ "'Bus stops, airports, train stations, etc.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Lodging', "
+ "'Places to stay temporarily or for the night.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('School', "
+ "'Elementary schools, college campuses, etc.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Business', "
+ "'General places of business.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Landmark', "
+ "'General landmarks.', 1);"
+ "insert into category (label, desc, enabled) "
+ "values ('Other', "
+ "'Miscellaneous category for everything else.', 1);",
+ NULL,
+ NULL,
+ &perror)
+ && (sqlite_get_table(_db, "select label from poi limit 1",
+ &pszResult, &nRow, &nColumn, NULL) != SQLITE_OK))
+ {
+ sprintf(buffer, _("Failed to open or create database:\n%s"),
+ _poi_db);
+ popup_error(_window, buffer);
+ sqlite_close(_db);
+ return;
+ }
}
+ else
+ sqlite_free_table(pszResult);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ _dbconn = TRUE;
}
-static void rcvr_connect_later(); /* Forward declaration. */
-
/**
- * Connect to the receiver.
- * This method assumes that _fd is -1 and _channel is NULL. If unsure, call
- * rcvr_disconnect() first.
- * Since this is an idle function, this function returns whether or not it
- * should be called again, which is always FALSE.
+ * Set the connection state. This function controls all connection-related
+ * banners.
*/
-static gboolean
-rcvr_connect_now()
+static void
+set_conn_state(ConnState new_conn_state)
{
- printf("%s(%d)\n", __PRETTY_FUNCTION__, _conn_state);
-
- if(_conn_state == RCVR_DOWN && _rcvr_mac) {
-#ifndef DEBUG
- /* Create the file descriptor. */
- if(*_rcvr_mac == '/')
- _fd = open(_rcvr_mac, O_RDONLY);
- else
- _fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+ printf("%s(%d)\n", __PRETTY_FUNCTION__, new_conn_state);
- /* If file descriptor creation failed, try again later. Note that
- * there is no need to call rcvr_disconnect() because the file
- * descriptor creation is the first step, so if it fails, there's
- * nothing to clean up. */
- if(_fd == -1)
- rcvr_connect_later();
- else
- {
- _channel = g_io_channel_unix_new(_fd);
- g_io_channel_set_flags(_channel, G_IO_FLAG_NONBLOCK, NULL);
- _error_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
- G_IO_ERR | G_IO_HUP, channel_cb_error, NULL, NULL);
- _connect_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
- G_IO_OUT, channel_cb_connect, NULL, NULL);
- if(*_rcvr_mac != '/'
- && connect(_fd, (struct sockaddr*)&_rcvr_addr,
- sizeof(_rcvr_addr))
- && errno != EAGAIN)
+ switch(_conn_state = new_conn_state)
+ {
+ case RCVR_OFF:
+ case RCVR_FIXED:
+ if(_connect_banner)
{
- /* Connection failed. Disconnect and try again later. */
- rcvr_disconnect();
- rcvr_connect_later();
+ gtk_widget_destroy(_connect_banner);
+ _connect_banner = NULL;
}
- }
-#else
- /* We're in DEBUG mode, so instead of connecting, skip to FIXED. */
- set_conn_state(RCVR_FIXED);
-#endif
+ if(_fix_banner)
+ {
+ gtk_widget_destroy(_fix_banner);
+ _fix_banner = NULL;
+ }
+ break;
+ case RCVR_DOWN:
+ if(_fix_banner)
+ {
+ gtk_widget_destroy(_fix_banner);
+ _fix_banner = NULL;
+ }
+ if(!_connect_banner)
+ _connect_banner = hildon_banner_show_animation(
+ _window, NULL, _("Searching for GPS receiver"));
+ break;
+ case RCVR_UP:
+ if(_connect_banner)
+ {
+ gtk_widget_destroy(_connect_banner);
+ _connect_banner = NULL;
+ }
+ if(!_fix_banner)
+ _fix_banner = hildon_banner_show_progress(
+ _window, NULL, _("Establishing GPS fix"));
+ break;
+ default: ; /* to quell warning. */
}
- _clater_sid = 0;
-
- vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
- return FALSE;
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Place a request to connect about 1 second after the function is called.
+ * Updates _near_point, _next_way, and _next_wpt. If quick is FALSE (as
+ * it is when this function is called from route_find_nearest_point), then
+ * the entire list (starting from _near_point) is searched. Otherwise, we
+ * stop searching when we find a point that is farther away.
*/
-static void
-rcvr_connect_later()
+static gboolean
+route_update_nears(gboolean quick)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ gboolean ret = FALSE;
+ Point *curr, *near;
+ WayPoint *wcurr, *wnext;
+ guint near_dist_rough;
+ printf("%s(%d)\n", __PRETTY_FUNCTION__, quick);
+
+ /* If we have waypoints (_next_way != NULL), then determine the "next
+ * waypoint", which is defined as the waypoint after the nearest point,
+ * UNLESS we've passed that waypoint, in which case the waypoint after
+ * that waypoint becomes the "next" waypoint. */
+ if(_next_way)
+ {
+ /* First, set near_dist_rough with the new distance from _near_point. */
+ near = _near_point;
+ near_dist_rough = DISTANCE_ROUGH(_pos, *near);
- _clater_sid = g_timeout_add(1000, (GSourceFunc)rcvr_connect_now, NULL);
+ /* Now, search _route for a closer point. If quick is TRUE, then we'll
+ * only search forward, only as long as we keep finding closer points.
+ */
+ for(curr = _near_point; curr++ != _route.tail; )
+ {
+ if(curr->unity)
+ {
+ guint dist_rough = DISTANCE_ROUGH(_pos, *curr);
+ if(dist_rough <= near_dist_rough)
+ {
+ near = curr;
+ near_dist_rough = dist_rough;
+ }
+ else if(quick)
+ break;
+ }
+ }
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ /* Update _near_point. */
+ _near_point = near;
+ _near_point_dist_rough = near_dist_rough;
+
+ for(wnext = wcurr = _next_way; wcurr != _route.wtail; wcurr++)
+ {
+ if(wcurr->point < near
+ /* Okay, this else if expression warrants explanation. If the
+ * nearest track point happens to be a waypoint, then we want to
+ * check if we have "passed" that waypoint. To check this, we
+ * test the distance from _pos to the waypoint and from _pos to
+ * _next_wpt, and if the former is increasing and the latter is
+ * decreasing, then we have passed the waypoint, and thus we
+ * should skip it. Note that if there is no _next_wpt, then
+ * there is no next waypoint, so we do not skip it in that case. */
+ || (wcurr->point == near && quick
+ && (_next_wpt
+ && (DISTANCE_ROUGH(_pos, *near) > _next_way_dist_rough
+ && DISTANCE_ROUGH(_pos, *_next_wpt)
+ < _next_wpt_dist_rough))))
+ wnext = wcurr + 1;
+ else
+ break;
+ }
+
+ if(wnext == _route.wtail && (wnext->point < near
+ || (wnext->point == near && quick
+ && (!_next_wpt
+ || (DISTANCE_ROUGH(_pos, *near) > _next_way_dist_rough
+ &&DISTANCE_ROUGH(_pos, *_next_wpt)
+ < _next_wpt_dist_rough)))))
+ {
+ _next_way = NULL;
+ _next_wpt = NULL;
+ _next_way_dist_rough = -1;
+ _next_wpt_dist_rough = -1;
+ ret = TRUE;
+ }
+ /* Only update _next_way (and consequently _next_wpt) if _next_way is
+ * different, and record that fact for return. */
+ else
+ {
+ if(!quick || _next_way != wnext)
+ {
+ _next_way = wnext;
+ _next_wpt = wnext->point;
+ if(_next_wpt == _route.tail)
+ _next_wpt = NULL;
+ else
+ {
+ while(!(++_next_wpt)->unity)
+ {
+ if(_next_wpt == _route.tail)
+ {
+ _next_wpt = NULL;
+ break;
+ }
+ }
+ }
+ ret = TRUE;
+ }
+ _next_way_dist_rough = DISTANCE_ROUGH(_pos, *wnext->point);
+ if(_next_wpt)
+ _next_wpt_dist_rough = DISTANCE_ROUGH(_pos, *_next_wpt);
+ }
+ }
+
+ vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, ret);
+ return ret;
}
/**
- * Convert the float lat/lon/speed/heading data into integer units.
+ * Reset the _near_point data by searching the entire route for the nearest
+ * route point and waypoint.
*/
static void
-integerize_data()
+route_find_nearest_point()
{
- gfloat tmp;
printf("%s()\n", __PRETTY_FUNCTION__);
- latlon2unit(_pos_lat, _pos_lon, _pos.unitx, _pos.unity);
+ /* Initialize _near_point. */
+ _near_point = _route.head;
+ while(!_near_point->unity && _near_point != _route.tail)
+ _near_point++;
- tmp = (_heading * (1.f / 180.f)) * PI;
- _vel_offsetx = (gint)(floorf(_speed * sinf(tmp) + 0.5f));
- _vel_offsety = -(gint)(floorf(_speed * cosf(tmp) + 0.5f));
+ /* Initialize _next_way. */
+ if(_route.wtail == _route.whead - 1
+ || (_autoroute_data.enabled && _route.wtail == _route.whead))
+ _next_way = NULL;
+ else
+ /* We have at least one waypoint. */
+ _next_way = (_autoroute_data.enabled ? _route.whead + 1 : _route.whead);
+ _next_way_dist_rough = -1;
+
+ /* Initialize _next_wpt. */
+ _next_wpt = NULL;
+ _next_wpt_dist_rough = -1;
+
+ route_update_nears(FALSE);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Update all GdkGC objects to reflect the current _draw_line_width.
+ * Render a single track line to _map_pixmap. If either point on the line
+ * is a break (defined as unity == 0), a circle is drawn at the other point.
+ * IT IS AN ERROR FOR BOTH POINTS TO INDICATE A BREAK.
*/
-#define UPDATE_GC(gc) \
- gdk_gc_set_line_attributes(gc, \
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
static void
-update_gcs()
+map_render_segment(GdkGC *gc_norm, GdkGC *gc_alt,
+ guint unitx1, guint unity1, guint unitx2, guint unity2)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
- &_color_mark);
- gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
- &_color_mark_velocity);
- gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
- &_color_mark_old);
- gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
- &_color_track);
- gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
- &_color_track_break);
- gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
- &_color_route);
- gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
- &_color_route_way);
- gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
- &_color_route_nextway);
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
- if(_gc_mark)
+ if(!unity1)
{
- g_object_unref(_gc_mark);
- g_object_unref(_gc_mark_velocity);
- g_object_unref(_gc_mark_old);
- g_object_unref(_gc_track);
- g_object_unref(_gc_track_break);
- g_object_unref(_gc_route);
- g_object_unref(_gc_route_way);
- g_object_unref(_gc_route_nextway);
+ guint x2, y2;
+ x2 = unit2bufx(unitx2);
+ y2 = unit2bufy(unity2);
+ /* Make sure this circle will be visible. */
+ if((x2 < BUF_WIDTH_PIXELS)
+ && (y2 < BUF_HEIGHT_PIXELS))
+ gdk_draw_arc(_map_pixmap, gc_alt,
+ FALSE, /* FALSE: not filled. */
+ x2 - _draw_line_width,
+ y2 - _draw_line_width,
+ 2 * _draw_line_width,
+ 2 * _draw_line_width,
+ 0, /* start at 0 degrees. */
+ 360 * 64);
+ }
+ else if(!unity2)
+ {
+ guint x1, y1;
+ x1 = unit2bufx(unitx1);
+ y1 = unit2bufy(unity1);
+ /* Make sure this circle will be visible. */
+ if((x1 < BUF_WIDTH_PIXELS)
+ && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
+ gdk_draw_arc(_map_pixmap, gc_alt,
+ FALSE, /* FALSE: not filled. */
+ x1 - _draw_line_width,
+ y1 - _draw_line_width,
+ 2 * _draw_line_width,
+ 2 * _draw_line_width,
+ 0, /* start at 0 degrees. */
+ 360 * 64);
+ }
+ else
+ {
+ gint x1, y1, x2, y2;
+ x1 = unit2bufx(unitx1);
+ y1 = unit2bufy(unity1);
+ x2 = unit2bufx(unitx2);
+ y2 = unit2bufy(unity2);
+ /* Make sure this line could possibly be visible. */
+ if(!((x1 > BUF_WIDTH_PIXELS && x2 > BUF_WIDTH_PIXELS)
+ || (x1 < 0 && x2 < 0)
+ || (y1 > BUF_HEIGHT_PIXELS && y2 > BUF_HEIGHT_PIXELS)
+ || (y1 < 0 && y2 < 0)))
+ gdk_draw_line(_map_pixmap, gc_norm, x1, y1, x2, y2);
}
- /* _gc_mark is used to draw the mark when data is current. */
- _gc_mark = gdk_gc_new(_map_pixmap);
- gdk_gc_set_foreground(_gc_mark, &_color_mark);
- gdk_gc_set_line_attributes(_gc_mark,
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
- /* _gc_mark_old is used to draw the mark when data is old. */
- _gc_mark_old = gdk_gc_new(_map_pixmap);
- gdk_gc_set_foreground(_gc_mark_old, &_color_mark_old);
- gdk_gc_set_line_attributes(_gc_mark_old,
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
- /* _gc_mark_velocity is used to draw the vel_current line. */
- _gc_mark_velocity = gdk_gc_new(_map_pixmap);
- gdk_gc_set_foreground(_gc_mark_velocity, &_color_mark_velocity);
- gdk_gc_set_line_attributes(_gc_mark_velocity,
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
- /* _gc_track is used to draw the track line. */
- _gc_track = gdk_gc_new(_map_pixmap);
- gdk_gc_set_foreground(_gc_track, &_color_track);
- gdk_gc_set_line_attributes(_gc_track,
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
- /* _gc_track_break is used to draw the track_break dots. */
- _gc_track_break = gdk_gc_new(_map_pixmap);
- gdk_gc_set_foreground(_gc_track_break, &_color_track_break);
- gdk_gc_set_line_attributes(_gc_track_break,
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
- /* _gc_route is used to draw the route line. */
- _gc_route = gdk_gc_new(_map_pixmap);
- gdk_gc_set_foreground(_gc_route, &_color_route);
- gdk_gc_set_line_attributes(_gc_route,
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- /* _way_gc is used to draw the waypoint dots. */
- _gc_route_way = gdk_gc_new(_map_pixmap);
- gdk_gc_set_foreground(_gc_route_way, &_color_route_way);
- gdk_gc_set_line_attributes(_gc_route_way,
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+/**
+ * Render all track data onto the _map_pixmap. Note that this does not
+ * clear the pixmap of previous track data (use map_force_redraw() for
+ * that), and also note that this method does not queue any redraws, so it
+ * is up to the caller to decide which part of the track really needs to be
+ * redrawn.
+ */
+static void
+map_render_track()
+{
+ TrackPoint *curr;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* _gc_route_nextway is used to draw the next_way labels. */
- _gc_route_nextway = gdk_gc_new(_map_pixmap);
- gdk_gc_set_foreground(_gc_route_nextway, &_color_route_nextway);
- gdk_gc_set_line_attributes(_gc_route_nextway,
- _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+ for(curr = _track.head; curr != _track.tail; curr++)
+ map_render_segment(_gc_track, _gc_track_break,
+ curr->point.unitx, curr->point.unity,
+ curr[1].point.unitx, curr[1].point.unity);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Change the map cache directory and update dependent variables.
+ * Render all track data onto the _map_pixmap. Note that this does not
+ * clear the pixmap of previous track data (use map_force_redraw() for
+ * that), and also note that this method does not queue any redraws, so it
+ * is up to the caller to decide which part of the track really needs to be
+ * redrawn.
*/
-static gboolean
-config_set_map_dir_name(gchar *new_map_dir_name)
+static void
+map_render_route()
{
- GnomeVFSURI *map_dir_uri;
- gboolean retval = FALSE;
+ Point *curr;
+ WayPoint *wcurr;
printf("%s()\n", __PRETTY_FUNCTION__);
- /* Rest of the function devoted to making sure the directory exists. */
- map_dir_uri = gnome_vfs_uri_new(new_map_dir_name);
- if(!gnome_vfs_uri_exists(map_dir_uri))
+ _visible_way_first = _visible_way_last = NULL;
+ for(curr = _route.head, wcurr = _route.whead; curr != _route.tail; curr++)
{
- GnomeVFSURI *parent, *curr_uri;
- GList *list = NULL;
-
- list = g_list_prepend(list, curr_uri = map_dir_uri);
- while(GNOME_VFS_ERROR_NOT_FOUND == gnome_vfs_make_directory_for_uri(
- parent = gnome_vfs_uri_get_parent(curr_uri), 0755))
- list = g_list_prepend(list, curr_uri = parent);
-
- while(list != NULL)
+ if(wcurr <= _route.wtail && curr == wcurr->point)
{
- retval = (GNOME_VFS_OK == gnome_vfs_make_directory_for_uri(
- (GnomeVFSURI*)list->data, 0755));
- gnome_vfs_uri_unref((GnomeVFSURI*)list->data);
- list = g_list_remove(list, list->data);
+ guint x1 = unit2bufx(wcurr->point->unitx);
+ guint y1 = unit2bufy(wcurr->point->unity);
+ if((x1 < BUF_WIDTH_PIXELS)
+ && (y1 < BUF_HEIGHT_PIXELS))
+ {
+ gdk_draw_arc(_map_pixmap,
+ (wcurr==_next_way ? _gc_route_nextway : _gc_route_way),
+ FALSE, /* FALSE: not filled. */
+ x1 - _draw_line_width,
+ y1 - _draw_line_width,
+ 2 * _draw_line_width,
+ 2 * _draw_line_width,
+ 0, /* start at 0 degrees. */
+ 360 * 64);
+ if(!_visible_way_first)
+ _visible_way_first = wcurr;
+ _visible_way_last = wcurr;
+ }
+ wcurr++;
+ if(!curr[1].unity)
+ continue;
}
- /* Retval now equals result of last make-dir attempt. */
+ map_render_segment(_gc_route, _gc_route_way,
+ curr->unitx, curr->unity, curr[1].unitx, curr[1].unity);
}
- else
- retval = TRUE;
- if(retval)
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+static void
+map_render_paths()
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ if((_show_tracks & ROUTES_MASK) && _route.head)
{
- if(_map_dir_name)
- g_free(_map_dir_name);
- _map_dir_name = new_map_dir_name;
+ map_render_route();
+ if(_next_way == NULL)
+ {
+ guint x1 = unit2bufx(_route.tail[-1].unitx);
+ guint y1 = unit2bufy(_route.tail[-1].unity);
+ if((x1 < BUF_WIDTH_PIXELS)
+ && (y1 < BUF_HEIGHT_PIXELS))
+ {
+ gdk_draw_arc(_map_pixmap,
+ _gc_route_nextway,
+ FALSE, /* FALSE: not filled. */
+ x1 - _draw_line_width,
+ y1 - _draw_line_width,
+ 2 * _draw_line_width,
+ 2 * _draw_line_width,
+ 0, /* start at 0 degrees. */
+ 360 * 64);
+ }
+ }
}
+ if(_show_tracks & TRACKS_MASK)
+ map_render_track();
- vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, retval);
- return retval;
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * Save all configuration data to GCONF.
- */
static void
-config_save()
+track_resize(Track *track, guint size)
{
- GConfClient *gconf_client = gconf_client_get_default();
- gchar buffer[16];
printf("%s()\n", __PRETTY_FUNCTION__);
- if(!gconf_client)
+ if(track->head + size != track->cap)
{
- popup_error(_window,
- _("Failed to initialize GConf. Settings were not saved."));
- return;
+ TrackPoint *old_head = track->head;
+ track->head = g_renew(TrackPoint, old_head, size);
+ track->cap = track->head + size;
+ if(track->head != old_head)
+ track->tail = track->head + (track->tail - old_head);
}
- /* Save Receiver MAC from GConf. */
- if(_rcvr_mac)
- gconf_client_set_string(gconf_client,
- GCONF_KEY_RCVR_MAC, _rcvr_mac, NULL);
- else
- gconf_client_unset(gconf_client,
- GCONF_KEY_RCVR_MAC, NULL);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- /* Save Receiver Channel to GConf. */
- gconf_client_set_int(gconf_client,
- GCONF_KEY_RCVR_CHAN, _rcvr_addr.rc_channel, NULL);
+static void
+route_resize(Route *route, guint size)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Save Map Download URI Format. */
- if(_map_uri_format)
- gconf_client_set_string(gconf_client,
- GCONF_KEY_MAP_URI_FORMAT, _map_uri_format, NULL);
+ if(route->head + size != route->cap)
+ {
+ Point *old_head = route->head;
+ WayPoint *curr;
+ route->head = g_renew(Point, old_head, size);
+ route->cap = route->head + size;
+ if(route->head != old_head)
+ {
+ route->tail = route->head + (route->tail - old_head);
- /* Save Map Download Zoom Steps. */
- gconf_client_set_int(gconf_client,
- GCONF_KEY_MAP_ZOOM_STEPS, _zoom_steps, NULL);
+ /* Adjust all of the waypoints. */
+ for(curr = route->whead - 1; curr++ != route->wtail; )
+ curr->point = route->head + (curr->point - old_head);
+ }
+ }
- /* Save Map Cache Directory. */
- if(_map_dir_name)
- gconf_client_set_string(gconf_client,
- GCONF_KEY_MAP_DIR_NAME, _map_dir_name, NULL);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- /* Save Auto-Download. */
- gconf_client_set_bool(gconf_client,
- GCONF_KEY_AUTO_DOWNLOAD, _auto_download, NULL);
+static void
+route_wresize(Route *route, guint wsize)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Save Auto-Center Sensitivity. */
- gconf_client_set_int(gconf_client,
- GCONF_KEY_CENTER_SENSITIVITY, _center_ratio, NULL);
+ if(route->whead + wsize != route->wcap)
+ {
+ WayPoint *old_whead = route->whead;
+ route->whead = g_renew(WayPoint, old_whead, wsize);
+ route->wtail = route->whead + (route->wtail - old_whead);
+ route->wcap = route->whead + wsize;
+ }
- /* Save Auto-Center Lead Amount. */
- gconf_client_set_int(gconf_client,
- GCONF_KEY_LEAD_AMOUNT, _lead_ratio, NULL);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- /* Save Draw Line Width. */
- gconf_client_set_int(gconf_client,
- GCONF_KEY_DRAW_LINE_WIDTH, _draw_line_width, NULL);
+#define MACRO_TRACK_INCREMENT_TAIL(track) { \
+ if(++(track).tail == (track).cap) \
+ track_resize(&(track), (track).cap - (track).head + ARRAY_CHUNK_SIZE); \
+}
- /* Save Announce Advance Notice Ratio. */
- gconf_client_set_int(gconf_client,
- GCONF_KEY_ANNOUNCE_NOTICE, _announce_notice_ratio, NULL);
+#define MACRO_ROUTE_INCREMENT_TAIL(route) { \
+ if(++(route).tail == (route).cap) \
+ route_resize(&(route), (route).cap - (route).head + ARRAY_CHUNK_SIZE); \
+}
- /* Save Enable Voice flag. */
- gconf_client_set_bool(gconf_client,
- GCONF_KEY_ENABLE_VOICE, _enable_voice, NULL);
+#define MACRO_ROUTE_INCREMENT_WTAIL(route) { \
+ if(++(route).wtail == (route).wcap) \
+ route_wresize(&(route), \
+ (route).wcap - (route).whead + ARRAY_CHUNK_SIZE); \
+}
- /* Save Keep On When Fullscreen flag. */
- gconf_client_set_bool(gconf_client,
- GCONF_KEY_ALWAYS_KEEP_ON, _always_keep_on, NULL);
+/**
+ * Add a point to the _track list. This function is slightly overloaded,
+ * since it is what houses the check for "have we moved
+ * significantly": it also initiates the re-calculation of the _near_point
+ * data, as well as calling osso_display_state_on() when we have the focus.
+ *
+ * If a non-zero time is given, then the current position (as taken from the
+ * _pos variable) is appended to _track with the given time. If time is zero,
+ * then _pos_null is appended to _track with time zero (this produces a "break"
+ * in the track).
+ */
+static void
+track_add(time_t time, gboolean newly_fixed)
+{
+ Point pos = (time == 0 ? _pos_null : _pos);
+ printf("%s(%u, %u)\n", __PRETTY_FUNCTION__, pos.unitx, pos.unity);
- /* Save Units. */
- gconf_client_set_string(gconf_client,
- GCONF_KEY_UNITS, _units, NULL);
+ printf("A: %p\n", _track.tail);
+ printf("A.1: %d %d\n", _track.tail->point.unitx, _track.tail->point.unity);
+ if(abs((gint)pos.unitx - _track.tail->point.unitx) > _draw_line_width
+ || abs((gint)pos.unity - _track.tail->point.unity) > _draw_line_width)
+ {
+ printf("B\n");
+ if(time && _route.head
+ && (newly_fixed ? (route_find_nearest_point(), TRUE)
+ : route_update_nears(TRUE)))
+ {
+ map_render_paths();
+ MACRO_QUEUE_DRAW_AREA();
+ }
+ printf("C\n");
+ if(_show_tracks & TRACKS_MASK)
+ {
+ /* Instead of calling map_render_paths(), we'll draw the new line
+ * ourselves and call gtk_widget_queue_draw_area(). */
+ gint tx1, ty1, tx2, ty2;
+ printf("C.a\n");
+ map_render_segment(_gc_track, _gc_track_break,
+ _track.tail->point.unitx, _track.tail->point.unity,
+ pos.unitx, pos.unity);
+ if(time && _track.tail->point.unity)
+ {
+ printf("C.b\n");
+ tx1 = unit2x(_track.tail->point.unitx);
+ ty1 = unit2y(_track.tail->point.unity);
+ tx2 = unit2x(pos.unitx);
+ ty2 = unit2y(pos.unity);
+ gtk_widget_queue_draw_area(_map_widget,
+ MIN(tx1, tx2) - _draw_line_width,
+ MIN(ty1, ty2) - _draw_line_width,
+ abs(tx1 - tx2) + (2 * _draw_line_width),
+ abs(ty1 - ty2) + (2 * _draw_line_width));
+ }
+ }
+ printf("D\n");
+ MACRO_TRACK_INCREMENT_TAIL(_track);
+ printf("E\n");
- /* Save last saved latitude. */
- gconf_client_set_float(gconf_client,
- GCONF_KEY_LAT, _pos_lat, NULL);
+ _track.tail->point = pos;
+ _track.tail->time = time;
- /* Save last saved longitude. */
- gconf_client_set_float(gconf_client,
- GCONF_KEY_LON, _pos_lon, NULL);
+ printf("F\n");
+ if(_autoroute_data.enabled && !_autoroute_data.in_progress
+ && _near_point_dist_rough > 400)
+ {
+ printf("F.a\n");
+ _autoroute_data.in_progress = TRUE;
+ g_idle_add((GSourceFunc)auto_route_dl_idle, NULL);
+ }
+ printf("G\n");
- /* Save last center point. */
+ /* Keep the display on. */
+ KEEP_DISPLAY_ON();
+ }
+
+ /* Check if we should announce upcoming waypoints. */
+ if(time && _next_way_dist_rough
+ < (20 + (guint)_speed) * _announce_notice_ratio * 3)
{
- gfloat center_lat, center_lon;
- unit2latlon(_center.unitx, _center.unity, center_lat, center_lon);
+ if(_enable_voice && strcmp(_next_way->desc, _last_spoken_phrase))
+ {
+ g_free(_last_spoken_phrase);
+ _last_spoken_phrase = g_strdup(_next_way->desc);
+ if(!fork())
+ {
+ /* We are the fork child. Synthesize the voice. */
+ hildon_play_system_sound(
+ "/usr/share/sounds/ui-information_note.wav");
+ sleep(1);
+# define _voice_synth_path "/usr/bin/flite"
+ printf("%s %s\n", _voice_synth_path, _last_spoken_phrase);
+ execl(_voice_synth_path, _voice_synth_path,
+ "-t", _last_spoken_phrase, (char *)NULL);
+ exit(0);
+ }
+ }
+ hildon_banner_show_information(_window, NULL, _next_way->desc);
+ }
- /* Save last center latitude. */
- gconf_client_set_float(gconf_client,
- GCONF_KEY_CENTER_LAT, center_lat, NULL);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- /* Save last center longitude. */
- gconf_client_set_float(gconf_client,
- GCONF_KEY_CENTER_LON, center_lon, NULL);
- }
+/**
+ * Disconnect from the receiver. This method cleans up any and everything
+ * that might be associated with the receiver.
+ */
+static void
+rcvr_disconnect()
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Save last Zoom Level. */
- gconf_client_set_int(gconf_client,
- GCONF_KEY_ZOOM, _zoom, NULL);
+ /* Remove watches. */
+ if(_clater_sid)
+ {
+ g_source_remove(_clater_sid);
+ _clater_sid = 0;
+ }
+ if(_error_sid)
+ {
+ g_source_remove(_error_sid);
+ _error_sid = 0;
+ }
+ if(_connect_sid)
+ {
+ g_source_remove(_connect_sid);
+ _connect_sid = 0;
+ }
+ if(_input_sid)
+ {
+ g_source_remove(_input_sid);
+ _input_sid = 0;
+ }
- /* Save Route Directory. */
- if(_route_dir_uri)
- gconf_client_set_string(gconf_client,
- GCONF_KEY_ROUTEDIR, _route_dir_uri, NULL);
+ /* Destroy the GIOChannel object. */
+ if(_channel)
+ {
+ g_io_channel_shutdown(_channel, FALSE, NULL);
+ g_io_channel_unref(_channel);
+ _channel = NULL;
+ }
- /* Save Last Track File. */
- if(_track_file_uri)
- gconf_client_set_string(gconf_client,
- GCONF_KEY_TRACKFILE, _track_file_uri, NULL);
+ /* Close the file descriptor. */
+ if(_fd != -1)
+ {
+ close(_fd);
+ _fd = -1;
+ }
- /* Save Auto-Center Mode. */
- gconf_client_set_int(gconf_client,
- GCONF_KEY_AUTOCENTER_MODE, _center_mode, NULL);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- /* Save Show Tracks flag. */
- gconf_client_set_bool(gconf_client,
- GCONF_KEY_SHOWTRACKS, _show_tracks & TRACKS_MASK, NULL);
+static void rcvr_connect_later(); /* Forward declaration. */
- /* Save Show Routes flag. */
- gconf_client_set_bool(gconf_client,
- GCONF_KEY_SHOWROUTES, _show_tracks & ROUTES_MASK, NULL);
+/**
+ * Connect to the receiver.
+ * This method assumes that _fd is -1 and _channel is NULL. If unsure, call
+ * rcvr_disconnect() first.
+ * Since this is an idle function, this function returns whether or not it
+ * should be called again, which is always FALSE.
+ */
+static gboolean
+rcvr_connect_now()
+{
+ printf("%s(%d)\n", __PRETTY_FUNCTION__, _conn_state);
- /* Save Show Velocity Vector flag. */
- gconf_client_set_bool(gconf_client,
- GCONF_KEY_SHOWVELVEC, _show_velvec, NULL);
+ if(_conn_state == RCVR_DOWN && _rcvr_mac) {
+#ifndef DEBUG
+ /* Create the file descriptor. */
+ if(*_rcvr_mac == '/')
+ _fd = open(_rcvr_mac, O_RDONLY);
+ else
+ _fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- /* Save Enable GPS flag. */
- gconf_client_set_bool(gconf_client,
- GCONF_KEY_ENABLE_GPS, _enable_gps, NULL);
+ /* If file descriptor creation failed, try again later. Note that
+ * there is no need to call rcvr_disconnect() because the file
+ * descriptor creation is the first step, so if it fails, there's
+ * nothing to clean up. */
+ if(_fd == -1)
+ rcvr_connect_later();
+ else
+ {
+ _gps_read_buf_pos = 0;
+ _channel = g_io_channel_unix_new(_fd);
+ g_io_channel_set_flags(_channel, G_IO_FLAG_NONBLOCK, NULL);
+ _error_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
+ G_IO_ERR | G_IO_HUP, channel_cb_error, NULL, NULL);
+ _connect_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
+ G_IO_OUT, channel_cb_connect, NULL, NULL);
+ if(*_rcvr_mac != '/'
+ && connect(_fd, (struct sockaddr*)&_rcvr_addr,
+ sizeof(_rcvr_addr))
+ && errno != EAGAIN)
+ {
+ /* Connection failed. Disconnect and try again later. */
+ rcvr_disconnect();
+ rcvr_connect_later();
+ }
+ }
+#else
+ /* We're in DEBUG mode, so instead of connecting, skip to FIXED. */
+ set_conn_state(RCVR_FIXED);
+#endif
+ }
- /* Save Route Locations. */
- gconf_client_set_list(gconf_client,
- GCONF_KEY_ROUTE_LOCATIONS, GCONF_VALUE_STRING, _loc_list, NULL);
+ _clater_sid = 0;
- /* Save Colors. */
- sprintf(buffer, "#%02x%02x%02x",
- _color_mark.red >> 8,
- _color_mark.green >> 8,
- _color_mark.blue >> 8);
- gconf_client_set_string(gconf_client,
- GCONF_KEY_COLOR_MARK, buffer, NULL);
+ vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return FALSE;
+}
- sprintf(buffer, "#%02x%02x%02x",
- _color_mark_velocity.red >> 8,
- _color_mark_velocity.green >> 8,
- _color_mark_velocity.blue >> 8);
- gconf_client_set_string(gconf_client,
- GCONF_KEY_COLOR_MARK_VELOCITY, buffer, NULL);
+/**
+ * Place a request to connect about 1 second after the function is called.
+ */
+static void
+rcvr_connect_later()
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- sprintf(buffer, "#%02x%02x%02x",
- _color_mark_old.red >> 8,
- _color_mark_old.green >> 8,
- _color_mark_old.blue >> 8);
- gconf_client_set_string(gconf_client,
- GCONF_KEY_COLOR_MARK_OLD, buffer, NULL);
+ _clater_sid = g_timeout_add(1000, (GSourceFunc)rcvr_connect_now, NULL);
- sprintf(buffer, "#%02x%02x%02x",
- _color_track.red >> 8,
- _color_track.green >> 8,
- _color_track.blue >> 8);
- gconf_client_set_string(gconf_client,
- GCONF_KEY_COLOR_TRACK, buffer, NULL);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- sprintf(buffer, "#%02x%02x%02x",
- _color_track_break.red >> 8,
- _color_track_break.green >> 8,
- _color_track_break.blue >> 8);
- gconf_client_set_string(gconf_client,
- GCONF_KEY_COLOR_TRACK_BREAK, buffer, NULL);
-
- sprintf(buffer, "#%02x%02x%02x",
- _color_route.red >> 8,
- _color_route.green >> 8,
- _color_route.blue >> 8);
- gconf_client_set_string(gconf_client,
- GCONF_KEY_COLOR_ROUTE, buffer, NULL);
-
- sprintf(buffer, "#%02x%02x%02x",
- _color_route_way.red >> 8,
- _color_route_way.green >> 8,
- _color_route_way.blue >> 8);
- gconf_client_set_string(gconf_client,
- GCONF_KEY_COLOR_ROUTE_WAY, buffer, NULL);
+/**
+ * Convert the float lat/lon/speed/heading data into integer units.
+ */
+static void
+integerize_data()
+{
+ gfloat tmp;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- sprintf(buffer, "#%02x%02x%02x",
- _color_route_nextway.red >> 8,
- _color_route_nextway.green >> 8,
- _color_route_nextway.blue >> 8);
- gconf_client_set_string(gconf_client,
- GCONF_KEY_COLOR_ROUTE_NEXTWAY, buffer, NULL);
+ latlon2unit(_pos_lat, _pos_lon, _pos.unitx, _pos.unity);
- g_object_unref(gconf_client);
+ tmp = (_heading * (1.f / 180.f)) * PI;
+ _vel_offsetx = (gint)(floorf(_speed * sinf(tmp) + 0.5f));
+ _vel_offsety = -(gint)(floorf(_speed * cosf(tmp) + 0.5f));
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
+/**
+ * Update all GdkGC objects to reflect the current _draw_line_width.
+ */
+#define UPDATE_GC(gc) \
+ gdk_gc_set_line_attributes(gc, \
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
static void
-force_min_visible_bars(HildonControlbar *control_bar, gint num_bars)
+update_gcs()
{
- GValue val;
- memset(&val, 0, sizeof(val));
- g_value_init(&val, G_TYPE_INT);
- g_value_set_int(&val, num_bars);
- g_object_set_property(G_OBJECT(control_bar), "minimum-visible-bars", &val);
-}
+ printf("%s()\n", __PRETTY_FUNCTION__);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_mark);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_mark_velocity);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_mark_old);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_track);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_track_break);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_route);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_route_way);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_route_nextway);
+ gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+ &_color_poi);
-typedef struct _ScanInfo ScanInfo;
-struct _ScanInfo {
- GtkWidget *settings_dialog;
- GtkWidget *txt_rcvr_mac;
- GtkWidget *scan_dialog;
- GtkWidget *banner;
- GtkListStore *store;
- guint sid;
-};
+ if(_gc_mark)
+ {
+ g_object_unref(_gc_mark);
+ g_object_unref(_gc_mark_velocity);
+ g_object_unref(_gc_mark_old);
+ g_object_unref(_gc_track);
+ g_object_unref(_gc_track_break);
+ g_object_unref(_gc_route);
+ g_object_unref(_gc_route_way);
+ g_object_unref(_gc_route_nextway);
+ g_object_unref(_gc_poi);
+ }
-static gboolean
-scan_bluetooth_idle(ScanInfo *scan_info)
-{
- gint devid, num_rsp;
- GtkTreeIter iter;
- inquiry_info *ii = NULL;
+ /* _gc_mark is used to draw the mark when data is current. */
+ _gc_mark = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_mark, &_color_mark);
+ gdk_gc_set_line_attributes(_gc_mark,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
- devid = hci_get_route(NULL);
+ /* _gc_mark_old is used to draw the mark when data is old. */
+ _gc_mark_old = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_mark_old, &_color_mark_old);
+ gdk_gc_set_line_attributes(_gc_mark_old,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
- ii = (inquiry_info*)malloc(255 * sizeof(inquiry_info));
- num_rsp = hci_inquiry(devid, 4, 255, NULL, &ii, IREQ_CACHE_FLUSH);
+ /* _gc_mark_velocity is used to draw the vel_current line. */
+ _gc_mark_velocity = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_mark_velocity, &_color_mark_velocity);
+ gdk_gc_set_line_attributes(_gc_mark_velocity,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
- if(num_rsp < 0)
- {
- gtk_widget_destroy(scan_info->banner);
- gtk_widget_hide(scan_info->scan_dialog);
- popup_error(scan_info->settings_dialog,
- _("An error occurred while scanning."));
- }
- else if(num_rsp == 0)
- {
- gtk_widget_destroy(scan_info->banner);
- gtk_widget_hide(scan_info->scan_dialog);
- popup_error(scan_info->settings_dialog,
- _("No bluetooth devices found."));
- }
- else
- {
- guint i;
- gint sock = hci_open_dev(devid);
- for(i = 0; i < num_rsp; i++)
- {
- gchar addr[19] = { 0 };
- gchar name[256] = { 0 };
+ /* _gc_track is used to draw the track line. */
+ _gc_track = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_track, &_color_track);
+ gdk_gc_set_line_attributes(_gc_track,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
- ba2str(&ii[i].bdaddr, addr);
- memset(name, 0, sizeof(name));
- if(hci_read_remote_name(sock, &ii[i].bdaddr, sizeof(name), name, 0))
- strcpy(name, _("Unknown"));
+ /* _gc_track_break is used to draw the track_break dots. */
+ _gc_track_break = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_track_break, &_color_track_break);
+ gdk_gc_set_line_attributes(_gc_track_break,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
- gtk_list_store_append(scan_info->store, &iter);
- gtk_list_store_set(scan_info->store, &iter,
- 0, g_strdup(addr),
- 1, g_strdup(name),
- -1);
- }
- close(sock);
- gtk_widget_destroy(scan_info->banner);
- }
- free(ii);
- scan_info->sid = 0;
- return FALSE;
+ /* _gc_route is used to draw the route line. */
+ _gc_route = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_route, &_color_route);
+ gdk_gc_set_line_attributes(_gc_route,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+ /* _way_gc is used to draw the waypoint dots. */
+ _gc_route_way = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_route_way, &_color_route_way);
+ gdk_gc_set_line_attributes(_gc_route_way,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+ /* _gc_route_nextway is used to draw the next_way labels. */
+ _gc_route_nextway = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_route_nextway, &_color_route_nextway);
+ gdk_gc_set_line_attributes(_gc_route_nextway,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+ /* _gc_poi is used to draw the default POI icon. */
+ _gc_poi = gdk_gc_new(_map_pixmap);
+ gdk_gc_set_foreground(_gc_poi, &_color_poi);
+ gdk_gc_set_background(_gc_poi, &_color_poi);
+ gdk_gc_set_line_attributes(_gc_poi,
+ _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Scan for all bluetooth devices. This method can take a few seconds,
- * during which the UI will freeze.
+ * Save all configuration data to GCONF.
*/
-static gboolean
-scan_bluetooth(GtkWidget *widget, ScanInfo *scan_info)
+static void
+config_save()
{
- /* Do an hci_inquiry for our boy. */
- GtkWidget *dialog;
- GtkWidget *lst_devices;
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
+ GConfClient *gconf_client = gconf_client_get_default();
+ gchar buffer[16];
printf("%s()\n", __PRETTY_FUNCTION__);
- dialog = gtk_dialog_new_with_buttons(_("Select Bluetooth Device"),
- GTK_WINDOW(scan_info->settings_dialog), GTK_DIALOG_MODAL,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
- NULL);
+ if(!gconf_client)
+ {
+ popup_error(_window,
+ _("Failed to initialize GConf. Settings were not saved."));
+ return;
+ }
- scan_info->scan_dialog = dialog;
+ /* Save Receiver MAC from GConf. */
+ if(_rcvr_mac)
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_RCVR_MAC, _rcvr_mac, NULL);
+ else
+ gconf_client_unset(gconf_client,
+ GCONF_KEY_RCVR_MAC, NULL);
- scan_info->banner = hildon_banner_show_animation(dialog, NULL,
- _("Scanning Bluetooth Devices"));
+ /* Save Receiver Channel to GConf. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_RCVR_CHAN, _rcvr_addr.rc_channel, NULL);
- scan_info->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
+ /* Save Map Download URI Format. */
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_MAP_URI_FORMAT, _curr_repo->url, NULL);
- scan_info->sid = g_idle_add((GSourceFunc)scan_bluetooth_idle, scan_info);
+ /* Save Map Download Zoom Steps. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_MAP_ZOOM_STEPS, _curr_repo->dl_zoom_steps, NULL);
- gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
+ /* Save Map Cache Directory. */
+ if(_curr_repo->cache_dir)
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_MAP_DIR_NAME, _curr_repo->cache_dir, NULL);
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
- lst_devices = gtk_tree_view_new_with_model(
- GTK_TREE_MODEL(scan_info->store)), TRUE, TRUE, 0);
+ /* Save Auto-Download. */
+ gconf_client_set_bool(gconf_client,
+ GCONF_KEY_AUTO_DOWNLOAD, _auto_download, NULL);
- g_object_unref(G_OBJECT(scan_info->store));
+ /* Save Auto-Center Sensitivity. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_CENTER_SENSITIVITY, _center_ratio, NULL);
- gtk_tree_selection_set_mode(
- gtk_tree_view_get_selection(GTK_TREE_VIEW(lst_devices)),
- GTK_SELECTION_SINGLE);
- gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(lst_devices), TRUE);
+ /* Save Auto-Center Lead Amount. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_LEAD_AMOUNT, _lead_ratio, NULL);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(
- _("MAC"), renderer, "text", 0);
- gtk_tree_view_append_column(GTK_TREE_VIEW(lst_devices), column);
+ /* Save Draw Line Width. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_DRAW_LINE_WIDTH, _draw_line_width, NULL);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(
- _("Description"), renderer, "text", 1);
- gtk_tree_view_append_column(GTK_TREE_VIEW(lst_devices), column);
+ /* Save Announce Advance Notice Ratio. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_ANNOUNCE_NOTICE, _announce_notice_ratio, NULL);
- gtk_widget_show_all(dialog);
+ /* Save Enable Voice flag. */
+ gconf_client_set_bool(gconf_client,
+ GCONF_KEY_ENABLE_VOICE, _enable_voice, NULL);
- while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
- {
- GtkTreeIter iter;
- if(gtk_tree_selection_get_selected(
- gtk_tree_view_get_selection(GTK_TREE_VIEW(lst_devices)),
- NULL, &iter))
- {
- gchar *mac;
- gtk_tree_model_get(GTK_TREE_MODEL(scan_info->store),
- &iter, 0, &mac, -1);
- gtk_entry_set_text(GTK_ENTRY(scan_info->txt_rcvr_mac), mac);
- break;
- }
- else
- popup_error(dialog,
- _("Please select a bluetooth device from the list."));
- }
+ /* Save Keep On When Fullscreen flag. */
+ gconf_client_set_bool(gconf_client,
+ GCONF_KEY_ALWAYS_KEEP_ON, _always_keep_on, NULL);
- if(scan_info->sid)
- g_source_remove(scan_info->sid);
- gtk_widget_destroy(dialog);
+ /* Save Units. */
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_UNITS, UNITS_TEXT[_units], NULL);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ /* Save Escape Key Function. */
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_ESCAPE_KEY, ESCAPE_KEY_TEXT[_escape_key], NULL);
-typedef struct _BrowseInfo BrowseInfo;
-struct _BrowseInfo {
- GtkWidget *dialog;
- GtkWidget *txt_map_dir_name;
-};
+ /* Save last saved latitude. */
+ gconf_client_set_float(gconf_client,
+ GCONF_KEY_LAT, _pos_lat, NULL);
-static gboolean
-settings_dialog_browse(GtkWidget *widget, BrowseInfo *browse_info)
-{
- GtkWidget *dialog;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ /* Save last saved longitude. */
+ gconf_client_set_float(gconf_client,
+ GCONF_KEY_LON, _pos_lon, NULL);
- dialog = GTK_WIDGET(
- hildon_file_chooser_dialog_new(GTK_WINDOW(browse_info->dialog),
- GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER));
+ /* Save last center point. */
+ {
+ gfloat center_lat, center_lon;
+ unit2latlon(_center.unitx, _center.unity, center_lat, center_lon);
- gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
- gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
- gtk_entry_get_text(GTK_ENTRY(browse_info->txt_map_dir_name)));
+ /* Save last center latitude. */
+ gconf_client_set_float(gconf_client,
+ GCONF_KEY_CENTER_LAT, center_lat, NULL);
- if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
- {
- gchar *filename = gtk_file_chooser_get_filename(
- GTK_FILE_CHOOSER(dialog));
- gtk_entry_set_text(GTK_ENTRY(browse_info->txt_map_dir_name), filename);
- g_free(filename);
+ /* Save last center longitude. */
+ gconf_client_set_float(gconf_client,
+ GCONF_KEY_CENTER_LON, center_lon, NULL);
}
- gtk_widget_destroy(dialog);
+ /* Save last Zoom Level. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_ZOOM, _zoom, NULL);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ /* Save Route Directory. */
+ if(_route_dir_uri)
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_ROUTEDIR, _route_dir_uri, NULL);
-typedef struct _ColorsDialogInfo ColorsDialogInfo;
-struct _ColorsDialogInfo {
- GtkWidget *col_mark;
- GtkWidget *col_mark_velocity;
- GtkWidget *col_mark_old;
- GtkWidget *col_track;
- GtkWidget *col_track_break;
- GtkWidget *col_route;
- GtkWidget *col_route_way;
- GtkWidget *col_route_nextway;
-};
+ /* Save the repositories. */
+ {
+ GList *curr = _repo_list;
+ GSList *temp_list = NULL;
+ gint curr_repo_index = 0;
+
+ for(curr = _repo_list; curr != NULL; curr = curr->next)
+ {
+ /* Build from each part of a repo, delimited by newline characters:
+ * 1. url
+ * 2. cache_dir
+ * 3. dl_zoom_steps
+ * 4. view_zoom_steps
+ */
+ RepoData *rd = curr->data;
+ gchar buffer[1024];
+ sprintf(buffer, "%s\n%s\n%s\n%d\n%d\n",
+ rd->name,
+ rd->url,
+ rd->cache_dir,
+ rd->dl_zoom_steps,
+ rd->view_zoom_steps);
+ temp_list = g_slist_append(temp_list, g_strdup(buffer));
+ if(rd == _curr_repo)
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_CURRREPO, curr_repo_index, NULL);
+ curr_repo_index++;
+ }
+ gconf_client_set_list(gconf_client,
+ GCONF_KEY_REPOSITORIES, GCONF_VALUE_STRING, temp_list, NULL);
+ }
-static gboolean
-settings_dialog_colors_reset(GtkWidget *widget, ColorsDialogInfo *cdi)
-{
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi->col_mark),
- &DEFAULT_COLOR_MARK);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi->col_mark_velocity),
- &DEFAULT_COLOR_MARK_VELOCITY);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi->col_mark_old),
- &DEFAULT_COLOR_MARK_OLD);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi->col_track),
- &DEFAULT_COLOR_TRACK);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi->col_track_break),
- &DEFAULT_COLOR_TRACK_BREAK);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi->col_route),
- &DEFAULT_COLOR_ROUTE);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi->col_route_way),
- &DEFAULT_COLOR_ROUTE_WAY);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi->col_route_nextway),
- &DEFAULT_COLOR_ROUTE_NEXTWAY);
- return TRUE;
-}
+ /* Save Last Track File. */
+ if(_track_file_uri)
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_TRACKFILE, _track_file_uri, NULL);
-static gboolean
-settings_dialog_colors(GtkWidget *widget, GtkWidget *parent)
-{
- GtkWidget *dialog;
- GtkWidget *table;
- GtkWidget *label;
- GtkWidget *btn_defaults;
- ColorsDialogInfo cdi;
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- dialog = gtk_dialog_new_with_buttons(_("Colors"),
- GTK_WINDOW(parent), GTK_DIALOG_MODAL,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- NULL);
+ /* Save Auto-Center Mode. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_AUTOCENTER_MODE, _center_mode, NULL);
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
- btn_defaults = gtk_button_new_with_label(_("Defaults")));
- g_signal_connect(G_OBJECT(btn_defaults), "clicked",
- G_CALLBACK(settings_dialog_colors_reset), &cdi);
+ /* Save Show Tracks flag. */
+ gconf_client_set_bool(gconf_client,
+ GCONF_KEY_SHOWTRACKS, _show_tracks & TRACKS_MASK, NULL);
- gtk_dialog_add_button(GTK_DIALOG(dialog),
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+ /* Save Show Routes flag. */
+ gconf_client_set_bool(gconf_client,
+ GCONF_KEY_SHOWROUTES, _show_tracks & ROUTES_MASK, NULL);
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
- table = gtk_table_new(4, 3, FALSE), TRUE, TRUE, 0);
+ /* Save Show Velocity Vector flag. */
+ gconf_client_set_bool(gconf_client,
+ GCONF_KEY_SHOWVELVEC, _show_velvec, NULL);
- /* Mark. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("GPS Mark")),
- 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- cdi.col_mark = hildon_color_button_new(),
- 1, 2, 0, 1, 0, 0, 2, 4);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi.col_mark), &_color_mark);
- gtk_table_attach(GTK_TABLE(table),
- cdi.col_mark_velocity = hildon_color_button_new(),
- 2, 3, 0, 1, 0, 0, 2, 4);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi.col_mark_velocity), &_color_mark_velocity);
- gtk_table_attach(GTK_TABLE(table),
- cdi.col_mark_old = hildon_color_button_new(),
- 3, 4, 0, 1, 0, 0, 2, 4);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi.col_mark_old), &_color_mark_old);
+ /* Save Enable GPS flag. */
+ gconf_client_set_bool(gconf_client,
+ GCONF_KEY_ENABLE_GPS, _enable_gps, NULL);
- /* Track. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Track")),
- 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- cdi.col_track = hildon_color_button_new(),
- 1, 2, 1, 2, 0, 0, 2, 4);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi.col_track), &_color_track);
- gtk_table_attach(GTK_TABLE(table),
- cdi.col_track_break = hildon_color_button_new(),
- 2, 3, 1, 2, 0, 0, 2, 4);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi.col_track_break), &_color_track_break);
+ /* Save Route Locations. */
+ gconf_client_set_list(gconf_client,
+ GCONF_KEY_ROUTE_LOCATIONS, GCONF_VALUE_STRING, _loc_list, NULL);
- /* Route. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Route")),
- 0, 1, 2, 3, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- cdi.col_route = hildon_color_button_new(),
- 1, 2, 2, 3, 0, 0, 2, 4);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi.col_route), &_color_route);
- gtk_table_attach(GTK_TABLE(table),
- cdi.col_route_way = hildon_color_button_new(),
- 2, 3, 2, 3, 0, 0, 2, 4);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi.col_route_way), &_color_route_way);
- gtk_table_attach(GTK_TABLE(table),
- cdi.col_route_nextway = hildon_color_button_new(),
- 3, 4, 2, 3, 0, 0, 2, 4);
- hildon_color_button_set_color(
- HILDON_COLOR_BUTTON(cdi.col_route_nextway), &_color_route_nextway);
+ /* Save GPS Info flag. */
+ gconf_client_set_bool(gconf_client,
+ GCONF_KEY_GPS_INFO, _gps_info, NULL);
- gtk_widget_show_all(dialog);
+ /* Save Colors. */
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_mark.red >> 8,
+ _color_mark.green >> 8,
+ _color_mark.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_MARK, buffer, NULL);
- while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
- {
- GdkColor *color;
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_mark_velocity.red >> 8,
+ _color_mark_velocity.green >> 8,
+ _color_mark_velocity.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_MARK_VELOCITY, buffer, NULL);
- color = hildon_color_button_get_color(
- HILDON_COLOR_BUTTON(cdi.col_mark));
- _color_mark = *color;
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_mark_old.red >> 8,
+ _color_mark_old.green >> 8,
+ _color_mark_old.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_MARK_OLD, buffer, NULL);
- color = hildon_color_button_get_color(
- HILDON_COLOR_BUTTON(cdi.col_mark_velocity));
- _color_mark_velocity = *color;
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_track.red >> 8,
+ _color_track.green >> 8,
+ _color_track.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_TRACK, buffer, NULL);
- color = hildon_color_button_get_color(
- HILDON_COLOR_BUTTON(cdi.col_mark_old));
- _color_mark_old = *color;
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_track_break.red >> 8,
+ _color_track_break.green >> 8,
+ _color_track_break.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_TRACK_BREAK, buffer, NULL);
- color = hildon_color_button_get_color(
- HILDON_COLOR_BUTTON(cdi.col_track));
- _color_track = *color;
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_route.red >> 8,
+ _color_route.green >> 8,
+ _color_route.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_ROUTE, buffer, NULL);
- color = hildon_color_button_get_color(
- HILDON_COLOR_BUTTON(cdi.col_track_break));
- _color_track_break = *color;
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_route_way.red >> 8,
+ _color_route_way.green >> 8,
+ _color_route_way.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_ROUTE_WAY, buffer, NULL);
- color = hildon_color_button_get_color(
- HILDON_COLOR_BUTTON(cdi.col_route));
- _color_route = *color;
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_route_nextway.red >> 8,
+ _color_route_nextway.green >> 8,
+ _color_route_nextway.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_ROUTE_NEXTWAY, buffer, NULL);
- color = hildon_color_button_get_color(
- HILDON_COLOR_BUTTON(cdi.col_route_way));
- _color_route_way = *color;
+ sprintf(buffer, "#%02x%02x%02x",
+ _color_poi.red >> 8,
+ _color_poi.green >> 8,
+ _color_poi.blue >> 8);
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_COLOR_POI, buffer, NULL);
- color = hildon_color_button_get_color(
- HILDON_COLOR_BUTTON(cdi.col_route_nextway));
- _color_route_nextway = *color;
+ /* Save POI database. */
+ if(_poi_db)
+ gconf_client_set_string(gconf_client,
+ GCONF_KEY_POI_DB, _poi_db, NULL);
+ else
+ gconf_client_unset(gconf_client, GCONF_KEY_POI_DB, NULL);
- update_gcs();
- break;
+ /* Save Show POI below zoom. */
+ gconf_client_set_int(gconf_client,
+ GCONF_KEY_POI_ZOOM, _poi_zoom, NULL);
+
+ g_object_unref(gconf_client);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+static void
+force_min_visible_bars(HildonControlbar *control_bar, gint num_bars)
+{
+ GValue val;
+ memset(&val, 0, sizeof(val));
+ g_value_init(&val, G_TYPE_INT);
+ g_value_set_int(&val, num_bars);
+ g_object_set_property(G_OBJECT(control_bar), "minimum-visible-bars", &val);
+}
+
+
+typedef struct _ScanInfo ScanInfo;
+struct _ScanInfo {
+ GtkWidget *settings_dialog;
+ GtkWidget *txt_rcvr_mac;
+ GtkWidget *scan_dialog;
+ GtkWidget *banner;
+ GtkListStore *store;
+ guint sid;
+};
+
+static gboolean
+scan_bluetooth_idle(ScanInfo *scan_info)
+{
+ gint devid, num_rsp;
+ GtkTreeIter iter;
+ inquiry_info *ii = NULL;
+
+ devid = hci_get_route(NULL);
+
+ ii = (inquiry_info*)malloc(255 * sizeof(inquiry_info));
+ num_rsp = hci_inquiry(devid, 4, 255, NULL, &ii, IREQ_CACHE_FLUSH);
+
+ if(num_rsp < 0)
+ {
+ gtk_widget_destroy(scan_info->banner);
+ gtk_widget_hide(scan_info->scan_dialog);
+ popup_error(scan_info->settings_dialog,
+ _("An error occurred while scanning."));
+ }
+ else if(num_rsp == 0)
+ {
+ gtk_widget_destroy(scan_info->banner);
+ gtk_widget_hide(scan_info->scan_dialog);
+ popup_error(scan_info->settings_dialog,
+ _("No bluetooth devices found."));
}
+ else
+ {
+ guint i;
+ gint sock = hci_open_dev(devid);
+ for(i = 0; i < num_rsp; i++)
+ {
+ gchar addr[19] = { 0 };
+ gchar name[256] = { 0 };
- gtk_widget_destroy(dialog);
+ ba2str(&ii[i].bdaddr, addr);
+ memset(name, 0, sizeof(name));
+ if(hci_read_remote_name(sock, &ii[i].bdaddr, sizeof(name), name, 0))
+ strcpy(name, _("Unknown"));
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
+ gtk_list_store_append(scan_info->store, &iter);
+ gtk_list_store_set(scan_info->store, &iter,
+ 0, g_strdup(addr),
+ 1, g_strdup(name),
+ -1);
+ }
+ close(sock);
+ gtk_widget_destroy(scan_info->banner);
+ }
+ free(ii);
+ scan_info->sid = 0;
+ return FALSE;
}
/**
- * Bring up the Settings dialog. Return TRUE if and only if the recever
- * information has changed (MAC or channel).
+ * Scan for all bluetooth devices. This method can take a few seconds,
+ * during which the UI will freeze.
*/
static gboolean
-settings_dialog()
+scan_bluetooth(GtkWidget *widget, ScanInfo *scan_info)
{
+ /* Do an hci_inquiry for our boy. */
GtkWidget *dialog;
- GtkWidget *notebook;
- GtkWidget *table;
- GtkWidget *hbox;
- GtkWidget *hbox2;
- GtkWidget *label;
- GtkWidget *txt_rcvr_mac;
- GtkWidget *num_rcvr_chan;
- GtkWidget *txt_map_uri_format;
- GtkWidget *txt_map_dir_name;
- GtkWidget *num_zoom_steps;
- GtkWidget *num_center_ratio;
- GtkWidget *num_lead_ratio;
- GtkWidget *num_announce_notice;
- GtkWidget *chk_enable_voice;
- GtkWidget *num_voice_speed;
- GtkWidget *num_voice_pitch;
- GtkWidget *num_draw_line_width;
- GtkWidget *chk_always_keep_on;
- GtkWidget *cmb_units;
- GtkWidget *btn_scan;
- GtkWidget *btn_browse;
- GtkWidget *btn_colors;
- BrowseInfo browse_info = {0, 0};
- ScanInfo scan_info = {0};
- gboolean rcvr_changed = FALSE;
+ GtkWidget *lst_devices;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
printf("%s()\n", __PRETTY_FUNCTION__);
- dialog = gtk_dialog_new_with_buttons(_("Maemo Mapper Settings"),
- GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ dialog = gtk_dialog_new_with_buttons(_("Select Bluetooth Device"),
+ GTK_WINDOW(scan_info->settings_dialog), GTK_DIALOG_MODAL,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
NULL);
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
- btn_colors = gtk_button_new_with_label(_("Colors...")));
+ scan_info->scan_dialog = dialog;
- gtk_dialog_add_button(GTK_DIALOG(dialog),
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+ scan_info->banner = hildon_banner_show_animation(dialog, NULL,
+ _("Scanning Bluetooth Devices"));
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
- notebook = gtk_notebook_new(), TRUE, TRUE, 0);
-
- /* Receiver page. */
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
- table = gtk_table_new(2, 3, FALSE),
- label = gtk_label_new(_("GPS")));
+ scan_info->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
- /* Receiver MAC Address. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("MAC")),
- 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- hbox = gtk_hbox_new(FALSE, 4),
- 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_box_pack_start(GTK_BOX(hbox),
- txt_rcvr_mac = gtk_entry_new(),
- TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox),
- btn_scan = gtk_button_new_with_label(_("Scan...")),
- FALSE, FALSE, 0);
+ scan_info->sid = g_idle_add((GSourceFunc)scan_bluetooth_idle, scan_info);
- /* Receiver Channel. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Channel")),
- 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
- 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_container_add(GTK_CONTAINER(label),
- num_rcvr_chan = hildon_number_editor_new(0, 255));
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
- /* Note!. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(
- _("Note: \"Channel\" refers to the device side!")),
- 0, 2, 2, 3, GTK_FILL, 0, 2, 4);
- gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
- gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ lst_devices = gtk_tree_view_new_with_model(
+ GTK_TREE_MODEL(scan_info->store)), TRUE, TRUE, 0);
+ g_object_unref(G_OBJECT(scan_info->store));
- /* Maps page. */
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
- table = gtk_table_new(2, 3, FALSE),
- label = gtk_label_new(_("Maps")));
+ gtk_tree_selection_set_mode(
+ gtk_tree_view_get_selection(GTK_TREE_VIEW(lst_devices)),
+ GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(lst_devices), TRUE);
- /* Map download URI. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("URI Format")),
- 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- txt_map_uri_format = gtk_entry_new(),
- 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("MAC"), renderer, "text", 0);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(lst_devices), column);
- /* Zoom Steps. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Zoom Steps")),
- 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
- 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_container_add(GTK_CONTAINER(label),
- num_zoom_steps = hildon_controlbar_new());
- hildon_controlbar_set_range(HILDON_CONTROLBAR(num_zoom_steps), 1, 4);
- force_min_visible_bars(HILDON_CONTROLBAR(num_zoom_steps), 1);
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Description"), renderer, "text", 1);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(lst_devices), column);
- /* Map Directory. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Cache Dir.")),
- 0, 1, 2, 3, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- hbox = gtk_hbox_new(FALSE, 4),
- 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_box_pack_start(GTK_BOX(hbox),
- txt_map_dir_name = gtk_entry_new(),
- TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox),
- btn_browse = gtk_button_new_with_label(_("Browse...")),
- FALSE, FALSE, 0);
+ gtk_widget_show_all(dialog);
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+ {
+ GtkTreeIter iter;
+ if(gtk_tree_selection_get_selected(
+ gtk_tree_view_get_selection(GTK_TREE_VIEW(lst_devices)),
+ NULL, &iter))
+ {
+ gchar *mac;
+ gtk_tree_model_get(GTK_TREE_MODEL(scan_info->store),
+ &iter, 0, &mac, -1);
+ gtk_entry_set_text(GTK_ENTRY(scan_info->txt_rcvr_mac), mac);
+ break;
+ }
+ else
+ popup_error(dialog,
+ _("Please select a bluetooth device from the list."));
+ }
- /* Auto-Center page. */
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
- table = gtk_table_new(2, 2, FALSE),
- label = gtk_label_new(_("Auto-Center")));
+ if(scan_info->sid)
+ g_source_remove(scan_info->sid);
+ gtk_widget_destroy(dialog);
- /* Auto-Center Sensitivity. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Sensitivity")),
- 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
- 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_container_add(GTK_CONTAINER(label),
- num_center_ratio = hildon_controlbar_new());
- hildon_controlbar_set_range(HILDON_CONTROLBAR(num_center_ratio), 1, 10);
- force_min_visible_bars(HILDON_CONTROLBAR(num_center_ratio), 1);
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Lead Amount. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Lead Amount")),
- 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
- 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_container_add(GTK_CONTAINER(label),
- num_lead_ratio = hildon_controlbar_new());
- hildon_controlbar_set_range(HILDON_CONTROLBAR(num_lead_ratio), 1, 10);
- force_min_visible_bars(HILDON_CONTROLBAR(num_lead_ratio), 1);
+typedef struct _BrowseInfo BrowseInfo;
+struct _BrowseInfo {
+ GtkWidget *dialog;
+ GtkWidget *txt;
+};
- /* Announcement. */
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
- table = gtk_table_new(2, 3, FALSE),
- label = gtk_label_new(_("Announce")));
+static gboolean
+settings_dialog_browse_forfile(GtkWidget *widget, BrowseInfo *browse_info)
+{
+ GtkWidget *dialog;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Announcement Advance Notice. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Advance Notice")),
- 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- num_announce_notice = hildon_controlbar_new(),
- 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- hildon_controlbar_set_range(HILDON_CONTROLBAR(num_announce_notice), 1, 20);
- force_min_visible_bars(HILDON_CONTROLBAR(num_announce_notice), 1);
+ dialog = GTK_WIDGET(
+ hildon_file_chooser_dialog_new(GTK_WINDOW(browse_info->dialog),
+ GTK_FILE_CHOOSER_ACTION_OPEN));
- /* Enable Voice. */
- gtk_table_attach(GTK_TABLE(table),
- chk_enable_voice = gtk_check_button_new_with_label(
- _("Enable Voice Synthesis (requires flite)")),
- 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enable_voice),
- _enable_voice);
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+ gtk_entry_get_text(GTK_ENTRY(browse_info->txt)));
- /* Voice Speed and Pitch. */
- gtk_table_attach(GTK_TABLE(table),
- hbox = gtk_hbox_new(FALSE, 12),
- 0, 2, 2, 3, 0, 0, 2, 6);
- gtk_box_pack_start(GTK_BOX(hbox),
- hbox2 = gtk_hbox_new(FALSE, 4),
- TRUE, TRUE, 4);
- gtk_box_pack_start(GTK_BOX(hbox2),
- label = gtk_label_new(_("Speed")),
- TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox2),
- num_voice_speed = hildon_controlbar_new(),
- TRUE, TRUE, 0);
- hildon_controlbar_set_range(HILDON_CONTROLBAR(num_voice_speed), 1, 10);
- force_min_visible_bars(HILDON_CONTROLBAR(num_voice_speed), 1);
+ if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
+ {
+ gchar *filename = gtk_file_chooser_get_filename(
+ GTK_FILE_CHOOSER(dialog));
+ gtk_entry_set_text(GTK_ENTRY(browse_info->txt), filename);
+ g_free(filename);
+ }
- gtk_box_pack_start(GTK_BOX(hbox),
- hbox2 = gtk_hbox_new(FALSE, 4),
- TRUE, TRUE, 4);
- gtk_box_pack_start(GTK_BOX(hbox2),
- label = gtk_label_new(_("Pitch")),
- TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox2),
- num_voice_pitch = hildon_controlbar_new(),
- TRUE, TRUE, 0);
- hildon_controlbar_set_range(HILDON_CONTROLBAR(num_voice_pitch), -2, 8);
- force_min_visible_bars(HILDON_CONTROLBAR(num_voice_pitch), 1);
+ gtk_widget_destroy(dialog);
- /* Misc. page. */
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
- table = gtk_table_new(2, 3, FALSE),
- label = gtk_label_new(_("Misc.")));
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Line Width. */
+
+typedef struct _ColorsDialogInfo ColorsDialogInfo;
+struct _ColorsDialogInfo {
+ GtkWidget *col_mark;
+ GtkWidget *col_mark_velocity;
+ GtkWidget *col_mark_old;
+ GtkWidget *col_track;
+ GtkWidget *col_track_break;
+ GtkWidget *col_route;
+ GtkWidget *col_route_way;
+ GtkWidget *col_route_nextway;
+ GtkWidget *col_poi;
+};
+
+static gboolean
+settings_dialog_colors_reset(GtkWidget *widget, ColorsDialogInfo *cdi)
+{
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_mark),
+ &DEFAULT_COLOR_MARK);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_mark_velocity),
+ &DEFAULT_COLOR_MARK_VELOCITY);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_mark_old),
+ &DEFAULT_COLOR_MARK_OLD);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_track),
+ &DEFAULT_COLOR_TRACK);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_track_break),
+ &DEFAULT_COLOR_TRACK_BREAK);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_route),
+ &DEFAULT_COLOR_ROUTE);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_route_way),
+ &DEFAULT_COLOR_ROUTE_WAY);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_route_nextway),
+ &DEFAULT_COLOR_ROUTE_NEXTWAY);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi->col_poi),
+ &DEFAULT_COLOR_POI);
+ return TRUE;
+}
+
+static gboolean
+settings_dialog_colors(GtkWidget *widget, GtkWidget *parent)
+{
+ GtkWidget *dialog;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *btn_defaults;
+ ColorsDialogInfo cdi;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ dialog = gtk_dialog_new_with_buttons(_("Colors"),
+ GTK_WINDOW(parent), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+ btn_defaults = gtk_button_new_with_label(_("Defaults")));
+ g_signal_connect(G_OBJECT(btn_defaults), "clicked",
+ G_CALLBACK(settings_dialog_colors_reset), &cdi);
+
+ gtk_dialog_add_button(GTK_DIALOG(dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ table = gtk_table_new(4, 3, FALSE), TRUE, TRUE, 0);
+
+ /* Mark. */
gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Line Width")),
+ label = gtk_label_new(_("GPS Mark")),
0, 1, 0, 1, GTK_FILL, 0, 2, 4);
gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
gtk_table_attach(GTK_TABLE(table),
- num_draw_line_width = hildon_controlbar_new(),
- 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- hildon_controlbar_set_range(HILDON_CONTROLBAR(num_draw_line_width), 1, 20);
- force_min_visible_bars(HILDON_CONTROLBAR(num_draw_line_width), 1);
+ cdi.col_mark = hildon_color_button_new(),
+ 1, 2, 0, 1, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_mark), &_color_mark);
+ gtk_table_attach(GTK_TABLE(table),
+ cdi.col_mark_velocity = hildon_color_button_new(),
+ 2, 3, 0, 1, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_mark_velocity), &_color_mark_velocity);
+ gtk_table_attach(GTK_TABLE(table),
+ cdi.col_mark_old = hildon_color_button_new(),
+ 3, 4, 0, 1, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_mark_old), &_color_mark_old);
- /* Keep Display On Only When Fullscreen. */
+ /* Track. */
gtk_table_attach(GTK_TABLE(table),
- chk_always_keep_on = gtk_check_button_new_with_label(
- _("Keep Display On Only in Fullscreen Mode")),
- 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ label = gtk_label_new(_("Track")),
+ 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ cdi.col_track = hildon_color_button_new(),
+ 1, 2, 1, 2, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_track), &_color_track);
+ gtk_table_attach(GTK_TABLE(table),
+ cdi.col_track_break = hildon_color_button_new(),
+ 2, 3, 1, 2, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_track_break), &_color_track_break);
- /* Units. */
+ /* Route. */
gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Units")),
+ label = gtk_label_new(_("Route")),
0, 1, 2, 3, GTK_FILL, 0, 2, 4);
gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
gtk_table_attach(GTK_TABLE(table),
- label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
- 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_container_add(GTK_CONTAINER(label),
- cmb_units = gtk_combo_box_new_text());
- gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_KM);
- gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_MI);
- gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_NM);
-
- /* Connect signals. */
- scan_info.settings_dialog = dialog;
- scan_info.txt_rcvr_mac = txt_rcvr_mac;
- g_signal_connect(G_OBJECT(btn_scan), "clicked",
- G_CALLBACK(scan_bluetooth), &scan_info);
- browse_info.dialog = dialog;
- browse_info.txt_map_dir_name = txt_map_dir_name;
- g_signal_connect(G_OBJECT(btn_browse), "clicked",
- G_CALLBACK(settings_dialog_browse), &browse_info);
- g_signal_connect(G_OBJECT(btn_colors), "clicked",
- G_CALLBACK(settings_dialog_colors), dialog);
-
- /* Initialize fields. */
- if(_rcvr_mac)
- gtk_entry_set_text(GTK_ENTRY(txt_rcvr_mac), _rcvr_mac);
- hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(num_rcvr_chan),
- _rcvr_addr.rc_channel);
- if(_map_uri_format)
- gtk_entry_set_text(GTK_ENTRY(txt_map_uri_format), _map_uri_format);
- hildon_controlbar_set_value(HILDON_CONTROLBAR(num_zoom_steps), _zoom_steps);
- if(_map_dir_name)
- gtk_entry_set_text(GTK_ENTRY(txt_map_dir_name), _map_dir_name);
- hildon_controlbar_set_value(HILDON_CONTROLBAR(num_center_ratio),
- _center_ratio);
- hildon_controlbar_set_value(HILDON_CONTROLBAR(num_lead_ratio),
- _lead_ratio);
- hildon_controlbar_set_value(HILDON_CONTROLBAR(num_announce_notice),
- _announce_notice_ratio);
- hildon_controlbar_set_value(HILDON_CONTROLBAR(num_voice_speed),
- (gint)(_voice_speed * 3 + 0.5));
- hildon_controlbar_set_value(HILDON_CONTROLBAR(num_voice_pitch),
- _voice_pitch);
- hildon_controlbar_set_value(HILDON_CONTROLBAR(num_draw_line_width),
- _draw_line_width);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_always_keep_on),
- !_always_keep_on);
- gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_units),
- !strcmp(_units, UNITS_MI) ? 1 :
- !strcmp(_units, UNITS_NM) ? 2 : 0);
+ cdi.col_route = hildon_color_button_new(),
+ 1, 2, 2, 3, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_route), &_color_route);
+ gtk_table_attach(GTK_TABLE(table),
+ cdi.col_route_way = hildon_color_button_new(),
+ 2, 3, 2, 3, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_route_way), &_color_route_way);
+ gtk_table_attach(GTK_TABLE(table),
+ cdi.col_route_nextway = hildon_color_button_new(),
+ 3, 4, 2, 3, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_route_nextway), &_color_route_nextway);
+
+ /* POI. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("POI")),
+ 0, 1, 3, 4, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ cdi.col_poi = hildon_color_button_new(),
+ 1, 2, 3, 4, 0, 0, 2, 4);
+ hildon_color_button_set_color(
+ HILDON_COLOR_BUTTON(cdi.col_poi), &_color_poi);
gtk_widget_show_all(dialog);
while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
{
- if(!config_set_map_dir_name(gnome_vfs_expand_initial_tilde(
- gtk_entry_get_text(GTK_ENTRY(txt_map_dir_name)))))
- {
- popup_error(dialog, _("Could not create Map Cache directory."));
- continue;
- }
-
- /* Set _rcvr_mac if necessary. */
- if(!*gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)))
- {
- /* User specified no rcvr mac - set _rcvr_mac to NULL. */
- if(_rcvr_mac)
- {
- g_free(_rcvr_mac);
- _rcvr_mac = NULL;
- rcvr_changed = TRUE;
- }
- if(_enable_gps)
- {
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), FALSE);
- popup_error(dialog, _("No GPS Receiver MAC Provided.\n"
- "GPS Disabled."));
- rcvr_changed = TRUE;
- }
- }
- else if(!_rcvr_mac || strcmp(_rcvr_mac,
- gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac))))
- {
- /* User specified a new rcvr mac. */
- if(_rcvr_mac)
- g_free(_rcvr_mac);
- _rcvr_mac = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)));
- str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr);
- rcvr_changed = TRUE;
- }
-
- if(_rcvr_addr.rc_channel != hildon_number_editor_get_value(
- HILDON_NUMBER_EDITOR(num_rcvr_chan)))
- {
- _rcvr_addr.rc_channel = hildon_number_editor_get_value(
- HILDON_NUMBER_EDITOR(num_rcvr_chan));
- rcvr_changed = TRUE;
- }
-
- if(_map_uri_format)
- g_free(_map_uri_format);
- if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_map_uri_format))))
- _map_uri_format = g_strdup(gtk_entry_get_text(
- GTK_ENTRY(txt_map_uri_format)));
- else
- _map_uri_format = NULL;
-
- _zoom_steps = hildon_controlbar_get_value(
- HILDON_CONTROLBAR(num_zoom_steps));
+ GdkColor *color;
- _center_ratio = hildon_controlbar_get_value(
- HILDON_CONTROLBAR(num_center_ratio));
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_mark));
+ _color_mark = *color;
- _lead_ratio = hildon_controlbar_get_value(
- HILDON_CONTROLBAR(num_lead_ratio));
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_mark_velocity));
+ _color_mark_velocity = *color;
- _draw_line_width = hildon_controlbar_get_value(
- HILDON_CONTROLBAR(num_draw_line_width));
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_mark_old));
+ _color_mark_old = *color;
- _always_keep_on = !gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(chk_always_keep_on));
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_track));
+ _color_track = *color;
- g_free(_units);
- _units = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cmb_units));
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_track_break));
+ _color_track_break = *color;
- _announce_notice_ratio = hildon_controlbar_get_value(
- HILDON_CONTROLBAR(num_announce_notice));
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_route));
+ _color_route = *color;
- _voice_speed = hildon_controlbar_get_value(
- HILDON_CONTROLBAR(num_voice_speed)) / 3.0;
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_route_way));
+ _color_route_way = *color;
- _voice_pitch = hildon_controlbar_get_value(
- HILDON_CONTROLBAR(num_voice_pitch));
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_route_nextway));
+ _color_route_nextway = *color;
- _enable_voice = gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(chk_enable_voice));
+ color = hildon_color_button_get_color(
+ HILDON_COLOR_BUTTON(cdi.col_poi));
+ _color_poi = *color;
update_gcs();
-
- config_save();
break;
}
- gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
+ gtk_widget_destroy(dialog);
- vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, rcvr_changed);
- return rcvr_changed;
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
/**
- * Initialize all configuration from GCONF. This should not be called more
- * than once during execution.
+ * Bring up the Settings dialog. Return TRUE if and only if the recever
+ * information has changed (MAC or channel).
*/
-static void
-config_init()
+static gboolean
+settings_dialog()
{
- GConfValue *value;
- GConfClient *gconf_client = gconf_client_get_default();
- gchar *str;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ GtkWidget *dialog;
+ GtkWidget *notebook;
+ GtkWidget *table;
+ GtkWidget *hbox;
+ GtkWidget *hbox2;
+ GtkWidget *label;
+ GtkWidget *txt_rcvr_mac;
+ GtkWidget *num_rcvr_chan;
+ GtkWidget *num_center_ratio;
+ GtkWidget *num_lead_ratio;
+ GtkWidget *num_announce_notice;
+ GtkWidget *chk_enable_voice;
+ GtkWidget *num_voice_speed;
+ GtkWidget *num_voice_pitch;
+ GtkWidget *num_draw_line_width;
+ GtkWidget *chk_always_keep_on;
+ GtkWidget *cmb_units;
+ GtkWidget *cmb_escape_key;
+ GtkWidget *btn_scan;
+ GtkWidget *btn_colors;
- if(!gconf_client)
- {
- popup_error(_window, _("Failed to initialize GConf. Quitting."));
- exit(1);
- }
+ GtkWidget *txt_poi_db;
+ GtkWidget *btn_browsepoi;
+ GtkWidget *num_poi_zoom;
- /* Get Receiver MAC from GConf. Default is scanned via hci_inquiry. */
- {
- _rcvr_mac = gconf_client_get_string(
- gconf_client, GCONF_KEY_RCVR_MAC, NULL);
- if(_rcvr_mac)
- str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr);
- }
+ BrowseInfo browse_info = {0, 0};
+ ScanInfo scan_info = {0};
+ gboolean rcvr_changed = FALSE;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Get Receiver Channel from GConf. Default is 1. */
- _rcvr_addr.rc_family = AF_BLUETOOTH;
- _rcvr_addr.rc_channel = gconf_client_get_int(gconf_client,
- GCONF_KEY_RCVR_CHAN, NULL);
- if(_rcvr_addr.rc_channel < 1)
- _rcvr_addr.rc_channel = 1;
+ dialog = gtk_dialog_new_with_buttons(_("Maemo Mapper Settings"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
- /* Get Map Download URI Format. Default is NULL. */
- _map_uri_format = gconf_client_get_string(gconf_client,
- GCONF_KEY_MAP_URI_FORMAT, NULL);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+ btn_colors = gtk_button_new_with_label(_("Colors...")));
- /* Get Map Download Zoom Steps. Default is 2. */
- _zoom_steps = gconf_client_get_int(gconf_client,
- GCONF_KEY_MAP_ZOOM_STEPS, NULL);
- if(!_zoom_steps)
- _zoom_steps = 2;
+ gtk_dialog_add_button(GTK_DIALOG(dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
- /* Get Map Cache Directory. Default is "~/apps/maemo-mapper". */
- {
- gchar *tmp = gconf_client_get_string(gconf_client,
- GCONF_KEY_MAP_DIR_NAME, NULL);
- if(!tmp)
- tmp = g_strdup("~/apps/maemo-mapper");
- if(!config_set_map_dir_name(gnome_vfs_expand_initial_tilde(tmp)))
- {
- popup_error(_window,
- _("Could not create Map Cache directory.\n"
- "Please set a valid Map Cache directory in the Settings"
- " dialog box."));
- }
- g_free(tmp);
- }
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ notebook = gtk_notebook_new(), TRUE, TRUE, 0);
+
+ /* Receiver page. */
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ table = gtk_table_new(2, 3, FALSE),
+ label = gtk_label_new(_("GPS")));
- /* Get Auto-Download. Default is FALSE. */
- _auto_download = gconf_client_get_bool(gconf_client,
- GCONF_KEY_AUTO_DOWNLOAD, NULL);
+ /* Receiver MAC Address. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("MAC")),
+ 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ hbox = gtk_hbox_new(FALSE, 4),
+ 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ txt_rcvr_mac = gtk_entry_new(),
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ btn_scan = gtk_button_new_with_label(_("Scan...")),
+ FALSE, FALSE, 0);
- /* Get Center Ratio - Default is 3. */
- _center_ratio = gconf_client_get_int(gconf_client,
- GCONF_KEY_CENTER_SENSITIVITY, NULL);
- if(!_center_ratio)
- _center_ratio = 7;
+ /* Receiver Channel. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Channel")),
+ 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_container_add(GTK_CONTAINER(label),
+ num_rcvr_chan = hildon_number_editor_new(0, 255));
- /* Get Lead Ratio - Default is 5. */
- _lead_ratio = gconf_client_get_int(gconf_client,
- GCONF_KEY_LEAD_AMOUNT, NULL);
- if(!_lead_ratio)
- _lead_ratio = 5;
+ /* Note!. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(
+ _("Note: \"Channel\" refers to the device side!")),
+ 0, 2, 2, 3, GTK_FILL, 0, 2, 4);
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
- /* Get Draw Line Width- Default is 5. */
- _draw_line_width = gconf_client_get_int(gconf_client,
- GCONF_KEY_DRAW_LINE_WIDTH, NULL);
- if(!_draw_line_width)
- _draw_line_width = 5;
- /* Get Announce Advance Notice - Default is 30. */
- value = gconf_client_get(gconf_client, GCONF_KEY_ANNOUNCE_NOTICE, NULL);
- if(value)
- {
- _announce_notice_ratio = gconf_value_get_int(value);
- gconf_value_free(value);
- }
- else
- _announce_notice_ratio = 6;
+ /* Auto-Center page. */
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ table = gtk_table_new(2, 2, FALSE),
+ label = gtk_label_new(_("Auto-Center")));
- /* Get Enable Voice flag. Default is TRUE. */
- value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_VOICE, NULL);
- if(value)
- {
- _enable_voice = gconf_value_get_bool(value);
- gconf_value_free(value);
- }
- else
- _enable_voice = TRUE;
+ /* Auto-Center Sensitivity. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Sensitivity")),
+ 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_container_add(GTK_CONTAINER(label),
+ num_center_ratio = hildon_controlbar_new());
+ hildon_controlbar_set_range(HILDON_CONTROLBAR(num_center_ratio), 1, 10);
+ force_min_visible_bars(HILDON_CONTROLBAR(num_center_ratio), 1);
- /* Get Voice Speed - Default is 1.0. */
- value = gconf_client_get(gconf_client, GCONF_KEY_VOICE_SPEED, NULL);
- if(value)
- {
- _voice_speed = gconf_value_get_float(value);
- gconf_value_free(value);
- }
- else
- _voice_speed = 1.0;
+ /* Lead Amount. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Lead Amount")),
+ 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_container_add(GTK_CONTAINER(label),
+ num_lead_ratio = hildon_controlbar_new());
+ hildon_controlbar_set_range(HILDON_CONTROLBAR(num_lead_ratio), 1, 10);
+ force_min_visible_bars(HILDON_CONTROLBAR(num_lead_ratio), 1);
- /* Get Voice Speed - Default is 0. */
- value = gconf_client_get(gconf_client, GCONF_KEY_VOICE_PITCH, NULL);
- if(value)
- {
- _voice_pitch = gconf_value_get_int(value);
- gconf_value_free(value);
- }
- else
- _voice_pitch = 3;
+ /* Announcement. */
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ table = gtk_table_new(2, 3, FALSE),
+ label = gtk_label_new(_("Announce")));
- /* Get Always Keep On flag. Default is FALSE. */
- _always_keep_on = gconf_client_get_bool(gconf_client,
- GCONF_KEY_ALWAYS_KEEP_ON, NULL);
+ /* Announcement Advance Notice. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Advance Notice")),
+ 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ num_announce_notice = hildon_controlbar_new(),
+ 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ hildon_controlbar_set_range(HILDON_CONTROLBAR(num_announce_notice), 1, 20);
+ force_min_visible_bars(HILDON_CONTROLBAR(num_announce_notice), 1);
- /* Get Always Keep On flag. Default is FALSE. */
- _units = gconf_client_get_string(gconf_client,
- GCONF_KEY_UNITS, NULL);
- if(!_units)
- _units = g_strdup(UNITS_KM);
+ /* Enable Voice. */
+ gtk_table_attach(GTK_TABLE(table),
+ chk_enable_voice = gtk_check_button_new_with_label(
+ _("Enable Voice Synthesis (requires flite)")),
+ 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enable_voice),
+ _enable_voice);
- /* Get last saved latitude. Default is 0. */
- _pos_lat = gconf_client_get_float(gconf_client, GCONF_KEY_LAT, NULL);
+ /* Voice Speed and Pitch. */
+ gtk_table_attach(GTK_TABLE(table),
+ hbox = gtk_hbox_new(FALSE, 12),
+ 0, 2, 2, 3, 0, 0, 2, 6);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ hbox2 = gtk_hbox_new(FALSE, 4),
+ TRUE, TRUE, 4);
+ gtk_box_pack_start(GTK_BOX(hbox2),
+ label = gtk_label_new(_("Speed")),
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox2),
+ num_voice_speed = hildon_controlbar_new(),
+ TRUE, TRUE, 0);
+ hildon_controlbar_set_range(HILDON_CONTROLBAR(num_voice_speed), 1, 10);
+ force_min_visible_bars(HILDON_CONTROLBAR(num_voice_speed), 1);
- /* Get last saved longitude. Default is somewhere in Midwest. */
- value = gconf_client_get(gconf_client, GCONF_KEY_LON, NULL);
- _pos_lon = gconf_client_get_float(gconf_client, GCONF_KEY_LON, NULL);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ hbox2 = gtk_hbox_new(FALSE, 4),
+ TRUE, TRUE, 4);
+ gtk_box_pack_start(GTK_BOX(hbox2),
+ label = gtk_label_new(_("Pitch")),
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox2),
+ num_voice_pitch = hildon_controlbar_new(),
+ TRUE, TRUE, 0);
+ hildon_controlbar_set_range(HILDON_CONTROLBAR(num_voice_pitch), -2, 8);
+ force_min_visible_bars(HILDON_CONTROLBAR(num_voice_pitch), 1);
- /* Get last center point. */
- {
- gfloat center_lat, center_lon;
+ /* Misc. page. */
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ table = gtk_table_new(2, 3, FALSE),
+ label = gtk_label_new(_("Misc.")));
- /* Get last saved latitude. Default is last saved latitude. */
- value = gconf_client_get(gconf_client, GCONF_KEY_CENTER_LAT, NULL);
- if(value)
- {
- center_lat = gconf_value_get_float(value);
- gconf_value_free(value);
- }
- else
- center_lat = _pos_lat;
+ /* Line Width. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Line Width")),
+ 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ num_draw_line_width = hildon_controlbar_new(),
+ 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ hildon_controlbar_set_range(HILDON_CONTROLBAR(num_draw_line_width), 1, 20);
+ force_min_visible_bars(HILDON_CONTROLBAR(num_draw_line_width), 1);
- /* Get last saved longitude. Default is last saved longitude. */
- value = gconf_client_get(gconf_client, GCONF_KEY_CENTER_LON, NULL);
- if(value)
- {
- center_lon = gconf_value_get_float(value);
- gconf_value_free(value);
- }
- else
- center_lon = _pos_lon;
+ /* Keep Display On Only When Fullscreen. */
+ gtk_table_attach(GTK_TABLE(table),
+ chk_always_keep_on = gtk_check_button_new_with_label(
+ _("Keep Display On Only in Fullscreen Mode")),
+ 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- latlon2unit(center_lat, center_lon, _center.unitx, _center.unity);
- }
+ /* Units. */
+ gtk_table_attach(GTK_TABLE(table),
+ hbox = gtk_hbox_new(FALSE, 4),
+ 0, 2, 2, 3, GTK_FILL, 0, 2, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ label = gtk_label_new(_("Units")),
+ FALSE, FALSE, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ TRUE, TRUE, 0);
+ gtk_container_add(GTK_CONTAINER(label),
+ cmb_units = gtk_combo_box_new_text());
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_KM_TEXT);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_MI_TEXT);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_NM_TEXT);
- /* Get last Zoom Level. Default is 16. */
- value = gconf_client_get(gconf_client, GCONF_KEY_ZOOM, NULL);
- if(value)
- {
- _zoom = gconf_value_get_int(value);
- gconf_value_free(value);
- }
- else
- _zoom = 16;
- BOUND(_zoom, 0, MAX_ZOOM - 1);
- _world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
+ /* Escape Key. */
+ gtk_box_pack_start(GTK_BOX(hbox),
+ label = gtk_label_new(_("Escape Key")),
+ FALSE, FALSE, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ TRUE, TRUE, 0);
+ gtk_container_add(GTK_CONTAINER(label),
+ cmb_escape_key = gtk_combo_box_new_text());
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_escape_key),
+ ESCAPE_KEY_TOGGLE_TRACKS_TEXT);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_escape_key),
+ ESCAPE_KEY_CHANGE_REPO_TEXT);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_escape_key),
+ ESCAPE_KEY_RESET_BLUETOOTH_TEXT);
+
+ /* POI page */
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ table = gtk_table_new(2, 3, FALSE),
+ label = gtk_label_new(_("POI")));
- /* Speed and Heading are always initialized as 0. */
- _speed = 0.f;
- _heading = 0.f;
+ /* POI database. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("POI database")),
+ 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ hbox = gtk_hbox_new(FALSE, 4),
+ 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ txt_poi_db = gtk_entry_new(),
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ btn_browsepoi = gtk_button_new_with_label(_("Browse...")),
+ FALSE, FALSE, 0);
- /* Get Route Directory. Default is NULL. */
- _route_dir_uri = gconf_client_get_string(gconf_client,
- GCONF_KEY_ROUTEDIR, NULL);
+ /* Show POI below zoom. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Show POI below zoom")),
+ 0, 1, 2, 3, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_container_add(GTK_CONTAINER(label),
+ num_poi_zoom = hildon_number_editor_new(0, MAX_ZOOM));
- /* Get Last Track File. Default is NULL. */
- _track_file_uri = gconf_client_get_string(gconf_client,
- GCONF_KEY_TRACKFILE, NULL);
- /* Get Auto-Center Mode. Default is CENTER_LEAD. */
- value = gconf_client_get(gconf_client, GCONF_KEY_AUTOCENTER_MODE, NULL);
- if(value)
- {
- _center_mode = gconf_value_get_int(value);
- gconf_value_free(value);
- }
- else
- _center_mode = CENTER_LEAD;
+ /* Connect signals. */
+ scan_info.settings_dialog = dialog;
+ scan_info.txt_rcvr_mac = txt_rcvr_mac;
+ g_signal_connect(G_OBJECT(btn_scan), "clicked",
+ G_CALLBACK(scan_bluetooth), &scan_info);
+ g_signal_connect(G_OBJECT(btn_colors), "clicked",
+ G_CALLBACK(settings_dialog_colors), dialog);
- /* Get Show Tracks flag. Default is TRUE. */
- value = gconf_client_get(gconf_client, GCONF_KEY_SHOWTRACKS, NULL);
- if(value)
- {
- _show_tracks |= (gconf_value_get_bool(value) ? TRACKS_MASK : 0);
- gconf_value_free(value);
- }
- else
- _show_tracks |= TRACKS_MASK;
+ browse_info.dialog = dialog;
+ browse_info.txt = txt_poi_db;
+ g_signal_connect(G_OBJECT(btn_browsepoi), "clicked",
+ G_CALLBACK(settings_dialog_browse_forfile), &browse_info);
- /* Get Show Routes flag. Default is TRUE. */
- value = gconf_client_get(gconf_client, GCONF_KEY_SHOWROUTES, NULL);
- if(value)
- {
- _show_tracks |= (gconf_value_get_bool(value) ? ROUTES_MASK : 0);
- gconf_value_free(value);
- }
- else
- _show_tracks |= ROUTES_MASK;
+ /* Initialize fields. */
+ if(_rcvr_mac)
+ gtk_entry_set_text(GTK_ENTRY(txt_rcvr_mac), _rcvr_mac);
+ hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(num_rcvr_chan),
+ _rcvr_addr.rc_channel);
+ if(_poi_db)
+ gtk_entry_set_text(GTK_ENTRY(txt_poi_db), _poi_db);
+ hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(num_poi_zoom),
+ _poi_zoom);
+ hildon_controlbar_set_value(HILDON_CONTROLBAR(num_center_ratio),
+ _center_ratio);
+ hildon_controlbar_set_value(HILDON_CONTROLBAR(num_lead_ratio),
+ _lead_ratio);
+ hildon_controlbar_set_value(HILDON_CONTROLBAR(num_announce_notice),
+ _announce_notice_ratio);
+ hildon_controlbar_set_value(HILDON_CONTROLBAR(num_voice_speed),
+ (gint)(_voice_speed * 3 + 0.5));
+ hildon_controlbar_set_value(HILDON_CONTROLBAR(num_voice_pitch),
+ _voice_pitch);
+ hildon_controlbar_set_value(HILDON_CONTROLBAR(num_draw_line_width),
+ _draw_line_width);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_always_keep_on),
+ !_always_keep_on);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_units), _units);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_escape_key), _escape_key);
- /* Get Show Velocity Vector flag. Default is TRUE. */
- value = gconf_client_get(gconf_client, GCONF_KEY_SHOWVELVEC, NULL);
- if(value)
- {
- _show_velvec = gconf_value_get_bool(value);
- gconf_value_free(value);
- }
- else
- _show_velvec = TRUE;
+ gtk_widget_show_all(dialog);
- /* Get Enable GPS flag. Default is TRUE. */
- value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_GPS, NULL);
- if(value)
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
{
- _enable_gps = gconf_value_get_bool(value);
- gconf_value_free(value);
- }
- else
- _enable_gps = TRUE;
-
- /* Initialize _conn_state based on _enable_gps. */
- _conn_state = (_enable_gps ? RCVR_DOWN : RCVR_OFF);
+ /* Set _rcvr_mac if necessary. */
+ if(!*gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)))
+ {
+ /* User specified no rcvr mac - set _rcvr_mac to NULL. */
+ if(_rcvr_mac)
+ {
+ g_free(_rcvr_mac);
+ _rcvr_mac = NULL;
+ rcvr_changed = TRUE;
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(_menu_gps_details_item), FALSE);
+ }
+ if(_enable_gps)
+ {
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), FALSE);
+ popup_error(dialog, _("No GPS Receiver MAC Provided.\n"
+ "GPS Disabled."));
+ rcvr_changed = TRUE;
+ gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_details_item),
+ FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_reset_item),
+ FALSE);
+ }
+ }
+ else if(!_rcvr_mac || strcmp(_rcvr_mac,
+ gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac))))
+ {
+ /* User specified a new rcvr mac. */
+ if(_rcvr_mac)
+ g_free(_rcvr_mac);
+ _rcvr_mac = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)));
+ str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr);
+ rcvr_changed = TRUE;
+ }
- /* Load the route locations. */
- {
- GSList *curr;
- _loc_list = gconf_client_get_list(gconf_client,
- GCONF_KEY_ROUTE_LOCATIONS, GCONF_VALUE_STRING, NULL);
- _loc_model = gtk_list_store_new(1, G_TYPE_STRING);
- for(curr = _loc_list; curr != NULL; curr = curr->next)
+ if(_rcvr_addr.rc_channel != hildon_number_editor_get_value(
+ HILDON_NUMBER_EDITOR(num_rcvr_chan)))
{
- GtkTreeIter iter;
- gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX,
- 0, curr->data, -1);
+ _rcvr_addr.rc_channel = hildon_number_editor_get_value(
+ HILDON_NUMBER_EDITOR(num_rcvr_chan));
+ rcvr_changed = TRUE;
}
- }
- /* Initialize colors. */
- str = gconf_client_get_string(gconf_client,
- GCONF_KEY_COLOR_MARK, NULL);
- if(!str || !gdk_color_parse(str, &_color_mark))
- _color_mark = DEFAULT_COLOR_MARK;
+ _center_ratio = hildon_controlbar_get_value(
+ HILDON_CONTROLBAR(num_center_ratio));
- str = gconf_client_get_string(gconf_client,
- GCONF_KEY_COLOR_MARK_VELOCITY, NULL);
- if(!str || !gdk_color_parse(str, &_color_mark_velocity))
- _color_mark_velocity = DEFAULT_COLOR_MARK_VELOCITY;
+ _lead_ratio = hildon_controlbar_get_value(
+ HILDON_CONTROLBAR(num_lead_ratio));
- str = gconf_client_get_string(gconf_client,
- GCONF_KEY_COLOR_MARK_OLD, NULL);
- if(!str || !gdk_color_parse(str, &_color_mark_old))
- _color_mark_old = DEFAULT_COLOR_MARK_OLD;
+ _draw_line_width = hildon_controlbar_get_value(
+ HILDON_CONTROLBAR(num_draw_line_width));
- str = gconf_client_get_string(gconf_client,
- GCONF_KEY_COLOR_TRACK, NULL);
- if(!str || !gdk_color_parse(str, &_color_track))
- _color_track = DEFAULT_COLOR_TRACK;
+ _always_keep_on = !gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(chk_always_keep_on));
- str = gconf_client_get_string(gconf_client,
- GCONF_KEY_COLOR_TRACK_BREAK, NULL);
- if(!str || !gdk_color_parse(str, &_color_track_break))
- _color_track_break = DEFAULT_COLOR_TRACK_BREAK;
+ _units = gtk_combo_box_get_active(GTK_COMBO_BOX(cmb_units));
+ _escape_key = gtk_combo_box_get_active(GTK_COMBO_BOX(cmb_escape_key));
- str = gconf_client_get_string(gconf_client,
- GCONF_KEY_COLOR_ROUTE, NULL);
- if(!str || !gdk_color_parse(str, &_color_route))
- _color_route = DEFAULT_COLOR_ROUTE;
+ _announce_notice_ratio = hildon_controlbar_get_value(
+ HILDON_CONTROLBAR(num_announce_notice));
- str = gconf_client_get_string(gconf_client,
- GCONF_KEY_COLOR_ROUTE_WAY, NULL);
- if(!str || !gdk_color_parse(str, &_color_route_way))
- _color_route_way = DEFAULT_COLOR_ROUTE_WAY;
+ _voice_speed = hildon_controlbar_get_value(
+ HILDON_CONTROLBAR(num_voice_speed)) / 3.0;
- str = gconf_client_get_string(gconf_client,
- GCONF_KEY_COLOR_ROUTE_NEXTWAY, NULL);
- if(!str || !gdk_color_parse(str, &_color_route_nextway))
- _color_route_nextway = DEFAULT_COLOR_ROUTE_NEXTWAY;
+ _voice_pitch = hildon_controlbar_get_value(
+ HILDON_CONTROLBAR(num_voice_pitch));
+
+ _enable_voice = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(chk_enable_voice));
+ if(_dbconn)
+ {
+ sqlite_close(_db);
+ _dbconn = FALSE;
+ gtk_widget_set_sensitive(_cmenu_add_poi, FALSE);
+ gtk_widget_set_sensitive(_cmenu_edit_poi, FALSE);
+ gtk_widget_set_sensitive(_menu_poi_item, FALSE);
+ }
+ if(_poi_db)
+ g_free(_poi_db);
+ if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_poi_db))))
+ {
+ _poi_db = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_poi_db)));
+ db_connect();
+ gtk_widget_set_sensitive(_cmenu_add_poi, _dbconn);
+ gtk_widget_set_sensitive(_cmenu_edit_poi, _dbconn);
+ gtk_widget_set_sensitive(_menu_poi_item, _dbconn);
+ }
+ else
+ _poi_db = NULL;
- g_object_unref(gconf_client);
+ _poi_zoom = hildon_number_editor_get_value(
+ HILDON_NUMBER_EDITOR(num_poi_zoom));
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ update_gcs();
+
+ config_save();
+ break;
+ }
+
+ gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
+
+ vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, rcvr_changed);
+ return rcvr_changed;
}
/**
- * Create the menu items needed for the drop down menu.
+ * Initialize all configuration from GCONF. This should not be called more
+ * than once during execution.
*/
static void
-menu_init()
+config_init()
{
- /* Create needed handles. */
- GtkMenu *menu;
- GtkWidget *submenu;
- GtkWidget *menu_item;
+ GConfValue *value;
+ GConfClient *gconf_client = gconf_client_get_default();
+ gchar *str;
printf("%s()\n", __PRETTY_FUNCTION__);
- /* Get the menu of our view. */
- menu = GTK_MENU(gtk_menu_new());
-
- /* Create the menu items. */
+ if(!gconf_client)
+ {
+ popup_error(_window, _("Failed to initialize GConf. Quitting."));
+ exit(1);
+ }
- /* The "Routes" submenu. */
- gtk_menu_append(menu, menu_item
- = gtk_menu_item_new_with_label(_("Route")));
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
- submenu = gtk_menu_new());
- gtk_menu_append(submenu, _menu_route_open_item
- = gtk_menu_item_new_with_label(_("Open...")));
- gtk_menu_append(submenu, _menu_route_download_item
- = gtk_menu_item_new_with_label(_("Download...")));
- gtk_menu_append(submenu, _menu_route_save_item
- = gtk_menu_item_new_with_label(_("Save...")));
- gtk_menu_append(submenu, _menu_route_reset_item
- = gtk_menu_item_new_with_label(_("Reset")));
- gtk_menu_append(submenu, _menu_route_clear_item
- = gtk_menu_item_new_with_label(_("Clear")));
+ /* Get Receiver MAC from GConf. Default is scanned via hci_inquiry. */
+ {
+ _rcvr_mac = gconf_client_get_string(
+ gconf_client, GCONF_KEY_RCVR_MAC, NULL);
+ if(_rcvr_mac)
+ str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr);
+ }
- /* The "Track" submenu. */
- gtk_menu_append(menu, menu_item
- = gtk_menu_item_new_with_label(_("Track")));
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
- submenu = gtk_menu_new());
- gtk_menu_append(submenu, _menu_track_open_item
- = gtk_menu_item_new_with_label(_("Open...")));
- gtk_menu_append(submenu, _menu_track_save_item
- = gtk_menu_item_new_with_label(_("Save...")));
- gtk_menu_append(submenu, _menu_track_mark_way_item
- = gtk_menu_item_new_with_label(_("Insert Breakpoint")));
- gtk_menu_append(submenu, _menu_track_clear_item
- = gtk_menu_item_new_with_label(_("Clear")));
+ /* Get Receiver Channel from GConf. Default is 1. */
+ _rcvr_addr.rc_family = AF_BLUETOOTH;
+ _rcvr_addr.rc_channel = gconf_client_get_int(gconf_client,
+ GCONF_KEY_RCVR_CHAN, NULL);
+ if(_rcvr_addr.rc_channel < 1)
+ _rcvr_addr.rc_channel = 1;
- gtk_menu_append(menu, menu_item
- = gtk_menu_item_new_with_label(_("Maps")));
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
- submenu = gtk_menu_new());
- gtk_menu_append(submenu, _menu_maps_dlroute_item
- = gtk_menu_item_new_with_label(_("Download Along Route")));
- gtk_menu_append(submenu, _menu_maps_dlarea_item
- = gtk_menu_item_new_with_label(_("Download Area...")));
- gtk_menu_append(submenu, _menu_auto_download_item
- = gtk_check_menu_item_new_with_label(_("Auto-Download")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_auto_download_item), _auto_download);
+ /* Get Auto-Download. Default is FALSE. */
+ _auto_download = gconf_client_get_bool(gconf_client,
+ GCONF_KEY_AUTO_DOWNLOAD, NULL);
- gtk_menu_append(menu, gtk_separator_menu_item_new());
+ /* Get Center Ratio - Default is 3. */
+ _center_ratio = gconf_client_get_int(gconf_client,
+ GCONF_KEY_CENTER_SENSITIVITY, NULL);
+ if(!_center_ratio)
+ _center_ratio = 7;
- gtk_menu_append(menu, menu_item
- = gtk_menu_item_new_with_label(_("Show")));
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
- submenu = gtk_menu_new());
- gtk_menu_append(submenu, _menu_show_routes_item
- = gtk_check_menu_item_new_with_label(_("Route")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_show_routes_item),
- _show_tracks & ROUTES_MASK);
- gtk_menu_append(submenu, _menu_show_tracks_item
- = gtk_check_menu_item_new_with_label(_("Track")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_show_tracks_item),
- _show_tracks & TRACKS_MASK);
- gtk_menu_append(submenu, _menu_show_velvec_item
- = gtk_check_menu_item_new_with_label(_("Velocity Vector")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_show_velvec_item), _show_velvec);
+ /* Get Lead Ratio - Default is 5. */
+ _lead_ratio = gconf_client_get_int(gconf_client,
+ GCONF_KEY_LEAD_AMOUNT, NULL);
+ if(!_lead_ratio)
+ _lead_ratio = 5;
- gtk_menu_append(menu, menu_item
- = gtk_menu_item_new_with_label(_("Auto-Center")));
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
- submenu = gtk_menu_new());
- gtk_menu_append(submenu, _menu_ac_latlon_item
- = gtk_radio_menu_item_new_with_label(NULL, _("Lat/Lon")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_ac_latlon_item),
- _center_mode == CENTER_LATLON);
- gtk_menu_append(submenu, _menu_ac_lead_item
- = gtk_radio_menu_item_new_with_label_from_widget(
- GTK_RADIO_MENU_ITEM(_menu_ac_latlon_item), _("Lead")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_ac_lead_item),
- _center_mode == CENTER_LEAD);
- gtk_menu_append(submenu, _menu_ac_none_item
- = gtk_radio_menu_item_new_with_label_from_widget(
- GTK_RADIO_MENU_ITEM(_menu_ac_latlon_item), _("None")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_ac_none_item),
- _center_mode < 0);
+ /* Get Draw Line Width- Default is 5. */
+ _draw_line_width = gconf_client_get_int(gconf_client,
+ GCONF_KEY_DRAW_LINE_WIDTH, NULL);
+ if(!_draw_line_width)
+ _draw_line_width = 5;
- gtk_menu_append(menu, _menu_fullscreen_item
- = gtk_check_menu_item_new_with_label(_("Full Screen")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_fullscreen_item), _fullscreen);
+ /* Get Announce Advance Notice - Default is 30. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_ANNOUNCE_NOTICE, NULL);
+ if(value)
+ {
+ _announce_notice_ratio = gconf_value_get_int(value);
+ gconf_value_free(value);
+ }
+ else
+ _announce_notice_ratio = 8;
- gtk_menu_append(menu, _menu_enable_gps_item
- = gtk_check_menu_item_new_with_label(_("Enable GPS")));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), _enable_gps);
+ /* Get Enable Voice flag. Default is TRUE. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_VOICE, NULL);
+ if(value)
+ {
+ _enable_voice = gconf_value_get_bool(value);
+ gconf_value_free(value);
+ }
+ else
+ _enable_voice = TRUE;
- gtk_menu_append(menu, gtk_separator_menu_item_new());
+ /* Get Voice Speed - Default is 1.0. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_VOICE_SPEED, NULL);
+ if(value)
+ {
+ _voice_speed = gconf_value_get_float(value);
+ gconf_value_free(value);
+ }
+ else
+ _voice_speed = 1.0;
- gtk_menu_append(menu, _menu_settings_item
- = gtk_menu_item_new_with_label(_("Settings...")));
+ /* Get Voice Speed - Default is 0. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_VOICE_PITCH, NULL);
+ if(value)
+ {
+ _voice_pitch = gconf_value_get_int(value);
+ gconf_value_free(value);
+ }
+ else
+ _voice_pitch = 3;
- gtk_menu_append(menu, gtk_separator_menu_item_new());
+ /* Get Always Keep On flag. Default is FALSE. */
+ _always_keep_on = gconf_client_get_bool(gconf_client,
+ GCONF_KEY_ALWAYS_KEEP_ON, NULL);
- gtk_menu_append(menu, _menu_help_item
- = gtk_menu_item_new_with_label(_("Help")));
+ /* Get Units. Default is UNITS_KM. */
+ {
+ gchar *units_str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_UNITS, NULL);
+ if(units_str == NULL)
+ _units = UNITS_KM;
+ else if(!strcmp(units_str, UNITS_MI_TEXT))
+ _units = UNITS_MI;
+ else if(!strcmp(units_str, UNITS_NM_TEXT))
+ _units = UNITS_NM;
+ else
+ _units = UNITS_KM;
+ }
- gtk_menu_append(menu, _menu_close_item
- = gtk_menu_item_new_with_label(_("Close")));
+ /* Get Escape Key. Default is ESCAPE_KEY_TOGGLE_TRACKS. */
+ {
+ gchar *escape_key_str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_ESCAPE_KEY, NULL);
+ if(escape_key_str == NULL)
+ _escape_key = ESCAPE_KEY_TOGGLE_TRACKS;
+ else if(!strcmp(escape_key_str, ESCAPE_KEY_CHANGE_REPO_TEXT))
+ _escape_key = ESCAPE_KEY_CHANGE_REPO;
+ else if(!strcmp(escape_key_str, ESCAPE_KEY_RESET_BLUETOOTH_TEXT))
+ _escape_key = ESCAPE_KEY_RESET_BLUETOOTH;
+ else
+ _escape_key = ESCAPE_KEY_TOGGLE_TRACKS;
+ }
- /* We need to show menu items. */
- gtk_widget_show_all(GTK_WIDGET(menu));
+ /* Get last saved latitude. Default is 0. */
+ _pos_lat = gconf_client_get_float(gconf_client, GCONF_KEY_LAT, NULL);
- hildon_window_set_menu(HILDON_WINDOW(_window), menu);
+ /* Get last saved longitude. Default is somewhere in Midwest. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_LON, NULL);
+ _pos_lon = gconf_client_get_float(gconf_client, GCONF_KEY_LON, NULL);
- /* Connect the signals. */
- g_signal_connect(G_OBJECT(_menu_route_open_item), "activate",
- G_CALLBACK(menu_cb_route_open), NULL);
- g_signal_connect(G_OBJECT(_menu_route_download_item), "activate",
- G_CALLBACK(menu_cb_route_download), NULL);
- g_signal_connect(G_OBJECT(_menu_route_save_item), "activate",
- G_CALLBACK(menu_cb_route_save), NULL);
- g_signal_connect(G_OBJECT(_menu_route_reset_item), "activate",
- G_CALLBACK(menu_cb_route_reset), NULL);
- g_signal_connect(G_OBJECT(_menu_route_clear_item), "activate",
- G_CALLBACK(menu_cb_route_clear), NULL);
- g_signal_connect(G_OBJECT(_menu_track_open_item), "activate",
- G_CALLBACK(menu_cb_track_open), NULL);
- g_signal_connect(G_OBJECT(_menu_track_save_item), "activate",
- G_CALLBACK(menu_cb_track_save), NULL);
- g_signal_connect(G_OBJECT(_menu_track_mark_way_item), "activate",
- G_CALLBACK(menu_cb_track_mark_way), NULL);
- g_signal_connect(G_OBJECT(_menu_track_clear_item), "activate",
- G_CALLBACK(menu_cb_track_clear), NULL);
- g_signal_connect(G_OBJECT(_menu_show_tracks_item), "toggled",
- G_CALLBACK(menu_cb_show_tracks), NULL);
- g_signal_connect(G_OBJECT(_menu_show_routes_item), "toggled",
- G_CALLBACK(menu_cb_show_routes), NULL);
- g_signal_connect(G_OBJECT(_menu_show_velvec_item), "toggled",
- G_CALLBACK(menu_cb_show_velvec), NULL);
- g_signal_connect(G_OBJECT(_menu_maps_dlroute_item), "activate",
- G_CALLBACK(menu_cb_maps_dlroute), NULL);
- g_signal_connect(G_OBJECT(_menu_maps_dlarea_item), "activate",
- G_CALLBACK(menu_cb_maps_dlarea), NULL);
- g_signal_connect(G_OBJECT(_menu_ac_latlon_item), "toggled",
- G_CALLBACK(menu_cb_ac_latlon), NULL);
- g_signal_connect(G_OBJECT(_menu_ac_lead_item), "toggled",
- G_CALLBACK(menu_cb_ac_lead), NULL);
- g_signal_connect(G_OBJECT(_menu_ac_none_item), "toggled",
- G_CALLBACK(menu_cb_ac_none), NULL);
- g_signal_connect(G_OBJECT(_menu_fullscreen_item), "toggled",
- G_CALLBACK(menu_cb_fullscreen), NULL);
- g_signal_connect(G_OBJECT(_menu_enable_gps_item), "toggled",
- G_CALLBACK(menu_cb_enable_gps), NULL);
- g_signal_connect(G_OBJECT(_menu_auto_download_item), "toggled",
- G_CALLBACK(menu_cb_auto_download), NULL);
- g_signal_connect(G_OBJECT(_menu_settings_item), "activate",
- G_CALLBACK(menu_cb_settings), NULL);
- g_signal_connect(G_OBJECT(_menu_help_item), "activate",
- G_CALLBACK(menu_cb_help), NULL);
- g_signal_connect(G_OBJECT(_menu_close_item), "activate",
- G_CALLBACK(gtk_main_quit), NULL);
+ /* Get last center point. */
+ {
+ gfloat center_lat, center_lon;
- /* Setup the context menu. */
- menu = GTK_MENU(gtk_menu_new());
+ /* Get last saved latitude. Default is last saved latitude. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_CENTER_LAT, NULL);
+ if(value)
+ {
+ center_lat = gconf_value_get_float(value);
+ gconf_value_free(value);
+ }
+ else
+ center_lat = _pos_lat;
- /* Setup the map context menu. */
- gtk_menu_append(menu, menu_item
- = gtk_menu_item_new_with_label(_("Location")));
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
- submenu = gtk_menu_new());
+ /* Get last saved longitude. Default is last saved longitude. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_CENTER_LON, NULL);
+ if(value)
+ {
+ center_lon = gconf_value_get_float(value);
+ gconf_value_free(value);
+ }
+ else
+ center_lon = _pos_lon;
- /* Setup the map context menu. */
- gtk_menu_append(submenu, _cmenu_loc_show_latlon_item
- = gtk_menu_item_new_with_label(_("Show Lat/Lon")));
- gtk_menu_append(submenu, _cmenu_loc_clip_latlon_item
- = gtk_menu_item_new_with_label(_("Copy Lat/Lon to Clipboard")));
- gtk_menu_append(submenu, gtk_separator_menu_item_new());
- gtk_menu_append(submenu, _cmenu_loc_route_to_item
- = gtk_menu_item_new_with_label(_("Download Route to...")));
- gtk_menu_append(submenu, _cmenu_loc_distance_to_item
- = gtk_menu_item_new_with_label(_("Show Distance to")));
+ latlon2unit(center_lat, center_lon, _center.unitx, _center.unity);
+ }
+ /* Load the repositories. */
+ {
+ GSList *curr;
+ guint curr_repo_index = gconf_client_get_int(gconf_client,
+ GCONF_KEY_CURRREPO, NULL);
+ curr = gconf_client_get_list(gconf_client,
+ GCONF_KEY_REPOSITORIES, GCONF_VALUE_STRING, NULL);
+
+ for(; curr != NULL; curr = curr->next)
+ {
+ /* Parse each part of a repo, delimited by newline characters:
+ * 1. url
+ * 2. cache_dir
+ * 3. dl_zoom_steps
+ * 4. view_zoom_steps
+ */
+ gchar *str = curr->data;
+ RepoData *rd = g_new(RepoData, 1);
+ rd->name = g_strdup(strsep(&str, "\n"));
+ rd->url = g_strdup(strsep(&str, "\n"));
+ rd->cache_dir = g_strdup(strsep(&str, "\n"));
+ rd->dl_zoom_steps = atoi(strsep(&str, "\n"));
+ if(rd->dl_zoom_steps == 0)
+ rd->dl_zoom_steps = 2;
+ rd->view_zoom_steps = atoi(strsep(&str, "\n"));
+ if(rd->view_zoom_steps == 0)
+ rd->view_zoom_steps = 1;
+
+ _repo_list = g_list_append(_repo_list, rd);
+ if(!curr_repo_index--)
+ _curr_repo = rd;
+ g_free(str);
+ }
+ g_slist_free(curr);
+ }
- /* Setup the waypoint context menu. */
- gtk_menu_append(menu, menu_item
- = gtk_menu_item_new_with_label(_("Waypoint")));
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
- submenu = gtk_menu_new());
+ if(_repo_list == NULL)
+ {
+ /* We have no repositories - create a default one. */
+ _curr_repo = g_new(RepoData, 1);
- gtk_menu_append(submenu, _cmenu_way_show_latlon_item
- = gtk_menu_item_new_with_label(_("Show Lat/Lon")));
- gtk_menu_append(submenu, _cmenu_way_show_desc_item
- = gtk_menu_item_new_with_label(_("Show Description")));
- gtk_menu_append(submenu, _cmenu_way_clip_latlon_item
- = gtk_menu_item_new_with_label(_("Copy Lat/Lon to Clipboard")));
- gtk_menu_append(submenu, _cmenu_way_clip_desc_item
- = gtk_menu_item_new_with_label(_("Copy Description to Clipboard")));
- gtk_menu_append(submenu, gtk_separator_menu_item_new());
- gtk_menu_append(submenu, _cmenu_way_route_to_item
- = gtk_menu_item_new_with_label(_("Download Route to...")));
- gtk_menu_append(submenu, _cmenu_way_distance_to_item
- = gtk_menu_item_new_with_label(_("Show Distance to")));
- gtk_menu_append(submenu, _cmenu_way_delete_item
- = gtk_menu_item_new_with_label(_("Delete")));
+ /* Many fields can be retrieved from the "old" gconf keys. */
- /* Connect signals for context menu. */
- g_signal_connect(G_OBJECT(_cmenu_loc_show_latlon_item), "activate",
- G_CALLBACK(cmenu_cb_loc_show_latlon), NULL);
- g_signal_connect(G_OBJECT(_cmenu_loc_clip_latlon_item), "activate",
- G_CALLBACK(cmenu_cb_loc_clip_latlon), NULL);
- g_signal_connect(G_OBJECT(_cmenu_loc_route_to_item), "activate",
- G_CALLBACK(cmenu_cb_loc_route_to), NULL);
- g_signal_connect(G_OBJECT(_cmenu_loc_distance_to_item), "activate",
- G_CALLBACK(cmenu_cb_loc_distance_to), NULL);
- g_signal_connect(G_OBJECT(_cmenu_way_show_latlon_item), "activate",
- G_CALLBACK(cmenu_cb_way_show_latlon), NULL);
- g_signal_connect(G_OBJECT(_cmenu_way_show_desc_item), "activate",
- G_CALLBACK(cmenu_cb_way_show_desc), NULL);
- g_signal_connect(G_OBJECT(_cmenu_way_clip_latlon_item), "activate",
- G_CALLBACK(cmenu_cb_way_clip_latlon), NULL);
- g_signal_connect(G_OBJECT(_cmenu_way_clip_desc_item), "activate",
- G_CALLBACK(cmenu_cb_way_clip_desc), NULL);
- g_signal_connect(G_OBJECT(_cmenu_way_route_to_item), "activate",
- G_CALLBACK(cmenu_cb_way_route_to), NULL);
- g_signal_connect(G_OBJECT(_cmenu_way_distance_to_item), "activate",
- G_CALLBACK(cmenu_cb_way_distance_to), NULL);
- g_signal_connect(G_OBJECT(_cmenu_way_delete_item), "activate",
- G_CALLBACK(cmenu_cb_way_delete), NULL);
+ /* Get Map Cache Dir. Default is ~/MyDocs/.documents/Maps. */
+ _curr_repo->cache_dir = gconf_client_get_string(gconf_client,
+ GCONF_KEY_MAP_DIR_NAME, NULL);
- gtk_widget_show_all(GTK_WIDGET(menu));
+ if(!_curr_repo->cache_dir)
+ _curr_repo->cache_dir = gnome_vfs_expand_initial_tilde(
+ "~/MyDocs/.documents/Maps");
- gtk_widget_tap_and_hold_setup(_map_widget, GTK_WIDGET(menu), NULL, 0);
+ /* Get Map Download URI Format. Default is "". */
+ _curr_repo->url = gconf_client_get_string(gconf_client,
+ GCONF_KEY_MAP_URI_FORMAT, NULL);
+ if(!_curr_repo->url)
+ _curr_repo->url = g_strdup("");
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+ /* Get Map Download Zoom Steps. Default is 2. */
+ _curr_repo->dl_zoom_steps = gconf_client_get_int(gconf_client,
+ GCONF_KEY_MAP_ZOOM_STEPS, NULL);
+ if(!_curr_repo->dl_zoom_steps)
+ _curr_repo->dl_zoom_steps = 2;
-/**
- * Call gtk_window_present() on Maemo Mapper. This also checks the
- * configuration and brings up the Settings dialog if the GPS Receiver is
- * not set up, the first time it is called.
- */
-static gboolean
-window_present()
-{
- static gint been_here = 0;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ /* Other fields are brand new. */
+ _curr_repo->name = g_strdup("Default");
+ _curr_repo->view_zoom_steps = 1;
+ _repo_list = g_list_append(_repo_list, _curr_repo);
+ }
- if(!been_here++)
+ /* Get last Zoom Level. Default is 16. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_ZOOM, NULL);
+ if(value)
{
- /* Set connection state first, to avoid going into this if twice. */
- if(_rcvr_mac || !_enable_gps || settings_dialog())
- {
- gtk_widget_show_all(_window);
-
- /* Connect to receiver. */
- if(_enable_gps)
- rcvr_connect_now();
- }
- else
- gtk_main_quit();
+ _zoom = gconf_value_get_int(value) / _curr_repo->view_zoom_steps
+ * _curr_repo->view_zoom_steps;
+ gconf_value_free(value);
}
- gtk_window_present(GTK_WINDOW(_window));
+ else
+ _zoom = 16 / _curr_repo->view_zoom_steps
+ * _curr_repo->view_zoom_steps;
+ BOUND(_zoom, 0, MAX_ZOOM - 1);
+ _world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
- /* Re-enable any banners that might have been up. */
+ /* Speed and Heading are always initialized as 0. */
+ _speed = 0.f;
+ _heading = 0.f;
+
+ /* Get Route Directory. Default is NULL. */
+ _route_dir_uri = gconf_client_get_string(gconf_client,
+ GCONF_KEY_ROUTEDIR, NULL);
+
+ /* Get Last Track File. Default is NULL. */
+ _track_file_uri = gconf_client_get_string(gconf_client,
+ GCONF_KEY_TRACKFILE, NULL);
+
+ /* Get Auto-Center Mode. Default is CENTER_LEAD. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_AUTOCENTER_MODE, NULL);
+ if(value)
{
- ConnState old_state = _conn_state;
- set_conn_state(RCVR_OFF);
- set_conn_state(old_state);
+ _center_mode = gconf_value_get_int(value);
+ gconf_value_free(value);
}
+ else
+ _center_mode = CENTER_LEAD;
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return FALSE;
-}
+ /* Get Show Tracks flag. Default is TRUE. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_SHOWTRACKS, NULL);
+ if(value)
+ {
+ _show_tracks |= (gconf_value_get_bool(value) ? TRACKS_MASK : 0);
+ gconf_value_free(value);
+ }
+ else
+ _show_tracks |= TRACKS_MASK;
-/**
- * Get the hash value of a ProgressUpdateInfo object. This is trivial, since
- * the hash is generated and stored when the object is created.
- */
-static guint
-download_hashfunc(ProgressUpdateInfo *pui)
-{
- vprintf("%s()\n", __PRETTY_FUNCTION__);
+ /* Get Show Routes flag. Default is TRUE. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_SHOWROUTES, NULL);
+ if(value)
+ {
+ _show_tracks |= (gconf_value_get_bool(value) ? ROUTES_MASK : 0);
+ gconf_value_free(value);
+ }
+ else
+ _show_tracks |= ROUTES_MASK;
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return pui->hash;
-}
+ /* Get Show Velocity Vector flag. Default is TRUE. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_SHOWVELVEC, NULL);
+ if(value)
+ {
+ _show_velvec = gconf_value_get_bool(value);
+ gconf_value_free(value);
+ }
+ else
+ _show_velvec = TRUE;
-/**
- * Return whether or not two ProgressUpdateInfo objects are equal. They
- * are equal if they are downloading the same tile.
- */
-static gboolean
-download_equalfunc(
- ProgressUpdateInfo *pui1, ProgressUpdateInfo *pui2)
-{
- vprintf("%s()\n", __PRETTY_FUNCTION__);
+ /* Get Enable GPS flag. Default is TRUE. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_GPS, NULL);
+ if(value)
+ {
+ _enable_gps = gconf_value_get_bool(value);
+ gconf_value_free(value);
+ }
+ else
+ _enable_gps = TRUE;
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return pui1->tilex == pui2->tilex && pui1->tiley == pui2->tiley
- && pui1->zoom == pui2->zoom;
-}
+ /* Initialize _conn_state based on _enable_gps. */
+ _conn_state = (_enable_gps ? RCVR_DOWN : RCVR_OFF);
-/**
- * Draw the current mark (representing the current GPS location) onto
- * _map_widget. This method does not queue the draw area.
- */
-static void
-map_draw_mark()
-{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ /* Load the route locations. */
+ {
+ GSList *curr;
+ _loc_list = gconf_client_get_list(gconf_client,
+ GCONF_KEY_ROUTE_LOCATIONS, GCONF_VALUE_STRING, NULL);
+ _loc_model = gtk_list_store_new(1, G_TYPE_STRING);
+ for(curr = _loc_list; curr != NULL; curr = curr->next)
+ {
+ GtkTreeIter iter;
+ gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX,
+ 0, curr->data, -1);
+ }
+ }
- if(_enable_gps)
+ /* Get POI Database. Default is in ~/MyDocs/.documents/Maps */
+ _poi_db = gconf_client_get_string(gconf_client,
+ GCONF_KEY_POI_DB, NULL);
+ if(_poi_db == NULL)
+ _poi_db = gnome_vfs_make_uri_full_from_relative(
+ _curr_repo->cache_dir, "poi.db");
+ db_connect();
+
+ _poi_zoom = gconf_client_get_int(gconf_client,
+ GCONF_KEY_POI_ZOOM, NULL);
+ if(!_poi_zoom)
+ _poi_zoom = 6;
+
+
+ /* Get GPS Info flag. Default is FALSE. */
+ value = gconf_client_get(gconf_client, GCONF_KEY_GPS_INFO, NULL);
+ if(value)
{
- gdk_draw_arc(
- _map_widget->window,
- _conn_state == RCVR_FIXED ? _gc_mark : _gc_mark_old,
- FALSE, /* not filled. */
- _mark_x1 - _draw_line_width, _mark_y1 - _draw_line_width,
- 2 * _draw_line_width, 2 * _draw_line_width,
- 0, 360 * 64);
- gdk_draw_line(
- _map_widget->window,
- _conn_state == RCVR_FIXED
- ? (_show_velvec ? _gc_mark_velocity : _gc_mark)
- : _gc_mark_old,
- _mark_x1, _mark_y1, _mark_x2, _mark_y2);
+ _gps_info = gconf_value_get_bool(value);
+ gconf_value_free(value);
}
+ else
+ _gps_info = FALSE;
+
+ /* Initialize colors. */
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_MARK, NULL);
+ if(!str || !gdk_color_parse(str, &_color_mark))
+ _color_mark = DEFAULT_COLOR_MARK;
+
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_MARK_VELOCITY, NULL);
+ if(!str || !gdk_color_parse(str, &_color_mark_velocity))
+ _color_mark_velocity = DEFAULT_COLOR_MARK_VELOCITY;
+
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_MARK_OLD, NULL);
+ if(!str || !gdk_color_parse(str, &_color_mark_old))
+ _color_mark_old = DEFAULT_COLOR_MARK_OLD;
+
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_TRACK, NULL);
+ if(!str || !gdk_color_parse(str, &_color_track))
+ _color_track = DEFAULT_COLOR_TRACK;
+
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_TRACK_BREAK, NULL);
+ if(!str || !gdk_color_parse(str, &_color_track_break))
+ _color_track_break = DEFAULT_COLOR_TRACK_BREAK;
+
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_ROUTE, NULL);
+ if(!str || !gdk_color_parse(str, &_color_route))
+ _color_route = DEFAULT_COLOR_ROUTE;
+
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_ROUTE_WAY, NULL);
+ if(!str || !gdk_color_parse(str, &_color_route_way))
+ _color_route_way = DEFAULT_COLOR_ROUTE_WAY;
+
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_ROUTE_NEXTWAY, NULL);
+ if(!str || !gdk_color_parse(str, &_color_route_nextway))
+ _color_route_nextway = DEFAULT_COLOR_ROUTE_NEXTWAY;
+
+ str = gconf_client_get_string(gconf_client,
+ GCONF_KEY_COLOR_POI, NULL);
+ if(!str || !gdk_color_parse(str, &_color_poi))
+ _color_poi = DEFAULT_COLOR_POI;
+
+
+ g_object_unref(gconf_client);
+
+ /* GPS data init */
+ _gps.fix = 1;
+ _gps.satinuse = 0;
+ _gps.satinview = 0;
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * "Set" the mark, which translates the current GPS position into on-screen
- * units in preparation for drawing the mark with map_draw_mark().
- */
-static void map_set_mark()
+static void
+menu_maps_remove_repos()
{
+ GList *curr;
printf("%s()\n", __PRETTY_FUNCTION__);
-
- _mark_x1 = unit2x(_pos.unitx);
- _mark_y1 = unit2y(_pos.unity);
- _mark_x2 = _mark_x1 + (_show_velvec ? _vel_offsetx : 0);
- _mark_y2 = _mark_y1 + (_show_velvec ? _vel_offsety : 0);
- _mark_minx = MIN(_mark_x1, _mark_x2) - (2 * _draw_line_width);
- _mark_miny = MIN(_mark_y1, _mark_y2) - (2 * _draw_line_width);
- _mark_width = abs(_mark_x1 - _mark_x2) + (4 * _draw_line_width);
- _mark_height = abs(_mark_y1 - _mark_y2) + (4 * _draw_line_width);
-
+
+ /* Delete one menu item for each repo. */
+ for(curr = _repo_list; curr; curr = curr->next)
+ {
+ gtk_widget_destroy(gtk_container_get_children(
+ GTK_CONTAINER(_menu_maps_submenu))->data);
+ }
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * Do an in-place scaling of a pixbuf's pixels at the given ratio from the
- * given source location. It would have been nice if gdk_pixbuf provided
- * this method, but I guess it's not general-purpose enough.
- */
static void
-map_pixbuf_scale_inplace(guchar *pixels, guint ratio_p2,
- guint src_x, guint src_y)
+menu_maps_add_repos()
{
- guint dest_x = 0, dest_y = 0, dest_dim = TILE_SIZE_PIXELS;
- vprintf("%s(%d, %d, %d)\n", __PRETTY_FUNCTION__, ratio_p2, src_x, src_y);
+ GList *curr;
+ GtkWidget *last_repo = NULL;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ for(curr = g_list_last(_repo_list); curr; curr = curr->prev)
+ {
+ RepoData *rd = (RepoData*)curr->data;
+ GtkWidget *menu_item;
+ if(last_repo)
+ gtk_menu_prepend(_menu_maps_submenu, menu_item
+ = gtk_radio_menu_item_new_with_label_from_widget(
+ GTK_RADIO_MENU_ITEM(last_repo), rd->name));
+ else
+ {
+ gtk_menu_prepend(_menu_maps_submenu, menu_item
+ = gtk_radio_menu_item_new_with_label(NULL, rd->name));
+ last_repo = menu_item;
+ }
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(menu_item),
+ rd == _curr_repo);
+ rd->menu_item = menu_item;
+ }
- /* Sweep through the entire dest area, copying as necessary, but
- * DO NOT OVERWRITE THE SOURCE AREA. We'll copy it afterward. */
- do {
- guint src_dim = dest_dim >> ratio_p2;
- guint src_endx = src_x - dest_x + src_dim;
- gint x, y;
- for(y = dest_dim - 1; y >= 0; y--)
+ /* Add signals (must be after entire menu is built). */
+ {
+ GList *currmi = gtk_container_get_children(
+ GTK_CONTAINER(_menu_maps_submenu));
+ for(curr = _repo_list; curr; curr = curr->next, currmi = currmi->next)
{
- guint src_offset_y, dest_offset_y;
- src_offset_y = (src_y + (y >> ratio_p2)) * TILE_PIXBUF_STRIDE;
- dest_offset_y = (dest_y + y) * TILE_PIXBUF_STRIDE;
- x = dest_dim - 1;
- if((unsigned)(dest_y + y - src_y) < src_dim
- && (unsigned)(dest_x + x - src_x) < src_dim)
- x -= src_dim;
- for(; x >= 0; x--)
- {
- guint src_offset, dest_offset;
- src_offset = src_offset_y + (src_x + (x >> ratio_p2)) * 3;
- dest_offset = dest_offset_y + (dest_x + x) * 3;
- pixels[dest_offset + 0] = pixels[src_offset + 0];
- pixels[dest_offset + 1] = pixels[src_offset + 1];
- pixels[dest_offset + 2] = pixels[src_offset + 2];
- if((unsigned)(dest_y + y - src_y) < src_dim && x == src_endx)
- x -= src_dim;
- }
+ g_signal_connect(G_OBJECT(currmi->data), "activate",
+ G_CALLBACK(menu_cb_maps_select), curr->data);
}
- /* Reuse src_dim and src_endx to store new src_x and src_y. */
- src_dim = src_x + ((src_x - dest_x) >> ratio_p2);
- src_endx = src_y + ((src_y - dest_y) >> ratio_p2);
- dest_x = src_x;
- dest_y = src_y;
- src_x = src_dim;
- src_y = src_endx;
}
- while((dest_dim >>= ratio_p2) > 1);
+ gtk_widget_show_all(_menu_maps_submenu);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Free a ProgressUpdateInfo data structure that was allocated during the
- * auto-map-download process.
+ * Create the menu items needed for the drop down menu.
*/
static void
-progress_update_info_free(ProgressUpdateInfo *pui)
+menu_init()
{
- vprintf("%s()\n", __PRETTY_FUNCTION__);
-
- gnome_vfs_uri_unref((GnomeVFSURI*)pui->src_list->data);
- g_list_free(pui->src_list);
- gnome_vfs_uri_unref((GnomeVFSURI*)pui->dest_list->data);
- g_list_free(pui->dest_list);
- g_free(pui);
+ /* Create needed handles. */
+ GtkMenu *menu;
+ GtkWidget *submenu;
+ GtkWidget *menu_item;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+ /* Get the menu of our view. */
+ menu = GTK_MENU(gtk_menu_new());
-/**
- * Given the xyz coordinates of our map coordinate system, write the qrst
- * quadtree coordinates to buffer.
- */
-static void
-map_convert_coords_to_quadtree_string(int x, int y, int zoomlevel,gchar *buffer)
-{
- static const gchar *const quadrant = "qrts";
- gchar *ptr = buffer;
- int n;
- *ptr++ = 't';
- for (n = 16 - zoomlevel; n >= 0; n--)
- {
- int xbit = (x >> n) & 1;
- int ybit = (y >> n) & 1;
- *ptr++ = quadrant[xbit + 2 * ybit];
- }
- *ptr++ = '\0';
-}
+ /* Create the menu items. */
-/**
- * Construct the URL that we should fetch, based on the current URI format.
- * This method works differently depending on if a "%s" string is present in
- * the URI format, since that would indicate a quadtree-based map coordinate
- * system.
- */
-static void
-map_construct_url(gchar *buffer, guint tilex, guint tiley, guint zoom)
-{
- if(strstr(_map_uri_format, "%s"))
- {
- /* This is a satellite-map URI. */
- gchar location[MAX_ZOOM + 2];
- map_convert_coords_to_quadtree_string(tilex, tiley, zoom, location);
- sprintf(buffer, _map_uri_format, location);
- }
- else
- /* This is a street-map URI. */
- sprintf(buffer, _map_uri_format, tilex, tiley, zoom);
-}
+ /* The "Routes" submenu. */
+ gtk_menu_append(menu, menu_item
+ = gtk_menu_item_new_with_label(_("Route")));
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+ submenu = gtk_menu_new());
+ gtk_menu_append(submenu, _menu_route_open_item
+ = gtk_menu_item_new_with_label(_("Open...")));
+ gtk_menu_append(submenu, _menu_route_download_item
+ = gtk_menu_item_new_with_label(_("Download...")));
+ gtk_menu_append(submenu, _menu_route_save_item
+ = gtk_menu_item_new_with_label(_("Save...")));
+ gtk_menu_append(submenu, _menu_route_reset_item
+ = gtk_menu_item_new_with_label(_("Reset")));
+ gtk_menu_append(submenu, _menu_route_clear_item
+ = gtk_menu_item_new_with_label(_("Clear")));
+ /* The "Track" submenu. */
+ gtk_menu_append(menu, menu_item
+ = gtk_menu_item_new_with_label(_("Track")));
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+ submenu = gtk_menu_new());
+ gtk_menu_append(submenu, _menu_track_open_item
+ = gtk_menu_item_new_with_label(_("Open...")));
+ gtk_menu_append(submenu, _menu_track_save_item
+ = gtk_menu_item_new_with_label(_("Save...")));
+ gtk_menu_append(submenu, _menu_track_mark_way_item
+ = gtk_menu_item_new_with_label(_("Insert Breakpoint")));
+ gtk_menu_append(submenu, _menu_track_clear_item
+ = gtk_menu_item_new_with_label(_("Clear")));
-/**
- * Initiate a download of the given xyz coordinates using the given buffer
- * as the URL. If the map already exists on disk, or if we are already
- * downloading the map, then this method does nothing.
- */
-static gboolean
-map_initiate_download(guint tilex, guint tiley, guint zoom, guint retries)
-{
- gchar buffer[1024];
- GnomeVFSURI *src, *dest;
- GList *src_list, *dest_list;
- gint priority;
- ProgressUpdateInfo *pui;
- vprintf("%s(%u, %u, %u, %u)\n", __PRETTY_FUNCTION__, tilex, tiley, zoom,
- retries);
+ gtk_menu_append(menu, menu_item
+ = gtk_menu_item_new_with_label(_("Maps")));
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+ _menu_maps_submenu = gtk_menu_new());
+ gtk_menu_append(_menu_maps_submenu, gtk_separator_menu_item_new());
+ gtk_menu_append(_menu_maps_submenu, _menu_maps_mapman_item
+ = gtk_menu_item_new_with_label(_("Manage Maps...")));
+ gtk_menu_append(_menu_maps_submenu, _menu_maps_repoman_item
+ = gtk_menu_item_new_with_label(_("Manage Repositories...")));
+ gtk_menu_append(_menu_maps_submenu, _menu_auto_download_item
+ = gtk_check_menu_item_new_with_label(_("Auto-Download")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_auto_download_item), _auto_download);
+ menu_maps_add_repos(_curr_repo);
- pui = g_new(ProgressUpdateInfo, 1);
- pui->hash = tilex + (tiley << 12) + (zoom << 24);
- if(g_hash_table_lookup(_downloads_hash, pui))
- {
- /* Already downloading - return FALSE. */
- g_free(pui);
- return FALSE;
- }
- sprintf(buffer, "%s/%u/%u/%u.jpg", _map_dir_name, zoom, tilex, tiley);
- dest = gnome_vfs_uri_new(buffer);
- if(gnome_vfs_uri_exists(dest))
- {
- /* Already downloaded - return FALSE. */
- gnome_vfs_uri_unref(dest);
- g_free(pui);
- return FALSE;
- }
+ gtk_menu_append(menu, gtk_separator_menu_item_new());
- /* Priority is based on proximity to _center.unitx - lower number means
- * higher priority, so the further we are, the higher the number. */
- priority = GNOME_VFS_PRIORITY_MIN
- + unit2ptile(abs(tile2punit(tilex, zoom) - _center.unitx)
- + abs(tile2punit(tiley, zoom) - _center.unity));
- BOUND(priority, GNOME_VFS_PRIORITY_MIN, GNOME_VFS_PRIORITY_MAX);
+ gtk_menu_append(menu, menu_item
+ = gtk_menu_item_new_with_label(_("View")));
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+ submenu = gtk_menu_new());
+ gtk_menu_append(submenu, _menu_fullscreen_item
+ = gtk_check_menu_item_new_with_label(_("Full Screen")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_fullscreen_item), _fullscreen);
+ gtk_menu_append(submenu, _menu_show_routes_item
+ = gtk_check_menu_item_new_with_label(_("Route")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_show_routes_item),
+ _show_tracks & ROUTES_MASK);
+ gtk_menu_append(submenu, _menu_show_tracks_item
+ = gtk_check_menu_item_new_with_label(_("Track")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_show_tracks_item),
+ _show_tracks & TRACKS_MASK);
+ gtk_menu_append(submenu, _menu_show_velvec_item
+ = gtk_check_menu_item_new_with_label(_("Velocity Vector")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_show_velvec_item), _show_velvec);
+ gtk_menu_append(submenu, _menu_poi_item
+ = gtk_menu_item_new_with_label(_("POI Categories...")));
+ gtk_widget_set_sensitive(_menu_poi_item, _dbconn);
- map_construct_url(buffer, tilex, tiley, zoom);
- src = gnome_vfs_uri_new(buffer);
- src_list = g_list_prepend(src_list = NULL, src);
- dest_list = g_list_prepend(dest_list = NULL, dest);
+ gtk_menu_append(menu, menu_item
+ = gtk_menu_item_new_with_label(_("Auto-Center")));
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+ submenu = gtk_menu_new());
+ gtk_menu_append(submenu, _menu_ac_latlon_item
+ = gtk_radio_menu_item_new_with_label(NULL, _("Lat/Lon")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_ac_latlon_item),
+ _center_mode == CENTER_LATLON);
+ gtk_menu_append(submenu, _menu_ac_lead_item
+ = gtk_radio_menu_item_new_with_label_from_widget(
+ GTK_RADIO_MENU_ITEM(_menu_ac_latlon_item), _("Lead")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_ac_lead_item),
+ _center_mode == CENTER_LEAD);
+ gtk_menu_append(submenu, _menu_ac_none_item
+ = gtk_radio_menu_item_new_with_label_from_widget(
+ GTK_RADIO_MENU_ITEM(_menu_ac_latlon_item), _("None")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_ac_none_item),
+ _center_mode < 0);
- pui->tilex = tilex;
- pui->tiley = tiley;
- pui->zoom = zoom;
- pui->src_list = src_list;
- pui->dest_list = dest_list;
- pui->retries_left = retries;
+ gtk_menu_append(menu, menu_item
+ = gtk_menu_item_new_with_label(_("GPS")));
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+ submenu = gtk_menu_new());
+ gtk_menu_append(submenu, _menu_enable_gps_item
+ = gtk_check_menu_item_new_with_label(_("Enable GPS")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), _enable_gps);
+ gtk_menu_append(submenu, _menu_gps_show_info_item
+ = gtk_check_menu_item_new_with_label(_("Show Information")));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_gps_show_info_item), _gps_info);
+ gtk_menu_append(submenu, _menu_gps_details_item
+ = gtk_menu_item_new_with_label(_("Details...")));
+ gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_details_item), _enable_gps);
+ gtk_menu_append(submenu, _menu_gps_reset_item
+ = gtk_menu_item_new_with_label(_("Reset Bluetooth")));
+ gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_reset_item), _enable_gps);
- /* Initiate asynchronous download. */
- if(GNOME_VFS_OK != gnome_vfs_async_xfer(
- &pui->handle,
- src_list, dest_list,
- GNOME_VFS_XFER_USE_UNIQUE_NAMES, /* needed for dupe detect. */
- GNOME_VFS_XFER_ERROR_MODE_QUERY,
- GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
- priority,
- (GnomeVFSAsyncXferProgressCallback)map_download_cb_async,
- pui,
- (GnomeVFSXferProgressCallback)gtk_true,
- NULL))
- {
- progress_update_info_free(pui);
- return FALSE;
- }
+ gtk_menu_append(menu, gtk_separator_menu_item_new());
- g_hash_table_insert(_downloads_hash, pui, pui);
- if(!_num_downloads++ && !_download_banner)
- _download_banner = hildon_banner_show_progress(
- _window, NULL, _("Downloading maps"));
+ gtk_menu_append(menu, _menu_settings_item
+ = gtk_menu_item_new_with_label(_("Settings...")));
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ gtk_menu_append(menu, gtk_separator_menu_item_new());
-static void
-map_render_tile(guint tilex, guint tiley, guint destx, guint desty,
- gboolean fast_fail) {
- gchar buffer[1024];
- GdkPixbuf *pixbuf = NULL;
- GError *error = NULL;
- guint zoff;
+ gtk_menu_append(menu, _menu_help_item
+ = gtk_menu_item_new_with_label(_("Help")));
- if(tilex < _world_size_tiles && tiley < _world_size_tiles)
- {
- /* The tile is possible. */
- vprintf("%s(%u, %u, %u, %u)\n", __PRETTY_FUNCTION__,
- tilex, tiley, destx, desty);
- sprintf(buffer, "%s/%u/%u/%u.jpg",
- _map_dir_name, _zoom, tilex, tiley);
- pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
+ gtk_menu_append(menu, _menu_close_item
+ = gtk_menu_item_new_with_label(_("Close")));
- if(error)
- {
- pixbuf = NULL;
- error = NULL;
- }
+ /* We need to show menu items. */
+ gtk_widget_show_all(GTK_WIDGET(menu));
- if(!pixbuf && !fast_fail && _auto_download && _map_uri_format
- && !(_zoom % _zoom_steps))
- {
- map_initiate_download(tilex, tiley, _zoom,
- INITIAL_DOWNLOAD_RETRIES);
- fast_fail = TRUE;
- }
+ hildon_window_set_menu(HILDON_WINDOW(_window), menu);
- for(zoff = 1; !pixbuf && (_zoom + zoff) <= MAX_ZOOM; zoff += 1)
- {
- /* Attempt to blit a wider map. */
- sprintf(buffer, "%s/%u/%u/%u.jpg",
- _map_dir_name, _zoom + zoff,
- (tilex >> zoff), (tiley >> zoff));
- pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
- if(error)
- {
- pixbuf = NULL;
- error = NULL;
- }
- if(pixbuf)
- {
- map_pixbuf_scale_inplace(gdk_pixbuf_get_pixels(pixbuf), zoff,
- (tilex - ((tilex >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff),
- (tiley - ((tiley >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff));
- }
- else
- {
- if(_auto_download && _map_uri_format
- && !((_zoom + zoff) % _zoom_steps))
- {
- if(!fast_fail)
- map_initiate_download(
- tilex >> zoff, tiley >> zoff, _zoom + zoff,
- INITIAL_DOWNLOAD_RETRIES);
- fast_fail = TRUE;
- }
- }
- }
- }
- if(!pixbuf)
- pixbuf = gdk_pixbuf_new(
- GDK_COLORSPACE_RGB,
- FALSE, /* no alpha. */
- 8, /* 8 bits per sample. */
- TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
- if(pixbuf)
- {
- gdk_draw_pixbuf(
- _map_pixmap,
- _gc_mark,
- pixbuf,
- 0, 0,
- destx, desty,
- TILE_SIZE_PIXELS, TILE_SIZE_PIXELS,
- GDK_RGB_DITHER_NONE, 0, 0);
- g_object_unref(pixbuf);
- }
+ /* Connect the signals. */
+ g_signal_connect(G_OBJECT(_menu_route_open_item), "activate",
+ G_CALLBACK(menu_cb_route_open), NULL);
+ g_signal_connect(G_OBJECT(_menu_route_download_item), "activate",
+ G_CALLBACK(menu_cb_route_download), NULL);
+ g_signal_connect(G_OBJECT(_menu_route_save_item), "activate",
+ G_CALLBACK(menu_cb_route_save), NULL);
+ g_signal_connect(G_OBJECT(_menu_route_reset_item), "activate",
+ G_CALLBACK(menu_cb_route_reset), NULL);
+ g_signal_connect(G_OBJECT(_menu_route_clear_item), "activate",
+ G_CALLBACK(menu_cb_route_clear), NULL);
+ g_signal_connect(G_OBJECT(_menu_track_open_item), "activate",
+ G_CALLBACK(menu_cb_track_open), NULL);
+ g_signal_connect(G_OBJECT(_menu_track_save_item), "activate",
+ G_CALLBACK(menu_cb_track_save), NULL);
+ g_signal_connect(G_OBJECT(_menu_track_mark_way_item), "activate",
+ G_CALLBACK(menu_cb_track_mark_way), NULL);
+ g_signal_connect(G_OBJECT(_menu_track_clear_item), "activate",
+ G_CALLBACK(menu_cb_track_clear), NULL);
+ g_signal_connect(G_OBJECT(_menu_show_tracks_item), "toggled",
+ G_CALLBACK(menu_cb_show_tracks), NULL);
+ g_signal_connect(G_OBJECT(_menu_show_routes_item), "toggled",
+ G_CALLBACK(menu_cb_show_routes), NULL);
+ g_signal_connect(G_OBJECT(_menu_show_velvec_item), "toggled",
+ G_CALLBACK(menu_cb_show_velvec), NULL);
+ g_signal_connect(G_OBJECT(_menu_poi_item), "activate",
+ G_CALLBACK(menu_cb_category), NULL);
+
+ g_signal_connect(G_OBJECT(_menu_maps_repoman_item), "activate",
+ G_CALLBACK(menu_cb_maps_repoman), NULL);
+ g_signal_connect(G_OBJECT(_menu_maps_mapman_item), "activate",
+ G_CALLBACK(menu_cb_mapman), NULL);
+ g_signal_connect(G_OBJECT(_menu_ac_latlon_item), "toggled",
+ G_CALLBACK(menu_cb_ac_latlon), NULL);
+ g_signal_connect(G_OBJECT(_menu_ac_lead_item), "toggled",
+ G_CALLBACK(menu_cb_ac_lead), NULL);
+ g_signal_connect(G_OBJECT(_menu_ac_none_item), "toggled",
+ G_CALLBACK(menu_cb_ac_none), NULL);
+ g_signal_connect(G_OBJECT(_menu_fullscreen_item), "toggled",
+ G_CALLBACK(menu_cb_fullscreen), NULL);
+ g_signal_connect(G_OBJECT(_menu_enable_gps_item), "toggled",
+ G_CALLBACK(menu_cb_enable_gps), NULL);
+ g_signal_connect(G_OBJECT(_menu_gps_show_info_item), "toggled",
+ G_CALLBACK(menu_cb_gps_show_info), NULL);
+ g_signal_connect(G_OBJECT(_menu_gps_details_item), "activate",
+ G_CALLBACK(menu_cb_gps_details), NULL);
+ g_signal_connect(G_OBJECT(_menu_gps_reset_item), "activate",
+ G_CALLBACK(menu_cb_gps_reset), NULL);
+ g_signal_connect(G_OBJECT(_menu_auto_download_item), "toggled",
+ G_CALLBACK(menu_cb_auto_download), NULL);
+ g_signal_connect(G_OBJECT(_menu_settings_item), "activate",
+ G_CALLBACK(menu_cb_settings), NULL);
+ g_signal_connect(G_OBJECT(_menu_help_item), "activate",
+ G_CALLBACK(menu_cb_help), NULL);
+ g_signal_connect(G_OBJECT(_menu_close_item), "activate",
+ G_CALLBACK(gtk_main_quit), NULL);
+
+ /* Setup the context menu. */
+ menu = GTK_MENU(gtk_menu_new());
+
+ /* Setup the map context menu. */
+ gtk_menu_append(menu, menu_item
+ = gtk_menu_item_new_with_label(_("Location")));
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+ submenu = gtk_menu_new());
+
+ /* Setup the map context menu. */
+ gtk_menu_append(submenu, _cmenu_loc_show_latlon_item
+ = gtk_menu_item_new_with_label(_("Show Lat/Lon")));
+ gtk_menu_append(submenu, _cmenu_loc_clip_latlon_item
+ = gtk_menu_item_new_with_label(_("Copy Lat/Lon to Clipboard")));
+ gtk_menu_append(submenu, gtk_separator_menu_item_new());
+ gtk_menu_append(submenu, _cmenu_loc_route_to_item
+ = gtk_menu_item_new_with_label(_("Download Route to...")));
+ gtk_menu_append(submenu, _cmenu_loc_distance_to_item
+ = gtk_menu_item_new_with_label(_("Show Distance to")));
+ gtk_menu_append(submenu, gtk_separator_menu_item_new());
+ gtk_menu_append(submenu, _cmenu_add_poi
+ = gtk_menu_item_new_with_label(_("Add POI")));
+ gtk_widget_set_sensitive(_cmenu_add_poi, _dbconn);
+ gtk_menu_append(submenu, _cmenu_edit_poi
+ = gtk_menu_item_new_with_label(_("Edit POI")));
+ gtk_widget_set_sensitive(_cmenu_edit_poi, _dbconn);
+
+ /* Setup the waypoint context menu. */
+ gtk_menu_append(menu, menu_item
+ = gtk_menu_item_new_with_label(_("Waypoint")));
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+ submenu = gtk_menu_new());
+
+ gtk_menu_append(submenu, _cmenu_way_show_latlon_item
+ = gtk_menu_item_new_with_label(_("Show Lat/Lon")));
+ gtk_menu_append(submenu, _cmenu_way_show_desc_item
+ = gtk_menu_item_new_with_label(_("Show Description")));
+ gtk_menu_append(submenu, _cmenu_way_clip_latlon_item
+ = gtk_menu_item_new_with_label(_("Copy Lat/Lon to Clipboard")));
+ gtk_menu_append(submenu, _cmenu_way_clip_desc_item
+ = gtk_menu_item_new_with_label(_("Copy Description to Clipboard")));
+ gtk_menu_append(submenu, gtk_separator_menu_item_new());
+ gtk_menu_append(submenu, _cmenu_way_route_to_item
+ = gtk_menu_item_new_with_label(_("Download Route to...")));
+ gtk_menu_append(submenu, _cmenu_way_distance_to_item
+ = gtk_menu_item_new_with_label(_("Show Distance to")));
+ gtk_menu_append(submenu, _cmenu_way_delete_item
+ = gtk_menu_item_new_with_label(_("Delete")));
+
+ /* Connect signals for context menu. */
+ g_signal_connect(G_OBJECT(_cmenu_loc_show_latlon_item), "activate",
+ G_CALLBACK(cmenu_cb_loc_show_latlon), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_loc_clip_latlon_item), "activate",
+ G_CALLBACK(cmenu_cb_loc_clip_latlon), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_loc_route_to_item), "activate",
+ G_CALLBACK(cmenu_cb_loc_route_to), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_loc_distance_to_item), "activate",
+ G_CALLBACK(cmenu_cb_loc_distance_to), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_add_poi), "activate",
+ G_CALLBACK(cmenu_cb_add_poi), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_edit_poi), "activate",
+ G_CALLBACK(cmenu_cb_edit_poi), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_way_show_latlon_item), "activate",
+ G_CALLBACK(cmenu_cb_way_show_latlon), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_way_show_desc_item), "activate",
+ G_CALLBACK(cmenu_cb_way_show_desc), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_way_clip_latlon_item), "activate",
+ G_CALLBACK(cmenu_cb_way_clip_latlon), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_way_clip_desc_item), "activate",
+ G_CALLBACK(cmenu_cb_way_clip_desc), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_way_route_to_item), "activate",
+ G_CALLBACK(cmenu_cb_way_route_to), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_way_distance_to_item), "activate",
+ G_CALLBACK(cmenu_cb_way_distance_to), NULL);
+ g_signal_connect(G_OBJECT(_cmenu_way_delete_item), "activate",
+ G_CALLBACK(cmenu_cb_way_delete), NULL);
+
+ gtk_widget_show_all(GTK_WIDGET(menu));
+
+ gtk_widget_tap_and_hold_setup(_map_widget, GTK_WIDGET(menu), NULL, 0);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Force a redraw of the entire _map_pixmap, including fetching the
- * background maps from disk and redrawing the tracks on top of them.
+ * Call gtk_window_present() on Maemo Mapper. This also checks the
+ * configuration and brings up the Settings dialog if the GPS Receiver is
+ * not set up, the first time it is called.
*/
-void
-map_force_redraw()
+static gboolean
+window_present()
{
- guint new_x, new_y;
+ static gint been_here = 0;
printf("%s()\n", __PRETTY_FUNCTION__);
- for(new_y = 0; new_y < BUF_HEIGHT_TILES; ++new_y)
- for(new_x = 0; new_x < BUF_WIDTH_TILES; ++new_x)
+ if(!been_here++)
+ {
+ /* Set connection state first, to avoid going into this if twice. */
+ if(_rcvr_mac || !_enable_gps || settings_dialog())
{
- map_render_tile(
- _base_tilex + new_x,
- _base_tiley + new_y,
- new_x * TILE_SIZE_PIXELS,
- new_y * TILE_SIZE_PIXELS,
- FALSE);
+ gtk_widget_show_all(_window);
+ gps_show_info();
+
+ /* Connect to receiver. */
+ if(_enable_gps)
+ rcvr_connect_now();
}
- map_render_paths();
- MACRO_QUEUE_DRAW_AREA();
+ else
+ gtk_main_quit();
+ }
+ gtk_window_present(GTK_WINDOW(_window));
+
+ /* Re-enable any banners that might have been up. */
+ {
+ ConnState old_state = _conn_state;
+ set_conn_state(RCVR_OFF);
+ set_conn_state(old_state);
+ }
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return FALSE;
}
/**
- * Set the current zoom level. If the given zoom level is the same as the
- * current zoom level, or if the new zoom is invalid
- * (not MIN_ZOOM <= new_zoom < MAX_ZOOM), then this method does nothing.
+ * Get the hash value of a ProgressUpdateInfo object. This is trivial, since
+ * the hash is generated and stored when the object is created.
*/
-void
-map_set_zoom(guint new_zoom)
+static guint
+download_hashfunc(ProgressUpdateInfo *pui)
{
- printf("%s(%d)\n", __PRETTY_FUNCTION__, _zoom);
-
- /* Note that, since new_zoom is a guint and MIN_ZOOM is 0, this if
- * condition also checks for new_zoom >= MIN_ZOOM. */
- if(new_zoom > (MAX_ZOOM - 1) || new_zoom == _zoom)
- return;
- _zoom = new_zoom;
- _world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
-
- /* If we're leading, update the center to reflect new zoom level. */
- MACRO_RECALC_CENTER(_center.unitx, _center.unity);
-
- /* Update center bounds to reflect new zoom level. */
- _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
- _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
- _max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1;
- _max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1;
-
- BOUND(_center.unitx, _min_center.unitx, _max_center.unitx);
- BOUND(_center.unity, _min_center.unity, _max_center.unity);
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
- _base_tilex = grid2tile((gint)pixel2grid(
- (gint)unit2pixel((gint)_center.unitx))
- - (gint)_screen_grids_halfwidth);
- _base_tiley = grid2tile(pixel2grid(
- unit2pixel(_center.unity))
- - _screen_grids_halfheight);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return pui->hash;
+}
- /* New zoom level, so we can't reuse the old buffer's pixels. */
+/**
+ * Return whether or not two ProgressUpdateInfo objects are equal. They
+ * are equal if they are downloading the same tile.
+ */
+static gboolean
+download_equalfunc(
+ ProgressUpdateInfo *pui1, ProgressUpdateInfo *pui2)
+{
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return pui1->tilex == pui2->tilex && pui1->tiley == pui2->tiley
+ && pui1->zoom == pui2->zoom;
+}
- /* Update state variables. */
- MACRO_RECALC_OFFSET();
- MACRO_RECALC_FOCUS_BASE();
- MACRO_RECALC_FOCUS_SIZE();
+/**
+ * Draw the current mark (representing the current GPS location) onto
+ * _map_widget. This method does not queue the draw area.
+ */
+static void
+map_draw_mark()
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- map_set_mark();
- map_force_redraw();
+ if(_enable_gps)
+ {
+ gdk_draw_arc(
+ _map_widget->window,
+ _conn_state == RCVR_FIXED ? _gc_mark : _gc_mark_old,
+ FALSE, /* not filled. */
+ _mark_x1 - _draw_line_width, _mark_y1 - _draw_line_width,
+ 2 * _draw_line_width, 2 * _draw_line_width,
+ 0, 360 * 64);
+ gdk_draw_line(
+ _map_widget->window,
+ _conn_state == RCVR_FIXED
+ ? (_show_velvec ? _gc_mark_velocity : _gc_mark)
+ : _gc_mark_old,
+ _mark_x1, _mark_y1, _mark_x2, _mark_y2);
+ }
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Center the view on the given unitx/unity.
+ * "Set" the mark, which translates the current GPS position into on-screen
+ * units in preparation for drawing the mark with map_draw_mark().
*/
-static void
-map_center_unit(guint new_center_unitx, guint new_center_unity)
+static void map_set_mark()
{
- gint new_base_tilex, new_base_tiley;
- guint new_x, new_y;
- guint j, k, base_new_x, base_old_x, old_x, old_y, iox, ioy;
- printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
- new_center_unitx, new_center_unity);
-
- /* Assure that _center.unitx/y are bounded. */
- BOUND(new_center_unitx, _min_center.unitx, _max_center.unitx);
- BOUND(new_center_unity, _min_center.unity, _max_center.unity);
-
- _center.unitx = new_center_unitx;
- _center.unity = new_center_unity;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- new_base_tilex = grid2tile((gint)pixel2grid(
- (gint)unit2pixel((gint)_center.unitx))
- - (gint)_screen_grids_halfwidth);
- new_base_tiley = grid2tile(pixel2grid(
- unit2pixel(_center.unity))
- - _screen_grids_halfheight);
+ _mark_x1 = unit2x(_pos.unitx);
+ _mark_y1 = unit2y(_pos.unity);
+ _mark_x2 = _mark_x1 + (_show_velvec ? _vel_offsetx : 0);
+ _mark_y2 = _mark_y1 + (_show_velvec ? _vel_offsety : 0);
+ _mark_minx = MIN(_mark_x1, _mark_x2) - (2 * _draw_line_width);
+ _mark_miny = MIN(_mark_y1, _mark_y2) - (2 * _draw_line_width);
+ _mark_width = abs(_mark_x1 - _mark_x2) + (4 * _draw_line_width);
+ _mark_height = abs(_mark_y1 - _mark_y2) + (4 * _draw_line_width);
- /* Same zoom level, so it's likely that we can reuse some of the old
- * buffer's pixels. */
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- if(new_base_tilex != _base_tilex
- || new_base_tiley != _base_tiley)
- {
- /* If copying from old parts to new parts, we need to make sure we
- * don't overwrite the old parts when copying, so set up new_x,
- * new_y, old_x, old_y, iox, and ioy with that in mind. */
- if(new_base_tiley < _base_tiley)
- {
- /* New is lower than old - start at bottom and go up. */
- new_y = BUF_HEIGHT_TILES - 1;
- ioy = -1;
- }
- else
- {
- /* New is higher than old - start at top and go down. */
- new_y = 0;
- ioy = 1;
- }
- if(new_base_tilex < _base_tilex)
- {
- /* New is righter than old - start at right and go left. */
- base_new_x = BUF_WIDTH_TILES - 1;
- iox = -1;
- }
- else
- {
- /* New is lefter than old - start at left and go right. */
- base_new_x = 0;
- iox = 1;
- }
+/**
+ * Do an in-place scaling of a pixbuf's pixels at the given ratio from the
+ * given source location. It would have been nice if gdk_pixbuf provided
+ * this method, but I guess it's not general-purpose enough.
+ */
+static void
+map_pixbuf_scale_inplace(guchar *pixels, guint ratio_p2,
+ guint src_x, guint src_y)
+{
+ guint dest_x = 0, dest_y = 0, dest_dim = TILE_SIZE_PIXELS;
+ vprintf("%s(%d, %d, %d)\n", __PRETTY_FUNCTION__, ratio_p2, src_x, src_y);
- /* Iterate over the y tile values. */
- old_y = new_y + new_base_tiley - _base_tiley;
- base_old_x = base_new_x + new_base_tilex - _base_tilex;
- _base_tilex = new_base_tilex;
- _base_tiley = new_base_tiley;
- for(j = 0; j < BUF_HEIGHT_TILES; ++j, new_y += ioy, old_y += ioy)
+ /* Sweep through the entire dest area, copying as necessary, but
+ * DO NOT OVERWRITE THE SOURCE AREA. We'll copy it afterward. */
+ do {
+ guint src_dim = dest_dim >> ratio_p2;
+ guint src_endx = src_x - dest_x + src_dim;
+ gint x, y;
+ for(y = dest_dim - 1; y >= 0; y--)
{
- new_x = base_new_x;
- old_x = base_old_x;
- /* Iterate over the x tile values. */
- for(k = 0; k < BUF_WIDTH_TILES; ++k, new_x += iox, old_x += iox)
+ guint src_offset_y, dest_offset_y;
+ src_offset_y = (src_y + (y >> ratio_p2)) * TILE_PIXBUF_STRIDE;
+ dest_offset_y = (dest_y + y) * TILE_PIXBUF_STRIDE;
+ x = dest_dim - 1;
+ if((unsigned)(dest_y + y - src_y) < src_dim
+ && (unsigned)(dest_x + x - src_x) < src_dim)
+ x -= src_dim;
+ for(; x >= 0; x--)
{
- /* Can we get this grid block from the old buffer?. */
- if(old_x >= 0 && old_x < BUF_WIDTH_TILES
- && old_y >= 0 && old_y < BUF_HEIGHT_TILES)
- {
- /* Copy from old buffer to new buffer. */
- gdk_draw_drawable(
- _map_pixmap,
- _gc_mark,
- _map_pixmap,
- old_x * TILE_SIZE_PIXELS,
- old_y * TILE_SIZE_PIXELS,
- new_x * TILE_SIZE_PIXELS,
- new_y * TILE_SIZE_PIXELS,
- TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
- }
- else
- {
- map_render_tile(
- new_base_tilex + new_x,
- new_base_tiley + new_y,
- new_x * TILE_SIZE_PIXELS,
- new_y * TILE_SIZE_PIXELS,
- FALSE);
- }
+ guint src_offset, dest_offset;
+ src_offset = src_offset_y + (src_x + (x >> ratio_p2)) * 3;
+ dest_offset = dest_offset_y + (dest_x + x) * 3;
+ pixels[dest_offset + 0] = pixels[src_offset + 0];
+ pixels[dest_offset + 1] = pixels[src_offset + 1];
+ pixels[dest_offset + 2] = pixels[src_offset + 2];
+ if((unsigned)(dest_y + y - src_y) < src_dim && x == src_endx)
+ x -= src_dim;
}
}
- map_render_paths();
+ /* Reuse src_dim and src_endx to store new src_x and src_y. */
+ src_dim = src_x + ((src_x - dest_x) >> ratio_p2);
+ src_endx = src_y + ((src_y - dest_y) >> ratio_p2);
+ dest_x = src_x;
+ dest_y = src_y;
+ src_x = src_dim;
+ src_y = src_endx;
}
-
- MACRO_RECALC_OFFSET();
- MACRO_RECALC_FOCUS_BASE();
-
- map_set_mark();
- MACRO_QUEUE_DRAW_AREA();
+ while((dest_dim >>= ratio_p2) > 1);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Pan the view by the given number of units in the X and Y directions.
+ * Free a ProgressUpdateInfo data structure that was allocated during the
+ * auto-map-download process.
*/
-void
-map_pan(gint delta_unitx, gint delta_unity)
+static void
+progress_update_info_free(ProgressUpdateInfo *pui)
{
- printf("%s(%d, %d)\n", __PRETTY_FUNCTION__, delta_unitx, delta_unity);
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
- if(_center_mode > 0)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
- _menu_ac_none_item), TRUE);
- map_center_unit(
- _center.unitx + delta_unitx,
- _center.unity + delta_unity);
+ gnome_vfs_uri_unref((GnomeVFSURI*)pui->src_list->data);
+ g_list_free(pui->src_list);
+ gnome_vfs_uri_unref((GnomeVFSURI*)pui->dest_list->data);
+ g_list_free(pui->dest_list);
+ g_free(pui);
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
/**
- * Initiate a move of the mark from the old location to the current
- * location. This function queues the draw area of the old mark (to force
- * drawing of the background map), then updates the mark, then queus the
- * draw area of the new mark.
+ * Given the xyz coordinates of our map coordinate system, write the qrst
+ * quadtree coordinates to buffer.
*/
static void
-map_move_mark()
+map_convert_coords_to_quadtree_string(int x, int y, int zoomlevel,gchar *buffer)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- /* Just queue the old and new draw areas. */
- gtk_widget_queue_draw_area(_map_widget,
- _mark_minx,
- _mark_miny,
- _mark_width,
- _mark_height);
- map_set_mark();
- gtk_widget_queue_draw_area(_map_widget,
- _mark_minx,
- _mark_miny,
- _mark_width,
- _mark_height);
-
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ static const gchar *const quadrant = "qrts";
+ gchar *ptr = buffer;
+ int n;
+ *ptr++ = 't';
+ for(n = 16 - zoomlevel; n >= 0; n--)
+ {
+ int xbit = (x >> n) & 1;
+ int ybit = (y >> n) & 1;
+ *ptr++ = quadrant[xbit + 2 * ybit];
+ }
+ *ptr++ = '\0';
}
/**
- * Make sure the mark is up-to-date. This function triggers a panning of
- * the view if the mark is appropriately close to the edge of the view.
+ * Construct the URL that we should fetch, based on the current URI format.
+ * This method works differently depending on if a "%s" string is present in
+ * the URI format, since that would indicate a quadtree-based map coordinate
+ * system.
*/
static void
-refresh_mark()
+map_construct_url(gchar *buffer, guint tilex, guint tiley, guint zoom)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- guint new_center_unitx;
- guint new_center_unity;
-
- MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
-
- if((new_center_unitx - _focus.unitx) < _focus_unitwidth
- && (new_center_unity - _focus.unity) < _focus_unitheight)
- /* We're not changing the view - just move the mark. */
- map_move_mark();
+ if(strstr(_curr_repo->url, "%s"))
+ {
+ /* This is a satellite-map URI. */
+ gchar location[MAX_ZOOM + 2];
+ map_convert_coords_to_quadtree_string(tilex, tiley, zoom, location);
+ sprintf(buffer, _curr_repo->url, location);
+ }
else
- map_center_unit(new_center_unitx, new_center_unity);
-
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ /* This is a street-map URI. */
+ sprintf(buffer, _curr_repo->url, tilex, tiley, zoom);
}
+
/**
- * Handle a start tag in the parsing of a GPX file.
+ * Initiate a download of the given xyz coordinates using the given buffer
+ * as the URL. If the map already exists on disk, or if we are already
+ * downloading the map, then this method does nothing.
*/
-#define MACRO_SET_UNKNOWN() { \
- data->prev_state = data->state; \
- data->state = UNKNOWN; \
- data->unknown_depth = 1; \
-}
-static void
-gpx_start_element(SaxData *data, const xmlChar *name, const xmlChar **attrs)
+static gboolean
+map_initiate_download(guint tilex, guint tiley, guint zoom, gint retries)
{
- vprintf("%s(%s)\n", __PRETTY_FUNCTION__, name);
+ gchar buffer[1024];
+ GnomeVFSURI *src, *dest;
+ GList *src_list, *dest_list;
+ gint priority;
+ ProgressUpdateInfo *pui;
+ vprintf("%s(%u, %u, %u, %d)\n", __PRETTY_FUNCTION__, tilex, tiley, zoom,
+ retries);
- switch(data->state)
+ pui = g_new(ProgressUpdateInfo, 1);
+ pui->hash = tilex + (tiley << 12) + (zoom << 24);
+ pui->tilex = tilex;
+ pui->tiley = tiley;
+ pui->zoom = zoom;
+ if(g_hash_table_lookup(_downloads_hash, pui))
{
- case ERROR:
- break;
- case START:
- if(!strcmp((gchar*)name, "gpx"))
- data->state = INSIDE_GPX;
- else
- MACRO_SET_UNKNOWN();
- break;
- case INSIDE_GPX:
- if(!strcmp((gchar*)name, "trk"))
- data->state = INSIDE_PATH;
- else
- MACRO_SET_UNKNOWN();
- break;
- case INSIDE_PATH:
- if(!strcmp((gchar*)name, "trkseg"))
- {
- data->state = INSIDE_PATH_SEGMENT;
- data->at_least_one_trkpt = FALSE;
- }
- else
- MACRO_SET_UNKNOWN();
- break;
- case INSIDE_PATH_SEGMENT:
- if(!strcmp((gchar*)name, "trkpt"))
+ /* Already downloading - return FALSE. */
+ g_free(pui);
+ return FALSE;
+ }
+ sprintf(buffer, "%s/%u/%u/%u.jpg", _curr_repo->cache_dir,
+ zoom, tilex, tiley);
+ dest = gnome_vfs_uri_new(buffer);
+ if(retries > 0 && gnome_vfs_uri_exists(dest))
+ {
+ /* Already downloaded and not overwriting - return FALSE. */
+ gnome_vfs_uri_unref(dest);
+ g_free(pui);
+ return FALSE;
+ }
+
+ /* Priority is based on proximity to _center.unitx - lower number means
+ * higher priority, so the further we are, the higher the number. */
+ priority = GNOME_VFS_PRIORITY_MIN
+ + unit2ptile(abs(tile2punit(tilex, zoom) - _center.unitx)
+ + abs(tile2punit(tiley, zoom) - _center.unity));
+ BOUND(priority, GNOME_VFS_PRIORITY_MIN, GNOME_VFS_PRIORITY_MAX);
+
+ map_construct_url(buffer, tilex, tiley, zoom);
+ src = gnome_vfs_uri_new(buffer);
+
+ src_list = g_list_prepend(src_list = NULL, src);
+ dest_list = g_list_prepend(dest_list = NULL, dest);
+
+ pui->src_list = src_list;
+ pui->dest_list = dest_list;
+ pui->retries_left = retries;
+
+ /* Initiate asynchronous download. */
+ if(retries)
+ {
+ /* This is a download; if retries < 0, then this is an overwrite */
+ if(GNOME_VFS_OK != gnome_vfs_async_xfer(
+ &pui->handle,
+ src_list, dest_list,
+ retries < 0 ? GNOME_VFS_XFER_DEFAULT
+ : GNOME_VFS_XFER_USE_UNIQUE_NAMES,
+ GNOME_VFS_XFER_ERROR_MODE_QUERY,
+ retries < 0 ? GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE
+ : GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+ priority,
+ (GnomeVFSAsyncXferProgressCallback)map_download_cb_async,
+ pui,
+ (GnomeVFSXferProgressCallback)gtk_true,
+ NULL))
+ {
+ progress_update_info_free(pui);
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* This is a deletion. */
+ if(GNOME_VFS_OK != gnome_vfs_async_xfer(
+ &pui->handle,
+ dest_list, NULL,
+ GNOME_VFS_XFER_DELETE_ITEMS,
+ GNOME_VFS_XFER_ERROR_MODE_QUERY,
+ GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+ priority,
+ (GnomeVFSAsyncXferProgressCallback)map_download_cb_async,
+ pui,
+ (GnomeVFSXferProgressCallback)gtk_true,
+ NULL))
+ {
+ progress_update_info_free(pui);
+ return FALSE;
+ }
+ }
+
+ g_hash_table_insert(_downloads_hash, pui, pui);
+ if(!_num_downloads++ && !_download_banner)
+ _download_banner = hildon_banner_show_progress(
+ _window, NULL, _("Downloading maps"));
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
+
+static void
+map_render_poi()
+{
+ guint unitx, unity;
+ gfloat lat1, lat2, lon1, lon2, tmp;
+ gchar slat1[10], slat2[10], slon1[10], slon2[10];
+ gchar buffer[100], *sql;
+ gchar **pszResult;
+ gint nRow, nColumn, row, poix, poiy;
+ GdkPixbuf *pixbuf = NULL;
+ GError *error = NULL;
+
+ if(_db && _poi_zoom > _zoom)
+ {
+ unitx = x2unit(1);
+ unity = y2unit(1);
+ unit2latlon(unitx, unity, lat1, lon1);
+ unitx = x2unit(BUF_WIDTH_PIXELS);
+ unity = y2unit(BUF_HEIGHT_PIXELS);
+ unit2latlon(unitx, unity, lat2, lon2);
+ if(lat1 > lat2)
+ {
+ tmp = lat2;
+ lat2 = lat1;
+ lat1 = tmp;
+ }
+ if(lon1 > lon2)
+ {
+ tmp = lon2;
+ lon2 = lon1;
+ lon1 = tmp;
+ }
+
+ g_ascii_dtostr(slat1, sizeof(slat1), lat1);
+ g_ascii_dtostr(slat2, sizeof(slat2), lat2);
+ g_ascii_dtostr(slon1, sizeof(slon1), lon1);
+ g_ascii_dtostr(slon2, sizeof(slon2), lon2);
+
+ sql = g_strdup_printf(
+ "select p.lat, p.lon, lower(p.label), lower(c.label)"
+ " from poi p, category c "
+ " where p.lat between %s and %s "
+ " and p.lon between %s and %s "
+ " and c.enabled = 1 and p.cat_id = c.cat_id",
+ slat1, slat2, slon1, slon2);
+
+ if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+ == SQLITE_OK)
+ {
+ for(row=1; row<nRow+1; row++)
{
- const xmlChar **curr_attr;
- gchar *error_check;
- gfloat lat = 0.f, lon = 0.f;
- gboolean has_lat, has_lon;
- has_lat = FALSE;
- has_lon = FALSE;
- for(curr_attr = attrs; *curr_attr != NULL; )
+ lat1 = g_ascii_strtod(pszResult[row*nColumn+0], NULL);
+ lon1 = g_ascii_strtod(pszResult[row*nColumn+1], NULL);
+ latlon2unit(lat1, lon1, unitx, unity);
+ poix = unit2bufx(unitx);
+ poiy = unit2bufy(unity);
+
+ /* Try to get icon for specific POI first. */
+ sprintf(buffer, "%s/poi/%s.jpg", _curr_repo->cache_dir,
+ pszResult[row*nColumn+2]);
+ pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
+ if(error)
{
- const gchar *attr_name = *curr_attr++;
- const gchar *attr_val = *curr_attr++;
- if(!strcmp(attr_name, "lat"))
- {
- lat = g_ascii_strtod(attr_val, &error_check);
- if(error_check != attr_val)
- has_lat = TRUE;
- }
- else if(!strcmp(attr_name, "lon"))
- {
- lon = g_ascii_strtod(attr_val, &error_check);
- if(error_check != attr_val)
- has_lon = TRUE;
- }
+ /* No icon for specific POI - try for category. */
+ error = NULL;
+ sprintf(buffer, "%s/poi/%s.jpg", _curr_repo->cache_dir,
+ pszResult[row*nColumn+3]);
+ pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
}
- if(has_lat && has_lon)
+ if(error)
{
- if(data->path.path_type == TRACK)
- {
- MACRO_TRACK_INCREMENT_TAIL(data->path.path.track);
- latlon2unit(lat, lon,
- data->path.path.track.tail->point.unitx,
- data->path.path.track.tail->point.unity);
- data->path.path.track.tail->time = 0;
- }
- else
- {
- MACRO_ROUTE_INCREMENT_TAIL(data->path.path.route);
- latlon2unit(lat, lon,
- data->path.path.route.tail->unitx,
- data->path.path.route.tail->unity);
- }
- data->state = INSIDE_PATH_POINT;
+ /* No icon for POI or for category - draw default. */
+ error = NULL;
+ gdk_draw_rectangle(_map_pixmap, _gc_poi, TRUE,
+ poix - (int)(0.5f * _draw_line_width),
+ poiy - (int)(0.5f * _draw_line_width),
+ 3 * _draw_line_width,
+ 3 * _draw_line_width);
}
else
- data->state = ERROR;
- }
- else
- MACRO_SET_UNKNOWN();
- break;
- case INSIDE_PATH_POINT:
- /* only parse time for tracks */
- if(data->path.path_type == TRACK
- && !strcmp((gchar*)name, "time"))
- data->state = INSIDE_PATH_POINT_TIME;
-
- /* only parse description for routes */
- else if(data->path.path_type == ROUTE
- && !strcmp((gchar*)name, "desc"))
- data->state = INSIDE_PATH_POINT_DESC;
-
- else
- MACRO_SET_UNKNOWN();
- break;
- case UNKNOWN:
- data->unknown_depth++;
- break;
- default:
- ;
+ {
+ gdk_draw_pixbuf(
+ _map_pixmap,
+ _gc_poi,
+ pixbuf,
+ 0, 0,
+ poix - gdk_pixbuf_get_width(pixbuf) / 2,
+ poix - gdk_pixbuf_get_height(pixbuf) / 2,
+ -1,-1,
+ GDK_RGB_DITHER_NONE, 0, 0);
+ g_object_unref(pixbuf);
+ }
+ }
+ sqlite_free_table(pszResult);
+ }
+ g_free(sql);
}
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * Handle an end tag in the parsing of a GPX file.
- */
static void
-gpx_end_element(SaxData *data, const xmlChar *name)
-{
- vprintf("%s(%s)\n", __PRETTY_FUNCTION__, name);
+map_render_tile(guint tilex, guint tiley, guint destx, guint desty,
+ gboolean fast_fail) {
+ gchar buffer[1024];
+ GdkPixbuf *pixbuf = NULL;
+ GError *error = NULL;
+ guint zoff;
- switch(data->state)
+ if(tilex < _world_size_tiles && tiley < _world_size_tiles)
{
- case ERROR:
- break;
- case START:
- data->state = ERROR;
- break;
- case INSIDE_GPX:
- if(!strcmp((gchar*)name, "gpx"))
- data->state = FINISH;
- else
- data->state = ERROR;
- break;
- case INSIDE_PATH:
- if(!strcmp((gchar*)name, "trk"))
- data->state = INSIDE_GPX;
- else
- data->state = ERROR;
- break;
- case INSIDE_PATH_SEGMENT:
- if(!strcmp((gchar*)name, "trkseg"))
+ /* The tile is possible. */
+ vprintf("%s(%u, %u, %u, %u)\n", __PRETTY_FUNCTION__,
+ tilex, tiley, destx, desty);
+ sprintf(buffer, "%s/%u/%u/%u.jpg",
+ _curr_repo->cache_dir, _zoom, tilex, tiley);
+ pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
+
+ if(error)
+ {
+ pixbuf = NULL;
+ error = NULL;
+ }
+
+ if(!pixbuf && !fast_fail && _auto_download && *_curr_repo->url
+ && !(_zoom % _curr_repo->dl_zoom_steps))
+ {
+ map_initiate_download(tilex, tiley, _zoom,
+ INITIAL_DOWNLOAD_RETRIES);
+ fast_fail = TRUE;
+ }
+
+ for(zoff = 1; !pixbuf && (_zoom + zoff) <= MAX_ZOOM
+ && zoff <= TILE_SIZE_P2; zoff += 1)
+ {
+ /* Attempt to blit a wider map. */
+ sprintf(buffer, "%s/%u/%u/%u.jpg",
+ _curr_repo->cache_dir, _zoom + zoff,
+ (tilex >> zoff), (tiley >> zoff));
+ pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
+ if(error)
{
- if(data->at_least_one_trkpt)
- {
- if(data->path.path_type == TRACK)
- {
- MACRO_TRACK_INCREMENT_TAIL(data->path.path.track);
- *data->path.path.track.tail = _track_null;
- }
- else
- {
- MACRO_ROUTE_INCREMENT_TAIL(data->path.path.route);
- *data->path.path.route.tail = _pos_null;
- }
- }
- data->state = INSIDE_PATH;
+ pixbuf = NULL;
+ error = NULL;
}
- else
- data->state = ERROR;
- break;
- case INSIDE_PATH_POINT:
- if(!strcmp((gchar*)name, "trkpt"))
+ if(pixbuf)
{
- data->state = INSIDE_PATH_SEGMENT;
- data->at_least_one_trkpt = TRUE;
+ map_pixbuf_scale_inplace(gdk_pixbuf_get_pixels(pixbuf), zoff,
+ (tilex - ((tilex >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff),
+ (tiley - ((tiley >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff));
}
else
- data->state = ERROR;
- break;
- case INSIDE_PATH_POINT_TIME:
- /* only parse time for tracks */
- if(!strcmp((gchar*)name, "time"))
{
- struct tm time;
- gchar *ptr;
-
- if(NULL == (ptr = strptime(data->chars->str,
- XML_DATE_FORMAT, &time)))
- /* Failed to parse dateTime format. */
- data->state = ERROR;
- else
+ if(_auto_download && *_curr_repo->url
+ && !((_zoom + zoff) % _curr_repo->dl_zoom_steps))
{
- /* Parse was successful. Now we have to parse timezone.
- * From here on, if there is an error, I just assume local
- * timezone. Yes, this is not proper XML, but I don't
- * care. */
- gchar *error_check;
-
- /* First, set time in "local" time zone. */
- data->path.path.track.tail->time = (mktime(&time));
+ if(!fast_fail)
+ map_initiate_download(
+ tilex >> zoff, tiley >> zoff, _zoom + zoff,
+ INITIAL_DOWNLOAD_RETRIES);
+ fast_fail = TRUE;
+ }
+ }
+ }
+ }
+ if(!pixbuf)
+ pixbuf = gdk_pixbuf_new(
+ GDK_COLORSPACE_RGB,
+ FALSE, /* no alpha. */
+ 8, /* 8 bits per sample. */
+ TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
+ if(pixbuf)
+ {
+ gdk_draw_pixbuf(
+ _map_pixmap,
+ _gc_mark,
+ pixbuf,
+ 0, 0,
+ destx, desty,
+ TILE_SIZE_PIXELS, TILE_SIZE_PIXELS,
+ GDK_RGB_DITHER_NONE, 0, 0);
+ g_object_unref(pixbuf);
+ }
- /* Now, skip inconsequential characters */
- while(*ptr && *ptr != 'Z' && *ptr != '-' && *ptr != '+')
- ptr++;
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- /* Check if we ran to the end of the string. */
- if(*ptr)
- {
- /* Next character is either 'Z', '-', or '+' */
- if(*ptr == 'Z')
- /* Zulu (UTC) time. Undo the local time zone's
- * offset. */
- data->path.path.track.tail->time += time.tm_gmtoff;
- else
- {
- /* Not Zulu (UTC). Must parse hours and minutes. */
- gint offhours = strtol(ptr, &error_check, 10);
- if(error_check != ptr
- && *(ptr = error_check) == ':')
- {
- /* Parse of hours worked. Check minutes. */
- gint offmins = strtol(ptr + 1,
- &error_check, 10);
- if(error_check != (ptr + 1))
- {
- /* Parse of minutes worked. Calculate. */
- data->path.path.track.tail->time
- += (time.tm_gmtoff
- - (offhours * 60 * 60
- + offmins * 60));
- }
- }
- }
- }
- /* Successfully parsed dateTime. */
- data->state = INSIDE_PATH_POINT;
- }
+/**
+ * Force a redraw of the entire _map_pixmap, including fetching the
+ * background maps from disk and redrawing the tracks on top of them.
+ */
+void
+map_force_redraw()
+{
+ guint new_x, new_y;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- g_string_free(data->chars, TRUE);
- data->chars = g_string_new("");
- }
- else
- data->state = ERROR;
- break;
- case INSIDE_PATH_POINT_DESC:
- /* only parse description for routes */
- if(!strcmp((gchar*)name, "desc"))
+ for(new_y = 0; new_y < BUF_HEIGHT_TILES; ++new_y)
+ for(new_x = 0; new_x < BUF_WIDTH_TILES; ++new_x)
+ {
+ map_render_tile(
+ _base_tilex + new_x,
+ _base_tiley + new_y,
+ new_x * TILE_SIZE_PIXELS,
+ new_y * TILE_SIZE_PIXELS,
+ FALSE);
+ }
+ map_render_paths();
+ map_render_poi();
+ MACRO_QUEUE_DRAW_AREA();
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Set the current zoom level. If the given zoom level is the same as the
+ * current zoom level, or if the new zoom is invalid
+ * (not MIN_ZOOM <= new_zoom < MAX_ZOOM), then this method does nothing.
+ */
+void
+map_set_zoom(guint new_zoom)
+{
+ printf("%s(%d)\n", __PRETTY_FUNCTION__, _zoom);
+
+ /* Note that, since new_zoom is a guint and MIN_ZOOM is 0, this if
+ * condition also checks for new_zoom >= MIN_ZOOM. */
+ if(new_zoom > (MAX_ZOOM - 1))
+ return;
+ _zoom = new_zoom / _curr_repo->view_zoom_steps
+ * _curr_repo->view_zoom_steps;
+ _world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
+
+ /* If we're leading, update the center to reflect new zoom level. */
+ MACRO_RECALC_CENTER(_center.unitx, _center.unity);
+
+ /* Update center bounds to reflect new zoom level. */
+ _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
+ _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
+ _max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1;
+ _max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1;
+
+ BOUND(_center.unitx, _min_center.unitx, _max_center.unitx);
+ BOUND(_center.unity, _min_center.unity, _max_center.unity);
+
+ _base_tilex = grid2tile((gint)pixel2grid(
+ (gint)unit2pixel((gint)_center.unitx))
+ - (gint)_screen_grids_halfwidth);
+ _base_tiley = grid2tile(pixel2grid(
+ unit2pixel(_center.unity))
+ - _screen_grids_halfheight);
+
+ /* New zoom level, so we can't reuse the old buffer's pixels. */
+
+
+ /* Update state variables. */
+ MACRO_RECALC_OFFSET();
+ MACRO_RECALC_FOCUS_BASE();
+ MACRO_RECALC_FOCUS_SIZE();
+
+ map_set_mark();
+ map_force_redraw();
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Center the view on the given unitx/unity.
+ */
+static void
+map_center_unit(guint new_center_unitx, guint new_center_unity)
+{
+ gint new_base_tilex, new_base_tiley;
+ guint new_x, new_y;
+ guint j, k, base_new_x, base_old_x, old_x, old_y, iox, ioy;
+ printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
+ new_center_unitx, new_center_unity);
+
+ /* Assure that _center.unitx/y are bounded. */
+ BOUND(new_center_unitx, _min_center.unitx, _max_center.unitx);
+ BOUND(new_center_unity, _min_center.unity, _max_center.unity);
+
+ _center.unitx = new_center_unitx;
+ _center.unity = new_center_unity;
+
+ new_base_tilex = grid2tile((gint)pixel2grid(
+ (gint)unit2pixel((gint)_center.unitx))
+ - (gint)_screen_grids_halfwidth);
+ new_base_tiley = grid2tile(pixel2grid(
+ unit2pixel(_center.unity))
+ - _screen_grids_halfheight);
+
+ /* Same zoom level, so it's likely that we can reuse some of the old
+ * buffer's pixels. */
+
+ if(new_base_tilex != _base_tilex
+ || new_base_tiley != _base_tiley)
+ {
+ /* If copying from old parts to new parts, we need to make sure we
+ * don't overwrite the old parts when copying, so set up new_x,
+ * new_y, old_x, old_y, iox, and ioy with that in mind. */
+ if(new_base_tiley < _base_tiley)
+ {
+ /* New is lower than old - start at bottom and go up. */
+ new_y = BUF_HEIGHT_TILES - 1;
+ ioy = -1;
+ }
+ else
+ {
+ /* New is higher than old - start at top and go down. */
+ new_y = 0;
+ ioy = 1;
+ }
+ if(new_base_tilex < _base_tilex)
+ {
+ /* New is righter than old - start at right and go left. */
+ base_new_x = BUF_WIDTH_TILES - 1;
+ iox = -1;
+ }
+ else
+ {
+ /* New is lefter than old - start at left and go right. */
+ base_new_x = 0;
+ iox = 1;
+ }
+
+ /* Iterate over the y tile values. */
+ old_y = new_y + new_base_tiley - _base_tiley;
+ base_old_x = base_new_x + new_base_tilex - _base_tilex;
+ _base_tilex = new_base_tilex;
+ _base_tiley = new_base_tiley;
+ for(j = 0; j < BUF_HEIGHT_TILES; ++j, new_y += ioy, old_y += ioy)
+ {
+ new_x = base_new_x;
+ old_x = base_old_x;
+ /* Iterate over the x tile values. */
+ for(k = 0; k < BUF_WIDTH_TILES; ++k, new_x += iox, old_x += iox)
{
- MACRO_ROUTE_INCREMENT_WTAIL(data->path.path.route);
- data->path.path.route.wtail->point = data->path.path.route.tail;
- data->path.path.route.wtail->desc
- = g_string_free(data->chars, FALSE);
- data->chars = g_string_new("");
- data->state = INSIDE_PATH_POINT;
+ /* Can we get this grid block from the old buffer?. */
+ if(old_x >= 0 && old_x < BUF_WIDTH_TILES
+ && old_y >= 0 && old_y < BUF_HEIGHT_TILES)
+ {
+ /* Copy from old buffer to new buffer. */
+ gdk_draw_drawable(
+ _map_pixmap,
+ _gc_mark,
+ _map_pixmap,
+ old_x * TILE_SIZE_PIXELS,
+ old_y * TILE_SIZE_PIXELS,
+ new_x * TILE_SIZE_PIXELS,
+ new_y * TILE_SIZE_PIXELS,
+ TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
+ }
+ else
+ {
+ map_render_tile(
+ new_base_tilex + new_x,
+ new_base_tiley + new_y,
+ new_x * TILE_SIZE_PIXELS,
+ new_y * TILE_SIZE_PIXELS,
+ FALSE);
+ }
}
- else
- data->state = ERROR;
- break;
- case UNKNOWN:
- if(!--data->unknown_depth)
- data->state = data->prev_state;
- else
- data->state = ERROR;
- break;
+ }
+ map_render_paths();
+ map_render_poi();
+ }
+
+ MACRO_RECALC_OFFSET();
+ MACRO_RECALC_FOCUS_BASE();
+
+ map_set_mark();
+ MACRO_QUEUE_DRAW_AREA();
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Pan the view by the given number of units in the X and Y directions.
+ */
+void
+map_pan(gint delta_unitx, gint delta_unity)
+{
+ printf("%s(%d, %d)\n", __PRETTY_FUNCTION__, delta_unitx, delta_unity);
+
+ if(_center_mode > 0)
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ _menu_ac_none_item), TRUE);
+ map_center_unit(
+ _center.unitx + delta_unitx,
+ _center.unity + delta_unity);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Initiate a move of the mark from the old location to the current
+ * location. This function queues the draw area of the old mark (to force
+ * drawing of the background map), then updates the mark, then queus the
+ * draw area of the new mark.
+ */
+static void
+map_move_mark()
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ /* Just queue the old and new draw areas. */
+ gtk_widget_queue_draw_area(_map_widget,
+ _mark_minx,
+ _mark_miny,
+ _mark_width,
+ _mark_height);
+ map_set_mark();
+ gtk_widget_queue_draw_area(_map_widget,
+ _mark_minx,
+ _mark_miny,
+ _mark_width,
+ _mark_height);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Make sure the mark is up-to-date. This function triggers a panning of
+ * the view if the mark is appropriately close to the edge of the view.
+ */
+static void
+refresh_mark()
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ guint new_center_unitx;
+ guint new_center_unity;
+
+ MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
+
+ if((new_center_unitx - _focus.unitx) < _focus_unitwidth
+ && (new_center_unity - _focus.unity) < _focus_unitheight)
+ /* We're not changing the view - just move the mark. */
+ map_move_mark();
+ else
+ map_center_unit(new_center_unitx, new_center_unity);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Handle a start tag in the parsing of a GPX file.
+ */
+#define MACRO_SET_UNKNOWN() { \
+ data->prev_state = data->state; \
+ data->state = UNKNOWN; \
+ data->unknown_depth = 1; \
+}
+static void
+gpx_start_element(SaxData *data, const xmlChar *name, const xmlChar **attrs)
+{
+ vprintf("%s(%s)\n", __PRETTY_FUNCTION__, name);
+
+ switch(data->state)
+ {
+ case ERROR:
+ break;
+ case START:
+ if(!strcmp((gchar*)name, "gpx"))
+ data->state = INSIDE_GPX;
+ else
+ MACRO_SET_UNKNOWN();
+ break;
+ case INSIDE_GPX:
+ if(!strcmp((gchar*)name, "trk"))
+ data->state = INSIDE_PATH;
+ else
+ MACRO_SET_UNKNOWN();
+ break;
+ case INSIDE_PATH:
+ if(!strcmp((gchar*)name, "trkseg"))
+ {
+ data->state = INSIDE_PATH_SEGMENT;
+ data->at_least_one_trkpt = FALSE;
+ }
+ else
+ MACRO_SET_UNKNOWN();
+ break;
+ case INSIDE_PATH_SEGMENT:
+ if(!strcmp((gchar*)name, "trkpt"))
+ {
+ const xmlChar **curr_attr;
+ gchar *error_check;
+ gfloat lat = 0.f, lon = 0.f;
+ gboolean has_lat, has_lon;
+ has_lat = FALSE;
+ has_lon = FALSE;
+ for(curr_attr = attrs; *curr_attr != NULL; )
+ {
+ const gchar *attr_name = *curr_attr++;
+ const gchar *attr_val = *curr_attr++;
+ if(!strcmp(attr_name, "lat"))
+ {
+ lat = g_ascii_strtod(attr_val, &error_check);
+ if(error_check != attr_val)
+ has_lat = TRUE;
+ }
+ else if(!strcmp(attr_name, "lon"))
+ {
+ lon = g_ascii_strtod(attr_val, &error_check);
+ if(error_check != attr_val)
+ has_lon = TRUE;
+ }
+ }
+ if(has_lat && has_lon)
+ {
+ if(data->path.path_type == TRACK)
+ {
+ MACRO_TRACK_INCREMENT_TAIL(data->path.path.track);
+ latlon2unit(lat, lon,
+ data->path.path.track.tail->point.unitx,
+ data->path.path.track.tail->point.unity);
+ data->path.path.track.tail->time = 0;
+ }
+ else
+ {
+ MACRO_ROUTE_INCREMENT_TAIL(data->path.path.route);
+ latlon2unit(lat, lon,
+ data->path.path.route.tail->unitx,
+ data->path.path.route.tail->unity);
+ }
+ data->state = INSIDE_PATH_POINT;
+ }
+ else
+ data->state = ERROR;
+ }
+ else
+ MACRO_SET_UNKNOWN();
+ break;
+ case INSIDE_PATH_POINT:
+ /* only parse time for tracks */
+ if(data->path.path_type == TRACK
+ && !strcmp((gchar*)name, "time"))
+ data->state = INSIDE_PATH_POINT_TIME;
+
+ /* only parse description for routes */
+ else if(data->path.path_type == ROUTE
+ && !strcmp((gchar*)name, "desc"))
+ data->state = INSIDE_PATH_POINT_DESC;
+
+ else
+ MACRO_SET_UNKNOWN();
+ break;
+ case UNKNOWN:
+ data->unknown_depth++;
+ break;
default:
;
}
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * Handle char data in the parsing of a GPX file.
- */
+/**
+ * Handle an end tag in the parsing of a GPX file.
+ */
+static void
+gpx_end_element(SaxData *data, const xmlChar *name)
+{
+ vprintf("%s(%s)\n", __PRETTY_FUNCTION__, name);
+
+ switch(data->state)
+ {
+ case ERROR:
+ break;
+ case START:
+ data->state = ERROR;
+ break;
+ case INSIDE_GPX:
+ if(!strcmp((gchar*)name, "gpx"))
+ data->state = FINISH;
+ else
+ data->state = ERROR;
+ break;
+ case INSIDE_PATH:
+ if(!strcmp((gchar*)name, "trk"))
+ data->state = INSIDE_GPX;
+ else
+ data->state = ERROR;
+ break;
+ case INSIDE_PATH_SEGMENT:
+ if(!strcmp((gchar*)name, "trkseg"))
+ {
+ if(data->at_least_one_trkpt)
+ {
+ if(data->path.path_type == TRACK)
+ {
+ MACRO_TRACK_INCREMENT_TAIL(data->path.path.track);
+ *data->path.path.track.tail = _track_null;
+ }
+ else
+ {
+ MACRO_ROUTE_INCREMENT_TAIL(data->path.path.route);
+ *data->path.path.route.tail = _pos_null;
+ }
+ }
+ data->state = INSIDE_PATH;
+ }
+ else
+ data->state = ERROR;
+ break;
+ case INSIDE_PATH_POINT:
+ if(!strcmp((gchar*)name, "trkpt"))
+ {
+ data->state = INSIDE_PATH_SEGMENT;
+ data->at_least_one_trkpt = TRUE;
+ }
+ else
+ data->state = ERROR;
+ break;
+ case INSIDE_PATH_POINT_TIME:
+ /* only parse time for tracks */
+ if(!strcmp((gchar*)name, "time"))
+ {
+ struct tm time;
+ gchar *ptr;
+
+ if(NULL == (ptr = strptime(data->chars->str,
+ XML_DATE_FORMAT, &time)))
+ /* Failed to parse dateTime format. */
+ data->state = ERROR;
+ else
+ {
+ /* Parse was successful. Now we have to parse timezone.
+ * From here on, if there is an error, I just assume local
+ * timezone. Yes, this is not proper XML, but I don't
+ * care. */
+ gchar *error_check;
+
+ /* First, set time in "local" time zone. */
+ data->path.path.track.tail->time = (mktime(&time));
+
+ /* Now, skip inconsequential characters */
+ while(*ptr && *ptr != 'Z' && *ptr != '-' && *ptr != '+')
+ ptr++;
+
+ /* Check if we ran to the end of the string. */
+ if(*ptr)
+ {
+ /* Next character is either 'Z', '-', or '+' */
+ if(*ptr == 'Z')
+ /* Zulu (UTC) time. Undo the local time zone's
+ * offset. */
+ data->path.path.track.tail->time += time.tm_gmtoff;
+ else
+ {
+ /* Not Zulu (UTC). Must parse hours and minutes. */
+ gint offhours = strtol(ptr, &error_check, 10);
+ if(error_check != ptr
+ && *(ptr = error_check) == ':')
+ {
+ /* Parse of hours worked. Check minutes. */
+ gint offmins = strtol(ptr + 1,
+ &error_check, 10);
+ if(error_check != (ptr + 1))
+ {
+ /* Parse of minutes worked. Calculate. */
+ data->path.path.track.tail->time
+ += (time.tm_gmtoff
+ - (offhours * 60 * 60
+ + offmins * 60));
+ }
+ }
+ }
+ }
+ /* Successfully parsed dateTime. */
+ data->state = INSIDE_PATH_POINT;
+ }
+
+ g_string_free(data->chars, TRUE);
+ data->chars = g_string_new("");
+ }
+ else
+ data->state = ERROR;
+ break;
+ case INSIDE_PATH_POINT_DESC:
+ /* only parse description for routes */
+ if(!strcmp((gchar*)name, "desc"))
+ {
+ MACRO_ROUTE_INCREMENT_WTAIL(data->path.path.route);
+ data->path.path.route.wtail->point = data->path.path.route.tail;
+ data->path.path.route.wtail->desc
+ = g_string_free(data->chars, FALSE);
+ data->chars = g_string_new("");
+ data->state = INSIDE_PATH_POINT;
+ }
+ else
+ data->state = ERROR;
+ break;
+ case UNKNOWN:
+ if(!--data->unknown_depth)
+ data->state = data->prev_state;
+ else
+ data->state = ERROR;
+ break;
+ default:
+ ;
+ }
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Handle char data in the parsing of a GPX file.
+ */
+static void
+gpx_chars(SaxData *data, const xmlChar *ch, int len)
+{
+ guint i;
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
+
+ switch(data->state)
+ {
+ case ERROR:
+ case UNKNOWN:
+ break;
+ case INSIDE_PATH_POINT_TIME:
+ case INSIDE_PATH_POINT_DESC:
+ for(i = 0; i < len; i++)
+ data->chars = g_string_append_c(data->chars, ch[i]);
+ vprintf("%s\n", data->chars->str);
+ break;
+ default:
+ break;
+ }
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Handle an entity in the parsing of a GPX file. We don't do anything
+ * special here.
+ */
+static xmlEntityPtr
+gpx_get_entity(SaxData *data, const xmlChar *name)
+{
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return xmlGetPredefinedEntity(name);
+}
+
+/**
+ * Handle an error in the parsing of a GPX file.
+ */
+static void
+gpx_error(SaxData *data, const gchar *msg, ...)
+{
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ data->state = ERROR;
+}
+
+/**
+ * Parse the given character buffer of the given size, replacing the given
+ * Track's pointers with pointers to new arrays depending on the given
+ * policy, adding extra_bins slots in the arrays for new data.
+ *
+ * policy_old should be negative to indicate that the existing data should
+ * be prepended to the new GPX data, positive to indicate the opposite, and
+ * zero to indicate that we should throw away the old data.
+ *
+ * When importing tracks, we *prepend* the GPX data and provide extra_bins.
+ * When importing routes, we *append* in the case of regular routes, and we
+ * *replace* in the case of automatic routing. Routes get no extra bins.
+ */
+static gboolean
+parse_track_gpx(gchar *buffer, gint size, gint policy_old)
+{
+ SaxData data;
+ xmlSAXHandler sax_handler;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ data.path.path_type = TRACK;
+ MACRO_INIT_TRACK(data.path.path.track);
+ data.state = START;
+ data.chars = g_string_new("");
+
+ memset(&sax_handler, 0, sizeof(sax_handler));
+ sax_handler.characters = (charactersSAXFunc)gpx_chars;
+ sax_handler.startElement = (startElementSAXFunc)gpx_start_element;
+ sax_handler.endElement = (endElementSAXFunc)gpx_end_element;
+ sax_handler.entityDecl = (entityDeclSAXFunc)gpx_get_entity;
+ sax_handler.warning = (warningSAXFunc)gpx_error;
+ sax_handler.error = (errorSAXFunc)gpx_error;
+ sax_handler.fatalError = (fatalErrorSAXFunc)gpx_error;
+
+ xmlSAXUserParseMemory(&sax_handler, &data, buffer, size);
+ g_string_free(data.chars, TRUE);
+
+ if(data.state != FINISH)
+ {
+ vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return FALSE;
+ }
+
+ /* Successful parsing - replace given Track structure. */
+ if(policy_old && _track.head)
+ {
+ TrackPoint *src_first;
+ Track *src, *dest;
+
+ if(policy_old > 0)
+ {
+ /* Append to current track. */
+ src = &data.path.path.track;
+ dest = &_track;
+ }
+ else
+ {
+ /* Prepend to current track. */
+ src = &_track;
+ dest = &data.path.path.track;
+ }
+
+ /* Find src_first non-zero point. */
+ for(src_first = src->head - 1; src_first++ != src->tail; )
+ if(src_first->point.unity)
+ break;
+
+ /* Append track points from src to dest. */
+ if(src->tail >= src_first)
+ {
+ guint num_dest_points = dest->tail - dest->head + 1;
+ guint num_src_points = src->tail - src_first + 1;
+
+ /* Adjust dest->tail to be able to fit src track data
+ * plus room for more track data. */
+ track_resize(dest,
+ num_dest_points + num_src_points + ARRAY_CHUNK_SIZE);
+
+ memcpy(dest->tail + 1, src_first,
+ num_src_points * sizeof(TrackPoint));
+
+ dest->tail += num_src_points;
+ }
+
+ MACRO_CLEAR_TRACK(*src);
+ if(policy_old < 0)
+ _track = *dest;
+ }
+ else
+ {
+ MACRO_CLEAR_TRACK(_track);
+ /* Overwrite with data.track. */
+ _track = data.path.path.track;
+ track_resize(&_track,
+ _track.tail - _track.head + 1 + ARRAY_CHUNK_SIZE);
+ }
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
+
+static gboolean
+parse_route_gpx(gchar *buffer, gint size, gint policy_old)
+{
+ SaxData data;
+ xmlSAXHandler sax_handler;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ data.path.path_type = ROUTE;
+ MACRO_INIT_ROUTE(data.path.path.route);
+ data.state = START;
+ data.chars = g_string_new("");
+
+ memset(&sax_handler, 0, sizeof(sax_handler));
+ sax_handler.characters = (charactersSAXFunc)gpx_chars;
+ sax_handler.startElement = (startElementSAXFunc)gpx_start_element;
+ sax_handler.endElement = (endElementSAXFunc)gpx_end_element;
+ sax_handler.entityDecl = (entityDeclSAXFunc)gpx_get_entity;
+ sax_handler.warning = (warningSAXFunc)gpx_error;
+ sax_handler.error = (errorSAXFunc)gpx_error;
+ sax_handler.fatalError = (fatalErrorSAXFunc)gpx_error;
+
+ xmlSAXUserParseMemory(&sax_handler, &data, buffer, size);
+ g_string_free(data.chars, TRUE);
+
+ if(data.state != FINISH)
+ {
+ vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return FALSE;
+ }
+
+ if(policy_old && _route.head)
+ {
+ Point *src_first;
+ Route *src, *dest;
+
+ if(policy_old > 0)
+ {
+ /* Append to current route. */
+ src = &data.path.path.route;
+ dest = &_route;
+ }
+ else
+ {
+ /* Prepend to current route. */
+ src = &_route;
+ dest = &data.path.path.route;
+ }
+
+ /* Find src_first non-zero point. */
+ for(src_first = src->head - 1; src_first++ != src->tail; )
+ if(src_first->unity)
+ break;
+
+ /* Append route points from src to dest. */
+ if(src->tail >= src_first)
+ {
+ WayPoint *curr;
+ guint num_dest_points = dest->tail - dest->head + 1;
+ guint num_src_points = src->tail - src_first + 1;
+
+ /* Adjust dest->tail to be able to fit src route data
+ * plus room for more route data. */
+ route_resize(dest, num_dest_points + num_src_points);
+
+ memcpy(dest->tail + 1, src_first,
+ num_src_points * sizeof(Point));
+
+ dest->tail += num_src_points;
+
+ /* Append waypoints from src to dest->. */
+ route_wresize(dest, (dest->wtail - dest->whead)
+ + (src->wtail - src->whead) + 2);
+ for(curr = src->whead - 1; curr++ != src->wtail; )
+ {
+ (++(dest->wtail))->point = dest->head + num_dest_points
+ + (curr->point - src_first);
+ dest->wtail->desc = curr->desc;
+ }
+
+ }
+
+ /* Kill old route - don't use MACRO_CLEAR_ROUTE(), because that
+ * would free the string desc's that we just moved to data.route. */
+ g_free(src->head);
+ g_free(src->whead);
+ if(policy_old < 0)
+ _route = *dest;
+ }
+ else
+ {
+ MACRO_CLEAR_ROUTE(_route);
+ /* Overwrite with data.route. */
+ _route = data.path.path.route;
+ route_resize(&_route, _route.tail - _route.head + 1);
+ }
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
+
+/**
+ * This is a multi-purpose function for allowing the user to select a file
+ * for either reading or writing. If chooser_action is
+ * GTK_FILE_CHOOSER_ACTION_OPEN, then bytes_out and size_out must be
+ * non-NULL. If chooser_action is GTK_FILE_CHOOSER_ACTION_SAVE, then
+ * handle_out must be non-NULL. Either dir or file (or both) can be NULL.
+ * This function returns TRUE if a file was successfully opened.
+ */
+static gboolean
+open_file(gchar **bytes_out, GnomeVFSHandle **handle_out, gint *size_out,
+ gchar **dir, gchar **file, GtkFileChooserAction chooser_action)
+{
+ GtkWidget *dialog;
+ gboolean success = FALSE;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(_window),chooser_action);
+
+ if(dir && *dir)
+ gtk_file_chooser_set_current_folder_uri(
+ GTK_FILE_CHOOSER(dialog), *dir);
+ if(file && *file)
+ {
+ GValue val;
+ gtk_file_chooser_set_uri(
+ GTK_FILE_CHOOSER(dialog), *file);
+ if(chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ {
+ /* Work around a bug in HildonFileChooserDialog. */
+ memset(&val, 0, sizeof(val));
+ g_value_init(&val, G_TYPE_BOOLEAN);
+ g_value_set_boolean(&val, FALSE);
+ g_object_set_property(G_OBJECT(dialog), "autonaming", &val);
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
+ strrchr(*file, '/') + 1);
+ }
+ }
+
+ gtk_widget_show_all(GTK_WIDGET(dialog));
+
+ while(!success && gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_OK)
+ {
+ gchar *file_uri_str;
+ GnomeVFSResult vfs_result;
+
+ /* Get the selected filename. */
+ file_uri_str = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
+
+ if((chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
+ && (GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
+ file_uri_str, size_out, bytes_out))))
+ || (chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE
+ && GNOME_VFS_OK != (vfs_result = gnome_vfs_create(
+ handle_out, file_uri_str,
+ GNOME_VFS_OPEN_WRITE, FALSE, 0664))))
+ {
+ gchar buffer[1024];
+ sprintf(buffer, "%s %s:\n%s", _("Failed to open file for"),
+ chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
+ ? _("reading") : _("writing"),
+ gnome_vfs_result_to_string(vfs_result));
+ popup_error(dialog, buffer);
+ }
+ else
+ success = TRUE;
+
+ g_free(file_uri_str);
+ }
+
+ if(success)
+ {
+ /* Success!. */
+ if(dir)
+ {
+ if(*dir)
+ g_free(*dir);
+ *dir = gtk_file_chooser_get_current_folder_uri(
+ GTK_FILE_CHOOSER(dialog));
+ }
+
+ /* If desired, save the file for later. */
+ if(file)
+ {
+ if(*file)
+ g_free(*file);
+ *file = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
+ }
+ }
+
+ gtk_widget_destroy(dialog);
+
+ vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
+ return success;
+}
+
+/**
+ * Refresh the view based on the fact that the route has been automatically
+ * updated.
+ */
+static gboolean
+auto_route_dl_idle_refresh()
+{
+ /* Make sure we're still supposed to do work. */
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
+
+ if(!_autoroute_data.enabled)
+ _autoroute_data.handle = NULL;
+ else
+ {
+ if(parse_route_gpx(_autoroute_data.bytes, _autoroute_data.bytes_read,0))
+ {
+ /* Find the nearest route point, if we're connected. */
+ route_find_nearest_point();
+
+ map_force_redraw();
+ }
+ }
+
+ _autoroute_data.in_progress = FALSE;
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return FALSE;
+}
+
+/**
+ * Read the data provided by the given handle as GPX data, updating the
+ * auto-route with that data.
+ */
+static void
+auto_route_dl_cb_read(GnomeVFSAsyncHandle *handle,
+ GnomeVFSResult result,
+ gpointer bytes,
+ GnomeVFSFileSize bytes_requested,
+ GnomeVFSFileSize bytes_read)
+{
+ vprintf("%s(%s)\n", __PRETTY_FUNCTION__,gnome_vfs_result_to_string(result));
+
+ _autoroute_data.bytes_read += bytes_read;
+ if(result == GNOME_VFS_OK)
+ {
+ /* Expand bytes and continue reading. */
+ if(_autoroute_data.bytes_read * 2 > _autoroute_data.bytes_maxsize)
+ {
+ _autoroute_data.bytes = g_renew(gchar, _autoroute_data.bytes,
+ 2 * _autoroute_data.bytes_read);
+ _autoroute_data.bytes_maxsize = 2 * _autoroute_data.bytes_read;
+ }
+ gnome_vfs_async_read(_autoroute_data.handle,
+ _autoroute_data.bytes + _autoroute_data.bytes_read,
+ _autoroute_data.bytes_maxsize - _autoroute_data.bytes_read,
+ (GnomeVFSAsyncReadCallback)auto_route_dl_cb_read, NULL);
+ }
+ else
+ g_idle_add((GSourceFunc)auto_route_dl_idle_refresh, NULL);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Open the given handle in preparation for reading GPX data.
+ */
+static void
+auto_route_dl_cb_open(GnomeVFSAsyncHandle *handle, GnomeVFSResult result)
+{
+ vprintf("%s()\n", __PRETTY_FUNCTION__);
+
+ if(result == GNOME_VFS_OK)
+ gnome_vfs_async_read(_autoroute_data.handle,
+ _autoroute_data.bytes,
+ _autoroute_data.bytes_maxsize,
+ (GnomeVFSAsyncReadCallback)auto_route_dl_cb_read, NULL);
+ else
+ {
+ _autoroute_data.in_progress = FALSE;
+ _autoroute_data.handle = NULL;
+ }
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * This function is periodically run to download updated auto-route data
+ * from the route source.
+ */
+static gboolean
+auto_route_dl_idle()
+{
+ gchar buffer[1024], latstr[32], lonstr[32];
+ vprintf("%s(%f, %f, %s)\n", __PRETTY_FUNCTION__,
+ _pos_lat, _pos_lon, _autoroute_data.dest);
+
+
+ g_ascii_dtostr(latstr, 32, _pos_lat);
+ g_ascii_dtostr(lonstr, 32, _pos_lon);
+ sprintf(buffer,"http://www.gnuite.com/cgi-bin/gpx.cgi?saddr=%s,%s&daddr=%s",
+ latstr, lonstr, _autoroute_data.dest);
+ _autoroute_data.bytes_read = 0;
+
+ gnome_vfs_async_open(&_autoroute_data.handle,
+ buffer, GNOME_VFS_OPEN_READ,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ (GnomeVFSAsyncOpenCallback)auto_route_dl_cb_open, NULL);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return FALSE;
+}
+
+/**
+ * Cancel the current auto-route.
+ */
+static void
+cancel_autoroute()
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ if(_autoroute_data.enabled)
+ {
+ _autoroute_data.enabled = FALSE;
+ if(_autoroute_data.dest)
+ {
+ g_free(_autoroute_data.dest);
+ _autoroute_data.dest = NULL;
+ }
+ if(_autoroute_data.handle)
+ {
+ gnome_vfs_async_cancel(_autoroute_data.handle);
+ _autoroute_data.handle = NULL;
+ }
+ if(_autoroute_data.bytes)
+ {
+ g_free(_autoroute_data.bytes);
+ _autoroute_data.bytes = NULL;
+ }
+ _autoroute_data.in_progress = FALSE;
+ }
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Save state and destroy all non-UI elements created by this program in
+ * preparation for exiting.
+ */
+static void
+maemo_mapper_destroy(void)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ config_save();
+ rcvr_disconnect();
+ /* _program and widgets have already been destroyed. */
+
+ if(_dbconn)
+ sqlite_close(_db);
+
+ MACRO_CLEAR_TRACK(_track);
+ if(_route.head)
+ MACRO_CLEAR_TRACK(_route);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Initialize everything required in preparation for calling gtk_main().
+ */
+static void
+maemo_mapper_init(gint argc, gchar **argv)
+{
+ GtkWidget *hbox, *label, *vbox;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ config_init();
+
+ /* Initialize _program. */
+ _program = HILDON_PROGRAM(hildon_program_get_instance());
+ g_set_application_name("Maemo Mapper");
+
+ /* Initialize _window. */
+ _window = GTK_WIDGET(hildon_window_new());
+ hildon_program_add_window(_program, HILDON_WINDOW(_window));
+
+ /* Create and add widgets and supporting data. */
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(_window), hbox);
+
+ _gps_widget = gtk_frame_new("GPS Info");
+ gtk_container_add(GTK_CONTAINER(_gps_widget),
+ vbox = gtk_vbox_new(FALSE, 0));
+ gtk_widget_set_size_request(GTK_WIDGET(_gps_widget), 180, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), _gps_widget, FALSE, TRUE, 0);
+
+ label = gtk_label_new(" ");
+ gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+
+ _text_lat = gtk_label_new(" --- ");
+ gtk_widget_set_size_request(GTK_WIDGET(_text_lat), -1, 30);
+ gtk_box_pack_start(GTK_BOX(vbox), _text_lat, FALSE, TRUE, 0);
+
+ _text_lon = gtk_label_new(" --- ");
+ gtk_widget_set_size_request(GTK_WIDGET(_text_lon), -1, 30);
+ gtk_box_pack_start(GTK_BOX(vbox), _text_lon, FALSE, TRUE, 0);
+
+ _text_speed = gtk_label_new(" --- ");
+ gtk_widget_set_size_request(GTK_WIDGET(_text_speed), -1, 30);
+ gtk_box_pack_start(GTK_BOX(vbox), _text_speed, FALSE, TRUE, 0);
+
+ _text_alt = gtk_label_new(" --- ");
+ gtk_widget_set_size_request(GTK_WIDGET(_text_alt), -1, 30);
+ gtk_box_pack_start(GTK_BOX(vbox), _text_alt, FALSE, TRUE, 0);
+
+ label = gtk_label_new(" ");
+ gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+
+ _sat_panel = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (_sat_panel, -1, 100);
+ gtk_box_pack_start(GTK_BOX(vbox), _sat_panel, TRUE, TRUE, 0);
+
+ label = gtk_label_new(" ");
+ gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+
+ _text_time = gtk_label_new("--:--:--");
+ gtk_widget_set_size_request(GTK_WIDGET(_text_time), -1, 30);
+ gtk_box_pack_start(GTK_BOX(vbox), _text_time, FALSE, TRUE, 0);
+
+ _heading_panel = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (_heading_panel, -1, 100);
+ gtk_box_pack_start(GTK_BOX(vbox), _heading_panel, TRUE, TRUE, 0);
+
+ _map_widget = gtk_drawing_area_new();
+ gtk_box_pack_start(GTK_BOX(hbox), _map_widget, TRUE, TRUE, 0);
+
+ gtk_widget_realize(_map_widget);
+
+ _map_pixmap = gdk_pixmap_new(
+ _map_widget->window,
+ BUF_WIDTH_PIXELS, BUF_HEIGHT_PIXELS,
+ -1); /* -1: use bit depth of widget->window. */
+
+ /* Connect signals. */
+ g_signal_connect(G_OBJECT(_sat_panel), "expose_event",
+ G_CALLBACK(sat_panel_expose), NULL);
+ g_signal_connect(G_OBJECT(_heading_panel), "expose_event",
+ G_CALLBACK(heading_panel_expose), NULL);
+ g_signal_connect(G_OBJECT(_window), "destroy",
+ G_CALLBACK(gtk_main_quit), NULL);
+
+ g_signal_connect(G_OBJECT(_window), "key_press_event",
+ G_CALLBACK(window_cb_key_press), NULL);
+
+ g_signal_connect(G_OBJECT(_window), "key_release_event",
+ G_CALLBACK(window_cb_key_release), NULL);
+
+ g_signal_connect(G_OBJECT(_map_widget), "configure_event",
+ G_CALLBACK(map_cb_configure), NULL);
+
+ g_signal_connect(G_OBJECT(_map_widget), "expose_event",
+ G_CALLBACK(map_cb_expose), NULL);
+
+ g_signal_connect(G_OBJECT(_map_widget), "button_press_event",
+ G_CALLBACK(map_cb_button_press), NULL);
+
+ g_signal_connect(G_OBJECT(_map_widget), "button_release_event",
+ G_CALLBACK(map_cb_button_release), NULL);
+
+ gtk_widget_add_events(_map_widget,
+ GDK_EXPOSURE_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK);
+
+ osso_hw_set_event_cb(_osso, NULL, osso_cb_hw_state, NULL);
+
+ gnome_vfs_async_set_job_limit(24);
+
+ /* Initialize data. */
+
+ UNITS_TEXT[UNITS_KM] = UNITS_KM_TEXT;
+ UNITS_TEXT[UNITS_MI] = UNITS_MI_TEXT;
+ UNITS_TEXT[UNITS_NM] = UNITS_NM_TEXT;
+
+ ESCAPE_KEY_TEXT[ESCAPE_KEY_TOGGLE_TRACKS] = ESCAPE_KEY_TOGGLE_TRACKS_TEXT;
+ ESCAPE_KEY_TEXT[ESCAPE_KEY_CHANGE_REPO] = ESCAPE_KEY_CHANGE_REPO_TEXT;
+ ESCAPE_KEY_TEXT[ESCAPE_KEY_RESET_BLUETOOTH]=ESCAPE_KEY_RESET_BLUETOOTH_TEXT;
+
+ /* set XML_TZONE */
+ {
+ time_t time1;
+ struct tm time2;
+ time1 = time(NULL);
+ localtime_r(&time1, &time2);
+ sprintf(XML_TZONE, "%+03ld:%02ld",
+ (time2.tm_gmtoff / 60 / 60), (time2.tm_gmtoff / 60) % 60);
+ _gmtoffset = time2.tm_gmtoff;
+ }
+
+ memset(&_track, 0, sizeof(_track));
+ memset(&_route, 0, sizeof(_route));
+ _last_spoken_phrase = g_strdup("");
+
+ /* Set up track array. */
+ MACRO_INIT_TRACK(_track);
+
+ _downloads_hash = g_hash_table_new((GHashFunc)download_hashfunc,
+ (GEqualFunc)download_equalfunc);
+ memset(&_autoroute_data, 0, sizeof(_autoroute_data));
+
+ integerize_data();
+
+ /* Initialize our line styles. */
+ update_gcs();
+
+ menu_init();
+
+ /* If present, attempt to load the file specified on the command line. */
+ if(argc > 1)
+ {
+ GnomeVFSResult vfs_result;
+ gint size;
+ gchar *buffer;
+ gchar *file_uri;
+
+ /* Get the selected filename. */
+ file_uri = gnome_vfs_make_uri_from_shell_arg(argv[1]);
+
+ if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
+ file_uri, &size, &buffer)))
+ {
+ gchar buffer[1024];
+ sprintf(buffer, "%s %s:\n%s", _("Failed to open file for"),
+ _("reading"), gnome_vfs_result_to_string(vfs_result));
+ popup_error(_window, buffer);
+ }
+ else
+ {
+ /* If auto is enabled, append the route, otherwise replace it. */
+ if(parse_route_gpx(buffer, size, 0))
+ hildon_banner_show_information(
+ _window, NULL, _("Route Opened"));
+ else
+ popup_error(_window, _("Error parsing GPX file."));
+ g_free(buffer);
+ }
+ g_free(file_uri);
+ }
+
+ gtk_idle_add((GSourceFunc)window_present, NULL);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/****************************************************************************
+ * ABOVE: ROUTINES **********************************************************
+ ****************************************************************************/
+
+
+
+/****************************************************************************
+ * BELOW: MAIN **************************************************************
+ ****************************************************************************/
+
+gint
+main(gint argc, gchar *argv[])
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ g_thread_init(NULL);
+
+ /* Initialize _osso. */
+ _osso = osso_initialize("com.gnuite.maemo_mapper", VERSION, TRUE, NULL);
+ if(!_osso)
+ {
+ fprintf(stderr, "osso_initialize failed.\n");
+ return 1;
+ }
+
+ gtk_init(&argc, &argv);
+
+ /* Init gconf. */
+ g_type_init();
+ gconf_init(argc, argv, NULL);
+
+ gnome_vfs_init();
+
+ maemo_mapper_init(argc, argv);
+
+ if(OSSO_OK != osso_rpc_set_default_cb_f(_osso, dbus_cb_default, NULL))
+ {
+ fprintf(stderr, "osso_rpc_set_default_cb_f failed.\n");
+ return 1;
+ }
+
+ gtk_main();
+
+ maemo_mapper_destroy();
+
+ osso_deinitialize(_osso);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return 0;
+}
+
+/****************************************************************************
+ * ABOVE: MAIN **************************************************************
+ ****************************************************************************/
+
+
+
+/****************************************************************************
+ * BELOW: CALLBACKS *********************************************************
+ ****************************************************************************/
+
+static gint
+dbus_cb_default(const gchar *interface, const gchar *method,
+ GArray *arguments, gpointer data, osso_rpc_t *retval)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ if(!strcmp(method, "top_application"))
+ gtk_idle_add((GSourceFunc)window_present, NULL);
+
+ retval->type = DBUS_TYPE_INVALID;
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return OSSO_OK;
+}
+
static void
-gpx_chars(SaxData *data, const xmlChar *ch, int len)
+osso_cb_hw_state(osso_hw_state_t *state, gpointer data)
{
- guint i;
- vprintf("%s()\n", __PRETTY_FUNCTION__);
+ static gboolean _must_save_data = FALSE;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- switch(data->state)
+ if(state->system_inactivity_ind)
{
- case ERROR:
- case UNKNOWN:
- break;
- case INSIDE_PATH_POINT_TIME:
- case INSIDE_PATH_POINT_DESC:
- for (i = 0; i < len; i++)
- data->chars = g_string_append_c(data->chars, ch[i]);
- vprintf("%s\n", data->chars->str);
- break;
- default:
- break;
+ if(_must_save_data)
+ _must_save_data = FALSE;
+ else if(_conn_state > RCVR_OFF)
+ {
+ set_conn_state(RCVR_OFF);
+ rcvr_disconnect();
+ track_add(0, FALSE);
+ /* Pretend the autoroute is in progress to avoid download. */
+ if(_autoroute_data.enabled)
+ _autoroute_data.in_progress = TRUE;
+ }
+ }
+ else if(state->save_unsaved_data_ind)
+ {
+ config_save();
+ _must_save_data = TRUE;
+ }
+ else if(_conn_state == RCVR_OFF && _enable_gps)
+ {
+ set_conn_state(RCVR_DOWN);
+ rcvr_connect_later();
+ if(_autoroute_data.enabled)
+ _autoroute_data.in_progress = TRUE;
}
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * Handle an entity in the parsing of a GPX file. We don't do anything
- * special here.
- */
-static xmlEntityPtr
-gpx_get_entity(SaxData *data, const xmlChar *name)
+static gboolean
+key_zoom_timeout()
{
- vprintf("%s()\n", __PRETTY_FUNCTION__);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return xmlGetPredefinedEntity(name);
+ if(_key_zoom_new < _zoom)
+ {
+ /* We're currently zooming in (_zoom is decreasing). */
+ guint test = _key_zoom_new - _curr_repo->view_zoom_steps;
+ if(test < MAX_ZOOM)
+ /* We can zoom some more. Hurray! */
+ _key_zoom_new = test;
+ else
+ /* We can't zoom anymore. Booooo! */
+ return FALSE;
+ }
+ else
+ {
+ /* We're currently zooming out (_zoom is increasing). */
+ guint test = _key_zoom_new + _curr_repo->view_zoom_steps;
+ if(test < MAX_ZOOM)
+ /* We can zoom some more. Hurray! */
+ _key_zoom_new = test;
+ else
+ /* We can't zoom anymore. Booooo! */
+ return FALSE;
+ }
+
+ /* We can zoom more - tell them how much they're zooming. */
+ {
+ gchar buffer[32];
+ sprintf(buffer, "%s %d", _("Zoom to Level"), _key_zoom_new);
+ hildon_banner_show_information(_window, NULL, buffer);
+ }
+ return TRUE;
}
-/**
- * Handle an error in the parsing of a GPX file.
- */
static void
-gpx_error(SaxData *data, const gchar *msg, ...)
+reset_bluetooth()
{
- vprintf("%s()\n", __PRETTY_FUNCTION__);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- data->state = ERROR;
+ if(system("/usr/bin/sudo -l | grep -q '/usr/sbin/hciconfig *hci0 *reset'"
+ " && sudo /usr/sbin/hciconfig hci0 reset"))
+ popup_error(_window,
+ _("An error occurred while trying to reset the bluetooth "
+ "radio.\n\n"
+ "Did you make sure to modify\nthe /etc/sudoers file?"));
+ else if(_conn_state > RCVR_OFF)
+ {
+ set_conn_state(RCVR_DOWN);
+ rcvr_connect_now();
+ }
}
-/**
- * Parse the given character buffer of the given size, replacing the given
- * Track's pointers with pointers to new arrays depending on the given
- * policy, adding extra_bins slots in the arrays for new data.
- *
- * policy_old should be negative to indicate that the existing data should
- * be prepended to the new GPX data, positive to indicate the opposite, and
- * zero to indicate that we should throw away the old data.
- *
- * When importing tracks, we *prepend* the GPX data and provide extra_bins.
- * When importing routes, we *append* in the case of regular routes, and we
- * *replace* in the case of automatic routing. Routes get no extra bins.
- */
static gboolean
-parse_track_gpx(gchar *buffer, gint size, gint policy_old)
+window_cb_key_press(GtkWidget* widget, GdkEventKey *event)
{
- SaxData data;
- xmlSAXHandler sax_handler;
printf("%s()\n", __PRETTY_FUNCTION__);
- data.path.path_type = TRACK;
- MACRO_INIT_TRACK(data.path.path.track);
- data.state = START;
- data.chars = g_string_new("");
-
- memset(&sax_handler, 0, sizeof(sax_handler));
- sax_handler.characters = (charactersSAXFunc)gpx_chars;
- sax_handler.startElement = (startElementSAXFunc)gpx_start_element;
- sax_handler.endElement = (endElementSAXFunc)gpx_end_element;
- sax_handler.entityDecl = (entityDeclSAXFunc)gpx_get_entity;
- sax_handler.warning = (warningSAXFunc)gpx_error;
- sax_handler.error = (errorSAXFunc)gpx_error;
- sax_handler.fatalError = (fatalErrorSAXFunc)gpx_error;
+ switch(event->keyval)
+ {
+ case HILDON_HARDKEY_UP:
+ map_pan(0, -PAN_UNITS);
+ return TRUE;
- xmlSAXUserParseMemory(&sax_handler, &data, buffer, size);
- g_string_free(data.chars, TRUE);
+ case HILDON_HARDKEY_DOWN:
+ map_pan(0, PAN_UNITS);
+ return TRUE;
- if(data.state != FINISH)
- {
- vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
- return FALSE;
- }
-
- /* Successful parsing - replace given Track structure. */
- if(policy_old && _track.head)
- {
- TrackPoint *src_first;
- Track *src, *dest;
+ case HILDON_HARDKEY_LEFT:
+ map_pan(-PAN_UNITS, 0);
+ return TRUE;
- if(policy_old > 0)
- {
- /* Append to current track. */
- src = &data.path.path.track;
- dest = &_track;
- }
- else
- {
- /* Prepend to current track. */
- src = &_track;
- dest = &data.path.path.track;
- }
+ case HILDON_HARDKEY_RIGHT:
+ map_pan(PAN_UNITS, 0);
+ return TRUE;
- /* Find src_first non-zero point. */
- for(src_first = src->head - 1; src_first++ != src->tail; )
- if(src_first->point.unity)
- break;
+ case HILDON_HARDKEY_SELECT:
+ switch(_center_mode)
+ {
+ case CENTER_LATLON:
+ case CENTER_WAS_LEAD:
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ _menu_ac_lead_item), TRUE);
+ break;
+ case CENTER_LEAD:
+ case CENTER_WAS_LATLON:
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ _menu_ac_latlon_item), TRUE);
+ break;
+ }
+ return TRUE;
- /* Append track points from src to dest. */
- if(src->tail >= src_first)
- {
- guint num_dest_points = dest->tail - dest->head + 1;
- guint num_src_points = src->tail - src_first + 1;
+ case HILDON_HARDKEY_FULLSCREEN:
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ _menu_fullscreen_item), !_fullscreen);
+ return TRUE;
- /* Adjust dest->tail to be able to fit src track data
- * plus room for more track data. */
- track_resize(dest,
- num_dest_points + num_src_points + ARRAY_CHUNK_SIZE);
+ case HILDON_HARDKEY_INCREASE:
+ case HILDON_HARDKEY_DECREASE:
+ if(!_key_zoom_timeout_sid)
+ {
+ _key_zoom_new = _zoom
+ + (event->keyval == HILDON_HARDKEY_INCREASE
+ ? -_curr_repo->view_zoom_steps
+ : _curr_repo->view_zoom_steps);
+ /* Remember, _key_zoom_new is unsigned. */
+ if(_key_zoom_new < MAX_ZOOM)
+ {
+ gchar buffer[80];
+ sprintf(buffer, "%s %d", _("Zoom to Level"), _key_zoom_new);
+ hildon_banner_show_information(_window, NULL, buffer);
+ _key_zoom_timeout_sid = g_timeout_add(
+ 500, key_zoom_timeout, NULL);
+ }
+ }
+ return TRUE;
- memcpy(dest->tail + 1, src_first,
- num_src_points * sizeof(TrackPoint));
+ case HILDON_HARDKEY_ESC:
+ switch(_escape_key)
+ {
+ case ESCAPE_KEY_CHANGE_REPO:
+ {
+ GList *curr = g_list_find(_repo_list, _curr_repo);
+ if(curr && curr->next)
+ curr = curr->next;
+ else
+ curr = _repo_list;
+ _curr_repo = curr->data;
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_curr_repo->menu_item),
+ TRUE);
+ }
+ break;
+ case ESCAPE_KEY_RESET_BLUETOOTH:
+ reset_bluetooth();
+ break;
+ default:
+ switch(_show_tracks)
+ {
+ case 0:
+ /* Nothing shown, nothing saved; just set both. */
+ _show_tracks = TRACKS_MASK | ROUTES_MASK;
+ break;
+ case TRACKS_MASK << 16:
+ case ROUTES_MASK << 16:
+ case (ROUTES_MASK | TRACKS_MASK) << 16:
+ /* Something was saved and nothing changed since.
+ * Restore saved. */
+ _show_tracks = _show_tracks >> 16;
+ break;
+ default:
+ /* There is no history, or they changed something
+ * since the last historical change. Save and
+ * clear. */
+ _show_tracks = _show_tracks << 16;
+ }
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ _menu_show_routes_item),
+ _show_tracks & ROUTES_MASK);
- dest->tail += num_src_points;
- }
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ _menu_show_tracks_item),
+ _show_tracks & TRACKS_MASK);
+ }
+ return TRUE;
- MACRO_CLEAR_TRACK(*src);
- if(policy_old < 0)
- _track = *dest;
- }
- else
- {
- MACRO_CLEAR_TRACK(_track);
- /* Overwrite with data.track. */
- _track = data.path.path.track;
- track_resize(&_track,
- _track.tail - _track.head + 1 + ARRAY_CHUNK_SIZE);
+ default:
+ return FALSE;
}
-
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
}
static gboolean
-parse_route_gpx(gchar *buffer, gint size, gint policy_old)
+window_cb_key_release(GtkWidget* widget, GdkEventKey *event)
{
- SaxData data;
- xmlSAXHandler sax_handler;
printf("%s()\n", __PRETTY_FUNCTION__);
- data.path.path_type = ROUTE;
- MACRO_INIT_ROUTE(data.path.path.route);
- data.state = START;
- data.chars = g_string_new("");
-
- memset(&sax_handler, 0, sizeof(sax_handler));
- sax_handler.characters = (charactersSAXFunc)gpx_chars;
- sax_handler.startElement = (startElementSAXFunc)gpx_start_element;
- sax_handler.endElement = (endElementSAXFunc)gpx_end_element;
- sax_handler.entityDecl = (entityDeclSAXFunc)gpx_get_entity;
- sax_handler.warning = (warningSAXFunc)gpx_error;
- sax_handler.error = (errorSAXFunc)gpx_error;
- sax_handler.fatalError = (fatalErrorSAXFunc)gpx_error;
-
- xmlSAXUserParseMemory(&sax_handler, &data, buffer, size);
- g_string_free(data.chars, TRUE);
-
- if(data.state != FINISH)
+ switch(event->keyval)
{
- vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
- return FALSE;
- }
-
- if(policy_old && _route.head)
- {
- Point *src_first;
- Route *src, *dest;
-
- if(policy_old > 0)
- {
- /* Append to current route. */
- src = &data.path.path.route;
- dest = &_route;
- }
- else
- {
- /* Prepend to current route. */
- src = &_route;
- dest = &data.path.path.route;
- }
+ case HILDON_HARDKEY_INCREASE:
+ case HILDON_HARDKEY_DECREASE:
+ if(_key_zoom_timeout_sid)
+ {
+ g_source_remove(_key_zoom_timeout_sid);
+ _key_zoom_timeout_sid = 0;
+ map_set_zoom(_key_zoom_new);
+ }
+ return TRUE;
- /* Find src_first non-zero point. */
- for(src_first = src->head - 1; src_first++ != src->tail; )
- if(src_first->unity)
- break;
+ default:
+ return FALSE;
+ }
+}
- /* Append route points from src to dest. */
- if(src->tail >= src_first)
- {
- WayPoint *curr;
- guint num_dest_points = dest->tail - dest->head + 1;
- guint num_src_points = src->tail - src_first + 1;
+static gboolean
+map_cb_configure(GtkWidget *widget, GdkEventConfigure *event)
+{
+ printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
+ _map_widget->allocation.width, _map_widget->allocation.height);
- /* Adjust dest->tail to be able to fit src route data
- * plus room for more route data. */
- route_resize(dest, num_dest_points + num_src_points);
+ _screen_width_pixels = _map_widget->allocation.width;
+ _screen_height_pixels = _map_widget->allocation.height;
+ _screen_grids_halfwidth = pixel2grid(_screen_width_pixels) / 2;
+ _screen_grids_halfheight = pixel2grid(_screen_height_pixels) / 2;
- memcpy(dest->tail + 1, src_first,
- num_src_points * sizeof(Point));
+ MACRO_RECALC_FOCUS_BASE();
+ MACRO_RECALC_FOCUS_SIZE();
- dest->tail += num_src_points;
+ _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
+ _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
+ _max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1;
+ _max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1;
- /* Append waypoints from src to dest->. */
- route_wresize(dest, (dest->wtail - dest->whead)
- + (src->wtail - src->whead) + 2);
- for(curr = src->whead - 1; curr++ != src->wtail; )
- {
- (++(dest->wtail))->point = dest->head + num_dest_points
- + (curr->point - src_first);
- dest->wtail->desc = curr->desc;
- }
+ map_center_unit(_center.unitx, _center.unity);
- }
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Kill old route - don't use MACRO_CLEAR_ROUTE(), because that
- * would free the string desc's that we just moved to data.route. */
- g_free(src->head);
- g_free(src->whead);
- if(policy_old < 0)
- _route = *dest;
- }
- else
+static gboolean
+sat_panel_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+ PangoContext *context = NULL;
+ PangoLayout *layout = NULL;
+ PangoFontDescription *fontdesc = NULL;
+ gchar *tmp = NULL;
+ guint x, y;
+
+ draw_sat_info(widget,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height,
+ FALSE);
+
+ context = gtk_widget_get_pango_context(widget);
+ layout = pango_layout_new(context);
+ fontdesc = pango_font_description_new();
+
+ pango_font_description_set_family(fontdesc,"Sans Serif");
+ pango_font_description_set_size(fontdesc, 14*PANGO_SCALE);
+
+ /* Sat View/In Use */
+ tmp = g_strdup_printf("%d/%d", _gps.satinuse, _gps.satinview);
+ pango_layout_set_font_description (layout, fontdesc);
+ pango_layout_set_text(layout, tmp, strlen(tmp));
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ 20, 2,
+ layout);
+ g_free(tmp);
+
+ switch(_gps.fix)
{
- MACRO_CLEAR_ROUTE(_route);
- /* Overwrite with data.route. */
- _route = data.path.path.route;
- route_resize(&_route, _route.tail - _route.head + 1);
- }
+ case 2:
+ case 3: tmp = g_strdup_printf("%dD fix", _gps.fix); break;
+ default: tmp = g_strdup_printf("nofix"); break;
+ }
+ pango_layout_set_text(layout, tmp, strlen(tmp));
+ pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
+ pango_layout_get_pixel_size(layout, &x, &y);
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ widget->allocation.width - 20 - x, 2,
+ layout);
+ g_free(tmp);
+
+ pango_font_description_free (fontdesc);
+ g_object_unref (layout);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
-/**
- * This is a multi-purpose function for allowing the user to select a file
- * for either reading or writing. If chooser_action is
- * GTK_FILE_CHOOSER_ACTION_OPEN, then bytes_out and size_out must be
- * non-NULL. If chooser_action is GTK_FILE_CHOOSER_ACTION_SAVE, then
- * handle_out must be non-NULL. Either dir or file (or both) can be NULL.
- * This function returns TRUE if a file was successfully opened.
- */
static gboolean
-open_file(gchar **bytes_out, GnomeVFSHandle **handle_out, gint *size_out,
- gchar **dir, gchar **file, GtkFileChooserAction chooser_action)
+heading_panel_expose(GtkWidget *widget, GdkEventExpose *event)
{
- GtkWidget *dialog;
- gboolean success = FALSE;
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(_window),chooser_action);
+ guint size, xoffset, yoffset, i, x, y;
+ gint dir;
+ gfloat tmp;
+ gchar *text;
+ PangoContext *context=NULL;
+ PangoLayout *layout=NULL;
+ PangoFontDescription *fontdesc=NULL;
- if(dir && *dir)
- gtk_file_chooser_set_current_folder_uri(
- GTK_FILE_CHOOSER(dialog), *dir);
- if(file && *file)
+ size = MIN(widget->allocation.width, widget->allocation.height);
+ if(widget->allocation.width > widget->allocation.height)
{
- GValue val;
- gtk_file_chooser_set_uri(
- GTK_FILE_CHOOSER(dialog), *file);
- if(chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE)
- {
- /* Work around a bug in HildonFileChooserDialog. */
- memset(&val, 0, sizeof(val));
- g_value_init(&val, G_TYPE_BOOLEAN);
- g_value_set_boolean(&val, FALSE);
- g_object_set_property(G_OBJECT(dialog), "autonaming", &val);
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
- strrchr(*file, '/') + 1);
- }
+ xoffset = (widget->allocation.width - widget->allocation.height) / 2;
+ yoffset = 0;
}
-
- gtk_widget_show_all(GTK_WIDGET(dialog));
-
- while(!success && gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_OK)
+ else
{
- gchar *file_uri_str;
- GnomeVFSResult vfs_result;
-
- /* Get the selected filename. */
- file_uri_str = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
+ xoffset = 0;
+ yoffset = (widget->allocation.height - widget->allocation.width) / 2;
+ }
+ context = gtk_widget_get_pango_context(widget);
+ layout = pango_layout_new(context);
+ fontdesc = pango_font_description_new();
+ pango_font_description_set_family(fontdesc,"Sans Serif");
+ pango_font_description_set_size(fontdesc,12*PANGO_SCALE);
+ pango_layout_set_font_description (layout, fontdesc);
+ pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+
+ text = g_strdup_printf("%3d°", (guint)_gps.heading);
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_size(layout, &x, &y);
+
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ xoffset + size/2 - x/2,
+ yoffset + size - y - 2, layout);
+ g_free(text);
+
+ gdk_draw_arc (widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ FALSE,
+ xoffset, yoffset + size/2,
+ size, size,
+ 0, 64 * 180);
+
+ /* Simple arrow for heading*/
+ gdk_draw_line(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ xoffset + size/2 + 3,
+ yoffset + size - y - 5,
+ xoffset + size/2,
+ yoffset + size/2 + 5);
+
+ gdk_draw_line(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ xoffset + size/2 - 3,
+ yoffset + size - y - 5,
+ xoffset + size/2,
+ yoffset + size/2 + 5);
+
+ gdk_draw_line(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ xoffset + size/2 - 3,
+ yoffset + size - y - 5,
+ xoffset + size/2,
+ yoffset + size - y - 8);
+
+ gdk_draw_line(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ xoffset + size/2 + 3,
+ yoffset + size - y - 5,
+ xoffset + size/2,
+ yoffset + size - y - 8);
+
+ gint angle[5] = {-90,-45,0,45,90};
+ gint fsize[5] = {0,4,10,4,0};
+ for(i = 0; i < 5; i++)
+ {
+ dir = (gint)(_gps.heading/45)*45 + angle[i];
- if((chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
- && (GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
- file_uri_str, size_out, bytes_out))))
- || (chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE
- && GNOME_VFS_OK != (vfs_result = gnome_vfs_create(
- handle_out, file_uri_str,
- GNOME_VFS_OPEN_WRITE, FALSE, 0664))))
+ switch(dir)
{
- gchar buffer[1024];
- sprintf(buffer, "%s %s:\n%s", _("Failed to open file for"),
- chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
- ? _("reading") : _("writing"),
- gnome_vfs_result_to_string(vfs_result));
- popup_error(dialog, buffer);
+ case 0:
+ case 360: text = g_strdup("N"); break;
+ case 45:
+ case 405:
+ text = g_strdup("NE"); break;
+ case 90:
+ text = g_strdup("E"); break;
+ case 135:
+ text = g_strdup("SE"); break;
+ case 180:
+ text = g_strdup("S"); break;
+ case 225:
+ text = g_strdup("SW"); break;
+ case 270:
+ case -90:
+ text = g_strdup("W"); break;
+ case 315:
+ case -45:
+ text = g_strdup("NW"); break;
+ default :
+ text = g_strdup("??");
+ break;
}
- else
- success = TRUE;
- g_free(file_uri_str);
+ tmp = ((dir - _gps.heading) * (1.f / 180.f)) * PI;
+ gdk_draw_line(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ xoffset + size/2 + ((size/2 - 5) * sinf(tmp)),
+ yoffset + size - ((size/2 - 5) * cosf(tmp)),
+ xoffset + size/2 + ((size/2 + 5) * sinf(tmp)),
+ yoffset + size - ((size/2 + 5) * cosf(tmp)));
+
+ x = fsize[i];
+ if(abs((guint)(_gps.heading/45)*45 - _gps.heading)
+ > abs((guint)(_gps.heading/45)*45 + 45 - _gps.heading)
+ && (i > 0))
+ x = fsize[i - 1];
+
+ pango_font_description_set_size(fontdesc,(10 + x)*PANGO_SCALE);
+ pango_layout_set_font_description (layout, fontdesc);
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_size(layout, &x, &y);
+ x = xoffset + size/2 + ((size/2 + 15) * sinf(tmp)) - x/2,
+ y = yoffset + size - ((size/2 + 15) * cosf(tmp)) - y/2,
+
+ gdk_draw_layout(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ x, y, layout);
+ g_free(text);
}
- if(success)
- {
- /* Success!. */
- if(dir)
- {
- if(*dir)
- g_free(*dir);
- *dir = gtk_file_chooser_get_current_folder_uri(
- GTK_FILE_CHOOSER(dialog));
- }
+ pango_font_description_free (fontdesc);
+ g_object_unref (layout);
+
+ return TRUE;
+}
+
+static gboolean
+map_cb_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+ printf("%s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ gdk_draw_drawable(
+ _map_widget->window,
+ _gc_mark,
+ _map_pixmap,
+ event->area.x + _offsetx, event->area.y + _offsety,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ map_draw_mark();
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* If desired, save the file for later. */
- if(file)
- {
- if(*file)
- g_free(*file);
- *file = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
- }
- }
+static gboolean
+map_cb_button_press(GtkWidget *widget, GdkEventButton *event)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- gtk_widget_destroy(dialog);
+ _cmenu_position_x = event->x + 0.5;
+ _cmenu_position_y = event->y + 0.5;
- vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
- return success;
+ /* Return FALSE to allow context menu to work. */
+ vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return FALSE;
}
-/**
- * Refresh the view based on the fact that the route has been automatically
- * updated.
- */
static gboolean
-auto_route_dl_idle_refresh()
+map_cb_button_release(GtkWidget *widget, GdkEventButton *event)
{
- /* Make sure we're still supposed to do work. */
- vprintf("%s()\n", __PRETTY_FUNCTION__);
+ printf("%s()\n", __PRETTY_FUNCTION__);
- if(!_autoroute_data.enabled)
- _autoroute_data.handle = NULL;
+#ifdef DEBUG
+ if(event->button != 1)
+ {
+ _pos.unitx = x2unit((gint)(event->x + 0.5));
+ _pos.unity = y2unit((gint)(event->y + 0.5));
+ unit2latlon(_pos.unitx, _pos.unity, _pos_lat, _pos_lon);
+ _speed = 20.f;
+ integerize_data();
+ track_add(time(NULL), FALSE);
+ refresh_mark();
+ }
else
+#endif
{
- if(parse_route_gpx(_autoroute_data.bytes, _autoroute_data.bytes_read,0))
- {
- /* Find the nearest route point, if we're connected. */
- route_find_nearest_point();
-
- map_force_redraw();
- }
+ if(_center_mode > 0)
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+ _menu_ac_none_item), TRUE);
+ map_center_unit(
+ x2unit((gint)(event->x + 0.5)),
+ y2unit((gint)(event->y + 0.5)));
}
- _autoroute_data.in_progress = FALSE;
+ /* Return FALSE to avoid context menu (if it hasn't popped up already). */
+ vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return FALSE;
+}
+
+static gboolean
+channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data)
+{
+ printf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
+
+ /* An error has occurred - re-connect(). */
+ rcvr_disconnect();
+ track_add(0, FALSE);
+
+ if(_conn_state > RCVR_OFF)
+ {
+ set_conn_state(RCVR_DOWN);
+ gps_hide_text();
+ rcvr_connect_now();
+ }
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
return FALSE;
}
-/**
- * Read the data provided by the given handle as GPX data, updating the
- * auto-route with that data.
- */
-static void
-auto_route_dl_cb_read(GnomeVFSAsyncHandle *handle,
- GnomeVFSResult result,
- gpointer bytes,
- GnomeVFSFileSize bytes_requested,
- GnomeVFSFileSize bytes_read)
+static gboolean
+channel_cb_connect(GIOChannel *src, GIOCondition condition, gpointer data)
{
- vprintf("%s(%s)\n", __PRETTY_FUNCTION__,gnome_vfs_result_to_string(result));
+ int error, size = sizeof(error);
+ printf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
- _autoroute_data.bytes_read += bytes_read;
- if(result == GNOME_VFS_OK)
+ if(*_rcvr_mac != '/'
+ && (getsockopt(_fd, SOL_SOCKET, SO_ERROR, &error, &size) || error))
{
- /* Expand bytes and continue reading. */
- if(_autoroute_data.bytes_read * 2 > _autoroute_data.bytes_maxsize)
- {
- _autoroute_data.bytes = g_renew(gchar, _autoroute_data.bytes,
- 2 * _autoroute_data.bytes_read);
- _autoroute_data.bytes_maxsize = 2 * _autoroute_data.bytes_read;
- }
- gnome_vfs_async_read(_autoroute_data.handle,
- _autoroute_data.bytes + _autoroute_data.bytes_read,
- _autoroute_data.bytes_maxsize - _autoroute_data.bytes_read,
- (GnomeVFSAsyncReadCallback)auto_route_dl_cb_read, NULL);
+ printf("%s(): Error connecting to receiver; retrying...\n",
+ __PRETTY_FUNCTION__);
+ /* Try again. */
+ rcvr_disconnect();
+ rcvr_connect_later();
}
else
- g_idle_add((GSourceFunc)auto_route_dl_idle_refresh, NULL);
+ {
+ printf("%s(): Connected to receiver!\n",
+ __PRETTY_FUNCTION__);
+ set_conn_state(RCVR_UP);
+ _input_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
+ G_IO_IN | G_IO_PRI, channel_cb_input, NULL, NULL);
+ }
+ _connect_sid = 0;
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return FALSE;
}
-/**
- * Open the given handle in preparation for reading GPX data.
- */
+#define MACRO_PARSE_INT(tofill, str) { \
+ gchar *error_check; \
+ (tofill) = strtol((str), &error_check, 10); \
+ if(error_check == (str)) \
+ { \
+ fprintf(stderr, "Line %d: Failed to parse string as int: %s\n", \
+ __LINE__, str); \
+ hildon_banner_show_information(_window, NULL, \
+ _("Invalid NMEA input from receiver!")); \
+ return; \
+ } \
+}
+#define MACRO_PARSE_FLOAT(tofill, str) { \
+ gchar *error_check; \
+ (tofill) = g_ascii_strtod((str), &error_check); \
+ if(error_check == (str)) \
+ { \
+ fprintf(stderr, "Failed to parse string as float: %s\n", str); \
+ hildon_banner_show_information(_window, NULL, \
+ _("Invalid NMEA input from receiver!")); \
+ return; \
+ } \
+}
static void
-auto_route_dl_cb_open(GnomeVFSAsyncHandle *handle, GnomeVFSResult result)
+channel_parse_rmc(gchar *sentence)
{
- vprintf("%s()\n", __PRETTY_FUNCTION__);
+ /* Recommended Minimum Navigation Information C
+ * 1) UTC Time
+ * 2) Status, V=Navigation receiver warning A=Valid
+ * 3) Latitude
+ * 4) N or S
+ * 5) Longitude
+ * 6) E or W
+ * 7) Speed over ground, knots
+ * 8) Track made good, degrees true
+ * 9) Date, ddmmyy
+ * 10) Magnetic Variation, degrees
+ * 11) E or W
+ * 12) FAA mode indicator (NMEA 2.3 and later)
+ * 13) Checksum
+ */
+ gchar *token, *dpoint, *gpstime, *gpsdate;
+ gdouble tmpd = 0.f;
+ guint tmpi = 0;
+ gboolean newly_fixed = FALSE;
+ vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
- if(result == GNOME_VFS_OK)
- gnome_vfs_async_read(_autoroute_data.handle,
- _autoroute_data.bytes,
- _autoroute_data.bytes_maxsize,
- (GnomeVFSAsyncReadCallback)auto_route_dl_cb_read, NULL);
+#define DELIM ","
+
+ /* Parse time. */
+ token = strsep(&sentence, DELIM);
+ gpstime = g_strdup(token);
+
+ token = strsep(&sentence, DELIM);
+ /* Token is now Status. */
+ if(*token != 'A')
+ {
+ /* Data is invalid - not enough satellites?. */
+ if(_conn_state != RCVR_UP)
+ {
+ set_conn_state(RCVR_UP);
+ track_add(0, FALSE);
+ }
+ }
else
{
- _autoroute_data.in_progress = FALSE;
- _autoroute_data.handle = NULL;
+ /* Data is valid. */
+ if(_conn_state != RCVR_FIXED)
+ {
+ newly_fixed = TRUE;
+ set_conn_state(RCVR_FIXED);
+ }
}
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+ /* Parse the latitude. */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ {
+ dpoint = strchr(token, '.');
+ MACRO_PARSE_FLOAT(tmpd, dpoint - 2);
+ dpoint[-2] = '\0';
+ MACRO_PARSE_INT(tmpi, token);
+ _pos_lat = tmpi + (tmpd * (1.0 / 60.0));
+ _gps.latitude = _pos_lat;
+ }
-/**
- * This function is periodically run to download updated auto-route data
- * from the route source.
- */
-static gboolean
-auto_route_dl_idle()
-{
- gchar buffer[1024];
- vprintf("%s(%f, %f, %s)\n", __PRETTY_FUNCTION__,
- _pos_lat, _pos_lon, _autoroute_data.dest);
+ /* Parse N or S. */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ sprintf(_gps.slatitude, "%c %u°%07.04f", token[0], tmpi, tmpd);
- sprintf(buffer,"http://www.gnuite.com/cgi-bin/gpx.cgi?saddr=%f,%f&daddr=%s",
- _pos_lat, _pos_lon, _autoroute_data.dest);
- _autoroute_data.bytes_read = 0;
+ if(*token && token[0] == 'S')
+ _pos_lat = -_pos_lat;
- gnome_vfs_async_open(&_autoroute_data.handle,
- buffer, GNOME_VFS_OPEN_READ,
- GNOME_VFS_PRIORITY_DEFAULT,
- (GnomeVFSAsyncOpenCallback)auto_route_dl_cb_open, NULL);
+ /* Parse the longitude. */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ {
+ dpoint = strchr(token, '.');
+ MACRO_PARSE_FLOAT(tmpd, dpoint - 2);
+ dpoint[-2] = '\0';
+ MACRO_PARSE_INT(tmpi, token);
+ _pos_lon = tmpi + (tmpd * (1.0 / 60.0));
+ _gps.longitude = _pos_lon;
+ }
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return FALSE;
-}
+ /* Parse E or W. */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ sprintf(_gps.slongitude, "%c %u°%07.04f", token[0], tmpi, tmpd);
-/**
- * Cancel the current auto-route.
- */
-static void
-cancel_autoroute()
-{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ if(*token && token[0] == 'W')
+ _pos_lon = -_pos_lon;
+
+ /* Parse speed over ground, knots. */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ {
+ MACRO_PARSE_FLOAT(_speed, token);
+ _gps.speed = _speed;
+ if(_gps.fix > 1)
+ _gps.maxspeed = MAX(_gps.maxspeed, _speed);
+ }
- if(_autoroute_data.enabled)
+ /* Parse heading, degrees from true north. */
+ token = strsep(&sentence, DELIM);
+ if(*token)
{
- _autoroute_data.enabled = FALSE;
- if(_autoroute_data.dest)
- {
- g_free(_autoroute_data.dest);
- _autoroute_data.dest = NULL;
- }
- if(_autoroute_data.handle)
- {
- gnome_vfs_async_cancel(_autoroute_data.handle);
- _autoroute_data.handle = NULL;
- }
- if(_autoroute_data.bytes)
- {
- g_free(_autoroute_data.bytes);
- _autoroute_data.bytes = NULL;
- }
- _autoroute_data.in_progress = FALSE;
+ MACRO_PARSE_FLOAT(_heading, token);
+ _gps.heading = _heading;
}
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+ /* Parse date. */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ {
+ time_t timeloc;
+ gpsdate = g_strdup_printf("%s%s", token, gpstime);
+ strptime(gpsdate, "%d%m%y%H%M%S", &_gps.time);
+ if(_gps.time.tm_year >= 0 && _gps.time.tm_year <= 68)
+ _gps.time.tm_year += 100; /* year 2000 */
+ _gps.time.tm_mon -= 1;
+ timeloc = mktime(&_gps.time);
+ timeloc += _gmtoffset;
+ localtime_r(&timeloc, &_gps.timeloc);
+ g_free(gpstime);
+ g_free(gpsdate);
+ }
-/**
- * Save state and destroy all non-UI elements created by this program in
- * preparation for exiting.
- */
-static void
-maemo_mapper_destroy(void)
-{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ /* Translate data into integers. */
+ integerize_data();
- config_save();
- rcvr_disconnect();
- /* _program and widgets have already been destroyed. */
+ /* Add new data to track. */
+ if(_conn_state == RCVR_FIXED)
+ track_add(time(NULL), newly_fixed);
- MACRO_CLEAR_TRACK(_track);
- if(_route.head)
- MACRO_CLEAR_TRACK(_route);
+ /* Move mark to new location. */
+ refresh_mark();
vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-/**
- * Initialize everything required in preparation for calling gtk_main().
- */
-static void
-maemo_mapper_init(gint argc, gchar **argv)
+ static void
+channel_parse_gga(gchar *sentence)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ /* GGA Global Positioning System Fix Data
+ 1. Fix Time
+ 2. Latitude
+ 3. N or S
+ 4. Longitude
+ 5. E or W
+ 6. Fix quality
+ 0 = invalid
+ 1 = GPS fix (SPS)
+ 2 = DGPS fix
+ 3 = PPS fix
+ 4 = Real Time Kinematic
+ 5 = Float RTK
+ 6 = estimated (dead reckoning) (2.3 feature)
+ 7 = Manual input mode
+ 8 = Simulation mode
+ 7. Number of satellites being tracked
+ 8. Horizontal dilution of position
+ 9. Altitude, Meters, above mean sea level
+ 10. Alt unit (meters)
+ 11. Height of geoid (mean sea level) above WGS84 ellipsoid
+ 12. unit
+ 13. (empty field) time in seconds since last DGPS update
+ 14. (empty field) DGPS station ID number
+ 15. the checksum data
+ */
+ gchar *token;
+ vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
- config_init();
+#define DELIM ","
- /* Initialize _program. */
- _program = HILDON_PROGRAM(hildon_program_get_instance());
- g_set_application_name("Maemo Mapper");
+ /* Skip Fix time */
+ token = strsep(&sentence, DELIM);
+ /* Skip latitude */
+ token = strsep(&sentence, DELIM);
+ /* Skip N or S */
+ token = strsep(&sentence, DELIM);
+ /* Skip longitude */
+ token = strsep(&sentence, DELIM);
+ /* Skip S or W */
+ token = strsep(&sentence, DELIM);
- /* Initialize _window. */
- _window = GTK_WIDGET(hildon_window_new());
- hildon_program_add_window(_program, HILDON_WINDOW(_window));
+ /* Parse Fix quality */
+ token = strsep(&sentence, DELIM);
- /* Create and add widgets and supporting data. */
- _map_widget = gtk_drawing_area_new();
- gtk_container_add(GTK_CONTAINER(_window), _map_widget);
+ /* Parse number of satellites */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ MACRO_PARSE_INT(_gps.satinuse, token);
- gtk_widget_realize(_map_widget);
+ /* Parse Horizontal dilution of position */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ MACRO_PARSE_INT(_gps.hdop, token);
- _map_pixmap = gdk_pixmap_new(
- _map_widget->window,
- BUF_WIDTH_PIXELS, BUF_HEIGHT_PIXELS,
- -1); /* -1: use bit depth of widget->window. */
+ /* Altitude */
+ token = strsep(&sentence, DELIM);
+ if(!sentence)
+ return; /* because this is an invalid sentence. */
+ if(*token)
+ MACRO_PARSE_INT(_gps.altitude, token);
- /* Connect signals. */
- g_signal_connect(G_OBJECT(_window), "destroy",
- G_CALLBACK(gtk_main_quit), NULL);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- g_signal_connect(G_OBJECT(_window), "key_press_event",
- G_CALLBACK(window_cb_key_press), NULL);
+static void
+channel_parse_gsa(gchar *sentence)
+{
+ /* GPS DOP and active satellites
+ * 1) Auto selection of 2D or 3D fix (M = manual)
+ * 2) 3D fix - values include: 1 = no fix, 2 = 2D, 3 = 2D
+ * 3) PRNs of satellites used for fix
+ * (space for 12)
+ * 4) PDOP (dilution of precision)
+ * 5) Horizontal dilution of precision (HDOP)
+ * 6) Vertical dilution of precision (VDOP)
+ * 7) Checksum
+ */
+ gchar *token;
+ guint i, sat;
+ vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
- g_signal_connect(G_OBJECT(_window), "key_release_event",
- G_CALLBACK(window_cb_key_release), NULL);
+#define DELIM ","
- g_signal_connect(G_OBJECT(_map_widget), "configure_event",
- G_CALLBACK(map_cb_configure), NULL);
+ /* Skip Auto selection. */
+ token = strsep(&sentence, DELIM);
- g_signal_connect(G_OBJECT(_map_widget), "expose_event",
- G_CALLBACK(map_cb_expose), NULL);
+ /* 3D fix. */
+ token = strsep(&sentence, DELIM);
+ if(!sentence)
+ return; /* because this is an invalid sentence. */
+ MACRO_PARSE_INT(_gps.fix, token);
- g_signal_connect(G_OBJECT(_map_widget), "button_press_event",
- G_CALLBACK(map_cb_button_press), NULL);
+ _gps.satinuse = 0;
+ for(i = 0; i < 12; i++)
+ {
+ token = strsep(&sentence, DELIM);
+ if((sat = atoi(token)))
+ _gps.satforfix[_gps.satinuse++] = sat;
+ }
- g_signal_connect(G_OBJECT(_map_widget), "button_release_event",
- G_CALLBACK(map_cb_button_release), NULL);
+ /* PDOP */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ MACRO_PARSE_FLOAT(_gps.pdop, token);
- gtk_widget_add_events(_map_widget,
- GDK_EXPOSURE_MASK
- | GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK);
+ /* HDOP */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ MACRO_PARSE_FLOAT(_gps.hdop, token);
- osso_hw_set_event_cb(_osso, NULL, osso_cb_hw_state, NULL);
+ /* VDOP */
+ token = strsep(&sentence, DELIM);
+ if(*token)
+ MACRO_PARSE_FLOAT(_gps.vdop, token);
- gnome_vfs_async_set_job_limit(24);
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
- /* Initialize data. */
+static void
+channel_parse_gsv(gchar *sentence)
+{
+ /* Must be GSV - Satellites in view
+ * 1) total number of messages
+ * 2) message number
+ * 3) satellites in view
+ * 4) satellite number
+ * 5) elevation in degrees (0-90)
+ * 6) azimuth in degrees to true north (0-359)
+ * 7) SNR in dB (0-99)
+ * more satellite infos like 4)-7)
+ * n) checksum
+ */
+ gchar *token;
+ guint msgcnt, nummsgs;
+ static guint running_total = 0;
+ static guint num_sats_used = 0;
+ static guint satcnt = 0;
+ vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
- /* set XML_TZONE */
- {
- time_t time1;
- struct tm time2;
- time1 = time(NULL);
- localtime_r(&time1, &time2);
- sprintf(XML_TZONE, "%+03ld:%02ld",
- (time2.tm_gmtoff / 60 / 60), (time2.tm_gmtoff / 60) % 60);
- }
+ /* Parse number of messages. */
+ token = strsep(&sentence, DELIM);
+ if(!sentence)
+ return; /* because this is an invalid sentence. */
+ MACRO_PARSE_INT(nummsgs, token);
- memset(&_track, 0, sizeof(_track));
- memset(&_route, 0, sizeof(_route));
- _last_spoken_phrase = g_strdup("");
+ /* Parse message number. */
+ token = strsep(&sentence, DELIM);
+ if(!sentence)
+ return; /* because this is an invalid sentence. */
+ MACRO_PARSE_INT(msgcnt, token);
- /* Set up track array. */
- MACRO_INIT_TRACK(_track);
+ /* Parse number of satellites in view. */
+ token = strsep(&sentence, DELIM);
+ if(!sentence)
+ return; /* because this is an invalid sentence. */
+ MACRO_PARSE_INT(_gps.satinview, token);
- _downloads_hash = g_hash_table_new((GHashFunc)download_hashfunc,
- (GEqualFunc)download_equalfunc);
- memset(&_autoroute_data, 0, sizeof(_autoroute_data));
+ /* Loop until there are no more satellites to parse. */
+ while(sentence)
+ {
+ /* Get token for Satellite Number. */
+ token = strsep(&sentence, DELIM);
+ if(!sentence)
+ break; /* because this is an invalid sentence. */
+ _gps_sat[satcnt].prn = atoi(token);
- integerize_data();
+ /* Get token for elevation in degrees (0-90). */
+ token = strsep(&sentence, DELIM);
+ if(!sentence)
+ break; /* because this is an invalid sentence. */
+ _gps_sat[satcnt].elevation = atoi(token);
- /* Initialize our line styles. */
- update_gcs();
+ /* Get token for azimuth in degrees to true north (0-359). */
+ token = strsep(&sentence, DELIM);
+ if(!sentence)
+ break; /* because this is an invalid sentence. */
+ _gps_sat[satcnt].azimuth = atoi(token);
- menu_init();
+ /* Get token for SNR. */
+ token = strsep(&sentence, DELIM);
+ _gps_sat[satcnt].snr = atoi(token);
+ if(_gps_sat[satcnt].snr)
+ {
+ /* Snr is non-zero - add to total and count as used. */
+ running_total += _gps_sat[satcnt].snr;
+ num_sats_used++;
+ }
+ satcnt++;
+ }
- /* If present, attempt to load the file specified on the command line. */
- if(argc > 1)
+ if(msgcnt == nummsgs)
{
- GnomeVFSResult vfs_result;
- gint size;
- gchar *buffer;
- gchar *file_uri;
-
- /* Get the selected filename. */
- file_uri = gnome_vfs_make_uri_from_shell_arg(argv[1]);
-
- if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
- file_uri, &size, &buffer)))
+ /* This is the last message. Calculate signal strength. */
+ if(num_sats_used)
{
- gchar buffer[1024];
- sprintf(buffer, "%s %s:\n%s", _("Failed to open file for"),
- _("reading"), gnome_vfs_result_to_string(vfs_result));
- popup_error(_window, buffer);
+ if(_conn_state == RCVR_UP)
+ {
+ gdouble fraction = running_total * sqrt(num_sats_used)
+ / num_sats_used / 100.0;
+ BOUND(fraction, 0.0, 1.0);
+ hildon_banner_set_fraction(
+ HILDON_BANNER(_fix_banner), fraction);
+ }
+ running_total = 0;
+ num_sats_used = 0;
}
- else
+ satcnt = 0;
+
+ /* Keep awake while they watch the progress bar. */
+ KEEP_DISPLAY_ON();
+ }
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+static gboolean
+channel_cb_input(GIOChannel *src, GIOCondition condition, gpointer data)
+{
+ gchar *sentence = _gps_read_buf;
+ gsize bytes_read;
+ vprintf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
+
+ if(G_IO_STATUS_NORMAL == g_io_channel_read_chars(
+ _channel,
+ _gps_read_buf + _gps_read_buf_pos,
+ sizeof(_gps_read_buf) - _gps_read_buf_pos -1,
+ &bytes_read,
+ NULL))
+ {
+ gchar *eol;
+ _gps_read_buf_pos += bytes_read;
+ _gps_read_buf[_gps_read_buf_pos] = '\0';
+ eol = strchr(_gps_read_buf, '\n');
+ while(eol)
{
- /* If auto is enabled, append the route, otherwise replace it. */
- if(parse_route_gpx(buffer, size, 0))
- hildon_banner_show_information(
- _window, NULL, _("Route Opened"));
+ gchar *sptr = sentence + 1;
+ guint csum = 0;
+ gint leftover = _gps_read_buf + _gps_read_buf_pos - eol - 1;
+ *eol = '\0';
+ while(*sptr && *sptr != '*')
+ csum ^= *sptr++;
+ if(!*sptr || csum == strtol(sptr + 1, NULL, 16))
+ {
+ if(*sptr)
+ *sptr = '\0'; /* take checksum out of the sentence. */
+ if(!strncmp(sentence + 3, "GSV", 3))
+ channel_parse_gsv(sentence + 7);
+ else if(!strncmp(sentence + 3, "RMC", 3))
+ channel_parse_rmc(sentence + 7);
+ else if(!strncmp(sentence + 3, "GGA", 3))
+ channel_parse_gga(sentence + 7);
+ else if(!strncmp(sentence + 3, "GSA", 3))
+ channel_parse_gsa(sentence + 7);
+
+ if(_gps_info)
+ gps_display_data();
+ if(_satdetails_on)
+ gps_display_details();
+ }
+ else
+ {
+ fprintf(stderr, "%s: Bad checksum in NMEA sentence:\n%s\n",
+ __PRETTY_FUNCTION__, sentence);
+ }
+ if(leftover <= 0)
+ {
+ /* last read was a newline */
+ _gps_read_buf_pos = 0;
+ eol = 0;
+ }
else
- popup_error(_window, _("Error parsing GPX file."));
- g_free(buffer);
+ {
+ memmove(_gps_read_buf, eol+1, leftover+1); /* incl term. 0 */
+ _gps_read_buf_pos = leftover;
+ eol = strchr(_gps_read_buf, '\n');
+ }
}
- g_free(file_uri);
}
- gtk_idle_add((GSourceFunc)window_present, NULL);
-
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
-/****************************************************************************
- * ABOVE: ROUTINES **********************************************************
- ****************************************************************************/
+static gboolean
+gps_toggled_from(GtkToggleButton *chk_gps,
+ GtkWidget *txt_from)
+{
+ gchar buffer[80];
+ gchar strlat[32];
+ gchar strlon[32];
+ printf("%s()\n", __PRETTY_FUNCTION__);
+ g_ascii_formatd(strlat, 80, "%.06f", _pos_lat);
+ g_ascii_formatd(strlon, 80, "%.06f", _pos_lon);
+ sprintf(buffer, "%s, %s", strlat, strlon);
+ gtk_widget_set_sensitive(txt_from, !gtk_toggle_button_get_active(chk_gps));
+ gtk_entry_set_text(GTK_ENTRY(txt_from), buffer);
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
-/****************************************************************************
- * BELOW: MAIN **************************************************************
- ****************************************************************************/
+static gboolean
+gps_toggled_auto(GtkToggleButton *chk_gps,
+ GtkWidget *chk_auto)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
-gint
-main(gint argc, gchar *argv[])
+ gtk_widget_set_sensitive(chk_auto, gtk_toggle_button_get_active(chk_gps));
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
+
+/**
+ * Display a dialog box to the user asking them to download a route. The
+ * "From" and "To" textfields may be initialized using the first two
+ * parameters. The third parameter, if set to TRUE, will cause the "Use GPS
+ * Location" checkbox to be enabled, which automatically sets the "From" to the
+ * current GPS position (this overrides any value that may have been passed as
+ * the "To" initializer).
+ * None of the passed strings are freed - that is left to the caller, and it is
+ * safe to free either string as soon as this function returns.
+ */
+static gboolean
+route_download(gchar *from, gchar *to, gboolean from_here)
{
+ GtkWidget *dialog;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *chk_gps;
+ GtkWidget *chk_auto;
+ GtkWidget *txt_from;
+ GtkWidget *txt_to;
+ GtkWidget *hbox;
+ GtkEntryCompletion *from_comp;
+ GtkEntryCompletion *to_comp;
+ gchar *bytes = NULL;
+ gint size;
printf("%s()\n", __PRETTY_FUNCTION__);
- g_thread_init(NULL);
+ dialog = gtk_dialog_new_with_buttons(_("Download Route"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL);
- /* Initialize _osso. */
- _osso = osso_initialize("com.gnuite.maemo_mapper", VERSION, TRUE, NULL);
- if(!_osso)
- {
- fprintf(stderr, "osso_initialize failed.\n");
- return 1;
- }
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ table = gtk_table_new(2, 4, FALSE), TRUE, TRUE, 0);
- gtk_init(&argc, &argv);
+ from_comp = gtk_entry_completion_new();
+ gtk_entry_completion_set_model(from_comp, GTK_TREE_MODEL(_loc_model));
+ gtk_entry_completion_set_text_column(from_comp, 0);
+ to_comp = gtk_entry_completion_new();
+ gtk_entry_completion_set_model(to_comp, GTK_TREE_MODEL(_loc_model));
+ gtk_entry_completion_set_text_column(to_comp, 0);
- /* Init gconf. */
- g_type_init();
- gconf_init(argc, argv, NULL);
+ /* Auto. */
+ gtk_table_attach(GTK_TABLE(table),
+ hbox = gtk_hbox_new(FALSE, 6),
+ 0, 2, 0, 1, 0, 0, 2, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ chk_gps = gtk_check_button_new_with_label(
+ _("Use GPS Location")),
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ chk_auto = gtk_check_button_new_with_label(
+ _("Auto-Update")),
+ TRUE, TRUE, 0);
+ gtk_widget_set_sensitive(chk_auto, FALSE);
- gnome_vfs_init();
+ /* Origin. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Origin")),
+ 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ txt_from = gtk_entry_new(),
+ 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_entry_set_completion(GTK_ENTRY(txt_from), from_comp);
+ gtk_entry_set_width_chars(GTK_ENTRY(txt_from), 25);
- maemo_mapper_init(argc, argv);
+ /* Destination. */
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Destination")),
+ 0, 1, 2, 3, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ txt_to = gtk_entry_new(),
+ 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_entry_set_completion(GTK_ENTRY(txt_to), to_comp);
+ gtk_entry_set_width_chars(GTK_ENTRY(txt_to), 25);
- if(OSSO_OK != osso_rpc_set_default_cb_f(_osso, dbus_cb_default, NULL))
+ g_signal_connect(G_OBJECT(chk_gps), _("toggled"),
+ G_CALLBACK(gps_toggled_from), txt_from);
+ g_signal_connect(G_OBJECT(chk_gps), _("toggled"),
+ G_CALLBACK(gps_toggled_auto), chk_auto);
+
+ /* Initialize fields. */
+ gtk_entry_set_text(GTK_ENTRY(txt_from), (from ? from : ""));
+ gtk_entry_set_text(GTK_ENTRY(txt_to), (to ? to : ""));
+
+ if(from_here)
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_gps), TRUE);
+
+ gtk_widget_show_all(dialog);
+
+ while(!bytes
+ && GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
{
- fprintf(stderr, "osso_rpc_set_default_cb_f failed.\n");
- return 1;
- }
+ GnomeVFSResult vfs_result;
+ gchar buffer[1024];
+ const gchar *from, *to;
+ gchar *from_escaped, *to_escaped;
- gtk_main();
+ from = gtk_entry_get_text(GTK_ENTRY(txt_from));
+ if(!strlen(from))
+ {
+ popup_error(dialog, _("Please specify a start location."));
+ continue;
+ }
- maemo_mapper_destroy();
+ to = gtk_entry_get_text(GTK_ENTRY(txt_to));
+ if(!strlen(to))
+ {
+ popup_error(dialog, _("Please specify an end location."));
+ continue;
+ }
- osso_deinitialize(_osso);
+ from_escaped = gnome_vfs_escape_string(from);
+ to_escaped = gnome_vfs_escape_string(to);
+ sprintf(buffer, "http://www.gnuite.com/cgi-bin/gpx.cgi?"
+ "saddr=%s&daddr=%s",
+ from_escaped, to_escaped);
+ g_free(from_escaped);
+ g_free(to_escaped);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return 0;
-}
+ if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
+ buffer, &size, &bytes)))
+ {
+ gchar buffer[1024];
+ sprintf(buffer, "%s:\n%s",
+ _("Failed to connect to GPX Directions server"),
+ gnome_vfs_result_to_string(vfs_result));
+ popup_error(dialog, buffer);
+ }
+ else if(strncmp(bytes, "<?xml", strlen("<?xml")))
+ {
+ /* Not an XML document - must be bad locations. */
+ popup_error(dialog,
+ _("Could not generate directions. Make sure your "
+ "source and destination are valid."));
+ g_free(bytes);
+ bytes = NULL;
+ }
+ else
+ {
+ /* If GPS is enabled, append the route, otherwise replace it. */
+ if(parse_route_gpx(bytes, size,
+ (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_gps))
+ ? 0 : 1)))
+ {
+ GtkTreeIter iter;
-/****************************************************************************
- * ABOVE: MAIN **************************************************************
- ****************************************************************************/
+ /* Find the nearest route point, if we're connected. */
+ route_find_nearest_point();
+ /* Cancel any autoroute that might be occurring. */
+ cancel_autoroute();
+ map_force_redraw();
-/****************************************************************************
- * BELOW: CALLBACKS *********************************************************
- ****************************************************************************/
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_auto)))
+ {
+ /* Kick off a timeout to start the first update. */
+ _autoroute_data.dest = gnome_vfs_escape_string(to);
+ _autoroute_data.enabled = TRUE;
+ _autoroute_data.bytes_maxsize = 2 * size;
+ _autoroute_data.bytes = g_new(gchar, 2 * size);
+ }
-static gint
-dbus_cb_default(const gchar *interface, const gchar *method,
- GArray *arguments, gpointer data, osso_rpc_t *retval)
-{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ /* Save Origin in Route Locations list if not from GPS. */
+ if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_gps))
+ && !g_slist_find_custom(_loc_list, from,
+ (GCompareFunc)strcmp))
+ {
+ _loc_list = g_slist_prepend(_loc_list, g_strdup(from));
+ gtk_list_store_insert_with_values(_loc_model, &iter,
+ INT_MAX, 0, from, -1);
+ }
+
+ /* Save Destination in Route Locations list. */
+ if(!g_slist_find_custom(_loc_list, to,
+ (GCompareFunc)strcmp))
+ {
+ _loc_list = g_slist_prepend(_loc_list, g_strdup(to));
+ gtk_list_store_insert_with_values(_loc_model, &iter,
+ INT_MAX, 0, to, -1);
+ }
+
+ hildon_banner_show_information(_window, NULL,
+ _("Route Downloaded"));
+ g_free(bytes);
+ }
+ else
+ {
+ popup_error(dialog, _("Error parsing GPX file."));
+ g_free(bytes);
+ bytes = NULL; /* Let them try again. */
+ }
+ }
+ }
- if(!strcmp(method, "top_application"))
- gtk_idle_add((GSourceFunc)window_present, NULL);
+ gtk_widget_destroy(dialog);
- retval->type = DBUS_TYPE_INVALID;
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return OSSO_OK;
+static gboolean
+menu_cb_route_download(GtkAction *action)
+{
+ route_download(NULL, NULL, FALSE);
+ return TRUE;
}
-static void
-osso_cb_hw_state(osso_hw_state_t *state, gpointer data)
+static gboolean
+menu_cb_route_open(GtkAction *action)
{
- static gboolean _must_save_data = FALSE;
+ gchar *buffer;
+ gint size;
printf("%s()\n", __PRETTY_FUNCTION__);
- if(state->system_inactivity_ind)
+ if(open_file(&buffer, NULL, &size, &_route_dir_uri, NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN))
{
- if(_must_save_data)
- _must_save_data = FALSE;
- else if(_conn_state > RCVR_OFF)
+ /* If auto is enabled, append the route, otherwise replace it. */
+ if(parse_route_gpx(buffer, size, _autoroute_data.enabled ? 0 : 1))
{
- set_conn_state(RCVR_OFF);
- rcvr_disconnect();
- track_add(0, FALSE);
- /* Pretend the autoroute is in progress to avoid download. */
- if(_autoroute_data.enabled)
- _autoroute_data.in_progress = TRUE;
- }
- }
- else if(state->save_unsaved_data_ind)
- {
- config_save();
- _must_save_data = TRUE;
- }
- else if(_conn_state == RCVR_OFF && _enable_gps)
- {
- set_conn_state(RCVR_DOWN);
- rcvr_connect_later();
- if(_autoroute_data.enabled)
- _autoroute_data.in_progress = TRUE;
- }
+ cancel_autoroute();
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+ /* Find the nearest route point, if we're connected. */
+ route_find_nearest_point();
-static gboolean
-key_zoom_timeout()
-{
- if(_key_zoom_new < _zoom)
- {
- /* We're currently zooming in (_zoom is decreasing). */
- if(_key_zoom_new)
- /* We can zoom some more. Hurray! */
- _key_zoom_new--;
- else
- /* We can't zoom anymore. Booooo! */
- return FALSE;
- }
- else
- {
- /* We're currently zooming out (_zoom is increasing). */
- if(_key_zoom_new < (MAX_ZOOM - 1))
- /* We can zoom some more. Hurray! */
- _key_zoom_new++;
+ map_force_redraw();
+ hildon_banner_show_information(_window, NULL,
+ _("Route Opened"));
+ }
else
- /* We can't zoom anymore. Booooo! */
- return FALSE;
+ popup_error(_window, _("Error parsing GPX file."));
+ g_free(buffer);
}
- /* We can zoom more - tell them how much they're zooming. */
- {
- gchar buffer[32];
- sprintf(buffer, "%s %d", _("Zoom to Level"), _key_zoom_new);
- hildon_banner_show_information(_window, NULL, buffer);
- }
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-window_cb_key_press(GtkWidget* widget, GdkEventKey *event)
+menu_cb_route_reset(GtkAction *action)
{
printf("%s()\n", __PRETTY_FUNCTION__);
- switch (event->keyval)
- {
- case HILDON_HARDKEY_UP:
- map_pan(0, -PAN_UNITS);
- return TRUE;
-
- case HILDON_HARDKEY_DOWN:
- map_pan(0, PAN_UNITS);
- return TRUE;
-
- case HILDON_HARDKEY_LEFT:
- map_pan(-PAN_UNITS, 0);
- return TRUE;
+ route_find_nearest_point();
+ map_render_paths();
+ map_render_poi();
+ MACRO_QUEUE_DRAW_AREA();
- case HILDON_HARDKEY_RIGHT:
- map_pan(PAN_UNITS, 0);
- return TRUE;
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- case HILDON_HARDKEY_SELECT:
- switch(_center_mode)
- {
- case CENTER_LATLON:
- case CENTER_WAS_LEAD:
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
- _menu_ac_lead_item), TRUE);
- break;
- case CENTER_LEAD:
- case CENTER_WAS_LATLON:
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
- _menu_ac_latlon_item), TRUE);
- break;
- }
- return TRUE;
+static gboolean
+menu_cb_route_clear(GtkAction *action)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- case HILDON_HARDKEY_FULLSCREEN:
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
- _menu_fullscreen_item), !_fullscreen);
- return TRUE;
+ _next_way_dist_rough = -1; /* to avoid announcement attempts. */
+ cancel_autoroute();
+ MACRO_CLEAR_TRACK(_route);
+ map_force_redraw();
- case HILDON_HARDKEY_INCREASE:
- case HILDON_HARDKEY_DECREASE:
- if(!_key_zoom_timeout_sid)
- {
- _key_zoom_new = _zoom
- + (event->keyval == HILDON_HARDKEY_INCREASE ? -1 : 1);
- /* Remember, _key_zoom_new is unsigned. */
- if(_key_zoom_new < MAX_ZOOM)
- {
- gchar buffer[80];
- sprintf(buffer, "%s %d", _("Zoom to Level"), _key_zoom_new);
- hildon_banner_show_information(_window, NULL, buffer);
- _key_zoom_timeout_sid = g_timeout_add(
- 500, key_zoom_timeout, NULL);
- }
- }
- return TRUE;
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- case HILDON_HARDKEY_ESC:
- {
- switch(_show_tracks)
- {
- case 0:
- /* Nothing shown, nothing saved; just set both. */
- _show_tracks = TRACKS_MASK | ROUTES_MASK;
- break;
- case TRACKS_MASK << 16:
- case ROUTES_MASK << 16:
- case (ROUTES_MASK | TRACKS_MASK) << 16:
- /* Something was saved and nothing changed since.
- * Restore saved. */
- _show_tracks = _show_tracks >> 16;
- break;
- default:
- /* There is no history, or they changed something since
- * the last historical change. Save and clear. */
- _show_tracks = _show_tracks << 16;
- }
+static gboolean
+menu_cb_track_open(GtkAction *action)
+{
+ gchar *buffer;
+ gint size;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
- _menu_show_routes_item),
- _show_tracks & ROUTES_MASK);
+ if(open_file(&buffer, NULL, &size, NULL, &_track_file_uri,
+ GTK_FILE_CHOOSER_ACTION_OPEN))
+ {
+ if(parse_track_gpx(buffer, size, -1))
+ {
+ map_force_redraw();
+ hildon_banner_show_information(_window, NULL, _("Track Opened"));
+ }
+ else
+ popup_error(_window, _("Error parsing GPX file."));
+ g_free(buffer);
+ }
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
- _menu_show_tracks_item),
- _show_tracks & TRACKS_MASK);
- }
- return TRUE;
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- default:
- return FALSE;
- }
+#define WRITE_STRING(string) { \
+ GnomeVFSResult vfs_result; \
+ GnomeVFSFileSize size; \
+ if(GNOME_VFS_OK != (vfs_result = gnome_vfs_write( \
+ handle, (string), strlen((string)), &size))) \
+ { \
+ gchar buffer[1024]; \
+ sprintf(buffer, "%s:\n%s\n%s", _("Error while writing to file"), \
+ _("File is incomplete."), \
+ gnome_vfs_result_to_string(vfs_result)); \
+ popup_error(_window, buffer); \
+ return FALSE; \
+ } \
}
static gboolean
-window_cb_key_release(GtkWidget* widget, GdkEventKey *event)
+write_track_gpx(GnomeVFSHandle *handle)
{
+ TrackPoint *curr;
+ gboolean trkseg_break = FALSE;
printf("%s()\n", __PRETTY_FUNCTION__);
- switch (event->keyval)
+ /* Find first non-zero point. */
+ for(curr = _track.head-1; curr++ != _track.tail; )
+ if(curr->point.unity)
+ break;
+
+ /* Write the header. */
+ WRITE_STRING(XML_TRKSEG_HEADER);
+
+ /* Curr points to first non-zero point. */
+ for(curr--; curr++ != _track.tail; )
{
- case HILDON_HARDKEY_INCREASE:
- case HILDON_HARDKEY_DECREASE:
- if(_key_zoom_timeout_sid)
+ gfloat lat, lon;
+ if(curr->point.unity)
+ {
+ gchar buffer[80];
+ gchar strlat[80], strlon[80];
+ if(trkseg_break)
{
- g_source_remove(_key_zoom_timeout_sid);
- _key_zoom_timeout_sid = 0;
- map_set_zoom(_key_zoom_new);
+ /* First trkpt of the segment - write trkseg header. */
+ WRITE_STRING(" </trkseg>\n"
+ /* Write trkseg header. */
+ " <trkseg>\n");
+ trkseg_break = FALSE;
}
- return TRUE;
-
- default:
- return FALSE;
+ unit2latlon(curr->point.unitx, curr->point.unity, lat, lon);
+ g_ascii_formatd(strlat, 80, "%.06f", lat);
+ g_ascii_formatd(strlon, 80, "%.06f", lon);
+ sprintf(buffer, " <trkpt lat=\"%s\" lon=\"%s\"",
+ strlat, strlon);
+ WRITE_STRING(buffer);
+
+ /* write the time */
+ if(curr->time)
+ {
+ WRITE_STRING(">\n <time>");
+ {
+ struct tm time;
+ localtime_r(&curr->time, &time);
+ strftime(buffer, 80, XML_DATE_FORMAT, &time);
+ WRITE_STRING(buffer);
+ WRITE_STRING(XML_TZONE);
+ }
+ WRITE_STRING("</time>\n"
+ " </trkpt>\n");
+ }
+ else
+ WRITE_STRING("/>\n");
+ }
+ else
+ trkseg_break = TRUE;
}
+
+ /* Write the footer. */
+ WRITE_STRING(XML_TRKSEG_FOOTER);
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
static gboolean
-map_cb_configure(GtkWidget *widget, GdkEventConfigure *event)
+write_route_gpx(GnomeVFSHandle *handle)
{
- printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
- _map_widget->allocation.width, _map_widget->allocation.height);
+ Point *curr;
+ WayPoint *wcurr;
+ gboolean trkseg_break = FALSE;
- _screen_width_pixels = _map_widget->allocation.width;
- _screen_height_pixels = _map_widget->allocation.height;
- _screen_grids_halfwidth = pixel2grid(_screen_width_pixels) / 2;
- _screen_grids_halfheight = pixel2grid(_screen_height_pixels) / 2;
+ /* Find first non-zero point. */
+ for(curr = _route.head-1, wcurr = _route.whead; curr++ != _route.tail; )
+ if(curr->unity)
+ break;
+ else if(curr == wcurr->point)
+ wcurr++;
- MACRO_RECALC_FOCUS_BASE();
- MACRO_RECALC_FOCUS_SIZE();
+ /* Write the header. */
+ WRITE_STRING(XML_TRKSEG_HEADER);
- _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
- _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
- _max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1;
- _max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1;
+ /* Curr points to first non-zero point. */
+ for(curr--; curr++ != _route.tail; )
+ {
+ gfloat lat, lon;
+ if(curr->unity)
+ {
+ gchar buffer[80];
+ gchar strlat[80], strlon[80];
+ if(trkseg_break)
+ {
+ /* First trkpt of the segment - write trkseg header. */
+ WRITE_STRING(" </trkseg>\n"
+ " <trkseg>\n");
+ trkseg_break = FALSE;
+ }
+ unit2latlon(curr->unitx, curr->unity, lat, lon);
+ g_ascii_formatd(strlat, 80, "%.06f", lat);
+ g_ascii_formatd(strlon, 80, "%.06f", lon);
+ sprintf(buffer, " <trkpt lat=\"%s\" lon=\"%s\"",
+ strlat, strlon);
+ if(curr == wcurr->point)
+ sprintf(buffer + strlen(buffer),
+ "><desc>%s</desc></trkpt>\n", wcurr++->desc);
+ else
+ strcat(buffer, "/>\n");
+ WRITE_STRING(buffer);
+ }
+ else
+ trkseg_break = TRUE;
+ }
- map_center_unit(_center.unitx, _center.unity);
+ /* Write the footer. */
+ WRITE_STRING(XML_TRKSEG_FOOTER);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-map_cb_expose(GtkWidget *widget, GdkEventExpose *event)
+menu_cb_track_save(GtkAction *action)
{
- printf("%s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
+ GnomeVFSHandle *handle;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- gdk_draw_drawable(
- _map_widget->window,
- _gc_mark,
- _map_pixmap,
- event->area.x + _offsetx, event->area.y + _offsety,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
- map_draw_mark();
+ if(open_file(NULL, &handle, NULL, NULL, &_track_file_uri,
+ GTK_FILE_CHOOSER_ACTION_SAVE))
+ {
+ if(write_track_gpx(handle))
+ hildon_banner_show_information(_window, NULL, _("Track Saved"));
+ else
+ popup_error(_window, _("Error writing GPX file."));
+ gnome_vfs_close(handle);
+ }
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-map_cb_button_press(GtkWidget *widget, GdkEventButton *event)
+menu_cb_track_mark_way(GtkAction *action)
{
printf("%s()\n", __PRETTY_FUNCTION__);
- _cmenu_position_x = event->x + 0.5;
- _cmenu_position_y = event->y + 0.5;
+ if(_track.tail->point.unity)
+ {
+ guint x1, y1;
- /* Return FALSE to allow context menu to work. */
- vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
- return FALSE;
+ /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then
+ * another instance of the most recent track point. */
+ MACRO_TRACK_INCREMENT_TAIL(_track);
+ *_track.tail = _track_null;
+ MACRO_TRACK_INCREMENT_TAIL(_track);
+ *_track.tail = _track.tail[2];
+
+ /** Instead of calling map_render_paths(), we'll just add the waypoint
+ * ourselves. */
+ x1 = unit2bufx(_track.tail->point.unitx);
+ y1 = unit2bufy(_track.tail->point.unity);
+ /* Make sure this circle will be visible. */
+ if((x1 < BUF_WIDTH_PIXELS)
+ && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
+ gdk_draw_arc(_map_pixmap, _gc_track_break,
+ FALSE, /* FALSE: not filled. */
+ x1 - _draw_line_width,
+ y1 - _draw_line_width,
+ 2 * _draw_line_width,
+ 2 * _draw_line_width,
+ 0, /* start at 0 degrees. */
+ 360 * 64);
+ }
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
static gboolean
-map_cb_button_release(GtkWidget *widget, GdkEventButton *event)
+menu_cb_route_save(GtkAction *action)
{
+ GnomeVFSHandle *handle;
printf("%s()\n", __PRETTY_FUNCTION__);
-#ifdef DEBUG
- if(event->button != 1)
- {
- _pos.unitx = x2unit((gint)(event->x + 0.5));
- _pos.unity = y2unit((gint)(event->y + 0.5));
- unit2latlon(_pos.unitx, _pos.unity, _pos_lat, _pos_lon);
- _speed = 20.f;
- integerize_data();
- track_add(time(NULL), FALSE);
- refresh_mark();
- }
- else
-#endif
+ if(!_route.head)
{
- if(_center_mode > 0)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
- _menu_ac_none_item), TRUE);
- map_center_unit(
- x2unit((gint)(event->x + 0.5)),
- y2unit((gint)(event->y + 0.5)));
+ popup_error(_window, _("No route is loaded."));
+ return TRUE;
}
- /* Return FALSE to avoid context menu (if it hasn't popped up already). */
- vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
- return FALSE;
-}
-
-static gboolean
-channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data)
-{
- printf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
-
- /* An error has occurred - re-connect(). */
- rcvr_disconnect();
- track_add(0, FALSE);
-
- if(_conn_state > RCVR_OFF)
+ if(open_file(NULL, &handle, NULL, &_route_dir_uri, NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE))
{
- set_conn_state(RCVR_DOWN);
- rcvr_connect_now();
+ if(write_route_gpx(handle))
+ hildon_banner_show_information(_window, NULL, _("Route Saved"));
+ else
+ popup_error(_window, _("Error writing GPX file."));
+ gnome_vfs_close(handle);
}
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return FALSE;
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
static gboolean
-channel_cb_connect(GIOChannel *src, GIOCondition condition, gpointer data)
+menu_cb_track_clear(GtkAction *action)
{
- int error, size = sizeof(error);
- printf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
-
- if(*_rcvr_mac != '/'
- && (getsockopt(_fd, SOL_SOCKET, SO_ERROR, &error, &size) || error))
- {
- printf("%s(): Error connecting to receiver; retrying...\n",
- __PRETTY_FUNCTION__);
- /* Try again. */
- rcvr_disconnect();
- rcvr_connect_later();
- }
- else
- {
- printf("%s(): Connected to receiver!\n",
- __PRETTY_FUNCTION__);
- set_conn_state(RCVR_UP);
- _input_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
- G_IO_IN | G_IO_PRI, channel_cb_input, NULL, NULL);
- }
+ printf("%s()\n", __PRETTY_FUNCTION__);
- _connect_sid = 0;
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return FALSE;
-}
+ _track.tail = _track.head;
+ map_force_redraw();
-#define MACRO_PARSE_INT(tofill, str) { \
- gchar *error_check; \
- (tofill) = strtol((str), &error_check, 10); \
- if(error_check == (str)) \
- { \
- fprintf(stderr, "Failed to parse string as int: %s\n", str); \
- hildon_banner_show_information(_window, NULL, \
- _("Invalid NMEA input from receiver!")); \
- return; \
- } \
-}
-#define MACRO_PARSE_FLOAT(tofill, str) { \
- gchar *error_check; \
- (tofill) = g_ascii_strtod((str), &error_check); \
- if(error_check == (str)) \
- { \
- fprintf(stderr, "Failed to parse string as float: %s\n", str); \
- hildon_banner_show_information(_window, NULL, \
- _("Invalid NMEA input from receiver!")); \
- return; \
- } \
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
-static void
-channel_parse_rmc(gchar *sentence)
-{
- /* Recommended Minimum Navigation Information C
- * 1) UTC Time
- * 2) Status, V=Navigation receiver warning A=Valid
- * 3) Latitude
- * 4) N or S
- * 5) Longitude
- * 6) E or W
- * 7) Speed over ground, knots
- * 8) Track made good, degrees true
- * 9) Date, ddmmyy
- * 10) Magnetic Variation, degrees
- * 11) E or W
- * 12) FAA mode indicator (NMEA 2.3 and later)
- * 13) Checksum
- */
- gchar *token, *dpoint;
- gdouble tmpd;
- guint tmpi;
- gboolean newly_fixed = FALSE;
- vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
-
-#define DELIM ","
- /* Skip time. */
- token = strsep(&sentence, DELIM);
+static gboolean
+menu_cb_show_tracks(GtkAction *action)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- token = strsep(&sentence, DELIM);
- /* Token is now Status. */
- if(*token != 'A')
+ _show_tracks ^= TRACKS_MASK;
+ if(gtk_check_menu_item_get_active(
+ GTK_CHECK_MENU_ITEM(_menu_show_tracks_item)))
{
- /* Data is invalid - not enough satellites?. */
- if(_conn_state != RCVR_UP)
- {
- set_conn_state(RCVR_UP);
- track_add(0, FALSE);
- }
+ _show_tracks |= TRACKS_MASK;
+ map_render_paths();
+ MACRO_QUEUE_DRAW_AREA();
+ hildon_banner_show_information(
+ _window, NULL, _("Tracks are now shown"));
}
else
{
- /* Data is valid. */
- if(_conn_state != RCVR_FIXED)
- {
- newly_fixed = TRUE;
- set_conn_state(RCVR_FIXED);
- }
+ _show_tracks &= ~TRACKS_MASK;
+ map_force_redraw();
+ hildon_banner_show_information(
+ _window, NULL, _("Tracks are now hidden"));
}
- /* Parse the latitude. */
- token = strsep(&sentence, DELIM);
- if(*token)
- {
- dpoint = strchr(token, '.');
- MACRO_PARSE_FLOAT(tmpd, dpoint - 2);
- dpoint[-2] = '\0';
- MACRO_PARSE_INT(tmpi, token);
- _pos_lat = tmpi + (tmpd * (1.0 / 60.0));
- }
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Parse N or S. */
- token = strsep(&sentence, DELIM);
- if(*token && token[0] == 'S')
- _pos_lat = -_pos_lat;
+static gboolean
+menu_cb_show_routes(GtkAction *action)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Parse the longitude. */
- token = strsep(&sentence, DELIM);
- if(*token)
+ if(gtk_check_menu_item_get_active(
+ GTK_CHECK_MENU_ITEM(_menu_show_routes_item)))
{
- dpoint = strchr(token, '.');
- MACRO_PARSE_FLOAT(tmpd, dpoint - 2);
- dpoint[-2] = '\0';
- MACRO_PARSE_INT(tmpi, token);
- _pos_lon = tmpi + (tmpd * (1.0 / 60.0));
+ _show_tracks |= ROUTES_MASK;
+ map_render_paths();
+ MACRO_QUEUE_DRAW_AREA();
+ hildon_banner_show_information(
+ _window, NULL, _("Routes are now shown"));
+ }
+ else
+ {
+ _show_tracks &= ~ROUTES_MASK;
+ map_force_redraw();
+ hildon_banner_show_information(
+ _window, NULL, _("Routes are now hidden"));
}
- /* Parse E or W. */
- token = strsep(&sentence, DELIM);
- if(*token && token[0] == 'W')
- _pos_lon = -_pos_lon;
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Parse speed over ground, knots. */
- token = strsep(&sentence, DELIM);
- if(*token)
- MACRO_PARSE_FLOAT(_speed, token);
+static gboolean
+menu_cb_show_velvec(GtkAction *action)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Parse heading, degrees from true north. */
- token = strsep(&sentence, DELIM);
- if(*token)
- MACRO_PARSE_FLOAT(_heading, token);
+ _show_velvec = gtk_check_menu_item_get_active(
+ GTK_CHECK_MENU_ITEM(_menu_show_velvec_item));
+ map_move_mark();
+ gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_details_item), _enable_gps);
+ gps_show_info();
- /* Translate data into integers. */
- integerize_data();
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Add new data to track. */
- if(_conn_state == RCVR_FIXED)
- track_add(time(NULL), newly_fixed);
+static gboolean
+menu_cb_gps_show_info(GtkAction *action)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Move mark to new location. */
- refresh_mark();
+ _gps_info = gtk_check_menu_item_get_active(
+ GTK_CHECK_MENU_ITEM(_menu_gps_show_info_item));
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ gps_show_info();
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
-static void
-channel_parse_gsv(gchar *sentence)
+static gboolean
+menu_cb_ac_lead(GtkAction *action)
{
- /* Must be GSV - Satellites in view
- * 1) total number of messages
- * 2) message number
- * 3) satellites in view
- * 4) satellite number
- * 5) elevation in degrees (0-90)
- * 6) azimuth in degrees to true north (0-359)
- * 7) SNR in dB (0-99)
- * more satellite infos like 4)-7)
- * n) checksum
- */
- gchar *token;
- guint msgcnt, nummsgs;
- static guint running_total = 0;
- static guint num_sats_used = 0;
- vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
+ guint new_center_unitx, new_center_unity;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Parse number of messages. */
- token = strsep(&sentence, DELIM);
- if(!sentence)
- return; /* because this is an invalid sentence. */
- MACRO_PARSE_INT(nummsgs, token);
+ _center_mode = CENTER_LEAD;
+ hildon_banner_show_information(_window, NULL, _("Auto-Center Mode: Lead"));
+ MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
+ map_center_unit(new_center_unitx, new_center_unity);
- /* Parse message number. */
- token = strsep(&sentence, DELIM);
- if(!sentence)
- return; /* because this is an invalid sentence. */
- MACRO_PARSE_INT(msgcnt, token);
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Skip number of satellites in view. */
- token = strsep(&sentence, DELIM);
+static gboolean
+menu_cb_ac_latlon(GtkAction *action)
+{
+ guint new_center_unitx, new_center_unity;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Loop until there are no more satellites to parse. */
- while(sentence)
- {
- guint snr;
- /* Skip satellite number. */
- token = strsep(&sentence, DELIM);
- if(!sentence)
- break; /* because this is an invalid sentence. */
- /* Skip elevation in degrees (0-90). */
- token = strsep(&sentence, DELIM);
- if(!sentence)
- break; /* because this is an invalid sentence. */
- /* Skip azimuth in degrees to true north (0-359). */
- token = strsep(&sentence, DELIM);
- if(!sentence)
- break; /* because this is an invalid sentence. */
+ _center_mode = CENTER_LATLON;
+ hildon_banner_show_information(_window, NULL,
+ _("Auto-Center Mode: Lat/Lon"));
+ MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
+ map_center_unit(new_center_unitx, new_center_unity);
- /* Parse SNR. */
- token = strsep(&sentence, DELIM);
- if((snr = atoi(token)))
- {
- /* Snr is non-zero - add to total and count as used. */
- running_total += snr;
- num_sats_used++;
- }
- }
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- if(msgcnt == nummsgs)
- {
- /* This is the last message. Calculate signal strength. */
- if(num_sats_used)
- {
- gdouble fraction = running_total * sqrt(num_sats_used)
- / num_sats_used / 100.0;
- BOUND(fraction, 0.0, 1.0);
- running_total = 0;
- num_sats_used = 0;
- hildon_banner_set_fraction(HILDON_BANNER(_fix_banner), fraction);
- }
+static gboolean
+menu_cb_ac_none(GtkAction *action)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Keep awake while they watch the progress bar. */
- KEEP_DISPLAY_ON();
+ _center_mode = -_center_mode;
+ hildon_banner_show_information(_window, NULL, _("Auto-Center Off"));
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
+
+
+typedef struct _RepoManInfo RepoManInfo;
+struct _RepoManInfo {
+ GtkWidget *dialog;
+ GtkWidget *notebook;
+ GtkWidget *cmb_repos;
+ GList *repo_edits;
+};
+
+typedef struct _RepoEditInfo RepoEditInfo;
+struct _RepoEditInfo {
+ gchar *name;
+ GtkWidget *page_table;
+ GtkWidget *txt_url;
+ GtkWidget *txt_cache_dir;
+ GtkWidget *num_dl_zoom_steps;
+ GtkWidget *num_view_zoom_steps;
+ GtkWidget *btn_browse;
+ BrowseInfo browse_info;
+};
+
+static gboolean
+repoman_dialog_select(GtkWidget *widget, RepoManInfo *rmi)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+ gint curr_index = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(rmi->notebook), curr_index);
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
+
+static gboolean
+repoman_dialog_browse(GtkWidget *widget, BrowseInfo *browse_info)
+{
+ GtkWidget *dialog;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ dialog = GTK_WIDGET(
+ hildon_file_chooser_dialog_new(GTK_WINDOW(browse_info->dialog),
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER));
+
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+ gtk_entry_get_text(GTK_ENTRY(browse_info->txt)));
+
+ if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
+ {
+ gchar *filename = gtk_file_chooser_get_filename(
+ GTK_FILE_CHOOSER(dialog));
+ gtk_entry_set_text(GTK_ENTRY(browse_info->txt), filename);
+ g_free(filename);
}
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ gtk_widget_destroy(dialog);
+
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
}
static gboolean
-channel_cb_input(GIOChannel *src, GIOCondition condition, gpointer data)
+repoman_dialog_rename(GtkWidget *widget, RepoManInfo *rmi)
{
- gchar *sentence;
- vprintf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
-
- while(G_IO_STATUS_NORMAL == g_io_channel_read_line(
- _channel,
- &sentence,
- NULL,
- NULL,
- NULL) && sentence)
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *txt_name;
+ GtkWidget *dialog;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ dialog = gtk_dialog_new_with_buttons(_("New Name"),
+ GTK_WINDOW(rmi->dialog), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL);
+
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4);
+
+ gtk_box_pack_start(GTK_BOX(hbox),
+ label = gtk_label_new(_("Name")),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ txt_name = gtk_entry_new(),
+ TRUE, TRUE, 0);
+
+ gtk_widget_show_all(dialog);
+
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
{
- gchar *sptr = sentence + 1;
- guint csum = 0;
- while(*sptr && *sptr != '*')
- csum ^= *sptr++;
- if (!*sptr || csum == strtol(sptr+1, NULL, 16))
- {
- if(*sptr)
- *sptr = '\0'; /* take checksum out of the sentence. */
- if(!strncmp(sentence + 3, "RMC", 3))
- channel_parse_rmc(sentence + 7);
- else if(_conn_state == RCVR_UP
- && !strncmp(sentence + 3, "GSV", 3))
- channel_parse_gsv(sentence + 7);
- }
- else
- {
- printf("%s: Bad checksum in NMEA sentence:\n%s\n",
- __PRETTY_FUNCTION__, sentence);
- }
- g_free(sentence);
+ gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
+ RepoEditInfo *rei = g_list_nth_data(rmi->repo_edits, active);
+ g_free(rei->name);
+ rei->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name)));
+ gtk_combo_box_insert_text(GTK_COMBO_BOX(rmi->cmb_repos),
+ active, g_strdup(rei->name));
+ gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos), active);
+ gtk_combo_box_remove_text(GTK_COMBO_BOX(rmi->cmb_repos), active + 1);
+ break;
}
+ gtk_widget_destroy(dialog);
+
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-gps_toggled_from(GtkToggleButton *chk_gps,
- GtkWidget *txt_from)
+repoman_dialog_delete(GtkWidget *widget, RepoManInfo *rmi)
{
- gchar buffer[80];
- gchar strlat[32];
- gchar strlon[32];
+ gchar buffer[100];
+ GtkWidget *confirm;
+ gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
printf("%s()\n", __PRETTY_FUNCTION__);
- g_ascii_formatd(strlat, 80, "%.06f", _pos_lat);
- g_ascii_formatd(strlon, 80, "%.06f", _pos_lon);
- sprintf(buffer, "%s, %s", strlat, strlon);
- gtk_widget_set_sensitive(txt_from, !gtk_toggle_button_get_active(chk_gps));
- gtk_entry_set_text(GTK_ENTRY(txt_from), buffer);
+ if(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
+ gtk_combo_box_get_model(GTK_COMBO_BOX(rmi->cmb_repos))),
+ NULL) <= 1)
+ {
+ popup_error(rmi->dialog,
+ _("Cannot delete the last repository - there must be at"
+ " lease one repository."));
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+ }
+
+ sprintf(buffer, "%s:\n%s\n",
+ _("Confirm delete of repository"),
+ gtk_combo_box_get_active_text(GTK_COMBO_BOX(rmi->cmb_repos)));
+ confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
+
+ if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
+ {
+ gtk_combo_box_remove_text(GTK_COMBO_BOX(rmi->cmb_repos), active);
+ gtk_notebook_remove_page(GTK_NOTEBOOK(rmi->notebook), active);
+ rmi->repo_edits = g_list_remove_link(
+ rmi->repo_edits,
+ g_list_nth(rmi->repo_edits, active));
+ gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos),
+ MAX(0, active - 1));
+ }
+
+ gtk_widget_destroy(confirm);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
-static gboolean
-gps_toggled_auto(GtkToggleButton *chk_gps,
- GtkWidget *chk_auto)
+static RepoEditInfo*
+repoman_dialog_add_repo(RepoManInfo *rmi, gchar *name)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ GtkWidget *label;
+ GtkWidget *hbox;
+ RepoEditInfo *rei = g_new(RepoEditInfo, 1);
+ printf("%s(%s)\n", __PRETTY_FUNCTION__, name);
- gtk_widget_set_sensitive(chk_auto, gtk_toggle_button_get_active(chk_gps));
+ rei->name = name;
+
+ /* Maps page. */
+ gtk_notebook_append_page(GTK_NOTEBOOK(rmi->notebook),
+ rei->page_table = gtk_table_new(4, 4, FALSE),
+ gtk_label_new(name));
+
+ /* Map download URI. */
+ gtk_table_attach(GTK_TABLE(rei->page_table),
+ label = gtk_label_new(_("URI Format")),
+ 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(rei->page_table),
+ rei->txt_url = gtk_entry_new(),
+ 1, 3, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+
+ /* Map Directory. */
+ gtk_table_attach(GTK_TABLE(rei->page_table),
+ label = gtk_label_new(_("Cache Dir.")),
+ 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(rei->page_table),
+ hbox = gtk_hbox_new(FALSE, 4),
+ 1, 3, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ rei->txt_cache_dir = gtk_entry_new(),
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ rei->btn_browse = gtk_button_new_with_label(_("Browse...")),
+ FALSE, FALSE, 0);
+
+ /* Download Zoom Steps. */
+ gtk_table_attach(GTK_TABLE(rei->page_table),
+ label = gtk_label_new(_("Download Zoom Steps")),
+ 0, 2, 2, 3, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(rei->page_table),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_container_add(GTK_CONTAINER(label),
+ rei->num_dl_zoom_steps = hildon_controlbar_new());
+ hildon_controlbar_set_range(
+ HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 1, 4);
+ hildon_controlbar_set_value(
+ HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 2);
+ force_min_visible_bars(HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 1);
+
+ /* Download Zoom Steps. */
+ gtk_table_attach(GTK_TABLE(rei->page_table),
+ label = gtk_label_new(_("View Zoom Steps")),
+ 0, 2, 3, 4, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(rei->page_table),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ 2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_container_add(GTK_CONTAINER(label),
+ rei->num_view_zoom_steps = hildon_controlbar_new());
+ hildon_controlbar_set_range(
+ HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1, 4);
+ hildon_controlbar_set_value(
+ HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1);
+ force_min_visible_bars(HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1);
+
+ rmi->repo_edits = g_list_append(rmi->repo_edits, rei);
+
+ /* Connect signals. */
+ rei->browse_info.dialog = rmi->dialog;
+ rei->browse_info.txt = rei->txt_cache_dir;
+ g_signal_connect(G_OBJECT(rei->btn_browse), "clicked",
+ G_CALLBACK(repoman_dialog_browse),
+ &rei->browse_info);
+
+ gtk_widget_show_all(rei->page_table);
+
+ gtk_combo_box_append_text(GTK_COMBO_BOX(rmi->cmb_repos), name);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos),
+ gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
+ gtk_combo_box_get_model(GTK_COMBO_BOX(rmi->cmb_repos))),
+ NULL) - 1);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
+ return rei;
}
-/**
- * Display a dialog box to the user asking them to download a route. The
- * "From" and "To" textfields may be initialized using the first two
- * parameters. The third parameter, if set to TRUE, will cause the "Use GPS
- * Location" checkbox to be enabled, which automatically sets the "From" to the
- * current GPS position (this overrides any value that may have been passed as
- * the "To" initializer).
- * None of the passed strings are freed - that is left to the caller, and it is
- * safe to free either string as soon as this function returns.
- */
static gboolean
-route_download(gchar *from, gchar *to, gboolean from_here)
+repoman_dialog_new(GtkWidget *widget, RepoManInfo *rmi)
{
- GtkWidget *dialog;
- GtkWidget *table;
- GtkWidget *label;
- GtkWidget *chk_gps;
- GtkWidget *chk_auto;
- GtkWidget *txt_from;
- GtkWidget *txt_to;
GtkWidget *hbox;
- GtkEntryCompletion *from_comp;
- GtkEntryCompletion *to_comp;
- gchar *bytes = NULL;
- gint size;
+ GtkWidget *label;
+ GtkWidget *txt_name;
+ GtkWidget *dialog;
printf("%s()\n", __PRETTY_FUNCTION__);
- dialog = gtk_dialog_new_with_buttons(_("Download Route"),
- GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ dialog = gtk_dialog_new_with_buttons(_("New Repository"),
+ GTK_WINDOW(rmi->dialog), GTK_DIALOG_MODAL,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
NULL);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
- table = gtk_table_new(2, 4, FALSE), TRUE, TRUE, 0);
-
- from_comp = gtk_entry_completion_new();
- gtk_entry_completion_set_model(from_comp, GTK_TREE_MODEL(_loc_model));
- gtk_entry_completion_set_text_column(from_comp, 0);
- to_comp = gtk_entry_completion_new();
- gtk_entry_completion_set_model(to_comp, GTK_TREE_MODEL(_loc_model));
- gtk_entry_completion_set_text_column(to_comp, 0);
+ hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4);
- /* Auto. */
- gtk_table_attach(GTK_TABLE(table),
- hbox = gtk_hbox_new(FALSE, 6),
- 0, 2, 0, 1, 0, 0, 2, 4);
gtk_box_pack_start(GTK_BOX(hbox),
- chk_gps = gtk_check_button_new_with_label(
- _("Use GPS Location")),
- TRUE, TRUE, 0);
+ label = gtk_label_new(_("Name")),
+ FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox),
- chk_auto = gtk_check_button_new_with_label(
- _("Auto-Update")),
+ txt_name = gtk_entry_new(),
TRUE, TRUE, 0);
- gtk_widget_set_sensitive(chk_auto, FALSE);
- /* Origin. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Origin")),
- 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- txt_from = gtk_entry_new(),
- 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_entry_set_completion(GTK_ENTRY(txt_from), from_comp);
- gtk_entry_set_width_chars(GTK_ENTRY(txt_from), 25);
+ gtk_widget_show_all(dialog);
- /* Destination. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Destination")),
- 0, 1, 2, 3, GTK_FILL, 0, 2, 4);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- txt_to = gtk_entry_new(),
- 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- gtk_entry_set_completion(GTK_ENTRY(txt_to), to_comp);
- gtk_entry_set_width_chars(GTK_ENTRY(txt_to), 25);
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+ {
+ repoman_dialog_add_repo(rmi,
+ g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name))));
+ break;
+ }
- g_signal_connect(G_OBJECT(chk_gps), _("toggled"),
- G_CALLBACK(gps_toggled_from), txt_from);
- g_signal_connect(G_OBJECT(chk_gps), _("toggled"),
- G_CALLBACK(gps_toggled_auto), chk_auto);
+ gtk_widget_destroy(dialog);
- /* Initialize fields. */
- gtk_entry_set_text(GTK_ENTRY(txt_from), (from ? from : ""));
- gtk_entry_set_text(GTK_ENTRY(txt_to), (to ? to : ""));
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- if(from_here)
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_gps), TRUE);
+static gboolean
+menu_cb_maps_repoman(GtkAction *action)
+{
+ RepoManInfo rmi;
+ GtkWidget *hbox;
+ GtkWidget *btn_rename;
+ GtkWidget *btn_delete;
+ GtkWidget *btn_new;
+ GList *curr;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- gtk_widget_show_all(dialog);
+ rmi.dialog = gtk_dialog_new_with_buttons(_("Repositories"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL);
- while(!bytes
- && GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
- {
- GnomeVFSResult vfs_result;
- gchar buffer[1024];
- const gchar *from, *to;
- gchar *from_escaped, *to_escaped;
+ hbox = gtk_hbox_new(FALSE, 4);
- from = gtk_entry_get_text(GTK_ENTRY(txt_from));
- if(!strlen(from))
- {
- popup_error(dialog, _("Please specify a start location."));
- continue;
- }
+ gtk_box_pack_start(GTK_BOX(hbox),
+ rmi.cmb_repos = gtk_combo_box_new_text(), FALSE, FALSE, 4);
- to = gtk_entry_get_text(GTK_ENTRY(txt_to));
- if(!strlen(to))
- {
- popup_error(dialog, _("Please specify an end location."));
- continue;
- }
+ gtk_box_pack_start(GTK_BOX(hbox),
+ gtk_vseparator_new(), TRUE, TRUE, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ btn_rename = gtk_button_new_with_label("Rename..."),
+ FALSE, FALSE, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ btn_delete = gtk_button_new_with_label("Delete..."),
+ FALSE, FALSE, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ btn_new = gtk_button_new_with_label("New..."),
+ FALSE, FALSE, 4);
- from_escaped = gnome_vfs_escape_string(from);
- to_escaped = gnome_vfs_escape_string(to);
- sprintf(buffer, "http://www.gnuite.com/cgi-bin/gpx.cgi?"
- "saddr=%s&daddr=%s",
- from_escaped, to_escaped);
- g_free(from_escaped);
- g_free(to_escaped);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(rmi.dialog)->vbox),
+ hbox, FALSE, FALSE, 4);
- if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
- buffer, &size, &bytes)))
- {
- gchar buffer[1024];
- sprintf(buffer, "%s:\n%s",
- _("Failed to connect to GPX Directions server"),
- gnome_vfs_result_to_string(vfs_result));
- popup_error(dialog, buffer);
- }
- else if(strncmp(bytes, "<?xml", strlen("<?xml")))
- {
- /* Not an XML document - must be bad locations. */
- popup_error(dialog,
- _("Could not generate directions. Make sure your "
- "source and destination are valid."));
- g_free(bytes);
- bytes = NULL;
- }
- else
- {
- /* If GPS is enabled, append the route, otherwise replace it. */
- if(parse_route_gpx(bytes, size,
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_gps))
- ? 0 : 1)))
- {
- GtkTreeIter iter;
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(rmi.dialog)->vbox),
+ gtk_hseparator_new(), TRUE, TRUE, 4);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(rmi.dialog)->vbox),
+ rmi.notebook = gtk_notebook_new(), TRUE, TRUE, 4);
- /* Find the nearest route point, if we're connected. */
- route_find_nearest_point();
+ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(rmi.notebook), FALSE);
+ gtk_notebook_set_show_border(GTK_NOTEBOOK(rmi.notebook), FALSE);
- /* Cancel any autoroute that might be occurring. */
- cancel_autoroute();
+ rmi.repo_edits = NULL;
- map_force_redraw();
+ /* Populate combo box and pages in notebook. */
+ for(curr = _repo_list; curr; curr = curr->next)
+ {
+ RepoData *rd = (RepoData*)curr->data;
+ RepoEditInfo *rei = repoman_dialog_add_repo(&rmi, g_strdup(rd->name));
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_auto)))
- {
- /* Kick off a timeout to start the first update. */
- _autoroute_data.dest = gnome_vfs_escape_string(to);
- _autoroute_data.enabled = TRUE;
- _autoroute_data.bytes_maxsize = 2 * size;
- _autoroute_data.bytes = g_new(gchar, 2 * size);
- }
+ /* Initialize fields with data from the RepoData object. */
+ gtk_entry_set_text(GTK_ENTRY(rei->txt_url), rd->url);
+ gtk_entry_set_text(GTK_ENTRY(rei->txt_cache_dir),
+ rd->cache_dir);
+ hildon_controlbar_set_value(
+ HILDON_CONTROLBAR(rei->num_dl_zoom_steps),
+ rd->dl_zoom_steps);
+ hildon_controlbar_set_value(
+ HILDON_CONTROLBAR(rei->num_view_zoom_steps),
+ rd->view_zoom_steps);
+ }
- /* Save Origin in Route Locations list if not from GPS. */
- if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_gps))
- && !g_slist_find_custom(_loc_list, from,
- (GCompareFunc)strcmp))
- {
- _loc_list = g_slist_prepend(_loc_list, g_strdup(from));
- gtk_list_store_insert_with_values(_loc_model, &iter,
- INT_MAX, 0, from, -1);
- }
+ /* Connect signals. */
+ g_signal_connect(G_OBJECT(btn_rename), "clicked",
+ G_CALLBACK(repoman_dialog_rename), &rmi);
+ g_signal_connect(G_OBJECT(btn_delete), "clicked",
+ G_CALLBACK(repoman_dialog_delete), &rmi);
+ g_signal_connect(G_OBJECT(btn_new), "clicked",
+ G_CALLBACK(repoman_dialog_new), &rmi);
+ g_signal_connect(G_OBJECT(rmi.cmb_repos), "changed",
+ G_CALLBACK(repoman_dialog_select), &rmi);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(rmi.cmb_repos), 0);
+ gtk_widget_show_all(rmi.dialog);
+
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(rmi.dialog)))
+ {
+ /* Iterate through repos and verify each. */
+ gboolean verified = TRUE;
+ gint i;
+ GList *curr;
+ gchar *old_curr_repo_name = NULL;
+ for(i = 0, curr = rmi.repo_edits;
+ verified && curr; curr = curr->next, i++)
+ {
+ RepoEditInfo *rei = curr->data;
+ /* Verify that cache directory exists or can be created. */
+ GnomeVFSURI *map_dir_uri = gnome_vfs_uri_new(gtk_entry_get_text(
+ GTK_ENTRY(rei->txt_cache_dir)));
+ if(!gnome_vfs_uri_exists(map_dir_uri))
+ {
+ GnomeVFSURI *parent, *curr_uri;
+ GList *list = NULL;
- /* Save Destination in Route Locations list. */
- if(!g_slist_find_custom(_loc_list, to,
- (GCompareFunc)strcmp))
+ list = g_list_prepend(list, curr_uri = map_dir_uri);
+ while(GNOME_VFS_ERROR_NOT_FOUND
+ == gnome_vfs_make_directory_for_uri(
+ parent = gnome_vfs_uri_get_parent(curr_uri), 0755))
+ list = g_list_prepend(list, curr_uri = parent);
+
+ while(list != NULL)
{
- _loc_list = g_slist_prepend(_loc_list, g_strdup(to));
- gtk_list_store_insert_with_values(_loc_model, &iter,
- INT_MAX, 0, to, -1);
+ if(verified)
+ {
+ verified = (GNOME_VFS_OK
+ == gnome_vfs_make_directory_for_uri(
+ (GnomeVFSURI*)list->data, 0755));
+ }
+ gnome_vfs_uri_unref((GnomeVFSURI*)list->data);
+ list = g_list_remove(list, list->data);
}
-
- hildon_banner_show_information(_window, NULL,
- _("Route Downloaded"));
- g_free(bytes);
+ /* verified now equals result of last make-dir attempt. */
}
- else
+
+ if(!verified)
{
- popup_error(dialog, _("Error parsing GPX file."));
- g_free(bytes);
- bytes = NULL; /* Let them try again. */
+ /* Failed to create Map Cache directory. */
+ gchar buffer[1024];
+ sprintf(buffer, "%s: %s",
+ _("Unable to create cache directory for repository"),
+ rei->name);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(rmi.cmb_repos), i);
+ popup_error(rmi.dialog, buffer);
}
}
+ if(!verified)
+ continue;
+
+ /* We're good to replace. Delete old _repo_list */
+ menu_maps_remove_repos();
+ while(_repo_list)
+ {
+ if(_repo_list->data == _curr_repo)
+ old_curr_repo_name = g_strdup(
+ ((RepoData*)_repo_list->data)->name);
+ g_free(((RepoData*)_repo_list->data)->name);
+ g_free(((RepoData*)_repo_list->data)->url);
+ g_free(((RepoData*)_repo_list->data)->cache_dir);
+ g_free(_repo_list->data);
+ _repo_list = g_list_delete_link(_repo_list, _repo_list);
+ }
+
+ /* Write new _repo_list. */
+ _curr_repo = NULL;
+ for(i = 0, curr = rmi.repo_edits; curr; curr = curr->next, i++)
+ {
+ RepoEditInfo *rei = curr->data;
+ RepoData *rd = g_new(RepoData, 1);
+ rd->name = g_strdup(rei->name);
+ rd->url = g_strdup(gtk_entry_get_text(GTK_ENTRY(rei->txt_url)));
+ rd->cache_dir = g_strdup(gtk_entry_get_text(
+ GTK_ENTRY(rei->txt_cache_dir)));
+ rd->dl_zoom_steps = hildon_controlbar_get_value(
+ HILDON_CONTROLBAR(rei->num_dl_zoom_steps));
+ rd->view_zoom_steps = hildon_controlbar_get_value(
+ HILDON_CONTROLBAR(rei->num_view_zoom_steps));
+ _repo_list = g_list_append(_repo_list, rd);
+
+ if(old_curr_repo_name && !strcmp(old_curr_repo_name, rd->name))
+ _curr_repo = rd;
+ }
+ if(!_curr_repo)
+ _curr_repo = (RepoData*)g_list_first(_repo_list)->data;
+ menu_maps_add_repos();
+ break;
}
- gtk_widget_destroy(dialog);
+ gtk_widget_hide(rmi.dialog); /* Destroying causes a crash (!?!?!??!) */
+
+ map_set_zoom(_zoom); /* make sure we're at an appropriate zoom level. */
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
-static gboolean
-menu_cb_route_download(GtkAction *action)
-{
- route_download(NULL, NULL, FALSE);
- return TRUE;
-}
+typedef struct _MapmanInfo MapmanInfo;
+struct _MapmanInfo {
+ GtkWidget *notebook;
+ GtkWidget *tbl_area;
-static gboolean
-menu_cb_route_open(GtkAction *action)
-{
- gchar *buffer;
- gint size;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ /* The "Setup" tab. */
+ GtkWidget *rad_download;
+ GtkWidget *rad_delete;
+ GtkWidget *chk_overwrite;
+ GtkWidget *rad_by_area;
+ GtkWidget *rad_along_route;
+ GtkWidget *txt_route_radius;
- if(open_file(&buffer, NULL, &size, &_route_dir_uri, NULL,
- GTK_FILE_CHOOSER_ACTION_OPEN))
- {
- /* If auto is enabled, append the route, otherwise replace it. */
- if(parse_route_gpx(buffer, size, _autoroute_data.enabled ? 0 : 1))
- {
- cancel_autoroute();
+ /* The "Area" tab. */
+ GtkWidget *txt_topleft_lat;
+ GtkWidget *txt_topleft_lon;
+ GtkWidget *txt_botright_lat;
+ GtkWidget *txt_botright_lon;
- /* Find the nearest route point, if we're connected. */
- route_find_nearest_point();
+ /* The "Zoom" tab. */
+ GtkWidget *chk_zoom_levels[MAX_ZOOM];
+};
- map_force_redraw();
- hildon_banner_show_information(_window, NULL,
- _("Route Opened"));
- }
- else
- popup_error(_window, _("Error parsing GPX file."));
- g_free(buffer);
+static void mapman_clear(GtkWidget *widget, MapmanInfo *mapman_info)
+{
+ guint i;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+ if(gtk_notebook_get_current_page(GTK_NOTEBOOK(mapman_info->notebook)))
+ /* This is the second page (the "Zoom" page) - clear the checks. */
+ for(i = 0; i < MAX_ZOOM; i++)
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[i]), FALSE);
+ else
+ {
+ /* This is the first page (the "Area" page) - clear the text fields. */
+ gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_topleft_lat), "");
+ gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_topleft_lon), "");
+ gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_botright_lat), "");
+ gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_botright_lon), "");
}
-
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
}
-static gboolean
-menu_cb_route_reset(GtkAction *action)
+static void mapman_update_state(GtkWidget *widget, MapmanInfo *mapman_info)
{
printf("%s()\n", __PRETTY_FUNCTION__);
+ gtk_widget_set_sensitive( mapman_info->chk_overwrite,
+ gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(mapman_info->rad_download)));
- route_find_nearest_point();
- map_render_paths();
- MACRO_QUEUE_DRAW_AREA();
+ if(gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(mapman_info->rad_by_area)))
+ gtk_widget_show(mapman_info->tbl_area);
+ else if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(mapman_info->notebook)) == 3)
+ gtk_widget_hide(mapman_info->tbl_area);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
+ gtk_widget_set_sensitive(mapman_info->txt_route_radius,
+ gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(mapman_info->rad_along_route)));
}
static gboolean
-menu_cb_route_clear(GtkAction *action)
+menu_cb_maps_select(GtkAction *action, gpointer new_repo)
{
printf("%s()\n", __PRETTY_FUNCTION__);
-
- _next_way_dist_rough = -1; /* to avoid announcement attempts. */
- cancel_autoroute();
- MACRO_CLEAR_TRACK(_route);
+ _curr_repo = new_repo;
map_force_redraw();
-
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_track_open(GtkAction *action)
+menu_cb_mapman(GtkAction *action)
{
- gchar *buffer;
- gint size;
+ GtkWidget *dialog;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkWidget *lbl_gps_lat;
+ GtkWidget *lbl_gps_lon;
+ GtkWidget *lbl_center_lat;
+ GtkWidget *lbl_center_lon;
+ MapmanInfo mapman_info;
+ gchar buffer[80];
+ gfloat lat, lon;
+ guint i;
printf("%s()\n", __PRETTY_FUNCTION__);
- if(open_file(&buffer, NULL, &size, NULL, &_track_file_uri,
- GTK_FILE_CHOOSER_ACTION_OPEN))
+ dialog = gtk_dialog_new_with_buttons(_("Manage Maps"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+ button = gtk_button_new_with_label(_("Clear")));
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(mapman_clear), &mapman_info);
+
+ /* Clear button. */
+ gtk_dialog_add_button(GTK_DIALOG(dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ mapman_info.notebook = gtk_notebook_new(), TRUE, TRUE, 0);
+
+ /* Setup page. */
+ gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
+ vbox = gtk_vbox_new(FALSE, 2),
+ label = gtk_label_new(_("Setup")));
+ gtk_notebook_set_tab_label_packing(
+ GTK_NOTEBOOK(mapman_info.notebook), vbox,
+ FALSE, FALSE, GTK_PACK_START);
+
+ gtk_box_pack_start(GTK_BOX(vbox),
+ hbox = gtk_hbox_new(FALSE, 4),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ mapman_info.rad_download
+ = gtk_radio_button_new_with_label(NULL, _("Download Maps")),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+ FALSE, FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(label),
+ mapman_info.chk_overwrite
+ = gtk_check_button_new_with_label(_("Overwrite"))),
+
+ gtk_box_pack_start(GTK_BOX(vbox),
+ mapman_info.rad_delete
+ = gtk_radio_button_new_with_label_from_widget(
+ GTK_RADIO_BUTTON(mapman_info.rad_download),
+ _("Delete Maps")),
+ FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(vbox),
+ gtk_hseparator_new(),
+ FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(vbox),
+ mapman_info.rad_by_area
+ = gtk_radio_button_new_with_label(NULL,
+ _("By Area (see tab)")),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox),
+ hbox = gtk_hbox_new(FALSE, 4),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ mapman_info.rad_along_route
+ = gtk_radio_button_new_with_label_from_widget(
+ GTK_RADIO_BUTTON(mapman_info.rad_by_area),
+ _("Along Route - Radius:")),
+ FALSE, FALSE, 0);
+ gtk_widget_set_sensitive(mapman_info.rad_along_route, _route.head != NULL);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ mapman_info.txt_route_radius
+ = gtk_entry_new(),
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ gtk_label_new(UNITS_TEXT[_units]), FALSE, FALSE, 0);
+ gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_route_radius), 1.f);
+
+
+ /* Zoom page. */
+ gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
+ table = gtk_table_new(5, 5, FALSE),
+ label = gtk_label_new(_("Zoom")));
+ gtk_notebook_set_tab_label_packing(
+ GTK_NOTEBOOK(mapman_info.notebook), table,
+ FALSE, FALSE, GTK_PACK_START);
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(
+ _("Zoom Levels to Download: (0 -> most detail)")),
+ 0, 5, 0, 1, GTK_FILL, 0, 4, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
+ for(i = 0; i < MAX_ZOOM; i++)
{
- if(parse_track_gpx(buffer, size, -1))
- {
- map_force_redraw();
- hildon_banner_show_information(_window, NULL, _("Track Opened"));
- }
- else
- popup_error(_window, _("Error parsing GPX file."));
- g_free(buffer);
+ sprintf(buffer, "%d", i);
+ gtk_table_attach(GTK_TABLE(table),
+ mapman_info.chk_zoom_levels[i]
+ = gtk_check_button_new_with_label(buffer),
+ i % 5, i % 5 + 1, i / 5 + 1, i / 5 + 2,
+ GTK_EXPAND | GTK_FILL, 0, 4, 0);
+ }
+
+ /* Area page. */
+ gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
+ mapman_info.tbl_area = gtk_table_new(3, 4, FALSE),
+ label = gtk_label_new(_("Area")));
+
+ /* Label Columns. */
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ label = gtk_label_new(_("Latitude")),
+ 1, 2, 0, 1, GTK_FILL, 0, 4, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ label = gtk_label_new(_("Longitude")),
+ 2, 3, 0, 1, GTK_FILL, 0, 4, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+
+ /* GPS. */
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ label = gtk_label_new(_("GPS Location")),
+ 0, 1, 1, 2, GTK_FILL, 0, 4, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ lbl_gps_lat = gtk_label_new(""),
+ 1, 2, 1, 2, GTK_FILL, 0, 4, 0);
+ gtk_label_set_selectable(GTK_LABEL(lbl_gps_lat), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(lbl_gps_lat), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ lbl_gps_lon = gtk_label_new(""),
+ 2, 3, 1, 2, GTK_FILL, 0, 4, 0);
+ gtk_label_set_selectable(GTK_LABEL(lbl_gps_lon), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(lbl_gps_lon), 1.f, 0.5f);
+
+ /* Center. */
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ label = gtk_label_new(_("View Center")),
+ 0, 1, 2, 3, GTK_FILL, 0, 4, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ lbl_center_lat = gtk_label_new(""),
+ 1, 2, 2, 3, GTK_FILL, 0, 4, 0);
+ gtk_label_set_selectable(GTK_LABEL(lbl_center_lat), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(lbl_center_lat), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ lbl_center_lon = gtk_label_new(""),
+ 2, 3, 2, 3, GTK_FILL, 0, 4, 0);
+ gtk_label_set_selectable(GTK_LABEL(lbl_center_lon), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(lbl_center_lon), 1.f, 0.5f);
+
+ /* default values for Top Left and Bottom Right are defined by the
+ * rectangle of the current and the previous Center */
+
+ /* Top Left. */
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ label = gtk_label_new(_("Top-Left")),
+ 0, 1, 3, 4, GTK_FILL, 0, 4, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ mapman_info.txt_topleft_lat = gtk_entry_new(),
+ 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 4, 0);
+ gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_topleft_lat), 1.f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ mapman_info.txt_topleft_lon = gtk_entry_new(),
+ 2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 4, 0);
+ gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_topleft_lon), 1.f);
+
+ /* Bottom Right. */
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ label = gtk_label_new(_("Bottom-Right")),
+ 0, 1, 4, 5, GTK_FILL, 0, 4, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ mapman_info.txt_botright_lat = gtk_entry_new(),
+ 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 4, 0);
+ gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_botright_lat), 1.f);
+ gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+ mapman_info.txt_botright_lon = gtk_entry_new(),
+ 2, 3, 4, 5, GTK_EXPAND | GTK_FILL, 0, 4, 0);
+ gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_botright_lon), 1.f);
+
+ /* Default action is to download by area. */
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(mapman_info.rad_by_area), TRUE);
+
+ /* Initialize fields. Do no use g_ascii_formatd; these strings will be
+ * output (and parsed) as locale-dependent. */
+
+ sprintf(buffer, "%.06f", _pos_lat);
+ gtk_label_set_text(GTK_LABEL(lbl_gps_lat), buffer);
+ sprintf(buffer, "%.06f", _pos_lon);
+ gtk_label_set_text(GTK_LABEL(lbl_gps_lon), buffer);
+
+ unit2latlon(_center.unitx, _center.unity, lat, lon);
+ sprintf(buffer, "%.06f", lat);
+ gtk_label_set_text(GTK_LABEL(lbl_center_lat), buffer);
+ sprintf(buffer, "%.06f", lon);
+ gtk_label_set_text(GTK_LABEL(lbl_center_lon), buffer);
+
+ /* Initialize to the bounds of the screen. */
+ unit2latlon(x2unit(0), y2unit(0), lat, lon);
+ sprintf(buffer, "%.06f", lat);
+ gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_topleft_lat), buffer);
+ sprintf(buffer, "%.06f", lon);
+ gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_topleft_lon), buffer);
+
+ unit2latlon(x2unit(_screen_width_pixels), y2unit(_screen_height_pixels),
+ lat, lon);
+ sprintf(buffer, "%.06f", lat);
+ gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_botright_lat), buffer);
+ sprintf(buffer, "%.06f", lon);
+ gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_botright_lon), buffer);
+
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[_zoom]), TRUE);
+
+ gtk_widget_show_all(dialog);
+
+ mapman_update_state(NULL, &mapman_info);
+
+ /* Connect signals. */
+ if(*_curr_repo->url)
+ {
+ g_signal_connect(G_OBJECT(mapman_info.rad_download), "clicked",
+ G_CALLBACK(mapman_update_state), &mapman_info);
+ gtk_widget_set_sensitive(mapman_info.rad_download, TRUE);
}
+ else
+ {
+ gtk_widget_set_sensitive(mapman_info.rad_download, FALSE);
+ popup_error(dialog,
+ _("NOTE: You must set a Map URI in the Repository Manager in "
+ "order to download maps."));
+ }
+ g_signal_connect(G_OBJECT(mapman_info.rad_delete), "clicked",
+ G_CALLBACK(mapman_update_state), &mapman_info);
+ g_signal_connect(G_OBJECT(mapman_info.rad_by_area), "clicked",
+ G_CALLBACK(mapman_update_state), &mapman_info);
+ g_signal_connect(G_OBJECT(mapman_info.rad_along_route), "clicked",
+ G_CALLBACK(mapman_update_state), &mapman_info);
+
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+ {
+ const gchar *text;
+ gchar *error_check;
+ gfloat start_lat, start_lon, end_lat, end_lon;
+ guint start_unitx, start_unity, end_unitx, end_unity;
+ guint num_maps = 0;
+ GtkWidget *confirm;
+ gboolean is_deleting, is_overwriting;
+
+ text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
+ start_lat = strtof(text, &error_check);
+ if(text == error_check) {
+ popup_error(dialog, _("Invalid Top-Left Latitude"));
+ continue;
+ }
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lon));
+ start_lon = strtof(text, &error_check);
+ if(text == error_check) {
+ popup_error(dialog, _("Invalid Top-Left Longitude"));
+ continue;
+ }
-#define WRITE_STRING(string) { \
- GnomeVFSResult vfs_result; \
- GnomeVFSFileSize size; \
- if(GNOME_VFS_OK != (vfs_result = gnome_vfs_write( \
- handle, (string), strlen((string)), &size))) \
- { \
- gchar buffer[1024]; \
- sprintf(buffer, "%s:\n%s\n%s", _("Error while writing to file"), \
- _("File is incomplete."), \
- gnome_vfs_result_to_string(vfs_result)); \
- popup_error(_window, buffer); \
- return FALSE; \
- } \
-}
+ text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_botright_lat));
+ end_lat = strtof(text, &error_check);
+ if(text == error_check) {
+ popup_error(dialog, _("Invalid Bottom-Right Latitude"));
+ continue;
+ }
-static gboolean
-write_track_gpx(GnomeVFSHandle *handle)
-{
- TrackPoint *curr;
- gboolean trkseg_break = FALSE;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_botright_lon));
+ end_lon = strtof(text, &error_check);
+ if(text == error_check) {
+ popup_error(dialog,_("Invalid Bottom-Right Longitude"));
+ continue;
+ }
- /* Find first non-zero point. */
- for(curr = _track.head-1; curr++ != _track.tail; )
- if(curr->point.unity)
- break;
+ latlon2unit(start_lat, start_lon, start_unitx, start_unity);
+ latlon2unit(end_lat, end_lon, end_unitx, end_unity);
- /* Write the header. */
- WRITE_STRING(XML_TRKSEG_HEADER);
+ /* Swap if they specified flipped lats or lons. */
+ if(start_unitx > end_unitx)
+ {
+ guint swap = start_unitx;
+ start_unitx = end_unitx;
+ end_unitx = swap;
+ }
+ if(start_unity > end_unity)
+ {
+ guint swap = start_unity;
+ start_unity = end_unity;
+ end_unity = swap;
+ }
- /* Curr points to first non-zero point. */
- for(curr--; curr++ != _track.tail; )
- {
- gfloat lat, lon;
- if(curr->point.unity)
+ /* First, get the number of maps to download. */
+ for(i = 0; i < MAX_ZOOM; i++)
{
- gchar buffer[80];
- gchar strlat[80], strlon[80];
- if(trkseg_break)
+ if(gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[i])))
{
- /* First trkpt of the segment - write trkseg header. */
- WRITE_STRING(" </trkseg>\n"
- /* Write trkseg header. */
- " <trkseg>\n");
- trkseg_break = FALSE;
+ guint start_tilex, start_tiley, end_tilex, end_tiley;
+ start_tilex = unit2ztile(start_unitx, i);
+ start_tiley = unit2ztile(start_unity, i);
+ end_tilex = unit2ztile(end_unitx, i);
+ end_tiley = unit2ztile(end_unity, i);
+ num_maps += (end_tilex - start_tilex + 1)
+ * (end_tiley - start_tiley + 1);
}
- unit2latlon(curr->point.unitx, curr->point.unity, lat, lon);
- g_ascii_formatd(strlat, 80, "%.06f", lat);
- g_ascii_formatd(strlon, 80, "%.06f", lon);
- sprintf(buffer, " <trkpt lat=\"%s\" lon=\"%s\"",
- strlat, strlon);
- WRITE_STRING(buffer);
-
- /* write the time */
- if(curr->time)
+ }
+ text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
+
+ is_deleting = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(mapman_info.rad_delete));
+ is_overwriting = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(mapman_info.chk_overwrite));
+
+ if(is_deleting)
+ {
+ sprintf(buffer, "%s %d %s", _("Confirm DELETION of"),
+ num_maps, _("maps"));
+ }
+ else
+ {
+ sprintf(buffer,
+ "%s %d %s\n(%s %.2f MB)\n", _("Confirm download of"),
+ num_maps, _("maps"), _("up to about"),
+ num_maps * (strstr(_curr_repo->url, "%s") ? 18e-3 : 6e-3));
+ }
+ text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
+ confirm = hildon_note_new_confirmation(GTK_WINDOW(dialog), buffer);
+ text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
+
+ if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
+ {
+ for(i = 0; i < MAX_ZOOM; i++)
{
- WRITE_STRING(">\n <time>");
+ if(gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[i])))
{
- struct tm time;
- localtime_r(&curr->time, &time);
- strftime(buffer, 80, XML_DATE_FORMAT, &time);
- WRITE_STRING(buffer);
- WRITE_STRING(XML_TZONE);
+ guint start_tilex, start_tiley, end_tilex, end_tiley;
+ guint tilex, tiley;
+ start_tilex = unit2ztile(start_unitx, i);
+ start_tiley = unit2ztile(start_unity, i);
+ end_tilex = unit2ztile(end_unitx, i);
+ end_tiley = unit2ztile(end_unity, i);
+ for(tiley = start_tiley; tiley <= end_tiley; tiley++)
+ for(tilex = start_tilex; tilex <= end_tilex; tilex++)
+ map_initiate_download(tilex, tiley, i,
+ is_deleting ? 0 :
+ (is_overwriting
+ ? -INITIAL_DOWNLOAD_RETRIES
+ : INITIAL_DOWNLOAD_RETRIES));
}
- WRITE_STRING("</time>\n"
- " </trkpt>\n");
}
- else
- WRITE_STRING("/>\n");
+ gtk_widget_destroy(confirm);
+ break;
}
- else
- trkseg_break = TRUE;
+ gtk_widget_destroy(confirm);
}
- /* Write the footer. */
- WRITE_STRING(XML_TRKSEG_FOOTER);
+ gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-write_route_gpx(GnomeVFSHandle *handle)
+menu_cb_fullscreen(GtkAction *action)
{
- Point *curr;
- WayPoint *wcurr;
- gboolean trkseg_break = FALSE;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Find first non-zero point. */
- for(curr = _route.head-1, wcurr = _route.whead; curr++ != _route.tail; )
- if(curr->unity)
- break;
- else if(curr == wcurr->point)
- wcurr++;
+ if((_fullscreen = gtk_check_menu_item_get_active(
+ GTK_CHECK_MENU_ITEM(_menu_fullscreen_item))))
+ gtk_window_fullscreen(GTK_WINDOW(_window));
+ else
+ gtk_window_unfullscreen(GTK_WINDOW(_window));
- /* Write the header. */
- WRITE_STRING(XML_TRKSEG_HEADER);
+ gtk_idle_add((GSourceFunc)window_present, NULL);
- /* Curr points to first non-zero point. */
- for(curr--; curr++ != _route.tail; )
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
+
+static gboolean
+menu_cb_enable_gps(GtkAction *action)
+{
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ if((_enable_gps = gtk_check_menu_item_get_active(
+ GTK_CHECK_MENU_ITEM(_menu_enable_gps_item))))
{
- gfloat lat, lon;
- if(curr->unity)
+ if(_rcvr_mac)
{
- gchar buffer[80];
- gchar strlat[80], strlon[80];
- if(trkseg_break)
- {
- /* First trkpt of the segment - write trkseg header. */
- WRITE_STRING(" </trkseg>\n"
- " <trkseg>\n");
- trkseg_break = FALSE;
- }
- unit2latlon(curr->unitx, curr->unity, lat, lon);
- g_ascii_formatd(strlat, 80, "%.06f", lat);
- g_ascii_formatd(strlon, 80, "%.06f", lon);
- sprintf(buffer, " <trkpt lat=\"%s\" lon=\"%s\"",
- strlat, strlon);
- if(curr == wcurr->point)
- sprintf(buffer + strlen(buffer),
- "><desc>%s</desc></trkpt>\n", wcurr++->desc);
- else
- strcat(buffer, "/>\n");
- WRITE_STRING(buffer);
+ set_conn_state(RCVR_DOWN);
+ rcvr_connect_now();
}
else
- trkseg_break = TRUE;
+ {
+ popup_error(_window,
+ _("Cannot enable GPS until a GPS Receiver MAC "
+ "is set in the Settings dialog box."));
+ gtk_check_menu_item_set_active(
+ GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), FALSE);
+ }
}
-
- /* Write the footer. */
- WRITE_STRING(XML_TRKSEG_FOOTER);
+ else
+ {
+ if(_conn_state > RCVR_OFF)
+ set_conn_state(RCVR_OFF);
+ rcvr_disconnect();
+ track_add(0, FALSE);
+ }
+ map_move_mark();
+ gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_reset_item), _enable_gps);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_track_save(GtkAction *action)
+menu_cb_auto_download(GtkAction *action)
{
- GnomeVFSHandle *handle;
printf("%s()\n", __PRETTY_FUNCTION__);
- if(open_file(NULL, &handle, NULL, NULL, &_track_file_uri,
- GTK_FILE_CHOOSER_ACTION_SAVE))
+ if((_auto_download = gtk_check_menu_item_get_active(
+ GTK_CHECK_MENU_ITEM(_menu_auto_download_item))))
{
- if(write_track_gpx(handle))
- hildon_banner_show_information(_window, NULL, _("Track Saved"));
- else
- popup_error(_window, _("Error writing GPX file."));
- gnome_vfs_close(handle);
+ if(!*_curr_repo->url)
+ popup_error(_window,
+ _("NOTE: You must set a Map URI in the Repository Manager in "
+ "order to download maps."));
+ map_force_redraw();
}
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
}
static gboolean
-menu_cb_track_mark_way(GtkAction *action)
+menu_cb_gps_reset(GtkAction *action)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
-
- if(_track.tail->point.unity)
- {
- guint x1, y1;
-
- /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then
- * another instance of the most recent track point. */
- MACRO_TRACK_INCREMENT_TAIL(_track);
- *_track.tail = _track_null;
- MACRO_TRACK_INCREMENT_TAIL(_track);
- *_track.tail = _track.tail[2];
-
- /** Instead of calling map_render_paths(), we'll just add the waypoint
- * ourselves. */
- x1 = unit2bufx(_track.tail->point.unitx);
- y1 = unit2bufy(_track.tail->point.unity);
- /* Make sure this circle will be visible. */
- if((x1 < BUF_WIDTH_PIXELS)
- && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
- gdk_draw_arc(_map_pixmap, _gc_track_break,
- FALSE, /* FALSE: not filled. */
- x1 - _draw_line_width,
- y1 - _draw_line_width,
- 2 * _draw_line_width,
- 2 * _draw_line_width,
- 0, /* start at 0 degrees. */
- 360 * 64);
- }
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ reset_bluetooth();
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_route_save(GtkAction *action)
+menu_cb_gps_details(GtkAction *action)
{
- GnomeVFSHandle *handle;
printf("%s()\n", __PRETTY_FUNCTION__);
- if(!_route.head)
- {
- popup_error(_window, "No route is loaded.");
- return TRUE;
- }
-
- if(open_file(NULL, &handle, NULL, &_route_dir_uri, NULL,
- GTK_FILE_CHOOSER_ACTION_SAVE))
- {
- if(write_route_gpx(handle))
- hildon_banner_show_information(_window, NULL, _("Route Saved"));
- else
- popup_error(_window, _("Error writing GPX file."));
- gnome_vfs_close(handle);
- }
+ gps_details();
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_track_clear(GtkAction *action)
+menu_cb_settings(GtkAction *action)
{
printf("%s()\n", __PRETTY_FUNCTION__);
- _track.tail = _track.head;
+ if(settings_dialog())
+ {
+ /* Settings have changed - reconnect to receiver. */
+ if(_enable_gps)
+ {
+ set_conn_state(RCVR_DOWN);
+ rcvr_disconnect();
+ rcvr_connect_now();
+ }
+ }
+ MACRO_RECALC_FOCUS_BASE();
+ MACRO_RECALC_FOCUS_SIZE();
map_force_redraw();
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
}
static gboolean
-menu_cb_show_tracks(GtkAction *action)
+menu_cb_help(GtkAction *action)
{
printf("%s()\n", __PRETTY_FUNCTION__);
- _show_tracks ^= TRACKS_MASK;
- if(gtk_check_menu_item_get_active(
- GTK_CHECK_MENU_ITEM(_menu_show_tracks_item)))
- {
- _show_tracks |= TRACKS_MASK;
- map_render_paths();
- MACRO_QUEUE_DRAW_AREA();
- hildon_banner_show_information(
- _window, NULL, _("Tracks are now shown"));
- }
- else
- {
- _show_tracks &= ~TRACKS_MASK;
- map_force_redraw();
- hildon_banner_show_information(
- _window, NULL, _("Tracks are now hidden"));
- }
+ ossohelp_show(_osso, HELP_ID_INTRO, OSSO_HELP_SHOW_DIALOG);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_show_routes(GtkAction *action)
+map_download_idle_refresh(ProgressUpdateInfo *pui)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ vprintf("%s(%p)\n", __PRETTY_FUNCTION__, pui);
- if(gtk_check_menu_item_get_active(
- GTK_CHECK_MENU_ITEM(_menu_show_routes_item)))
+ /* Remove pui from hash now in case we need to retry. */
+ g_hash_table_remove(_downloads_hash, pui);
+
+ /* Test if download succeeded (only if retries_left != 0). */
+ if(!pui->retries_left
+ || gnome_vfs_uri_exists((GnomeVFSURI*)pui->dest_list->data))
{
- _show_tracks |= ROUTES_MASK;
- map_render_paths();
- MACRO_QUEUE_DRAW_AREA();
- hildon_banner_show_information(
- _window, NULL, _("Routes are now shown"));
+ gint zoom_diff = pui->zoom - _zoom;
+ /* Only refresh at same or "lower" (more detailed) zoom level. */
+ if(zoom_diff >= 0)
+ {
+ /* If zoom has changed since we first put in the request for this
+ * tile, then we may have to update more than one tile. */
+ guint tilex, tiley, tilex_end, tiley_end;
+ for(tilex = pui->tilex << zoom_diff,
+ tilex_end = tilex + (1 << zoom_diff);
+ tilex < tilex_end; tilex++)
+ {
+ for(tiley = pui->tiley<<zoom_diff,
+ tiley_end = tiley + (1 << zoom_diff);
+ tiley < tiley_end; tiley++)
+ {
+ if((tilex - _base_tilex) < 4 && (tiley - _base_tiley) < 3)
+ {
+ map_render_tile(
+ tilex, tiley,
+ ((tilex - _base_tilex) << TILE_SIZE_P2),
+ ((tiley - _base_tiley) << TILE_SIZE_P2),
+ TRUE);
+ map_render_paths();
+ map_render_poi();
+ gtk_widget_queue_draw_area(
+ _map_widget,
+ ((tilex-_base_tilex)<<TILE_SIZE_P2) - _offsetx,
+ ((tiley-_base_tiley)<<TILE_SIZE_P2) - _offsety,
+ TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
+ }
+ }
+ }
+ }
}
+ /* Else the download failed. Update retries_left and maybe try again. */
else
{
- _show_tracks &= ~ROUTES_MASK;
- map_force_redraw();
- hildon_banner_show_information(
- _window, NULL, "Routes are now hidden");
+ if(pui->retries_left > 0)
+ --pui->retries_left;
+ else if(pui->retries_left < 0)
+ ++pui->retries_left;
+ if(pui->retries_left)
+ map_initiate_download(pui->tilex, pui->tiley,
+ pui->zoom, pui->retries_left);
}
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
+ progress_update_info_free(pui);
+
+ if(++_curr_download == _num_downloads)
+ {
+ gtk_widget_destroy(_download_banner);
+ _download_banner = NULL;
+ _num_downloads = _curr_download = 0;
+ }
+ else
+ hildon_banner_set_fraction(HILDON_BANNER(_download_banner),
+ _curr_download / (double)_num_downloads);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return FALSE;
}
-static gboolean
-menu_cb_show_velvec(GtkAction *action)
+static gint
+map_download_cb_async(GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *info, ProgressUpdateInfo*pui)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ vprintf("%s(%p, %d, %d, %d, %s)\n", __PRETTY_FUNCTION__, pui->handle,
+ info->status, info->vfs_status, info->phase,
+ info->target_name ? info->target_name + 7 : info->target_name);
- _show_velvec = gtk_check_menu_item_get_active(
- GTK_CHECK_MENU_ITEM(_menu_show_velvec_item));
- map_move_mark();
+ if(info->phase == GNOME_VFS_XFER_PHASE_COMPLETED)
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE,
+ (GSourceFunc)map_download_idle_refresh, pui, NULL);
+ else if(info->status != GNOME_VFS_XFER_PROGRESS_STATUS_OK)
+ {
+ if(info->vfs_status == GNOME_VFS_ERROR_NOT_FOUND)
+ {
+ /* Directory doesn't exist yet - create it, then we'll retry */
+ gchar buffer[1024];
+ sprintf(buffer, "%s/%u", _curr_repo->cache_dir, pui->zoom);
+ gnome_vfs_make_directory(buffer, 0775);
+ sprintf(buffer, "%s/%u/%u",
+ _curr_repo->cache_dir, pui->zoom, pui->tilex);
+ gnome_vfs_make_directory(buffer, 0775);
+ }
+ vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return FALSE;
+ }
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
+
static gboolean
-menu_cb_ac_lead(GtkAction *action)
+cmenu_cb_loc_show_latlon(GtkAction *action)
{
- guint new_center_unitx, new_center_unity;
+ gchar buffer[80];
+ guint unitx, unity;
+ gfloat lat, lon;
printf("%s()\n", __PRETTY_FUNCTION__);
- _center_mode = CENTER_LEAD;
- hildon_banner_show_information(_window, NULL, _("Auto-Center Mode: Lead"));
- MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
- map_center_unit(new_center_unitx, new_center_unity);
+ unitx = x2unit(_cmenu_position_x);
+ unity = y2unit(_cmenu_position_y);
+ unit2latlon(unitx, unity, lat, lon);
+
+ sprintf(buffer,
+ "%s: %.06f\n"
+ "%s: %.06f",
+ _("Latitude"), lat,
+ _("Longitude"), lon);
+
+ hildon_banner_show_information(_window, NULL, buffer);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_ac_latlon(GtkAction *action)
+cmenu_cb_loc_clip_latlon(GtkAction *action)
{
- guint new_center_unitx, new_center_unity;
+ gchar buffer[80];
+ guint unitx, unity;
+ gfloat lat, lon;
printf("%s()\n", __PRETTY_FUNCTION__);
- _center_mode = CENTER_LATLON;
- hildon_banner_show_information(_window, NULL,
- _("Auto-Center Mode: Lat/Lon"));
- MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
- map_center_unit(new_center_unitx, new_center_unity);
+ unitx = x2unit(_cmenu_position_x);
+ unity = y2unit(_cmenu_position_y);
+ unit2latlon(unitx, unity, lat, lon);
+
+ sprintf(buffer, "%.06f, %.06f", lat, lon);
+ gtk_clipboard_set_text(
+ gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
+
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_ac_none(GtkAction *action)
+cmenu_cb_loc_route_to(GtkAction *action)
{
+ gchar buffer[80];
+ gchar strlat[32];
+ gchar strlon[32];
+ guint unitx, unity;
+ gfloat lat, lon;
printf("%s()\n", __PRETTY_FUNCTION__);
+
+ unitx = x2unit(_cmenu_position_x);
+ unity = y2unit(_cmenu_position_y);
+ unit2latlon(unitx, unity, lat, lon);
- _center_mode = -_center_mode;
- hildon_banner_show_information(_window, NULL, _("Auto-Center Off"));
+ g_ascii_formatd(strlat, 32, "%.06f", lat);
+ g_ascii_formatd(strlon, 32, "%.06f", lon);
+ sprintf(buffer, "%s, %s", strlat, strlon);
+
+ route_download(NULL, buffer, TRUE);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_maps_dlroute(GtkAction *action)
+cmenu_cb_loc_distance_to(GtkAction *action)
{
- guint last_tilex, last_tiley;
- Point *curr;
+ gchar buffer[80];
+ guint unitx, unity;
+ gfloat lat, lon;
printf("%s()\n", __PRETTY_FUNCTION__);
+
+ unitx = x2unit(_cmenu_position_x);
+ unity = y2unit(_cmenu_position_y);
+ unit2latlon(unitx, unity, lat, lon);
- if(!_route.head)
- {
- popup_error(_window, "No route is loaded.");
- return TRUE;
- }
-
- last_tilex = 0;
- last_tiley = 0;
- for(curr = _route.head - 1; ++curr != _route.tail; )
- {
- if(curr->unity)
- {
- guint tilex = unit2tile(curr->unitx);
- guint tiley = unit2tile(curr->unity);
- if(tilex != last_tilex || tiley != last_tiley)
- {
- guint minx, miny, maxx, maxy, x, y;
- if(last_tiley != 0)
- {
- minx = MIN(tilex, last_tilex) - 2;
- miny = MIN(tiley, last_tiley) - 2;
- maxx = MAX(tilex, last_tilex) + 2;
- maxy = MAX(tiley, last_tiley) + 2;
- }
- else
- {
- minx = tilex - 2;
- miny = tiley - 2;
- maxx = tilex + 2;
- maxy = tiley + 2;
- }
- for(x = minx; x <= maxx; x++)
- for(y = miny; y <= maxy; y++)
- map_initiate_download(x, y, _zoom,
- INITIAL_DOWNLOAD_RETRIES);
- last_tilex = tilex;
- last_tiley = tiley;
- }
- }
- }
+ sprintf(buffer, "%s: %.02f %s", _("Distance to Location"),
+ calculate_distance(_pos_lat, _pos_lon, lat, lon),
+ UNITS_TEXT[_units]);
+ hildon_banner_show_information(_window, NULL, buffer);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
-typedef struct _DlAreaInfo DlAreaInfo;
-struct _DlAreaInfo {
- GtkWidget *notebook;
- GtkWidget *txt_topleft_lat;
- GtkWidget *txt_topleft_lon;
- GtkWidget *txt_botright_lat;
- GtkWidget *txt_botright_lon;
- GtkWidget *chk_zoom_levels[MAX_ZOOM];
-};
-
-static void dlarea_clear(GtkWidget *widget, DlAreaInfo *dlarea_info)
+static WayPoint *
+find_nearest_visible_waypoint(guint unitx, guint unity)
{
- guint i;
- printf("%s()\n", __PRETTY_FUNCTION__);
- if(gtk_notebook_get_current_page(GTK_NOTEBOOK(dlarea_info->notebook)))
- /* This is the second page (the "Zoom" page) - clear the checks. */
- for(i = 0; i < MAX_ZOOM; i++)
- gtk_toggle_button_set_active(
- GTK_TOGGLE_BUTTON(dlarea_info->chk_zoom_levels[i]), FALSE);
- else
+ WayPoint *wcurr;
+ WayPoint *wnear;
+ guint nearest_squared;
+ Point pos = { unitx, unity };
+
+ wcurr = wnear = _visible_way_first;
+ if(wcurr && wcurr != _visible_way_last)
{
- /* This is the first page (the "Area" page) - clear the text fields. */
- gtk_entry_set_text(GTK_ENTRY(dlarea_info->txt_topleft_lat), "");
- gtk_entry_set_text(GTK_ENTRY(dlarea_info->txt_topleft_lon), "");
- gtk_entry_set_text(GTK_ENTRY(dlarea_info->txt_botright_lat), "");
- gtk_entry_set_text(GTK_ENTRY(dlarea_info->txt_botright_lon), "");
+ nearest_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
+
+ while(wcurr++ != _visible_way_last)
+ {
+ guint test_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
+ if(test_squared < nearest_squared)
+ {
+ wnear = wcurr;
+ nearest_squared = test_squared;
+ }
+ }
}
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return wnear;
}
static gboolean
-menu_cb_maps_dlarea(GtkAction *action)
+cmenu_cb_way_show_latlon(GtkAction *action)
{
- GtkWidget *dialog;
- GtkWidget *table;
- GtkWidget *label;
- GtkWidget *button;
- GtkWidget *lbl_gps_lat;
- GtkWidget *lbl_gps_lon;
- GtkWidget *lbl_center_lat;
- GtkWidget *lbl_center_lon;
- DlAreaInfo dlarea_info;
gchar buffer[80];
gfloat lat, lon;
- guint i;
+ WayPoint *way;
printf("%s()\n", __PRETTY_FUNCTION__);
- dialog = gtk_dialog_new_with_buttons(_("Download Maps by Area"),
- GTK_WINDOW(_window), GTK_DIALOG_MODAL,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- NULL);
+ way = find_nearest_visible_waypoint(
+ x2unit(_cmenu_position_x),
+ y2unit(_cmenu_position_y));
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
- button = gtk_button_new_with_label(_("Clear")));
- g_signal_connect(G_OBJECT(button), "clicked",
- G_CALLBACK(dlarea_clear), &dlarea_info);
+ if(way)
+ {
+ unit2latlon(way->point->unitx, way->point->unity, lat, lon);
- gtk_dialog_add_button(GTK_DIALOG(dialog),
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+ sprintf(buffer,
+ "%s: %.06f\n"
+ "%s: %.06f",
+ _("Latitude"), lat,
+ _("Longitude"), lon);
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
- dlarea_info.notebook = gtk_notebook_new(), TRUE, TRUE, 0);
-
- gtk_notebook_append_page(GTK_NOTEBOOK(dlarea_info.notebook),
- table = gtk_table_new(2, 3, FALSE),
- label = gtk_label_new(_("Area")));
+ hildon_banner_show_information(_window, NULL, buffer);
+ }
+ else
+ hildon_banner_show_information(_window, NULL,
+ _("No waypoints are visible."));
- /* Clear button and Label Columns. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Latitude")),
- 1, 2, 0, 1, GTK_FILL, 0, 4, 0);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Longitude")),
- 2, 3, 0, 1, GTK_FILL, 0, 4, 0);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* GPS. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("GPS Location")),
- 0, 1, 1, 2, GTK_FILL, 0, 4, 0);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- lbl_gps_lat = gtk_label_new(""),
- 1, 2, 1, 2, GTK_FILL, 0, 4, 0);
- gtk_label_set_selectable(GTK_LABEL(lbl_gps_lat), TRUE);
- gtk_misc_set_alignment(GTK_MISC(lbl_gps_lat), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- lbl_gps_lon = gtk_label_new(""),
- 2, 3, 1, 2, GTK_FILL, 0, 4, 0);
- gtk_label_set_selectable(GTK_LABEL(lbl_gps_lon), TRUE);
- gtk_misc_set_alignment(GTK_MISC(lbl_gps_lon), 1.f, 0.5f);
+static gboolean
+cmenu_cb_way_show_desc(GtkAction *action)
+{
+ WayPoint *way;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* Center. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("View Center")),
- 0, 1, 2, 3, GTK_FILL, 0, 4, 0);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- lbl_center_lat = gtk_label_new(""),
- 1, 2, 2, 3, GTK_FILL, 0, 4, 0);
- gtk_label_set_selectable(GTK_LABEL(lbl_center_lat), TRUE);
- gtk_misc_set_alignment(GTK_MISC(lbl_center_lat), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- lbl_center_lon = gtk_label_new(""),
- 2, 3, 2, 3, GTK_FILL, 0, 4, 0);
- gtk_label_set_selectable(GTK_LABEL(lbl_center_lon), TRUE);
- gtk_misc_set_alignment(GTK_MISC(lbl_center_lon), 1.f, 0.5f);
+ way = find_nearest_visible_waypoint(
+ x2unit(_cmenu_position_x),
+ y2unit(_cmenu_position_y));
- /* default values for Top Left and Bottom Right are defined by the
- * rectangle of the current and the previous Center */
+ if(way)
+ hildon_banner_show_information(_window, NULL, way->desc);
+ else
+ hildon_banner_show_information(_window, NULL,
+ _("No waypoints are visible."));
- /* Top Left. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Top-Left")),
- 0, 1, 3, 4, GTK_FILL, 0, 4, 0);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- dlarea_info.txt_topleft_lat = gtk_entry_new(),
- 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 4, 0);
- gtk_entry_set_alignment(GTK_ENTRY(dlarea_info.txt_topleft_lat), 1.f);
- gtk_table_attach(GTK_TABLE(table),
- dlarea_info.txt_topleft_lon = gtk_entry_new(),
- 2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 4, 0);
- gtk_entry_set_alignment(GTK_ENTRY(dlarea_info.txt_topleft_lon), 1.f);
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Bottom Right. */
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(_("Bottom-Right")),
- 0, 1, 4, 5, GTK_FILL, 0, 4, 0);
- gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- gtk_table_attach(GTK_TABLE(table),
- dlarea_info.txt_botright_lat = gtk_entry_new(),
- 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 4, 0);
- gtk_entry_set_alignment(GTK_ENTRY(dlarea_info.txt_botright_lat), 1.f);
- gtk_table_attach(GTK_TABLE(table),
- dlarea_info.txt_botright_lon = gtk_entry_new(),
- 2, 3, 4, 5, GTK_EXPAND | GTK_FILL, 0, 4, 0);
- gtk_entry_set_alignment(GTK_ENTRY(dlarea_info.txt_botright_lon), 1.f);
+static gboolean
+cmenu_cb_way_clip_latlon(GtkAction *action)
+{
+ gchar buffer[80];
+ gfloat lat, lon;
+ WayPoint *way;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+ way = find_nearest_visible_waypoint(
+ x2unit(_cmenu_position_x),
+ y2unit(_cmenu_position_y));
- gtk_notebook_append_page(GTK_NOTEBOOK(dlarea_info.notebook),
- table = gtk_table_new(5, 5, FALSE),
- label = gtk_label_new(_("Zoom")));
- gtk_table_attach(GTK_TABLE(table),
- label = gtk_label_new(
- _("Zoom Levels to Download: (0 -> most detail)")),
- 0, 5, 0, 1, GTK_FILL, 0, 4, 0);
- gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
- for(i = 0; i < MAX_ZOOM; i++)
+ if(way)
{
- sprintf(buffer, "%d", i);
- gtk_table_attach(GTK_TABLE(table),
- dlarea_info.chk_zoom_levels[i]
- = gtk_check_button_new_with_label(buffer),
- i % 5, i % 5 + 1, i / 5 + 1, i / 5 + 2,
- GTK_EXPAND | GTK_FILL, 0, 4, 0);
- }
-
- /* Initialize fields. Do no use g_ascii_formatd; these strings will be
- * output (and parsed) as locale-dependent. */
- sprintf(buffer, "%.06f", _pos_lat);
- gtk_label_set_text(GTK_LABEL(lbl_gps_lat), buffer);
- sprintf(buffer, "%.06f", _pos_lon);
- gtk_label_set_text(GTK_LABEL(lbl_gps_lon), buffer);
-
- unit2latlon(_center.unitx, _center.unity, lat, lon);
- sprintf(buffer, "%.06f", lat);
- gtk_label_set_text(GTK_LABEL(lbl_center_lat), buffer);
- sprintf(buffer, "%.06f", lon);
- gtk_label_set_text(GTK_LABEL(lbl_center_lon), buffer);
-
- /* Initialize to the bounds of the screen. */
- unit2latlon(x2unit(0), y2unit(0), lat, lon);
- sprintf(buffer, "%.06f", lat);
- gtk_entry_set_text(GTK_ENTRY(dlarea_info.txt_topleft_lat), buffer);
- sprintf(buffer, "%.06f", lon);
- gtk_entry_set_text(GTK_ENTRY(dlarea_info.txt_topleft_lon), buffer);
-
- unit2latlon(x2unit(_screen_width_pixels), y2unit(_screen_height_pixels),
- lat, lon);
- sprintf(buffer, "%.06f", lat);
- gtk_entry_set_text(GTK_ENTRY(dlarea_info.txt_botright_lat), buffer);
- sprintf(buffer, "%.06f", lon);
- gtk_entry_set_text(GTK_ENTRY(dlarea_info.txt_botright_lon), buffer);
-
- for(i = 0; i < MAX_ZOOM; i++)
- gtk_toggle_button_set_active(
- GTK_TOGGLE_BUTTON(dlarea_info.chk_zoom_levels[i]), FALSE);
- gtk_toggle_button_set_active(
- GTK_TOGGLE_BUTTON(dlarea_info.chk_zoom_levels[_zoom]), TRUE);
-
+ unit2latlon(way->point->unitx, way->point->unity, lat, lon);
- gtk_widget_show_all(dialog);
+ sprintf(buffer, "%.06f, %.06f", lat, lon);
- while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
- {
- const gchar *text;
- gchar *error_check;
- gfloat start_lat, start_lon, end_lat, end_lon;
- guint start_unitx, start_unity, end_unitx, end_unity;
- guint num_maps = 0;
- GtkWidget *confirm;
+ gtk_clipboard_set_text(
+ gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
+ }
+ else
+ hildon_banner_show_information(_window, NULL,
+ _("No waypoints are visible."));
- text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lat));
- start_lat = strtof(text, &error_check);
- if(text == error_check) {
- popup_error(dialog, _("Invalid Top-Left Latitude"));
- continue;
- }
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lon));
- start_lon = strtof(text, &error_check);
- if(text == error_check) {
- popup_error(dialog, _("Invalid Top-Left Longitude"));
- continue;
- }
+static gboolean
+cmenu_cb_way_clip_desc(GtkAction *action)
+{
+ WayPoint *way;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_botright_lat));
- end_lat = strtof(text, &error_check);
- if(text == error_check) {
- popup_error(dialog, _("Invalid Bottom-Right Latitude"));
- continue;
- }
+ way = find_nearest_visible_waypoint(
+ x2unit(_cmenu_position_x),
+ y2unit(_cmenu_position_y));
- text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_botright_lon));
- end_lon = strtof(text, &error_check);
- if(text == error_check) {
- popup_error(dialog,_("Invalid Bottom-Right Longitude"));
- continue;
- }
+ if(way)
+ gtk_clipboard_set_text(
+ gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), way->desc, -1);
+ else
+ hildon_banner_show_information(_window, NULL,
+ _("No waypoints are visible."));
- latlon2unit(start_lat, start_lon, start_unitx, start_unity);
- latlon2unit(end_lat, end_lon, end_unitx, end_unity);
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return TRUE;
+}
- /* Swap if they specified flipped lats or lons. */
- if(start_unitx > end_unitx)
- {
- guint swap = start_unitx;
- start_unitx = end_unitx;
- end_unitx = swap;
- }
- if(start_unity > end_unity)
- {
- guint swap = start_unity;
- start_unity = end_unity;
- end_unity = swap;
- }
+static gboolean
+cmenu_cb_way_route_to(GtkAction *action)
+{
+ WayPoint *way;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- /* First, get the number of maps to download. */
- for(i = 0; i < MAX_ZOOM; i++)
- {
- if(gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(dlarea_info.chk_zoom_levels[i])))
- {
- guint start_tilex, start_tiley, end_tilex, end_tiley;
- start_tilex = unit2ztile(start_unitx, i);
- start_tiley = unit2ztile(start_unity, i);
- end_tilex = unit2ztile(end_unitx, i);
- end_tiley = unit2ztile(end_unity, i);
- num_maps += (end_tilex - start_tilex + 1)
- * (end_tiley - start_tiley + 1);
- }
- }
- text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lat));
+ way = find_nearest_visible_waypoint(
+ x2unit(_cmenu_position_x),
+ y2unit(_cmenu_position_y));
- sprintf(buffer,
- "%s %d %s\n(%s %.2f MB)\n", _("Confirm download of"),
- num_maps, _("maps"), _("up to about"),
- num_maps * (strstr(_map_uri_format, "%s") ? 18e-3 : 6e-3));
- text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lat));
- confirm = hildon_note_new_confirmation(GTK_WINDOW(dialog), buffer);
- text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lat));
+ if(way)
+ {
+ gchar buffer[80];
+ gchar strlat[32];
+ gchar strlon[32];
+ gfloat lat, lon;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
- {
- for(i = 0; i < MAX_ZOOM; i++)
- {
- if(gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(dlarea_info.chk_zoom_levels[i])))
- {
- guint start_tilex, start_tiley, end_tilex, end_tiley;
- guint tilex, tiley;
- start_tilex = unit2ztile(start_unitx, i);
- start_tiley = unit2ztile(start_unity, i);
- end_tilex = unit2ztile(end_unitx, i);
- end_tiley = unit2ztile(end_unity, i);
- for(tiley = start_tiley; tiley <= end_tiley; tiley++)
- for(tilex = start_tilex; tilex <= end_tilex; tilex++)
- map_initiate_download(tilex, tiley, i,
- INITIAL_DOWNLOAD_RETRIES);
- }
- }
- gtk_widget_destroy(confirm);
- break;
- }
- gtk_widget_destroy(confirm);
+ unit2latlon(way->point->unitx, way->point->unity, lat, lon);
+ g_ascii_formatd(strlat, 32, "%.06f", lat);
+ g_ascii_formatd(strlon, 32, "%.06f", lon);
+ sprintf(buffer, "%s, %s", strlat, strlon);
+
+ route_download(NULL, buffer, TRUE);
}
-
- gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
+ else
+ hildon_banner_show_information(_window, NULL,
+ _("No waypoints are visible."));
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_fullscreen(GtkAction *action)
+cmenu_cb_way_distance_to(GtkAction *action)
{
+ WayPoint *way;
printf("%s()\n", __PRETTY_FUNCTION__);
- if((_fullscreen = gtk_check_menu_item_get_active(
- GTK_CHECK_MENU_ITEM(_menu_fullscreen_item))))
- gtk_window_fullscreen(GTK_WINDOW(_window));
- else
- gtk_window_unfullscreen(GTK_WINDOW(_window));
+ way = find_nearest_visible_waypoint(
+ x2unit(_cmenu_position_x),
+ y2unit(_cmenu_position_y));
- gtk_idle_add((GSourceFunc)window_present, NULL);
+ if(way)
+ {
+ gchar buffer[80];
+ gfloat lat, lon;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ unit2latlon(way->point->unitx, way->point->unity, lat, lon);
+
+ sprintf(buffer, "%s: %.02f %s", _("Distance to Waypoint"),
+ calculate_distance(_pos_lat, _pos_lon, lat, lon),
+ UNITS_TEXT[_units]);
+ hildon_banner_show_information(_window, NULL, buffer);
+ }
+ else
+ hildon_banner_show_information(_window, NULL,
+ _("No waypoints are visible."));
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_enable_gps(GtkAction *action)
+cmenu_cb_way_delete(GtkAction *action)
{
+ WayPoint *way;
printf("%s()\n", __PRETTY_FUNCTION__);
- if((_enable_gps = gtk_check_menu_item_get_active(
- GTK_CHECK_MENU_ITEM(_menu_enable_gps_item))))
+ way = find_nearest_visible_waypoint(
+ x2unit(_cmenu_position_x),
+ y2unit(_cmenu_position_y));
+
+ if(way)
{
- if(_rcvr_mac)
- {
- set_conn_state(RCVR_DOWN);
- rcvr_connect_now();
- }
- else
+ gchar buffer[1024];
+ GtkWidget *confirm;
+
+ sprintf(buffer, "%s:\n%s\n",
+ _("Confirm delete of waypoint"), way->desc);
+ confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
+
+ if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
{
- popup_error(_window,
- _("Cannot enable GPS until a GPS Receiver MAC "
- "is set in the Settings dialog box."));
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), FALSE);
+ while(way++ != _route.wtail)
+ way[-1] = *way;
+ _route.wtail--;
+ map_force_redraw();
}
+ gtk_widget_destroy(confirm);
}
else
- {
- if(_conn_state > RCVR_OFF)
- set_conn_state(RCVR_OFF);
- rcvr_disconnect();
- track_add(0, FALSE);
- }
- map_move_mark();
+ hildon_banner_show_information(_window, NULL,
+ _("No waypoints are visible."));
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_auto_download(GtkAction *action)
+category_delete(GtkWidget *widget, DeletePOI *dpoi)
{
- printf("%s()\n", __PRETTY_FUNCTION__);
+ GtkWidget *dialog;
+ guint i;
+ gchar *buffer;
- if((_auto_download = gtk_check_menu_item_get_active(
- GTK_CHECK_MENU_ITEM(_menu_auto_download_item))))
+ buffer = g_strdup_printf(_("Delete category?\n%s"), dpoi->txt_label);
+ dialog = hildon_note_new_confirmation (GTK_WINDOW(_window), buffer);
+ g_free(buffer);
+ i = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ if(i == GTK_RESPONSE_OK)
+ {
+ /* delete dpoi->poi_id */
+ buffer = g_strdup_printf("delete from poi where cat_id = %d",
+ dpoi->id);
+
+ if(sqlite_exec(_db, buffer, NULL, NULL, NULL)
+ != SQLITE_OK)
+ {
+ hildon_banner_show_information(_window, NULL,
+ _("Problem deleting POI"));
+ g_free(buffer);
+ return FALSE;
+ }
+
+ g_free(buffer);
+ buffer = g_strdup_printf("delete from category where cat_id = %d",
+ dpoi->id);
+
+ if(sqlite_exec(_db, buffer, NULL, NULL, NULL)
+ != SQLITE_OK)
+ {
+ hildon_banner_show_information(_window, NULL,
+ _("Problem deleting category"));
+ g_free(buffer);
+ return FALSE;
+ }
+
+ gtk_widget_hide_all(dpoi->dialog);
map_force_redraw();
+ g_free(buffer);
+ }
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-menu_cb_settings(GtkAction *action)
+category_dialog(guint cat_id)
{
+ gchar **pszResult;
+ gint nRow, nColumn;
+ gchar *sql;
+ gchar *cat_label = NULL, *cat_desc = NULL;
+ guint cat_enabled;
+ GtkWidget *dialog;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *txt_label;
+ GtkWidget *txt_desc;
+ GtkWidget *btn_delete = NULL;
+ GtkWidget *txt_scroll;
+ GtkWidget *chk_enabled;
+ GtkTextBuffer *desc_txt;
+ GtkTextIter begin, end;
+ gboolean results = TRUE;
+ DeletePOI dpoi = {NULL, NULL, 0};
printf("%s()\n", __PRETTY_FUNCTION__);
- if(settings_dialog())
+ if(cat_id > 0)
{
- /* Settings have changed - reconnect to receiver. */
- if(_enable_gps)
+ sql = g_strdup_printf(
+ "select c.label, c. desc, c.enabled"
+ " from category c"
+ " where c.cat_id = %d",
+ cat_id);
+
+ if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+ != SQLITE_OK)
{
- set_conn_state(RCVR_DOWN);
- rcvr_disconnect();
- rcvr_connect_now();
+ g_free(sql);
+ printf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return FALSE;
}
+ g_free(sql);
+
+ if(nRow == 0)
+ return FALSE;
+
+ cat_label = g_strdup(pszResult[1 * nColumn + 0]);
+ cat_desc = g_strdup(pszResult[1 * nColumn + 1]);
+ cat_enabled = atoi(pszResult[1 * nColumn + 2]);
+ sqlite_free_table(pszResult);
+
+ dialog = gtk_dialog_new_with_buttons(_("Edit Category"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+ btn_delete = gtk_button_new_with_label(_("Delete")));
+
+ dpoi.dialog = dialog;
+ dpoi.txt_label = g_strdup_printf("%s (%s)", cat_label, cat_desc);
+ dpoi.id = cat_id;
+
+ g_signal_connect(G_OBJECT(btn_delete), "clicked",
+ G_CALLBACK(category_delete), &dpoi);
+
+ gtk_dialog_add_button(GTK_DIALOG(dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
}
- MACRO_RECALC_FOCUS_BASE();
- MACRO_RECALC_FOCUS_SIZE();
- map_force_redraw();
+ else
+ {
+ cat_enabled = 1;
+ cat_label = g_strdup("");
+ cat_id = 0;
+ cat_desc = g_strdup("");
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
+ dialog = gtk_dialog_new_with_buttons(_("Add Category"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL);
+ }
+
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Label: ")),
+ 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ txt_label = gtk_entry_new(),
+ 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Desc.: ")),
+ 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+
+ txt_scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll),
+ GTK_SHADOW_IN);
+ gtk_table_attach(GTK_TABLE(table),
+ txt_scroll,
+ 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ txt_desc = gtk_text_view_new ();
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
+
+ gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
+ gtk_widget_show(txt_scroll);
+ gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60);
+
+ desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
+
+ gtk_table_attach(GTK_TABLE(table),
+ chk_enabled = gtk_check_button_new_with_label(
+ _("Enabled")),
+ 0, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+
+ /* label */
+ gtk_entry_set_text(GTK_ENTRY(txt_label), cat_label);
+
+ /* desc */
+ gtk_text_buffer_set_text(desc_txt, cat_desc, -1);
+
+ /* enabled */
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enabled),
+ (cat_enabled == 1 ? TRUE : FALSE));
+
+ g_free(cat_label);
+ cat_label = NULL;
+ g_free(cat_desc);
+ cat_desc = NULL;
+
+ gtk_widget_show_all(dialog);
+
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+ {
+ if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_label))))
+ cat_label = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_label)));
+ else
+ {
+ popup_error(dialog, _("Please specify a name for the category."));
+ continue;
+ }
+
+ gtk_text_buffer_get_iter_at_offset(desc_txt, &begin,0 );
+ gtk_text_buffer_get_end_iter (desc_txt, &end);
+ cat_desc = gtk_text_buffer_get_text(desc_txt, &begin, &end, TRUE);
+
+ cat_enabled = (gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(chk_enabled)) ? 1 : 0);
+
+ if(cat_id > 0)
+ {
+ /* edit category */
+ sql = g_strdup_printf(
+ "update category set label = '%s', desc = '%s', "
+ "enabled = %d where poi_id = %d",
+ cat_label, cat_desc, cat_enabled, cat_id);
+ if(sqlite_exec(_db, sql, NULL, NULL, NULL) != SQLITE_OK)
+ {
+ hildon_banner_show_information(_window, NULL,
+ _("Problem updating category"));
+ results = FALSE;
+ }
+ }
+ else
+ {
+ /* add category */
+ sql = g_strdup_printf(
+ "insert into category (label, desc, enabled) "
+ "values ('%s', '%s', %d)",
+ cat_label, cat_desc, cat_enabled);
+ if(sqlite_exec(_db, sql, NULL, NULL, NULL) != SQLITE_OK)
+ {
+ hildon_banner_show_information(_window, NULL,
+ _("Problem adding category"));
+ results = FALSE;
+ }
+ }
+ g_free(sql);
+ break;
+ }
+
+ if(cat_label)
+ g_free(cat_label);
+ if(cat_desc)
+ g_free(cat_desc);
+ g_object_unref (desc_txt);
+
+ gtk_widget_hide_all(dialog);
+
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return results;
}
-static gboolean
-menu_cb_help(GtkAction *action)
+static void
+category_toggled (GtkCellRendererToggle *cell,
+ gchar *path,
+ gpointer data)
{
+ GtkTreeIter iter;
+ gboolean cat_enabled;
+ guint cat_id;
+ gchar buffer[100];
printf("%s()\n", __PRETTY_FUNCTION__);
- ossohelp_show(_osso, HELP_ID_INTRO, OSSO_HELP_SHOW_DIALOG);
+ GtkTreeModel *model = GTK_TREE_MODEL(data);
+ if( !gtk_tree_model_get_iter_from_string(model, &iter, path) )
+ return;
+
+ gtk_tree_model_get(model, &iter, CAT_ENABLED, &cat_enabled, -1);
+ gtk_tree_model_get(model, &iter, CAT_ID, &cat_id, -1);
+
+ cat_enabled ^= 1;
+
+ sprintf(buffer, "update category set enabled = %d where cat_id = %d",
+ (cat_enabled ? 1 : 0), cat_id);
+
+ if(sqlite_exec(_db, buffer, NULL, NULL, NULL) != SQLITE_OK)
+ hildon_banner_show_information(_window, NULL,
+ _("Problem updating Category"));
+ else
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+ CAT_ENABLED, cat_enabled, -1);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
}
-static gboolean
-map_download_idle_refresh(ProgressUpdateInfo *pui)
+static GtkListStore*
+generate_store()
{
- vprintf("%s(%p)\n", __PRETTY_FUNCTION__, pui);
-
- /* Remove pui from hash now in case we need to retry. */
- g_hash_table_remove(_downloads_hash, pui);
-
- /* Test if download succeeded. */
- if(gnome_vfs_uri_exists((GnomeVFSURI*)pui->dest_list->data))
+ guint i;
+ GtkTreeIter iter;
+ GtkListStore *store;
+ gchar *sql;
+ gchar **pszResult;
+ gint nRow, nColumn;
+ sql = g_strdup(
+ "select c.cat_id, c.enabled, c.label, c.desc"
+ " from category c "
+ " order by c.label");
+
+ if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+ != SQLITE_OK)
{
- gint zoom_diff = pui->zoom - _zoom;
- /* Only refresh at same or "lower" (more detailed) zoom level. */
- if(zoom_diff >= 0)
- {
- /* If zoom has changed since we first put in the request for this
- * tile, then we may have to update more than one tile. */
- guint tilex, tiley, tilex_end, tiley_end;
- for(tilex = pui->tilex << zoom_diff,
- tilex_end = tilex + (1 << zoom_diff);
- tilex < tilex_end; tilex++)
- {
- for(tiley = pui->tiley<<zoom_diff,
- tiley_end = tiley + (1 << zoom_diff);
- tiley < tiley_end; tiley++)
- {
- if((tilex - _base_tilex) < 4 && (tiley - _base_tiley) < 3)
- {
- map_render_tile(
- tilex, tiley,
- ((tilex - _base_tilex) << TILE_SIZE_P2),
- ((tiley - _base_tiley) << TILE_SIZE_P2),
- TRUE);
- map_render_paths();
- gtk_widget_queue_draw_area(
- _map_widget,
- ((tilex-_base_tilex)<<TILE_SIZE_P2) - _offsetx,
- ((tiley-_base_tiley)<<TILE_SIZE_P2) - _offsety,
- TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
- }
- }
- }
- }
+ g_free(sql);
+ printf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return NULL;
}
- /* Else the download failed. Update retries_left and maybe try again. */
- else if(pui->retries_left--)
- map_initiate_download(pui->tilex, pui->tiley,
- pui->zoom, pui->retries_left);
+ g_free(sql);
- progress_update_info_free(pui);
+ store = gtk_list_store_new(CAT_NUM_COLUMNS,
+ G_TYPE_UINT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
- if(++_curr_download == _num_downloads)
+ for(i = 1; i < nRow + 1; i++)
{
- gtk_widget_destroy(_download_banner);
- _download_banner = NULL;
- _num_downloads = _curr_download = 0;
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ CAT_ID, atoi(pszResult[i * nColumn + 0]),
+ CAT_ENABLED,
+ (atoi(pszResult[i * nColumn + 1]) == 1 ? TRUE : FALSE),
+ CAT_LABEL, pszResult[i * nColumn + 2],
+ CAT_DESCRIPTION, pszResult[i * nColumn + 3],
+ -1);
}
- else
- hildon_banner_set_fraction(HILDON_BANNER(_download_banner),
- _curr_download / (double)_num_downloads);
- vprintf("%s(): return\n", __PRETTY_FUNCTION__);
- return FALSE;
+ sqlite_free_table(pszResult);
+ vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, store);
+ return store;
}
-static gint
-map_download_cb_async(GnomeVFSAsyncHandle *handle,
- GnomeVFSXferProgressInfo *info, ProgressUpdateInfo*pui)
+static gboolean
+category_add(GtkWidget *widget, GtkWidget *tree_view)
{
- vprintf("%s(%p, %d, %d, %d, %s)\n", __PRETTY_FUNCTION__, pui->handle,
- info->status, info->vfs_status, info->phase,
- info->target_name ? info->target_name + 7 : info->target_name);
+ GtkListStore *store;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- if(info->phase == GNOME_VFS_XFER_PHASE_COMPLETED)
- g_idle_add_full(G_PRIORITY_HIGH_IDLE,
- (GSourceFunc)map_download_idle_refresh, pui, NULL);
- else if(info->status != GNOME_VFS_XFER_PROGRESS_STATUS_OK)
+ if(category_dialog(0))
{
- if(info->vfs_status == GNOME_VFS_ERROR_NOT_FOUND)
- {
- /* Directory doesn't exist yet - create it, then we'll retry */
- gchar buffer[1024];
- sprintf(buffer, "%s/%u", _map_dir_name, pui->zoom);
- gnome_vfs_make_directory(buffer, 0775);
- sprintf(buffer, "%s/%u/%u", _map_dir_name, pui->zoom, pui->tilex);
- gnome_vfs_make_directory(buffer, 0775);
- }
- vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
- return FALSE;
+ store = generate_store();
+ gtk_tree_view_set_model(
+ GTK_TREE_VIEW(tree_view),
+ GTK_TREE_MODEL(store));
+ g_object_unref(G_OBJECT(store));
}
-
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
-
static gboolean
-cmenu_cb_loc_show_latlon(GtkAction *action)
+category_edit(GtkWidget *widget, GtkWidget *tree_view)
{
- gchar buffer[80];
- guint unitx, unity;
- gfloat lat, lon;
+ GtkTreeIter iter;
+ GtkTreeModel *store;
+ GtkTreeSelection *selection;
printf("%s()\n", __PRETTY_FUNCTION__);
- unitx = x2unit(_cmenu_position_x);
- unity = y2unit(_cmenu_position_y);
- unit2latlon(unitx, unity, lat, lon);
-
- sprintf(buffer,
- "%s: %.06f\n"
- "%s: %.06f",
- _("Latitude"), lat,
- _("Longitude"), lon);
-
- hildon_banner_show_information(_window, NULL, buffer);
-
+ store = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view));
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
+ if(gtk_tree_selection_get_selected(selection, &store, &iter))
+ {
+ GValue val;
+ memset(&val, 0, sizeof(val));
+ gtk_tree_model_get_value(store, &iter, 0, &val);
+ if(category_dialog(g_value_get_uint(&val)))
+ {
+ GtkListStore *new_store = generate_store();
+ gtk_tree_view_set_model(
+ GTK_TREE_VIEW(tree_view),
+ GTK_TREE_MODEL(new_store));
+ g_object_unref(G_OBJECT(new_store));
+ }
+ }
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-cmenu_cb_loc_clip_latlon(GtkAction *action)
+category_list()
{
- gchar buffer[80];
- guint unitx, unity;
- gfloat lat, lon;
+ GtkWidget *dialog;
+ GtkWidget *tree_view;
+ GtkWidget *sw;
+ GtkWidget *btn_edit;
+ GtkWidget *btn_add;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkListStore *store;
printf("%s()\n", __PRETTY_FUNCTION__);
- unitx = x2unit(_cmenu_position_x);
- unity = y2unit(_cmenu_position_y);
- unit2latlon(unitx, unity, lat, lon);
+ dialog = gtk_dialog_new_with_buttons(_("Category List"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
- sprintf(buffer, "%.06f, %.06f", lat, lon);
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+ btn_edit = gtk_button_new_with_label(_("Edit")));
+
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+ btn_add = gtk_button_new_with_label(_("Add")));
+
+ store = generate_store();
+
+ if(!store)
+ return TRUE;
+
+ sw = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ sw, TRUE, TRUE, 0);
+
+ tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+ /* Maemo-related? */
+ g_object_set(tree_view, "allow-checkbox-mode", FALSE, NULL);
+ gtk_container_add (GTK_CONTAINER (sw), tree_view);
+
+ gtk_tree_selection_set_mode(
+ gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
+ GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), TRUE);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("ID"), renderer, "text", CAT_ID);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+ gtk_tree_view_column_set_max_width (column, 1);
+
+ renderer = gtk_cell_renderer_toggle_new();
+ g_signal_connect (renderer, "toggled",
+ G_CALLBACK (category_toggled), store);
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Enabled"), renderer, "active", CAT_ENABLED);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+
+ g_object_unref(G_OBJECT(store));
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Label"), renderer, "text", CAT_LABEL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Desc."), renderer, "text", CAT_DESCRIPTION);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
+ gtk_widget_show_all(dialog);
+
+ g_signal_connect(G_OBJECT(btn_edit), "clicked",
+ G_CALLBACK(category_edit), tree_view);
+
+ g_signal_connect(G_OBJECT(btn_add), "clicked",
+ G_CALLBACK(category_add), tree_view);
+
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+ {
+ break;
+ }
+ gtk_widget_destroy(dialog);
- gtk_clipboard_set_text(
- gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
-
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-cmenu_cb_loc_route_to(GtkAction *action)
+menu_cb_category(GtkAction *action)
{
- gchar buffer[80];
- gchar strlat[32];
- gchar strlon[32];
- guint unitx, unity;
- gfloat lat, lon;
printf("%s()\n", __PRETTY_FUNCTION__);
-
- unitx = x2unit(_cmenu_position_x);
- unity = y2unit(_cmenu_position_y);
- unit2latlon(unitx, unity, lat, lon);
- g_ascii_formatd(strlat, 32, "%.06f", lat);
- g_ascii_formatd(strlon, 32, "%.06f", lon);
- sprintf(buffer, "%s, %s", strlat, strlon);
-
- route_download(NULL, buffer, TRUE);
+ if(category_list())
+ map_force_redraw();
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-cmenu_cb_loc_distance_to(GtkAction *action)
+poi_delete(GtkWidget *widget, DeletePOI *dpoi)
{
- gchar buffer[80];
- guint unitx, unity;
- gfloat lat, lon;
+ GtkWidget *dialog;
+ guint i;
+ gchar *buffer;
printf("%s()\n", __PRETTY_FUNCTION__);
-
- unitx = x2unit(_cmenu_position_x);
- unity = y2unit(_cmenu_position_y);
- unit2latlon(unitx, unity, lat, lon);
- sprintf(buffer, "%s: %.02f %s", _("Distance to Location"),
- calculate_distance(_pos_lat, _pos_lon, lat, lon), _units);
- hildon_banner_show_information(_window, NULL, buffer);
-
+ buffer = g_strdup_printf(_("Delete POI?\n%s"), dpoi->txt_label);
+ dialog = hildon_note_new_confirmation (GTK_WINDOW(_window), buffer);
+ g_free(buffer);
+ i = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ if(i == GTK_RESPONSE_OK)
+ {
+ /* delete dpoi->poi_id */
+ buffer = g_strdup_printf("delete from poi where poi_id = %d",
+ dpoi->id);
+
+ if(sqlite_exec(_db, buffer, NULL, NULL, NULL)
+ != SQLITE_OK)
+ {
+ hildon_banner_show_information(_window, NULL,
+ _("Problem deleting POI"));
+ }
+ else
+ {
+ gtk_widget_hide_all(dpoi->dialog);
+ map_force_redraw();
+ }
+ g_free(buffer);
+ }
+
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
-static WayPoint *
-find_nearest_visible_waypoint(guint unitx, guint unity)
+static guint
+poi_list(gchar **pszResult, gint nRow, gint nColumn)
{
- WayPoint *wcurr;
- WayPoint *wnear;
- guint nearest_squared;
- Point pos = { unitx, unity };
+ GtkWidget *dialog;
+ GtkWidget *list;
+ GtkWidget *sw;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ guint i, row = -1;
+ printf("%s()\n", __PRETTY_FUNCTION__);
+
+ dialog = gtk_dialog_new_with_buttons(_("Select POI"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL);
+
+ store = gtk_list_store_new(POI_NUM_COLUMNS,
+ G_TYPE_INT,
+ G_TYPE_FLOAT,
+ G_TYPE_FLOAT,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ for(i = 1; i < nRow + 1; i++)
+ {
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ POI_INDEX, i,
+ POI_LATITUDE, atof(pszResult[i * nColumn + 0]),
+ POI_LONGITUDE, atof(pszResult[i * nColumn + 1]),
+ POI_LABEL, pszResult[i * nColumn + 2],
+ POI_CATEGORY, pszResult[i * nColumn + 6],
+ -1);
+ }
+
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+ GTK_SHADOW_ETCHED_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ sw, TRUE, TRUE, 0);
+
+ list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+ g_object_unref(G_OBJECT(store));
+ gtk_container_add (GTK_CONTAINER (sw), list);
+
+ gtk_tree_selection_set_mode(
+ gtk_tree_view_get_selection(GTK_TREE_VIEW(list)),
+ GTK_SELECTION_SINGLE);
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("POI_INDEX"), renderer, "text", POI_INDEX);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+ gtk_tree_view_column_set_max_width (column, 1);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Latitude"), renderer, "text", POI_LATITUDE);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Longitude"), renderer, "text", POI_LONGITUDE);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Label"), renderer, "text", POI_LABEL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Category"), renderer, "text", POI_CATEGORY);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+
+ gtk_widget_show_all(dialog);
+
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+ {
+ GtkTreeIter iter;
+ if(gtk_tree_selection_get_selected(
+ gtk_tree_view_get_selection(GTK_TREE_VIEW(list)),
+ NULL, &iter))
+ {
+ gtk_tree_model_get(GTK_TREE_MODEL(store),
+ &iter, 0, &row, -1);
+ break;
+ }
+ else
+ popup_error(dialog, _("Select one POI from the list."));
+ }
+
+ gtk_widget_destroy(dialog);
+
+ vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, row);
+ return row;
+}
- wcurr = wnear = _visible_way_first;
- if(wcurr && wcurr != _visible_way_last)
+static void
+poi_populate_cat_combo(GtkWidget *cmb_category, guint cat_id)
+{
+ gchar **pszResult;
+ gint nRow, nColumn, row;
+ guint i, catindex = 0;
+ gint n_children = gtk_tree_model_iter_n_children(
+ gtk_combo_box_get_model(GTK_COMBO_BOX(cmb_category)), NULL);
+
+ for(i = 0; i < n_children; i++)
+ gtk_combo_box_remove_text(GTK_COMBO_BOX(cmb_category), 0);
+
+ if(sqlite_get_table(_db,
+ "select c.label, c.cat_id from category c order by c.label",
+ &pszResult, &nRow, &nColumn, NULL) == SQLITE_OK)
{
- nearest_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
-
- while(wcurr++ != _visible_way_last)
+ for(row=1; row<nRow+1; row++)
{
- guint test_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
- if(test_squared < nearest_squared)
- {
- wnear = wcurr;
- nearest_squared = test_squared;
- }
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_category),
+ pszResult[row*nColumn]);
+ if(atoi(pszResult[row*nColumn+1]) == cat_id)
+ catindex = row - 1;
}
+ sqlite_free_table(pszResult);
}
- return wnear;
+ gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_category), catindex);
+}
+
+typedef struct _PoiCategoryEditInfo PoiCategoryEditInfo;
+struct _PoiCategoryEditInfo
+{
+ GtkWidget *cmb_category;
+ guint cat_id;
+};
+
+static gboolean
+poi_edit_cat(GtkWidget *widget, PoiCategoryEditInfo *data)
+{
+ if(category_list())
+ poi_populate_cat_combo(data->cmb_category, data->cat_id);
+ return TRUE;
}
static gboolean
-cmenu_cb_way_show_latlon(GtkAction *action)
+poi_dialog(guint action)
{
- gchar buffer[80];
- gfloat lat, lon;
- WayPoint *way;
+ gchar **pszResult;
+ gint nRow, nColumn, rowindex;
+ gchar *sql;
+ gchar *poi_label = NULL;
+ gchar *poi_category = NULL;
+ gchar *poi_desc = NULL;
+ guint unitx, unity, cat_id = 0, poi_id = 0;
+ gfloat lat, lon, lat1, lon1, lat2, lon2, tmp;
+ gchar slat1[10], slon1[10];
+ gchar slat2[10], slon2[10];
+ gchar *p_latlon, *p_label = NULL, *p_desc = NULL;
+ GtkWidget *dialog;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *txt_label;
+ GtkWidget *cmb_category;
+ GtkWidget *txt_desc;
+ GtkWidget *btn_delete = NULL;
+ GtkWidget *btn_catedit;
+ GtkWidget *hbox;
+ GtkWidget *txt_scroll;
+ GtkTextBuffer *desc_txt;
+ GtkTextIter begin, end;
+ DeletePOI dpoi = {NULL, NULL, 0};
+ PoiCategoryEditInfo pcedit;
printf("%s()\n", __PRETTY_FUNCTION__);
- way = find_nearest_visible_waypoint(
- x2unit(_cmenu_position_x),
- y2unit(_cmenu_position_y));
+ unitx = x2unit(_cmenu_position_x);
+ unity = y2unit(_cmenu_position_y);
+ unit2latlon(unitx, unity, lat, lon);
- if(way)
+ if(action == ACTION_EDIT_POI)
{
- unit2latlon(way->point->unitx, way->point->unity, lat, lon);
-
- sprintf(buffer,
- "%s: %.06f\n"
- "%s: %.06f",
- _("Latitude"), lat,
- _("Longitude"), lon);
+ unitx = x2unit(_cmenu_position_x - (3 * _draw_line_width));
+ unity = y2unit(_cmenu_position_y - (3 * _draw_line_width));
+ unit2latlon(unitx, unity, lat1, lon1);
- hildon_banner_show_information(_window, NULL, buffer);
- }
- else
- hildon_banner_show_information(_window, NULL,
- _("No waypoints are visible."));
+ unitx = x2unit(_cmenu_position_x + (3 * _draw_line_width));
+ unity = y2unit(_cmenu_position_y + (3 * _draw_line_width));
+ unit2latlon(unitx, unity, lat2, lon2);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ if(lat1 > lat2)
+ {
+ tmp = lat2;
+ lat2 = lat1;
+ lat1 = tmp;
+ }
+ if(lon1 > lon2)
+ {
+ tmp = lon2;
+ lon2 = lon1;
+ lon1 = tmp;
+ }
-static gboolean
-cmenu_cb_way_show_desc(GtkAction *action)
-{
- WayPoint *way;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ g_ascii_dtostr(slat1, sizeof(slat1), lat1);
+ g_ascii_dtostr(slon1, sizeof(slon1), lon1);
+ g_ascii_dtostr(slat2, sizeof(slat2), lat2);
+ g_ascii_dtostr(slon2, sizeof(slon2), lon2);
+
+ sql = g_strdup_printf(
+ "select p.lat, p.lon, p.label, p.desc, p.cat_id, p.poi_id, c.label"
+ " from poi p, category c "
+ " where p.lat between %s and %s "
+ " and p.lon between %s and %s "
+ " and c.enabled = 1 and p.cat_id = c.cat_id",
+ slat1, slat2, slon1, slon2);
+
+ if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+ != SQLITE_OK)
+ {
+ g_free(sql);
+ printf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+ return FALSE;
+ }
+ g_free(sql);
- way = find_nearest_visible_waypoint(
- x2unit(_cmenu_position_x),
- y2unit(_cmenu_position_y));
+ if(nRow == 0)
+ return FALSE;
- if(way)
- hildon_banner_show_information(_window, NULL, way->desc);
- else
- hildon_banner_show_information(_window, NULL,
- _("No waypoints are visible."));
+ if(nRow > 1)
+ {
+ rowindex = poi_list(pszResult, nRow, nColumn);
+ if(rowindex == -1)
+ return FALSE;
+ }
+ else
+ rowindex = 1;
+
+ p_latlon = g_strdup_printf("%s, %s",
+ pszResult[rowindex * nColumn + 0],
+ pszResult[rowindex * nColumn + 1]);
+ p_label = g_strdup(pszResult[rowindex * nColumn + 2]);
+ p_desc = g_strdup(pszResult[rowindex * nColumn + 3]);
+ cat_id = atoi(pszResult[rowindex * nColumn + 4]);
+ poi_id = atoi(pszResult[rowindex * nColumn + 5]);
+ sqlite_free_table(pszResult);
+
+ dialog = gtk_dialog_new_with_buttons(_("Edit POI"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+ btn_delete = gtk_button_new_with_label(_("Delete")));
-static gboolean
-cmenu_cb_way_clip_latlon(GtkAction *action)
-{
- gchar buffer[80];
- gfloat lat, lon;
- WayPoint *way;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ dpoi.dialog = dialog;
+ dpoi.txt_label = g_strdup(p_label);
+ dpoi.id = poi_id;
- way = find_nearest_visible_waypoint(
- x2unit(_cmenu_position_x),
- y2unit(_cmenu_position_y));
+ g_signal_connect(G_OBJECT(btn_delete), "clicked",
+ G_CALLBACK(poi_delete), &dpoi);
- if(way)
+ gtk_dialog_add_button(GTK_DIALOG(dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+ }
+ else
{
- unit2latlon(way->point->unitx, way->point->unity, lat, lon);
+ p_latlon = g_strdup_printf("%.06f, %.06f", lat, lon);
- sprintf(buffer,
- "%s: %.06f\n"
- "%s: %.06f",
- _("Latitude"), lat,
- _("Longitude"), lon);
+ if(sqlite_get_table(_db, "select ifnull(max(poi_id) + 1,1) from poi",
+ &pszResult, &nRow, &nColumn, NULL) == SQLITE_OK)
+ {
+ p_label = g_strdup_printf("Point%06d", atoi(pszResult[nColumn]));
+ sqlite_free_table(pszResult);
+ }
- gtk_clipboard_set_text(
- gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
+ p_desc = g_strdup("");
+ cat_id = 0;
+ poi_id = 0;
+
+ dialog = gtk_dialog_new_with_buttons(_("Add POI"),
+ GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL);
}
- else
- hildon_banner_show_information(_window, NULL,
- _("No waypoints are visible."));
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0);
-static gboolean
-cmenu_cb_way_clip_desc(GtkAction *action)
-{
- WayPoint *way;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Lat, Lon: ")),
+ 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- way = find_nearest_visible_waypoint(
- x2unit(_cmenu_position_x),
- y2unit(_cmenu_position_y));
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(p_latlon),
+ 1, 3, 0, 1, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- if(way)
- gtk_clipboard_set_text(
- gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), way->desc, -1);
- else
- hildon_banner_show_information(_window, NULL,
- _("No waypoints are visible."));
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Label: ")),
+ 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table),
+ txt_label = gtk_entry_new(),
+ 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Category: ")),
+ 0, 1, 3, 4, GTK_FILL, 0, 2, 4);
+ gtk_table_attach(GTK_TABLE(table),
+ hbox = gtk_hbox_new(FALSE, 4),
+ 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ cmb_category = gtk_combo_box_new_text(),
+ FALSE, FALSE, 4);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ btn_catedit = gtk_button_new_with_label(_("Edit Categories...")),
+ FALSE, FALSE, 4);
-static gboolean
-cmenu_cb_way_route_to(GtkAction *action)
-{
- WayPoint *way;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ gtk_table_attach(GTK_TABLE(table),
+ label = gtk_label_new(_("Desc.: ")),
+ 0, 1, 5, 6, GTK_FILL, 0, 2, 4);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
- way = find_nearest_visible_waypoint(
- x2unit(_cmenu_position_x),
- y2unit(_cmenu_position_y));
+ txt_scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll),
+ GTK_SHADOW_IN);
+ gtk_table_attach(GTK_TABLE(table),
+ txt_scroll,
+ 1, 2, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
- if(way)
- {
- gchar buffer[80];
- gchar strlat[32];
- gchar strlon[32];
- gfloat lat, lon;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- unit2latlon(way->point->unitx, way->point->unity, lat, lon);
- g_ascii_formatd(strlat, 32, "%.06f", lat);
- g_ascii_formatd(strlon, 32, "%.06f", lon);
- sprintf(buffer, "%s, %s", strlat, strlon);
-
- route_download(NULL, buffer, TRUE);
- }
- else
- hildon_banner_show_information(_window, NULL,
- _("No waypoints are visible."));
+ txt_desc = gtk_text_view_new ();
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
-}
+ gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
+ gtk_widget_show(txt_scroll);
+ gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60);
-static gboolean
-cmenu_cb_way_distance_to(GtkAction *action)
-{
- WayPoint *way;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ desc_txt = gtk_text_view_get_buffer (GTK_TEXT_VIEW (txt_desc));
- way = find_nearest_visible_waypoint(
- x2unit(_cmenu_position_x),
- y2unit(_cmenu_position_y));
+ /* label */
+ gtk_entry_set_text(GTK_ENTRY(txt_label), p_label);
- if(way)
+ /* category */
+ poi_populate_cat_combo(cmb_category, cat_id);
+
+ /* poi_desc */
+ gtk_text_buffer_set_text(desc_txt, p_desc, -1);
+
+ /* Connect Signals */
+ pcedit.cmb_category = cmb_category;
+ pcedit.cat_id = cat_id;
+ g_signal_connect(G_OBJECT(btn_catedit), "clicked",
+ G_CALLBACK(poi_edit_cat), &pcedit);
+ gtk_widget_show_all(dialog);
+
+ while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
{
- gchar buffer[80];
- gfloat lat, lon;
- printf("%s()\n", __PRETTY_FUNCTION__);
+ if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_label))))
+ poi_label = g_strdup(gtk_entry_get_text(
+ GTK_ENTRY(txt_label)));
+ else
+ {
+ popup_error(dialog, _("Please specify a name for the POI."));
+ continue;
+ }
- unit2latlon(way->point->unitx, way->point->unity, lat, lon);
+ gtk_text_buffer_get_iter_at_offset(desc_txt, &begin,0 );
+ gtk_text_buffer_get_end_iter (desc_txt, &end);
+ poi_desc = gtk_text_buffer_get_text(desc_txt, &begin, &end, TRUE);
- sprintf(buffer, "%s: %.02f %s", _("Distance to Waypoint"),
- calculate_distance(_pos_lat, _pos_lon, lat, lon), _units);
- hildon_banner_show_information(_window, NULL, buffer);
+ poi_category = gtk_combo_box_get_active_text(
+ GTK_COMBO_BOX(cmb_category));
+
+ sql = g_strdup_printf("select cat_id from category where label = '%s'",
+ poi_category);
+ if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+ == SQLITE_OK)
+ {
+ g_free(sql);
+
+ if(action == ACTION_EDIT_POI)
+ {
+ /* edit poi */
+ sql = g_strdup_printf(
+ "update poi set label = '%s', desc = '%s', "
+ "cat_id = %d where poi_id = %d",
+ poi_label, poi_desc, atoi(pszResult[nColumn]), poi_id);
+ if(sqlite_exec(_db, sql, NULL, NULL, NULL) != SQLITE_OK)
+ hildon_banner_show_information(_window, NULL,
+ _("Problem updating POI"));
+ else
+ map_render_poi();
+ }
+ else
+ {
+ /* add poi */
+ g_ascii_dtostr(slat1, sizeof(slat1), lat);
+ g_ascii_dtostr(slon1, sizeof(slon1), lon);
+ sql = g_strdup_printf(
+ "insert into poi (lat, lon, label, desc, cat_id)"
+ " values (%s, %s, '%s', '%s', %d)",
+ slat1, slon1, poi_label, poi_desc,
+ atoi(pszResult[nColumn]));
+ if(sqlite_exec(_db, sql, NULL, NULL, NULL) != SQLITE_OK)
+ hildon_banner_show_information(_window, NULL,
+ _("Problem adding POI"));
+ else
+ map_render_poi();
+ }
+
+ sqlite_free_table(pszResult);
+ }
+ g_free(sql);
+ break;
}
- else
- hildon_banner_show_information(_window, NULL,
- _("No waypoints are visible."));
+
+ g_object_unref (desc_txt);
+ g_free(poi_label);
+ g_free(poi_category);
+ g_free(poi_desc);
+
+ g_free(p_latlon);
+ g_free(p_label);
+ g_free(p_desc);
+
+ gtk_widget_hide_all(dialog);
vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
return TRUE;
}
static gboolean
-cmenu_cb_way_delete(GtkAction *action)
+cmenu_cb_add_poi(GtkAction *action)
{
- WayPoint *way;
+ gboolean results;
printf("%s()\n", __PRETTY_FUNCTION__);
- way = find_nearest_visible_waypoint(
- x2unit(_cmenu_position_x),
- y2unit(_cmenu_position_y));
+ results = poi_dialog(ACTION_ADD_POI);
- if(way)
- {
- gchar buffer[1024];
- GtkWidget *confirm;
+ vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+ return results;
+}
- sprintf(buffer, "%s:\n%s\n",
- _("Confirm delete of waypoint"), way->desc);
- confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
+static gboolean
+cmenu_cb_edit_poi(GtkAction *action)
+{
+ gboolean results;
+ printf("%s()\n", __PRETTY_FUNCTION__);
- if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
- {
- while(way++ != _route.wtail)
- way[-1] = *way;
- _route.wtail--;
- map_force_redraw();
- }
- gtk_widget_destroy(confirm);
- }
- else
- hildon_banner_show_information(_window, NULL,
- _("No waypoints are visible."));
+ results = poi_dialog(ACTION_EDIT_POI);
- vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
- return TRUE;
+ vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+ return results;
}
-
/****************************************************************************
* ABOVE: CALLBACKS *********************************************************
****************************************************************************/