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 216 by harbaum, Thu Nov 26 14:32:41 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    #include <hildon/hildon-touch-selector.h>
32    #include <hildon/hildon-picker-button.h>
33    #include <hildon/hildon-picker-dialog.h>
34    #endif
35    
36  char strlastchr(char *str) {  char strlastchr(char *str) {
37    return str[strlen(str)]-1;    return str[strlen(str)]-1;
38  }  }
# Line 148  float pos_parse_lon(char *str) { Line 158  float pos_parse_lon(char *str) {
158    
159  const char *pos_get_bearing_str(pos_t from, pos_t to) {  const char *pos_get_bearing_str(pos_t from, pos_t to) {
160    static const char *bear_str[]={    static const char *bear_str[]={
161      "N", "NE", "E", "SE", "S", "SW", "W", "NW" };      "N", "NE", "E", "SE", "S", "SW", "W", "NW", "" };
162    int idx = (gpx_pos_get_bearing(from, to)+22.5)/45.0;  
163    /* make sure we stay in icon bounds */    float bearing = gpx_pos_get_bearing(from, to);
164    while(idx < 0) idx += 8;    if(!isnan(bearing)) {
165    while(idx > 7) idx -= 8;      int idx = (bearing+22.5)/45.0;
166    return _(bear_str[idx]);      /* make sure we stay in icon bounds */
167        while(idx < 0) idx += 8;
168        while(idx > 7) idx -= 8;
169        return _(bear_str[idx]);
170      }
171    
172      return bear_str[8];  // empty string
173  }  }
174    
175  /* 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 257  pos_t *get_pos(appdata_t *appdata) {
257  }  }
258    
259  void distance_str(char *str, int len, float dist, gboolean imperial) {  void distance_str(char *str, int len, float dist, gboolean imperial) {
260    if(imperial) {    if(isnan(dist))
261        snprintf(str, len, "---");
262      else if(imperial) {
263      /* 1 mil = 1760 yd = 5280 ft ... */      /* 1 mil = 1760 yd = 5280 ft ... */
264      if(dist<0.018)      snprintf(str, len, "%.1f ft", dist*5280.0);      if(dist<0.018)      snprintf(str, len, "%.1f ft", dist*5280.0);
265      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 313  static void callback_modified_lat(GtkWid
313  /* a entry that is colored red when being "active" */  /* a entry that is colored red when being "active" */
314  GtkWidget *lat_entry_new(float lat) {  GtkWidget *lat_entry_new(float lat) {
315    GdkColor color;    GdkColor color;
316    GtkWidget *widget = gtk_entry_new();  
317      GtkWidget *widget = entry_new();
318    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
319    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
320    
# Line 317  static void callback_modified_lon(GtkWid Line 336  static void callback_modified_lon(GtkWid
336  /* a entry that is colored red when filled with invalid coordinate */  /* a entry that is colored red when filled with invalid coordinate */
337  GtkWidget *lon_entry_new(float lon) {  GtkWidget *lon_entry_new(float lon) {
338    GdkColor color;    GdkColor color;
339    GtkWidget *widget = gtk_entry_new();  
340      GtkWidget *widget = entry_new();
341      //  gtk_entry_set_width_chars(GTK_ENTRY(widget), 14);
342    
343    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
344    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
345    
# Line 352  static void callback_modified_dist(GtkWi Line 374  static void callback_modified_dist(GtkWi
374  /* a entry that is colored red when filled with invalid distance */  /* a entry that is colored red when filled with invalid distance */
375  GtkWidget *dist_entry_new(float dist, gboolean mil) {  GtkWidget *dist_entry_new(float dist, gboolean mil) {
376    GdkColor color;    GdkColor color;
377    GtkWidget *widget = gtk_entry_new();    GtkWidget *widget = entry_new();
378    gdk_color_parse("#ff0000", &color);    gdk_color_parse("#ff0000", &color);
379    gtk_widget_modify_text(widget, TAG_STATE, &color);    gtk_widget_modify_text(widget, TAG_STATE, &color);
380    
# Line 383  int browser_url(appdata_t *appdata, char Line 405  int browser_url(appdata_t *appdata, char
405  }  }
406  #endif  #endif
407  #endif  #endif
408    
409    /* recursively remove an entire file system */
410    void rmdir_recursive(char *path) {
411      GDir *dir = g_dir_open(path, 0, NULL);
412      if(dir) {
413        const char *name = g_dir_read_name(dir);
414        while(name) {
415          char *fullname = g_strdup_printf("%s/%s", path, name);
416          //      printf("deleting %s\n", fullname);
417    
418          if(g_file_test(fullname, G_FILE_TEST_IS_DIR))
419            rmdir_recursive(fullname);
420          else if(g_file_test(fullname, G_FILE_TEST_IS_REGULAR))
421            g_remove(fullname);
422    
423          g_free(fullname);
424          name = g_dir_read_name(dir);
425        }
426    
427        g_dir_close(dir);
428      }
429      g_rmdir(path);
430    }
431    
432    #ifdef ENABLE_BROWSER_INTERFACE
433    static void on_link_clicked(GtkButton *button, gpointer data) {
434      appdata_t *appdata = (appdata_t*)data;
435      char *url = g_object_get_data(G_OBJECT(button), "url");
436      if(url) browser_url(appdata, url);
437    }
438    #endif
439    
440    /* a button containing a weblink */
441    GtkWidget *link_button_attrib(appdata_t *appdata, char *str, char *url,
442                           int size, int strikethrough) {
443    
444    #ifdef ENABLE_BROWSER_INTERFACE
445      if(url) {
446        GtkWidget *button = gtk_button_attrib(str, size, strikethrough);
447        g_object_set_data(G_OBJECT(button), "url", url);
448        gtk_signal_connect(GTK_OBJECT(button), "clicked",
449                           (GtkSignalFunc)on_link_clicked, appdata);
450    
451        return button;
452      }
453    #endif
454      return gtk_label_attrib(str, size, strikethrough);
455    }
456    
457    #ifdef ENABLE_BROWSER_INTERFACE
458    static void on_link_id_clicked(GtkButton *button, gpointer data) {
459      appdata_t *appdata = (appdata_t*)data;
460    
461      unsigned int id = (unsigned int)g_object_get_data(G_OBJECT(button), "id");
462      char *type = g_object_get_data(G_OBJECT(button), "type");
463    
464      char *url = g_strdup_printf("http://www.geocaching.com/%s?id=%u",
465                                  type, id);
466    
467      if(url) {
468        browser_url(appdata, url);
469        g_free(url);
470      }
471    }
472    #endif
473    
474    GtkWidget *link_button_by_id(appdata_t *appdata, char *str,
475                                 const char *type, int id) {
476    
477    #ifdef ENABLE_BROWSER_INTERFACE
478      if(id) {
479        GtkWidget *ref = gtk_button_new_with_label(str);
480    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
481        //    hildon_gtk_widget_set_theme_size(ref,
482        //         (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
483    #endif
484        g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
485        g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
486        gtk_signal_connect(GTK_OBJECT(ref), "clicked",
487                           GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
488    
489        return ref;
490      }
491    #endif
492      return gtk_label_new(str);
493    }
494    
495    
496    GtkWidget *link_icon_button_by_id(appdata_t *appdata, GtkWidget *icon,
497                                 const char *type, int id) {
498    
499    #ifdef ENABLE_BROWSER_INTERFACE
500      if(id) {
501        GtkWidget *ref = gtk_button_new();
502        gtk_button_set_image(GTK_BUTTON(ref), icon);
503    
504    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
505        //    hildon_gtk_widget_set_theme_size(ref,
506        //         (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
507    #endif
508        g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
509        g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
510        gtk_signal_connect(GTK_OBJECT(ref), "clicked",
511                           GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
512    
513        return ref;
514      }
515    #endif
516      return icon;
517    }
518    
519    /* left aligned, word wrapped multiline widget */
520    GtkWidget *simple_text_widget(char *text) {
521      GtkWidget *label = gtk_label_new(text);
522    
523      gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
524      gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD);
525      gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
526    
527      return label;
528    }
529    
530    
531    /* a label that is left aligned */
532    GtkWidget *left_label_new(char *str) {
533      GtkWidget *widget = gtk_label_new(str);
534      gtk_misc_set_alignment(GTK_MISC(widget), 0.0f, 0.5f);
535      return widget;
536    }
537    
538    static void pos_set(GtkMenuItem *item, float lat, float lon) {
539      char str[32];
540    
541      pos_lat_str(str, sizeof(str)-1, lat);
542      GtkWidget *lat_entry = g_object_get_data(G_OBJECT(item), "lat_entry");
543      gtk_entry_set_text(GTK_ENTRY(lat_entry), str);
544    
545      pos_lon_str(str, sizeof(str)-1, lon);
546      GtkWidget *lon_entry = g_object_get_data(G_OBJECT(item), "lon_entry");
547      gtk_entry_set_text(GTK_ENTRY(lon_entry), str);
548    }
549    
550    static void cb_gps(GtkMenuItem *item, gpointer data) {
551      appdata_t *appdata = (appdata_t*)data;
552    
553      pos_t *refpos = get_pos(appdata);
554      if(!refpos) pos_set(item, NAN, NAN);
555      else        pos_set(item, refpos->lat, refpos->lon);
556    }
557    
558    static void cb_geomath(GtkMenuItem *item, gpointer data) {
559      appdata_t *appdata = (appdata_t*)data;
560    
561      pos_set(item, appdata->geomath.lat, appdata->geomath.lon);
562    }
563    
564    #ifdef ENABLE_OSM_GPS_MAP
565    static void cb_map(GtkMenuItem *item, gpointer data) {
566      appdata_t *appdata = (appdata_t*)data;
567    
568      pos_set(item, appdata->map.pos.lat, appdata->map.pos.lon);
569    }
570    #endif
571    
572    static const gchar *menu_item_get_label(GtkMenuItem *menu_item) {
573      GList *children, *l;
574      GtkWidget *child;
575      children = gtk_container_get_children (GTK_CONTAINER (menu_item));
576      for (l = g_list_first (children); l != NULL;
577           l = g_list_next (l)) {
578        child = (GtkWidget *)l->data;
579        if (GTK_IS_LABEL (child)) {
580          return gtk_label_get_label (GTK_LABEL (child));
581        }
582      }
583      return NULL;
584    }
585    
586    static void cb_cache(GtkMenuItem *item, gpointer data) {
587      const char *label = menu_item_get_label(item);
588      appdata_t *appdata = (appdata_t*)data;
589    
590      cache_t *cache = appdata->cur_cache;
591      g_assert(cache);
592    
593      if(!strcmp(label, cache->id))
594        pos_set(item, cache->pos.lat, cache->pos.lon);
595      else {
596        wpt_t *wpt = cache->wpt;
597        while(wpt) {
598          if(!strcmp(label, wpt->id)) {
599            pos_set(item, wpt->pos.lat, wpt->pos.lon);
600            return;
601          }
602    
603          wpt = wpt->next;
604        }
605      }
606    }
607    
608    static GtkWidget *menu_add(GtkWidget *menu, appdata_t *appdata,
609                               GtkWidget *icon, char *menu_str,
610                               void(*func)(GtkMenuItem*, gpointer),
611                               GtkWidget *lon_entry, GtkWidget *lat_entry) {
612    
613      GtkWidget *item = gtk_image_menu_item_new_with_label(menu_str);
614    
615      if(icon)
616        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon);
617    
618      g_object_set_data(G_OBJECT(item), "lat_entry", (gpointer)lat_entry);
619      g_object_set_data(G_OBJECT(item), "lon_entry", (gpointer)lon_entry);
620    
621      if(func)
622        gtk_signal_connect(GTK_OBJECT(item), "activate",
623                           (GtkSignalFunc)func, appdata);
624    
625      gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
626    
627      return item;
628    }
629    
630    static GtkWidget *popup_menu_create(appdata_t *appdata,
631                        GtkWidget *lat_entry, GtkWidget *lon_entry) {
632      GtkWidget *menu = gtk_menu_new();
633    
634      menu_add(menu, appdata, icon_get_widget(ICON_POS, 18),
635               _("Current position (GPS)"), cb_gps, lon_entry, lat_entry);
636      menu_add(menu, appdata, icon_get_widget(ICON_POS, 19),
637               _("Geomath projection"), cb_geomath, lon_entry, lat_entry);
638    #ifdef ENABLE_OSM_GPS_MAP
639      menu_add(menu, appdata, icon_get_widget(ICON_POS, 20),
640               _("Map position"), cb_map, lon_entry, lat_entry);
641    #endif
642    
643      printf("popup cache present: %s\n", appdata->cur_cache?"Yes":"No");
644    
645      if(appdata->cur_cache) {
646        cache_t *cache = appdata->cur_cache;
647    
648        if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) {
649          menu_add(menu, appdata, icon_get_widget(ICON_POS, cache->type + 6),
650                   cache->id, cb_cache, lon_entry, lat_entry);
651        }
652    
653        printf("appending cache waypoints\n");
654        wpt_t *wpt = cache->wpt;
655        while(wpt) {
656          GtkWidget *icon = NULL;
657          if(wpt->sym != WPT_SYM_UNKNOWN)
658            icon = icon_get_widget(ICON_POS, wpt->sym);
659    
660          menu_add(menu, appdata, icon, wpt->id, cb_cache,
661                   lon_entry, lat_entry);
662    
663          wpt = wpt->next;
664        }
665      }
666    
667      gtk_widget_show_all(menu);
668    
669      return menu;
670    }
671    
672    static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event,
673                                      gpointer data) {
674    
675      if(event->type == GDK_BUTTON_PRESS) {
676        GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");
677    
678        /* draw a popup menu */
679        gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
680                       event->button, event->time);
681        return TRUE;
682      }
683      return FALSE;
684    }
685    
686    static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) {
687      GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
688      gtk_widget_destroy(menu);
689    }
690    
691    GtkWidget *coo_popup(appdata_t *appdata,
692                         GtkWidget *lat_entry, GtkWidget *lon_entry) {
693    
694      GtkWidget *button = gtk_button_new();
695    #ifdef FREMANTLE
696      hildon_gtk_widget_set_theme_size(button,
697              (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
698    #endif
699    
700      gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17));
701    
702      gtk_widget_set_tooltip_text(button, _("Preset coordinates"));
703    
704      gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
705                         (GtkSignalFunc)on_popup_button_press, appdata);
706    
707      gtk_signal_connect(GTK_OBJECT(button), "destroy",
708                         (GtkSignalFunc)on_popup_destroy, appdata);
709    
710      g_object_set_data(G_OBJECT(button), "menu",
711                        popup_menu_create(appdata, lat_entry, lon_entry));
712    
713      return button;
714    }
715    
716    GtkWidget *entry_new(void) {
717    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
718      return gtk_entry_new();
719    #else
720      return hildon_entry_new(HILDON_SIZE_AUTO);
721    #endif
722    }
723    
724    gboolean pos_differ(pos_t *pos1, pos_t *pos2) {
725      int lat1 = (60000 * pos1->lat)+0.5, lon1 = (60000 * pos1->lon)+0.5;
726      int lat2 = (60000 * pos2->lat)+0.5, lon2 = (60000 * pos2->lon)+0.5;
727    
728      return((lat1 != lat2) || (lon1 != lon2));
729    }
730    
731    #ifdef FREMANTLE
732    void selection_changed (HildonTouchSelector * selector,
733                       gpointer *user_data) {
734      gchar *current_selection = NULL;
735    
736      current_selection = hildon_touch_selector_get_current_text (selector);
737      g_debug ("Current selection : %s", current_selection);
738    }
739    
740    static GtkWidget *create_customized_selector() {
741      GtkWidget *selector = NULL;
742      GSList *icon_list = NULL;
743      GtkListStore *store_icons = NULL;
744      GSList *item = NULL;
745      GtkCellRenderer *renderer = NULL;
746      HildonTouchSelectorColumn *column = NULL;
747    
748      selector = hildon_touch_selector_new ();
749    
750      icon_list = gtk_stock_list_ids ();
751    
752      store_icons = gtk_list_store_new (1, G_TYPE_STRING);
753      for (item = icon_list; item; item = g_slist_next (item)) {
754        GtkTreeIter iter;
755        gchar *label = item->data;
756    
757        gtk_list_store_append (store_icons, &iter);
758        gtk_list_store_set (store_icons, &iter, 0, label, -1);
759        g_free (label);
760      }
761      g_slist_free (icon_list);
762    
763      renderer = gtk_cell_renderer_pixbuf_new ();
764      gtk_cell_renderer_set_fixed_size (renderer, -1, 100);
765    
766      column = hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector),
767                                                    GTK_TREE_MODEL (store_icons),
768                                                    renderer, "stock-id", 0, NULL);
769    
770      g_object_set (G_OBJECT (column), "text-column", 0, NULL);
771    
772      hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector),
773                                                       HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE);
774    
775    
776      g_signal_connect (G_OBJECT (selector), "changed",
777                        G_CALLBACK (selection_changed), NULL);
778    
779      return selector;
780    }
781    
782    static gint on_picker_request(GtkWidget *button, GdkEventButton *event,
783                                  gpointer data) {
784    
785      if(event->type == GDK_BUTTON_PRESS) {
786        GtkWidget *dialog = hildon_picker_dialog_new(NULL);
787        GtkWidget *selector = create_customized_selector();
788        hildon_picker_dialog_set_selector(HILDON_PICKER_DIALOG(dialog),
789                          HILDON_TOUCH_SELECTOR(selector));
790    
791        hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR (selector), 1, -1);
792    
793        gtk_widget_show_all(dialog);
794        gtk_dialog_run(GTK_DIALOG(dialog));
795        gtk_widget_destroy(dialog);
796    
797        return TRUE;
798      }
799      return FALSE;
800    }
801    
802    GtkWidget *picker_button_new(void) {
803      GtkWidget *button;
804    
805    #if 1
806      button = gtk_button_new();
807      hildon_gtk_widget_set_theme_size(button,
808              (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
809    
810      gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 17));
811    
812      gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
813                         (GtkSignalFunc)on_picker_request, NULL);
814    
815    #else
816      button = hildon_picker_button_new(HILDON_SIZE_AUTO,
817                                        HILDON_BUTTON_ARRANGEMENT_VERTICAL);
818    
819      hildon_button_set_title(HILDON_BUTTON(button), "Test");
820      hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(button),
821                        HILDON_TOUCH_SELECTOR(create_customized_selector()));
822    #endif
823    
824      return button;
825    }
826    #endif

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