Diff of /trunk/src/misc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 13 by harbaum, Sat Jun 27 11:09:19 2009 UTC revision 215 by harbaum, Thu Nov 26 10:30:50 2009 UTC
# Line 21  Line 21 
21  #include <string.h>  #include <string.h>
22  #include <ctype.h>  #include <ctype.h>
23    
24    #include <glib.h>
25    #include <glib/gstdio.h>
26    
27  #include "gpxview.h"  #include "gpxview.h"
28    
29    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
30    #include <hildon/hildon-entry.h>
31    #endif
32    
33  char strlastchr(char *str) {  char strlastchr(char *str) {
34    return str[strlen(str)]-1;    return str[strlen(str)]-1;
35  }  }
# Line 148  float pos_parse_lon(char *str) { Line 155  float pos_parse_lon(char *str) {
155    
156  const char *pos_get_bearing_str(pos_t from, pos_t to) {  const char *pos_get_bearing_str(pos_t from, pos_t to) {
157    static const char *bear_str[]={    static const char *bear_str[]={
158      "N", "NE", "E", "SE", "S", "SW", "W", "NW" };      "N", "NE", "E", "SE", "S", "SW", "W", "NW", "" };
159    int idx = (gpx_pos_get_bearing(from, to)+22.5)/45.0;  
160    /* make sure we stay in icon bounds */    float bearing = gpx_pos_get_bearing(from, to);
161    while(idx < 0) idx += 8;    if(!isnan(bearing)) {
162    while(idx > 7) idx -= 8;      int idx = (bearing+22.5)/45.0;
163    return _(bear_str[idx]);      /* make sure we stay in icon bounds */
164        while(idx < 0) idx += 8;
165        while(idx > 7) idx -= 8;
166        return _(bear_str[idx]);
167      }
168    
169      return bear_str[8];  // empty string
170  }  }
171    
172  /* the maemo font size is quite huge, so we adjust some fonts */  /* the maemo font size is quite huge, so we adjust some fonts */
# Line 241  pos_t *get_pos(appdata_t *appdata) { Line 254  pos_t *get_pos(appdata_t *appdata) {
254  }  }
255    
256  void distance_str(char *str, int len, float dist, gboolean imperial) {  void distance_str(char *str, int len, float dist, gboolean imperial) {
257    if(imperial) {    if(isnan(dist))
258        snprintf(str, len, "---");
259      else if(imperial) {
260      /* 1 mil = 1760 yd = 5280 ft ... */      /* 1 mil = 1760 yd = 5280 ft ... */
261      if(dist<0.018)      snprintf(str, len, "%.1f ft", dist*5280.0);      if(dist<0.018)      snprintf(str, len, "%.1f ft", dist*5280.0);
262      else if(dist<0.055) snprintf(str, len, "%.1f yd", dist*1760.0);      else if(dist<0.055) snprintf(str, len, "%.1f yd", dist*1760.0);
# Line 295  static void callback_modified_lat(GtkWid Line 310  static void callback_modified_lat(GtkWid
310  /* a entry that is colored red when being "active" */  /* a entry that is colored red when being "active" */
311  GtkWidget *lat_entry_new(float lat) {  GtkWidget *lat_entry_new(float lat) {
312    GdkColor color;    GdkColor color;
313    GtkWidget *widget = gtk_entry_new();  
314      GtkWidget *widget = entry_new();
315    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
316    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
317    
# Line 317  static void callback_modified_lon(GtkWid Line 333  static void callback_modified_lon(GtkWid
333  /* a entry that is colored red when filled with invalid coordinate */  /* a entry that is colored red when filled with invalid coordinate */
334  GtkWidget *lon_entry_new(float lon) {  GtkWidget *lon_entry_new(float lon) {
335    GdkColor color;    GdkColor color;
336    GtkWidget *widget = gtk_entry_new();  
337      GtkWidget *widget = entry_new();
338      //  gtk_entry_set_width_chars(GTK_ENTRY(widget), 14);
339    
340    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
341    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
342    
# Line 352  static void callback_modified_dist(GtkWi Line 371  static void callback_modified_dist(GtkWi
371  /* a entry that is colored red when filled with invalid distance */  /* a entry that is colored red when filled with invalid distance */
372  GtkWidget *dist_entry_new(float dist, gboolean mil) {  GtkWidget *dist_entry_new(float dist, gboolean mil) {
373    GdkColor color;    GdkColor color;
374    GtkWidget *widget = gtk_entry_new();    GtkWidget *widget = entry_new();
375    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
376    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
377    
# Line 383  int browser_url(appdata_t *appdata, char Line 402  int browser_url(appdata_t *appdata, char
402  }  }
403  #endif  #endif
404  #endif  #endif
405    
406    /* recursively remove an entire file system */
407    void rmdir_recursive(char *path) {
408      GDir *dir = g_dir_open(path, 0, NULL);
409      if(dir) {
410        const char *name = g_dir_read_name(dir);
411        while(name) {
412          char *fullname = g_strdup_printf("%s/%s", path, name);
413          //      printf("deleting %s\n", fullname);
414    
415          if(g_file_test(fullname, G_FILE_TEST_IS_DIR))
416            rmdir_recursive(fullname);
417          else if(g_file_test(fullname, G_FILE_TEST_IS_REGULAR))
418            g_remove(fullname);
419    
420          g_free(fullname);
421          name = g_dir_read_name(dir);
422        }
423    
424        g_dir_close(dir);
425      }
426      g_rmdir(path);
427    }
428    
429    #ifdef ENABLE_BROWSER_INTERFACE
430    static void on_link_clicked(GtkButton *button, gpointer data) {
431      appdata_t *appdata = (appdata_t*)data;
432      char *url = g_object_get_data(G_OBJECT(button), "url");
433      if(url) browser_url(appdata, url);
434    }
435    #endif
436    
437    /* a button containing a weblink */
438    GtkWidget *link_button_attrib(appdata_t *appdata, char *str, char *url,
439                           int size, int strikethrough) {
440    
441    #ifdef ENABLE_BROWSER_INTERFACE
442      if(url) {
443        GtkWidget *button = gtk_button_attrib(str, size, strikethrough);
444        g_object_set_data(G_OBJECT(button), "url", url);
445        gtk_signal_connect(GTK_OBJECT(button), "clicked",
446                           (GtkSignalFunc)on_link_clicked, appdata);
447    
448        return button;
449      }
450    #endif
451      return gtk_label_attrib(str, size, strikethrough);
452    }
453    
454    #ifdef ENABLE_BROWSER_INTERFACE
455    static void on_link_id_clicked(GtkButton *button, gpointer data) {
456      appdata_t *appdata = (appdata_t*)data;
457    
458      unsigned int id = (unsigned int)g_object_get_data(G_OBJECT(button), "id");
459      char *type = g_object_get_data(G_OBJECT(button), "type");
460    
461      char *url = g_strdup_printf("http://www.geocaching.com/%s?id=%u",
462                                  type, id);
463    
464      if(url) {
465        browser_url(appdata, url);
466        g_free(url);
467      }
468    }
469    #endif
470    
471    GtkWidget *link_button_by_id(appdata_t *appdata, char *str,
472                                 const char *type, int id) {
473    
474    #ifdef ENABLE_BROWSER_INTERFACE
475      if(id) {
476        GtkWidget *ref = gtk_button_new_with_label(str);
477    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
478        //    hildon_gtk_widget_set_theme_size(ref,
479        //         (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
480    #endif
481        g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
482        g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
483        gtk_signal_connect(GTK_OBJECT(ref), "clicked",
484                           GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
485    
486        return ref;
487      }
488    #endif
489      return gtk_label_new(str);
490    }
491    
492    
493    GtkWidget *link_icon_button_by_id(appdata_t *appdata, GtkWidget *icon,
494                                 const char *type, int id) {
495    
496    #ifdef ENABLE_BROWSER_INTERFACE
497      if(id) {
498        GtkWidget *ref = gtk_button_new();
499        gtk_button_set_image(GTK_BUTTON(ref), icon);
500    
501    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
502        //    hildon_gtk_widget_set_theme_size(ref,
503        //         (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
504    #endif
505        g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
506        g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
507        gtk_signal_connect(GTK_OBJECT(ref), "clicked",
508                           GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
509    
510        return ref;
511      }
512    #endif
513      return icon;
514    }
515    
516    /* left aligned, word wrapped multiline widget */
517    GtkWidget *simple_text_widget(char *text) {
518      GtkWidget *label = gtk_label_new(text);
519    
520      gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
521      gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD);
522      gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
523    
524      return label;
525    }
526    
527    
528    /* a label that is left aligned */
529    GtkWidget *left_label_new(char *str) {
530      GtkWidget *widget = gtk_label_new(str);
531      gtk_misc_set_alignment(GTK_MISC(widget), 0.0f, 0.5f);
532      return widget;
533    }
534    
535    static void pos_set(GtkMenuItem *item, float lat, float lon) {
536      char str[32];
537    
538      pos_lat_str(str, sizeof(str)-1, lat);
539      GtkWidget *lat_entry = g_object_get_data(G_OBJECT(item), "lat_entry");
540      gtk_entry_set_text(GTK_ENTRY(lat_entry), str);
541    
542      pos_lon_str(str, sizeof(str)-1, lon);
543      GtkWidget *lon_entry = g_object_get_data(G_OBJECT(item), "lon_entry");
544      gtk_entry_set_text(GTK_ENTRY(lon_entry), str);
545    }
546    
547    static void cb_gps(GtkMenuItem *item, gpointer data) {
548      appdata_t *appdata = (appdata_t*)data;
549    
550      pos_t *refpos = get_pos(appdata);
551      if(!refpos) pos_set(item, NAN, NAN);
552      else        pos_set(item, refpos->lat, refpos->lon);
553    }
554    
555    static void cb_geomath(GtkMenuItem *item, gpointer data) {
556      appdata_t *appdata = (appdata_t*)data;
557    
558      pos_set(item, appdata->geomath.lat, appdata->geomath.lon);
559    }
560    
561    #ifdef ENABLE_OSM_GPS_MAP
562    static void cb_map(GtkMenuItem *item, gpointer data) {
563      appdata_t *appdata = (appdata_t*)data;
564    
565      pos_set(item, appdata->map.pos.lat, appdata->map.pos.lon);
566    }
567    #endif
568    
569    static const gchar *menu_item_get_label(GtkMenuItem *menu_item) {
570      GList *children, *l;
571      GtkWidget *child;
572      children = gtk_container_get_children (GTK_CONTAINER (menu_item));
573      for (l = g_list_first (children); l != NULL;
574           l = g_list_next (l)) {
575        child = (GtkWidget *)l->data;
576        if (GTK_IS_LABEL (child)) {
577          return gtk_label_get_label (GTK_LABEL (child));
578        }
579      }
580      return NULL;
581    }
582    
583    static void cb_cache(GtkMenuItem *item, gpointer data) {
584      const char *label = menu_item_get_label(item);
585      appdata_t *appdata = (appdata_t*)data;
586    
587      cache_t *cache = appdata->cur_cache;
588      g_assert(cache);
589    
590      if(!strcmp(label, cache->id))
591        pos_set(item, cache->pos.lat, cache->pos.lon);
592      else {
593        wpt_t *wpt = cache->wpt;
594        while(wpt) {
595          if(!strcmp(label, wpt->id)) {
596            pos_set(item, wpt->pos.lat, wpt->pos.lon);
597            return;
598          }
599    
600          wpt = wpt->next;
601        }
602      }
603    }
604    
605    static GtkWidget *menu_add(GtkWidget *menu, appdata_t *appdata,
606                               GtkWidget *icon, char *menu_str,
607                               void(*func)(GtkMenuItem*, gpointer),
608                               GtkWidget *lon_entry, GtkWidget *lat_entry) {
609    
610      GtkWidget *item = gtk_image_menu_item_new_with_label(menu_str);
611    
612      if(icon)
613        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon);
614    
615      g_object_set_data(G_OBJECT(item), "lat_entry", (gpointer)lat_entry);
616      g_object_set_data(G_OBJECT(item), "lon_entry", (gpointer)lon_entry);
617    
618      if(func)
619        gtk_signal_connect(GTK_OBJECT(item), "activate",
620                           (GtkSignalFunc)func, appdata);
621    
622      gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
623    
624      return item;
625    }
626    
627    static GtkWidget *popup_menu_create(appdata_t *appdata,
628                        GtkWidget *lat_entry, GtkWidget *lon_entry) {
629      GtkWidget *menu = gtk_menu_new();
630    
631      menu_add(menu, appdata, icon_get_widget(ICON_POS, 18),
632               _("Current position (GPS)"), cb_gps, lon_entry, lat_entry);
633      menu_add(menu, appdata, icon_get_widget(ICON_POS, 19),
634               _("Geomath projection"), cb_geomath, lon_entry, lat_entry);
635    #ifdef ENABLE_OSM_GPS_MAP
636      menu_add(menu, appdata, icon_get_widget(ICON_POS, 20),
637               _("Map position"), cb_map, lon_entry, lat_entry);
638    #endif
639    
640      printf("popup cache present: %s\n", appdata->cur_cache?"Yes":"No");
641    
642      if(appdata->cur_cache) {
643        cache_t *cache = appdata->cur_cache;
644    
645        if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) {
646          menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),
647                   cache->id, cb_cache, lon_entry, lat_entry);
648        }
649    
650        printf("appending cache waypoints\n");
651        wpt_t *wpt = cache->wpt;
652        while(wpt) {
653          GtkWidget *icon = NULL;
654          if(wpt->sym != WPT_SYM_UNKNOWN)
655            icon = icon_get_widget(ICON_POS, wpt->sym);
656    
657          menu_add(menu, appdata, icon, wpt->id, cb_cache,
658                   lon_entry, lat_entry);
659    
660          wpt = wpt->next;
661        }
662      }
663    
664      gtk_widget_show_all(menu);
665    
666      return menu;
667    }
668    
669    static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event,
670                                      gpointer data) {
671    
672      if(event->type == GDK_BUTTON_PRESS) {
673        GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");
674    
675        /* draw a popup menu */
676        gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
677                       event->button, event->time);
678        return TRUE;
679      }
680      return FALSE;
681    }
682    
683    static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) {
684      GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
685      gtk_widget_destroy(menu);
686    }
687    
688    GtkWidget *coo_popup(appdata_t *appdata,
689                         GtkWidget *lat_entry, GtkWidget *lon_entry) {
690    
691      GtkWidget *button = gtk_button_new();
692    #ifdef FREMANTLE
693      hildon_gtk_widget_set_theme_size(button,
694              (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
695    #endif
696    
697      gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17));
698    
699      gtk_widget_set_tooltip_text(button, _("Preset coordinates"));
700    
701      gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
702                         (GtkSignalFunc)on_popup_button_press, appdata);
703    
704      gtk_signal_connect(GTK_OBJECT(button), "destroy",
705                         (GtkSignalFunc)on_popup_destroy, appdata);
706    
707      g_object_set_data(G_OBJECT(button), "menu",
708                        popup_menu_create(appdata, lat_entry, lon_entry));
709    
710      return button;
711    }
712    
713    GtkWidget *entry_new(void) {
714    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
715      return gtk_entry_new();
716    #else
717      return hildon_entry_new(HILDON_SIZE_AUTO);
718    #endif
719    }
720    
721    gboolean pos_differ(pos_t *pos1, pos_t *pos2) {
722      int lat1 = (60000 * pos1->lat)+0.5, lon1 = (60000 * pos1->lon)+0.5;
723      int lat2 = (60000 * pos2->lat)+0.5, lon2 = (60000 * pos2->lon)+0.5;
724    
725      return((lat1 != lat2) || (lon1 != lon2));
726    }

Legend:
Removed from v.13  
changed lines
  Added in v.215