Fixing the way recent destinations and bookmarks are handled.
authortinloaf <tinloaf@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Sun, 19 Oct 2008 19:47:36 +0000 (19:47 +0000)
committertinloaf <tinloaf@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Sun, 19 Oct 2008 19:47:36 +0000 (19:47 +0000)
git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk@1514 ffa7fe5e-494d-0410-b361-a75ebd5db220

navit/navit/attr_def.h
navit/navit/gui/gtk/gui_gtk.h
navit/navit/gui/gtk/gui_gtk_window.c
navit/navit/navit.c
navit/navit/navit.xml

index e1a6d48..d5f0746 100644 (file)
@@ -70,6 +70,7 @@ ATTR(icon_xs)
 ATTR(icon_l)
 ATTR(icon_s)
 ATTR(spacing)
+ATTR(recent_dest)
 ATTR(destination_distance)
 ATTR2(0x00028000,type_boolean_begin)
 /* boolean */
index 0241606..45d144e 100644 (file)
@@ -40,6 +40,8 @@ struct gui_priv {
        GSList *layout_group;
        GSList *projection_group;
        GSList *vehicle_group;
+       GList *dest_menuitems;
+       GList *bookmarks_menuitems;
        GtkUIManager *menu_manager; // old
         struct statusbar_priv *statusbar;
        int menubar_enable;
index fc2ce12..d45ebe3 100644 (file)
@@ -250,18 +250,36 @@ gui_gtk_action_activate(GtkAction *action, struct action_cb_data *data)
                g_free(label);
        }
 }
+
+struct gui_menu_info {
+       guint merge_id;
+       GtkAction *action;
+};
+
 static void
+gui_gtk_del_menu(struct gui_priv *this, struct gui_menu_info *meninfo)
+{
+       gtk_action_group_remove_action(this->dyn_group, meninfo->action);
+       gtk_ui_manager_remove_ui(this->ui_manager, meninfo->merge_id);
+}
+
+static struct gui_menu_info
 gui_gtk_add_menu(struct gui_priv *this, char *name, char *label, char *path, int submenu, struct action_cb_data *data)
 {
+       struct gui_menu_info meninfo;
        GtkAction *action;
        guint merge_id;
 
        action=gtk_action_new(name, label, NULL, NULL);
+       meninfo.action = action;
        if (data)
                g_signal_connect(action, "activate", G_CALLBACK(gui_gtk_action_activate), data);
        gtk_action_group_add_action(this->dyn_group, action);
-       merge_id=gtk_ui_manager_new_merge_id(this->ui_manager);
+       merge_id =gtk_ui_manager_new_merge_id(this->ui_manager);
+       meninfo.merge_id = merge_id;
        gtk_ui_manager_add_ui(this->ui_manager, merge_id, path, name, name, submenu ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, FALSE);
+
+       return meninfo;
 }
 
 static void
@@ -406,16 +424,29 @@ gui_gtk_maps_init(struct gui_priv *this)
 }
 
 static void
-gui_gtk_destinations_init(struct gui_priv *this)
+gui_gtk_destinations_update(struct gui_priv *this)
 {
+       GList *curr;
        struct attr attr;
        struct action_cb_data *data;
        struct map_rect *mr=NULL;
        struct item *item;
+       struct gui_menu_info *meninfo;
        struct coord c;
        int count=0;
        char *name, *label;
 
+       curr = g_list_first(this->dest_menuitems);
+
+       while (curr) {
+               gui_gtk_del_menu(this, (struct gui_menu_info *)curr->data);
+               g_free((struct gui_menu_info *)curr->data);
+               curr = g_list_next(curr);
+       };
+
+       g_list_free(this->dest_menuitems);
+       this->dest_menuitems = NULL;
+
        if(navit_get_attr(this->nav, attr_former_destination_map, &attr, NULL) && attr.u.map && (mr=map_rect_new(attr.u.map, NULL))) {
                while ((item=map_rect_get_item(mr))) {
                        if (item->type != type_former_destination) continue;
@@ -430,7 +461,10 @@ gui_gtk_destinations_init(struct gui_priv *this)
                        data->attr.u.pcoord->pro=projection_mg;
                        data->attr.u.pcoord->x=c.x;
                        data->attr.u.pcoord->y=c.y;
-                       gui_gtk_add_menu(this, name, label, "/ui/MenuBar/Route/FormerDestinations/FormerDestinationMenuAdditions",0,data); 
+                       
+                       meninfo = g_new(struct gui_menu_info, 1);
+                       *meninfo = gui_gtk_add_menu(this, name, label, "/ui/MenuBar/Route/FormerDestinations/FormerDestinationMenuAdditions",0,data); 
+                       this->dest_menuitems = g_list_prepend(this->dest_menuitems, meninfo);
                        g_free(name);
                }
                map_rect_destroy(mr);
@@ -438,17 +472,37 @@ gui_gtk_destinations_init(struct gui_priv *this)
 }
 
 static void
-gui_gtk_bookmarks_init(struct gui_priv *this)
+gui_gtk_destinations_init(struct gui_priv *this)
 {
+       navit_add_callback(this->nav, callback_new_attr_1(gui_gtk_destinations_update, attr_destination, this));
+       gui_gtk_destinations_update(this);
+}
+
+static void
+gui_gtk_bookmarks_update(struct gui_priv *this)
+{
+       GList *curr;
        struct attr attr;
        struct action_cb_data *data;
        struct map_rect *mr=NULL;
+       struct gui_menu_info *meninfo;
        struct item *item;
        struct coord c;
        int count=0;
        char *parent, *name, *label, *label_full, *menu_label, *tmp_parent, *s;
        GHashTable *hash;
 
+       curr = g_list_first(this->bookmarks_menuitems);
+
+       while (curr) {
+               gui_gtk_del_menu(this, (struct gui_menu_info *)curr->data);
+               g_free((struct gui_menu_info *)curr->data);
+               curr = g_list_next(curr);
+       };
+
+       g_list_free(this->bookmarks_menuitems);
+       this->bookmarks_menuitems = NULL;
+
        if(navit_get_attr(this->nav, attr_bookmark_map, &attr, NULL) && attr.u.map && (mr=map_rect_new(attr.u.map, NULL))) {
                hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
                while ((item=map_rect_get_item(mr))) {
@@ -466,7 +520,9 @@ gui_gtk_bookmarks_init(struct gui_priv *this)
                                        tmp_parent=g_strdup(tmp_parent);
                                } else {
                                        name=g_strdup_printf("Bookmark %d", count++);
-                                       gui_gtk_add_menu(this, name, menu_label+(label-label_full),parent,1,NULL);
+                                       meninfo = g_new(struct gui_menu_info, 1);
+                                       *meninfo = gui_gtk_add_menu(this, name, menu_label+(label-label_full),parent,1,NULL);
+                                       this->bookmarks_menuitems = g_list_prepend(this->bookmarks_menuitems, meninfo);
                                        tmp_parent=g_strdup_printf("%s/%s", parent, name);
                                        g_hash_table_insert(hash, g_strdup(menu_label), g_strdup(tmp_parent));
                                        g_free(name);
@@ -484,7 +540,9 @@ gui_gtk_bookmarks_init(struct gui_priv *this)
                        data->attr.u.pcoord->x=c.x;
                        data->attr.u.pcoord->y=c.y;
                        name=g_strdup_printf("Bookmark %d", count++);
-                       gui_gtk_add_menu(this, name, label, parent,0,data); 
+                       meninfo = g_new(struct gui_menu_info, 1);
+                       *meninfo = gui_gtk_add_menu(this, name, label, parent,0,data);
+                       this->bookmarks_menuitems = g_list_prepend(this->bookmarks_menuitems, meninfo);
                        g_free(name);
                        g_free(parent);
                }
@@ -493,6 +551,13 @@ gui_gtk_bookmarks_init(struct gui_priv *this)
 }
 
 static void
+gui_gtk_bookmarks_init(struct gui_priv *this)
+{
+       navit_add_callback(this->nav, callback_new_attr_1(gui_gtk_bookmarks_update, attr_bookmark_map, this));
+       gui_gtk_bookmarks_update(this);
+}
+
+static void
 gui_gtk_init(struct gui_priv *this, struct navit *nav)
 {
 
index 9506332..9c8f453 100644 (file)
@@ -101,6 +101,7 @@ struct navit {
        int cursor_flag;
        int tracking_flag;
        int orient_north_flag;
+       int recentdest_count;
        GList *vehicles;
        GList *windows_items;
        struct navit_vehicle *vehicle;
@@ -112,9 +113,7 @@ struct navit {
        struct datawindow *roadbook_window;
        struct map *bookmark;
        struct map *former_destination;
-       struct menu *bookmarks;
        GHashTable *bookmarks_hash;
-       struct menu *destinations;
        struct point pressed, last, current;
        int button_pressed,moved,popped;
        struct event_timer *button_timeout, *motion_timeout;
@@ -428,6 +427,7 @@ navit_new(struct attr *parent, struct attr **attrs)
        this_->cursor_flag=1;
        this_->orient_north_flag=0;
        this_->tracking_flag=1;
+       this_->recentdest_count=10;
 
        for (;*attrs; attrs++) {
                switch((*attrs)->type) {
@@ -446,6 +446,9 @@ navit_new(struct attr *parent, struct attr **attrs)
                case attr_tracking:
                        this_->tracking_flag=!!(*attrs)->u.num;
                        break;
+               case attr_recent_dest:
+                       this_->recentdest_count=(*attrs)->u.num;
+                       break;
                default:
                        dbg(0, "Unexpected attribute %x\n",(*attrs)->type);
                        break;
@@ -513,43 +516,73 @@ navit_projection_set(struct navit *this_, enum projection pro)
        navit_draw(this_);
 }
 
+/**
+ * @param limit Limits the number of entries in the "backlog". Set to 0 for "infinite"
+ */
 static void
-navit_add_menu_destinations(struct navit *this_, char *name, struct menu *rmen, GHashTable *h, struct callback *cb)
-{
-       char buffer2[2048];
-       char *i,*n;
-       struct menu *men,*nmen;
-
-       if (rmen) {
-               i=name;
-               n=name;
-               men=rmen;
-               while (h && (i=strchr(n, '/'))) {
-                       strcpy(buffer2, name);
-                       buffer2[i-name]='\0';
-                       if (!(nmen=g_hash_table_lookup(h, buffer2))) {
-                               nmen=menu_add(men, buffer2+(n-name), menu_type_submenu, NULL);
-                               g_hash_table_insert(h, g_strdup(buffer2), nmen);
-                       }
-                       n=i+1;
-                       men=nmen;
-               }
-               menu_add(men, n, menu_type_menu, cb);
-       }
-}
-
-static void
-navit_append_coord(struct navit *this_, char *file, struct pcoord *c, char *type, char *description, struct menu *rmen, GHashTable *h, void (*cb_func)(void))
+navit_append_coord(struct navit *this_, char *file, struct pcoord *c, char *type, char *description, GHashTable *h, int limit)
 {
        FILE *f;
        int offset=0;
        char *buffer;
+       int ch,prev,lines=0;
+       int numc,readc;
+       int fd;
        const char *prostr;
        struct callback *cb;
 
+       f=fopen(file, "r");
+       if (limit != 0) {
+               prev = '\n';
+               while ((ch = fgetc(f)) != EOF) {
+                       if ((ch == '\n') && (prev != '\n')) {
+                               lines++;
+                       }
+                       prev = ch;
+               }
+
+               if (prev != '\n') { // Last line did not end with a newline
+                       lines++;
+               }
+
+               fclose(f);
+               f = fopen(file, "r+");
+               fd = fileno(f);
+               while (lines >= limit) { // We have to "scroll up"
+                       rewind(f);
+                       numc = 0; // Counts how many bytes we have in our line to scroll up
+                       while ((ch = fgetc(f)) != EOF) {
+                               numc++;
+                               if (ch == '\n') {
+                                       break;
+                               }
+                       }
+
+                       buffer=g_malloc(numc);
+                       offset = numc; // Offset holds where we currently are
+                       
+                       do {
+                               fseek(f,offset,SEEK_SET);
+                               readc = fread(buffer,1,numc,f);
+                               
+                               fseek(f,-(numc+readc),SEEK_CUR);
+                               fwrite(buffer,1,readc,f);
+
+                               offset += readc;
+                       } while (readc == numc);
+
+                       g_free(buffer);
+                       fflush(f);
+                       ftruncate(fd,(offset-numc));
+                       fsync(fd);
+
+                       lines--;
+               }
+               fclose(f);
+       }
+
        f=fopen(file, "a");
        if (f) {
-               offset=ftell(f);
                if (c) {
                        prostr = projection_to_name(c->pro);
                        fprintf(f,"%s%s%s0x%x %s0x%x type=%s label=\"%s\"\n",
@@ -561,12 +594,6 @@ navit_append_coord(struct navit *this_, char *file, struct pcoord *c, char *type
                        fprintf(f,"\n");
                fclose(f);
        }
-       if (c) {
-               buffer=g_strdup(description);
-               cb=callback_new_2(cb_func, this_, (void *)offset);
-               navit_add_menu_destinations(this_, buffer, rmen, h, cb);
-               g_free(buffer);
-       }
 }
 
 static int
@@ -673,44 +700,6 @@ navit_get_center_file(gboolean create)
        return g_strjoin(NULL, navit_get_user_data_directory(create), "center.txt", NULL);
 }
 
-
-static void
-navit_set_destination_from_file(struct navit *this_, char *file, int bookmark, int offset)
-{
-       FILE *f;
-       char *name, *description, buffer[2048];
-       struct pcoord c;
-
-       f=fopen(file, "r");
-       if (! f)
-               return;
-       fseek(f, offset, SEEK_SET);
-       if (parse_line(f, buffer, &name, &c) <= 0)
-               return;
-       if (bookmark) {
-               description=g_strdup_printf("Bookmark %s", name);
-               navit_set_destination(this_, &c, description);
-               g_free(description);
-       } else
-               navit_set_destination(this_, &c, name);
-}
-
-static void
-navit_set_destination_from_destination(struct navit *this_, void *offset_p)
-{
-       char *destination_file = navit_get_destination_file(FALSE);
-       navit_set_destination_from_file(this_, destination_file, 0, (int)offset_p);
-       g_free(destination_file);
-}
-
-static void
-navit_set_destination_from_bookmark(struct navit *this_, void *offset_p)
-{
-       char *bookmark_file = navit_get_bookmark_file(FALSE);
-       navit_set_destination_from_file(this_, bookmark_file, 1, (int)offset_p);
-       g_free(bookmark_file);
-}
-
 static void
 navit_set_center_from_file(struct navit *this_, char *file)
 {
@@ -772,9 +761,9 @@ navit_set_destination(struct navit *this_, struct pcoord *c, char *description)
        } else
                this_->destination_valid=0;
        char *destination_file = navit_get_destination_file(TRUE);
-       navit_append_coord(this_, destination_file, c, "former_destination", description, this_->destinations, NULL, callback_cast(navit_set_destination_from_destination));
+       navit_append_coord(this_, destination_file, c, "former_destination", description, NULL, this_->recentdest_count);
        g_free(destination_file);
-       callback_list_call_attr_1(this_->attr_cbl, attr_destination, this_);
+       callback_list_call_attr_0(this_->attr_cbl, attr_destination);
        if (this_->route) {
                route_set_destination(this_->route, c);
                if (this_->navigation)
@@ -795,66 +784,13 @@ void
 navit_add_bookmark(struct navit *this_, struct pcoord *c, const char *description)
 {
        char *bookmark_file = navit_get_bookmark_file(TRUE);
-       navit_append_coord(this_,bookmark_file, c, "bookmark", description, this_->bookmarks, this_->bookmarks_hash, callback_cast(navit_set_destination_from_bookmark));
+       navit_append_coord(this_,bookmark_file, c, "bookmark", description, this_->bookmarks_hash,0);
        g_free(bookmark_file);
-}
 
-struct navit *global_navit;
-
-static void
-navit_add_menu_destinations_from_file(struct navit *this_, char *file, struct menu *rmen, GHashTable *h, struct route *route, void (*cb_func)(void))
-{
-       int pos,flag=0;
-       FILE *f;
-       char buffer[2048];
-       struct pcoord c;
-       char *name;
-       int offset=0;
-       struct callback *cb;
-
-       f=fopen(file, "r");
-       if (f) {
-               while (! feof(f) && (pos=parse_line(f, buffer, &name, &c)) > -3) {
-                       if (pos > 0) {
-                               cb=callback_new_2(cb_func, this_, (void *)offset);
-                               navit_add_menu_destinations(this_, name, rmen, h, cb);
-                               flag=1;
-                       } else
-                               flag=0;
-                       offset=ftell(f);
-               }
-               fclose(f);
-               if (route && flag) {
-                       this_->destination=c;
-                       this_->destination_valid=1;
-                       route_set_destination(route, &c);
-               }
-       }
-}
-
-static void
-navit_add_menu_former_destinations(struct navit *this_, struct menu *men, struct route *route)
-{
-       if (men)
-               this_->destinations=menu_add(men, _("Former Destinations"), menu_type_submenu, NULL);
-       else
-               this_->destinations=NULL;
-       char *destination_file = navit_get_destination_file(FALSE);
-       navit_add_menu_destinations_from_file(this_, destination_file, this_->destinations, NULL, route, callback_cast(navit_set_destination_from_destination));
-       g_free(destination_file);
+       callback_list_call_attr_0(this_->attr_cbl, attr_bookmark_map);
 }
 
-static void
-navit_add_menu_bookmarks(struct navit *this_, struct menu *men)
-{
-       if (men)
-               this_->bookmarks=menu_add(men, _("Bookmarks"), menu_type_submenu, NULL);
-       else
-               this_->bookmarks=NULL;
-       char *bookmark_file = navit_get_bookmark_file(FALSE);
-       navit_add_menu_destinations_from_file(this_, bookmark_file, this_->bookmarks, this_->bookmarks_hash, NULL, callback_cast(navit_set_destination_from_bookmark));
-       g_free(bookmark_file);
-}
+struct navit *global_navit;
 
 static void
 navit_add_bookmarks_from_file(struct navit *this_)
@@ -1269,7 +1205,6 @@ navit_init(struct navit *this_)
                }
                navit_add_bookmarks_from_file(this_);
                navit_add_former_destinations_from_file(this_);
-               navit_add_menu_former_destinations(this_, NULL, this_->route);
        }
        if (this_->navigation && this_->speech) {
                this_->nav_speech_cb=callback_new_1(callback_cast(navit_speak), this_);
@@ -1545,6 +1480,9 @@ navit_add_attr(struct navit *this_, struct attr *attr)
        case attr_navigation:
                this_->navigation=attr->u.navigation;
                break;
+       case attr_recent_dest:
+               this_->recentdest_count = attr->u.num;
+               break;
        default:
                return 0;
        }
index 48ee4f6..eb9690e 100644 (file)
@@ -25,7 +25,7 @@ http://wiki.navit-project.org/index.php/Configuring_NavIt
        This line defines which location on the map navit will show after startup.
        It makes sense to set it to your home coordinates.
        -->
-       <navit center="4808 N 1134 E" zoom="256" tracking="1" cursor="1" orientation="0">
+       <navit center="4808 N 1134 E" zoom="256" tracking="1" cursor="1" orientation="0" recent_dest="10">
 
 
                <!--
@@ -70,6 +70,8 @@ http://wiki.navit-project.org/index.php/Configuring_NavIt
 
                <tracking>
                </tracking>
+               
+               
 
                <route destination_distance="50">
                        <speed type="street_0,street_1_city" value="10" />