Diff of /trunk/src/relation_edit.c

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

revision 73 by harbaum, Thu Feb 12 14:27:52 2009 UTC revision 148 by harbaum, Fri Mar 27 14:49:30 2009 UTC
# Line 19  Line 19 
19    
20  #include "appdata.h"  #include "appdata.h"
21    
22    /* UI sizes */
23    
24    #ifdef USE_HILDON
25    // Making the dialog a little wider makes it less "crowded"
26    static const guint LIST_OF_RELATIONS_DIALOG_WIDTH   = 500;
27    static const guint LIST_OF_RELATIONS_DIALOG_HEIGHT  = 300;
28    static const guint LIST_OF_MEMBERS_DIALOG_WIDTH   = 500;
29    static const guint LIST_OF_MEMBERS_DIALOG_HEIGHT  = 300;
30    #else
31    // Desktop mode dialogs should be narrower and taller
32    static const guint LIST_OF_RELATIONS_DIALOG_WIDTH  = 475;
33    static const guint LIST_OF_RELATIONS_DIALOG_HEIGHT = 350;
34    static const guint LIST_OF_MEMBERS_DIALOG_WIDTH   = 450;
35    static const guint LIST_OF_MEMBERS_DIALOG_HEIGHT  = 350;
36    #endif
37    
38    
39  /* --------------- relation dialog for an item (node or way) ----------- */  /* --------------- relation dialog for an item (node or way) ----------- */
40    
41  typedef struct {  typedef struct {
42    relation_item_t *item;    relation_item_t *item;
43    appdata_t *appdata;    appdata_t *appdata;
44    GtkWidget *dialog, *view;    GtkWidget *dialog, *list;
45    GtkListStore *store;    GtkListStore *store;
   GtkWidget *but_add, *but_edit, *but_remove;  
46  } relitem_context_t;  } relitem_context_t;
47    
48  enum {  enum {
# Line 192  static void relation_remove_item(relatio Line 208  static void relation_remove_item(relatio
208    g_assert(0);    g_assert(0);
209  }  }
210    
211  static void relation_list_selected(relitem_context_t *context,  static void relation_item_list_selected(relitem_context_t *context,
212                                     gboolean selected) {                                     gboolean selected) {
213    
214    if(context->but_remove)    list_button_enable(context->list, LIST_BUTTON_REMOVE, selected);
215      gtk_widget_set_sensitive(context->but_remove, FALSE);    list_button_enable(context->list, LIST_BUTTON_EDIT, selected);
   if(context->but_edit)  
     gtk_widget_set_sensitive(context->but_edit, selected);  
216  }  }
217    
218  static gboolean  /* try to find something descriptive */
219  relation_list_selection_func(GtkTreeSelection *selection, GtkTreeModel *model,  static char *relation_get_descriptive_name(relation_t *relation) {
220                       GtkTreePath *path, gboolean path_currently_selected,    char *name = osm_tag_get_by_key(relation->tag, "ref");
221                       gpointer userdata) {    if (!name)
222    relitem_context_t *context = (relitem_context_t*)userdata;      name = osm_tag_get_by_key(relation->tag, "name");
223    GtkTreeIter iter;    if (!name)
224        name = osm_tag_get_by_key(relation->tag, "note");
225    if(gtk_tree_model_get_iter(model, &iter, path)) {    if (!name)
226      g_assert(gtk_tree_path_get_depth(path) == 1);      name = osm_tag_get_by_key(relation->tag, "fix" "me");
227      relation_list_selected(context, TRUE);    return name;
   }  
   
   return TRUE; /* allow selection state to change */  
228  }  }
229    
230  static void on_relation_add(GtkWidget *but, relitem_context_t *context) {  static void on_relation_item_add(GtkWidget *but, relitem_context_t *context) {
231    /* create a new relation */    /* create a new relation */
232    
233    relation_t *relation = osm_relation_new();    relation_t *relation = osm_relation_new();
# Line 229  static void on_relation_add(GtkWidget *b Line 240  static void on_relation_add(GtkWidget *b
240      /* add to list */      /* add to list */
241    
242      /* append a row for the new data */      /* append a row for the new data */
243      /* try to find something descriptive */      char *name = relation_get_descriptive_name(relation);
     char *name = osm_tag_get_by_key(relation->tag, "name");  
     if(!name) name = osm_tag_get_by_key(relation->tag, "ref");  
244    
245      GtkTreeIter iter;      GtkTreeIter iter;
246      gtk_list_store_append(context->store, &iter);      gtk_list_store_append(context->store, &iter);
# Line 243  static void on_relation_add(GtkWidget *b Line 252  static void on_relation_add(GtkWidget *b
252                         RELITEM_COL_DATA, relation,                         RELITEM_COL_DATA, relation,
253                         -1);                         -1);
254    
255      gtk_tree_selection_select_iter(gtk_tree_view_get_selection(      gtk_tree_selection_select_iter(list_get_selection(context->list), &iter);
                GTK_TREE_VIEW(context->view)), &iter);  
256    
257      /* scroll to end */      /* scroll to end */
258      //    GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment();      //    GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment();
# Line 257  static relation_t *get_selection(relitem Line 265  static relation_t *get_selection(relitem
265    GtkTreeModel     *model;    GtkTreeModel     *model;
266    GtkTreeIter       iter;    GtkTreeIter       iter;
267    
268    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view));    selection = list_get_selection(context->list);
269    if(gtk_tree_selection_get_selected(selection, &model, &iter)) {    if(gtk_tree_selection_get_selected(selection, &model, &iter)) {
270      relation_t *relation;      relation_t *relation;
271      gtk_tree_model_get(model, &iter, RELITEM_COL_DATA, &relation, -1);      gtk_tree_model_get(model, &iter, RELITEM_COL_DATA, &relation, -1);
# Line 266  static relation_t *get_selection(relitem Line 274  static relation_t *get_selection(relitem
274    return NULL;    return NULL;
275  }  }
276    
277  static void on_relation_edit(GtkWidget *but, relitem_context_t *context) {  static void on_relation_item_edit(GtkWidget *but, relitem_context_t *context) {
278    relation_t *sel = get_selection(context);    relation_t *sel = get_selection(context);
279    if(!sel) return;    if(!sel) return;
280    
281    printf("edit relation #%ld\n", sel->id);    printf("edit relation item #%ld\n", sel->id);
282    
283      if (!info_dialog(context->dialog, context->appdata, sel))
284        return;
285    
286      // Locate the changed item
287      GtkTreeIter iter;
288      gboolean valid = gtk_tree_model_get_iter_first(
289        GTK_TREE_MODEL(context->store), &iter);
290      while (valid) {
291        relation_t *row_rel;
292        gtk_tree_model_get(GTK_TREE_MODEL(context->store), &iter,
293                           RELITEM_COL_DATA, &row_rel,
294                           -1);
295        if (row_rel == sel)
296          break;
297        valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(context->store), &iter);
298      }
299      if (!valid)
300        return;
301    
302      // Found it. Update all visible fields that belong to the relation iself.
303      gtk_list_store_set(context->store, &iter,
304        RELITEM_COL_TYPE,    osm_tag_get_by_key(sel->tag, "type"),
305        RELITEM_COL_NAME,    relation_get_descriptive_name(sel),
306        -1);
307    
308    info_dialog(context->dialog, context->appdata, sel);    // Order will probably have changed, so refocus
309      list_focus_on(context->list, &iter, TRUE);
310  }  }
311    
312  static void on_relation_remove(GtkWidget *but, relitem_context_t *context) {  /* remove the selected relation */
313    static void on_relation_item_remove(GtkWidget *but, relitem_context_t *context) {
314    relation_t *sel = get_selection(context);    relation_t *sel = get_selection(context);
315    if(!sel) return;    if(!sel) return;
316    
317    printf("remove relation #%ld\n", sel->id);    printf("remove relation #%ld\n", sel->id);
318    
319      gint members = osm_relation_members_num(sel);
320    
321      if(members)
322        if(!yes_no_f(context->dialog, NULL, 0, 0,
323                     _("Delete non-empty relation?"),
324                     _("This relation still has %d members. "
325                       "Delete it anyway?"), members))
326          return;
327    
328      /* first remove selected row from list */
329      GtkTreeIter       iter;
330      GtkTreeSelection *selection = list_get_selection(context->list);
331      if(gtk_tree_selection_get_selected(selection, NULL, &iter))
332        gtk_list_store_remove(context->store, &iter);
333    
334      /* then really delete it */
335      osm_relation_delete(context->appdata->osm, sel, FALSE);
336    
337      relation_item_list_selected(context, FALSE);
338  }  }
339    
340  static char *relitem_get_role_in_relation(relation_item_t *item, relation_t *relation) {  static char *relitem_get_role_in_relation(relation_item_t *item, relation_t *relation) {
# Line 307  static char *relitem_get_role_in_relatio Line 362  static char *relitem_get_role_in_relatio
362    
363  static void  static void
364  relitem_toggled(GtkCellRendererToggle *cell, const gchar *path_str,  relitem_toggled(GtkCellRendererToggle *cell, const gchar *path_str,
365                relitem_context_t *context) {                  relitem_context_t *context) {
366    GtkTreePath *path;    GtkTreePath *path;
367    GtkTreeIter iter;    GtkTreeIter iter;
368    
# Line 323  relitem_toggled(GtkCellRendererToggle *c Line 378  relitem_toggled(GtkCellRendererToggle *c
378                       RELITEM_COL_DATA, &relation,                       RELITEM_COL_DATA, &relation,
379                       -1);                       -1);
380    
381      list_pre_inplace_edit_tweak(GTK_TREE_MODEL(context->store));
382    
383    if(!enabled) {    if(!enabled) {
384      printf("will now become be part of this relation\n");      printf("will now become be part of this relation\n");
385      if(relation_add_item(context->dialog, relation, context->item))      if(relation_add_item(context->dialog, relation, context->item))
# Line 339  relitem_toggled(GtkCellRendererToggle *c Line 396  relitem_toggled(GtkCellRendererToggle *c
396                         RELITEM_COL_ROLE, NULL,                         RELITEM_COL_ROLE, NULL,
397                         -1);                         -1);
398    }    }
399    
400  }  }
401    
402  static gboolean relitem_is_in_relation(relation_item_t *item, relation_t *relation) {  static gboolean relitem_is_in_relation(relation_item_t *item, relation_t *relation) {
# Line 364  static gboolean relitem_is_in_relation(r Line 422  static gboolean relitem_is_in_relation(r
422    return FALSE;    return FALSE;
423  }  }
424    
425  static GtkWidget *relation_list(relitem_context_t *context) {  static GtkWidget *relation_item_list_widget(relitem_context_t *context) {
426      context->list = list_new(LIST_HILDON_WITH_HEADERS);
427    
428      list_set_columns(context->list,
429                       _(""), RELITEM_COL_SELECTED, LIST_FLAG_TOGGLE,
430                                G_CALLBACK(relitem_toggled), context,
431                       _("Type"), RELITEM_COL_TYPE, 0,
432                       _("Role"), RELITEM_COL_ROLE, 0,
433                       _("Name"), RELITEM_COL_NAME, LIST_FLAG_ELLIPSIZE,
434                       NULL);
435    
436      /* build and fill the store */
437      context->store = gtk_list_store_new(RELITEM_NUM_COLS,
438                    G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING,
439                    G_TYPE_STRING, G_TYPE_POINTER);
440    
441      list_set_store(context->list, context->store);
442    
443      // Debatable whether to sort by the "selected" or the "Name" column by
444      // default. Both are be useful, in different ways.
445      gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(context->store),
446                                           RELITEM_COL_NAME, GTK_SORT_ASCENDING);
447    
448      GtkTreeIter iter;
449      relation_t *relation = context->appdata->osm->relation;
450      while(relation) {
451        /* try to find something descriptive */
452        char *name = relation_get_descriptive_name(relation);
453    
454        /* Append a row and fill in some data */
455        gtk_list_store_append(context->store, &iter);
456        gtk_list_store_set(context->store, &iter,
457           RELITEM_COL_SELECTED, relitem_is_in_relation(context->item, relation),
458           RELITEM_COL_TYPE, osm_tag_get_by_key(relation->tag, "type"),
459           RELITEM_COL_ROLE, relitem_get_role_in_relation(context->item, relation),
460           RELITEM_COL_NAME, name,
461           RELITEM_COL_DATA, relation,
462           -1);
463    
464        relation = relation->next;
465      }
466    
467      g_object_unref(context->store);
468    
469      list_set_static_buttons(context->list, G_CALLBACK(on_relation_item_add),
470              G_CALLBACK(on_relation_item_edit),G_CALLBACK(on_relation_item_remove), context);
471    
472      relation_item_list_selected(context, FALSE);
473    
474      return context->list;
475    }
476    
477    void relation_add_dialog(appdata_t *appdata, relation_item_t *relitem) {
478      relitem_context_t *context = g_new0(relitem_context_t, 1);
479      map_t *map = appdata->map;
480      g_assert(map);
481    
482      context->appdata = appdata;
483      context->item = relitem;
484    
485      char *str = NULL;
486      switch(relitem->type) {
487      case NODE:
488        str = g_strdup_printf(_("Relations for node #%ld"), relitem->node->id);
489        break;
490      case WAY:
491        str = g_strdup_printf(_("Relations for way #%ld"), relitem->way->id);
492        break;
493      default:
494        g_assert((relitem->type == NODE) || (relitem->type == WAY));
495        break;
496      }
497    
498      context->dialog = gtk_dialog_new_with_buttons(str,
499            GTK_WINDOW(appdata->window), GTK_DIALOG_MODAL,
500            GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
501            NULL);
502      g_free(str);
503    
504      gtk_dialog_set_default_response(GTK_DIALOG(context->dialog),
505                                      GTK_RESPONSE_CLOSE);
506    
507      gtk_window_set_default_size(GTK_WINDOW(context->dialog),
508                                  LIST_OF_RELATIONS_DIALOG_WIDTH,
509                                  LIST_OF_RELATIONS_DIALOG_HEIGHT);
510      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context->dialog)->vbox),
511                         relation_item_list_widget(context), TRUE, TRUE, 0);
512    
513      /* ----------------------------------- */
514    
515      gtk_widget_show_all(context->dialog);
516      gtk_dialog_run(GTK_DIALOG(context->dialog));
517      gtk_widget_destroy(context->dialog);
518    
519      g_free(context);
520    }
521    
522    /* -------------------- global relation list ----------------- */
523    
524    typedef struct {
525      appdata_t *appdata;
526      GtkWidget *dialog, *list;
527      GtkListStore *store;
528    } relation_context_t;
529    
530    enum {
531      RELATION_COL_ID = 0,
532      RELATION_COL_TYPE,
533      RELATION_COL_NAME,
534      RELATION_COL_MEMBERS,
535      RELATION_COL_DATA,
536      RELATION_NUM_COLS
537    };
538    
539    static relation_t *get_selected_relation(relation_context_t *context) {
540      GtkTreeSelection *selection;
541      GtkTreeModel     *model;
542      GtkTreeIter       iter;
543    
544      selection = list_get_selection(context->list);
545      if(gtk_tree_selection_get_selected(selection, &model, &iter)) {
546        relation_t *relation;
547        gtk_tree_model_get(model, &iter, RELATION_COL_DATA, &relation, -1);
548        return(relation);
549      }
550      return NULL;
551    }
552    
553    static void relation_list_selected(relation_context_t *context,
554                                       relation_t *selected) {
555    
556      list_button_enable(context->list, LIST_BUTTON_USER0,
557                         (selected != NULL) && (selected->member != NULL));
558    
559      list_button_enable(context->list, LIST_BUTTON_REMOVE, selected != NULL);
560      list_button_enable(context->list, LIST_BUTTON_EDIT, selected != NULL);
561    }
562    
563    static gboolean
564    relation_list_selection_func(GtkTreeSelection *selection, GtkTreeModel *model,
565                         GtkTreePath *path, gboolean path_currently_selected,
566                         gpointer userdata) {
567      relation_context_t *context = (relation_context_t*)userdata;
568      GtkTreeIter iter;
569    
570      if(gtk_tree_model_get_iter(model, &iter, path)) {
571        g_assert(gtk_tree_path_get_depth(path) == 1);
572    
573        relation_t *relation = NULL;
574        gtk_tree_model_get(model, &iter, RELATION_COL_DATA, &relation, -1);
575        relation_list_selected(context, relation);
576      }
577    
578      return TRUE; /* allow selection state to change */
579    }
580    
581    typedef struct {
582      relation_t *relation;
583      GtkWidget *dialog, *view;
584      GtkListStore *store;
585    } member_context_t;
586    
587    enum {
588      MEMBER_COL_TYPE = 0,
589      MEMBER_COL_ID,
590      MEMBER_COL_NAME,
591      MEMBER_COL_ROLE,
592      MEMBER_COL_REF_ONLY,
593      MEMBER_COL_DATA,
594      MEMBER_NUM_COLS
595    };
596    
597    static gboolean
598    member_list_selection_func(GtkTreeSelection *selection, GtkTreeModel *model,
599                         GtkTreePath *path, gboolean path_currently_selected,
600                         gpointer userdata) {
601      GtkTreeIter iter;
602    
603      if(gtk_tree_model_get_iter(model, &iter, path)) {
604        g_assert(gtk_tree_path_get_depth(path) == 1);
605    
606        member_t *member = NULL;
607        gtk_tree_model_get(model, &iter, MEMBER_COL_DATA, &member, -1);
608        if(member && member->type < NODE_ID)
609          return TRUE;
610      }
611    
612      return FALSE;
613    }
614    
615    
616    static GtkWidget *member_list_widget(member_context_t *context) {
617    GtkWidget *vbox = gtk_vbox_new(FALSE,3);    GtkWidget *vbox = gtk_vbox_new(FALSE,3);
618    context->view = gtk_tree_view_new();    context->view = gtk_tree_view_new();
619    
620    gtk_tree_selection_set_select_function(    gtk_tree_selection_set_select_function(
621           gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)),           gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)),
622           relation_list_selection_func,           member_list_selection_func,
623           context, NULL);           context, NULL);
624    
625      /* --- "type" column --- */
626    /* --- "selected" column --- */    GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
627    GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();    g_object_set(renderer, "foreground", "grey", NULL);
   g_signal_connect(renderer, "toggled", G_CALLBACK(relitem_toggled), context);  
628    gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view),    gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view),
629          -1, _(""), renderer,          -1, _("Type"), renderer, "text", MEMBER_COL_TYPE,
630          "active", RELITEM_COL_SELECTED,          "foreground-set", MEMBER_COL_REF_ONLY,  NULL);
         NULL);  
631    
   /* --- "Type" column --- */  
   renderer = gtk_cell_renderer_text_new();  
   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view),  
         -1, _("Type"), renderer, "text", RELITEM_COL_TYPE, NULL);  
632    
633    /* --- "Role" column --- */    /* --- "id" column --- */
634    renderer = gtk_cell_renderer_text_new();    renderer = gtk_cell_renderer_text_new();
635      g_object_set(renderer, "foreground", "grey", NULL);
636    gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view),    gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view),
637          -1, _("Role"), renderer, "text", RELITEM_COL_ROLE, NULL);          -1, _("Id"), renderer, "text", MEMBER_COL_ID,
638            "foreground-set", MEMBER_COL_REF_ONLY, NULL);
639    
640    /* --- "Name" column --- */    /* --- "Name" column --- */
641    renderer = gtk_cell_renderer_text_new();    renderer = gtk_cell_renderer_text_new();
642      g_object_set(renderer, "foreground", "grey", NULL);
643    g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);    g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
644    GtkTreeViewColumn *column =    GtkTreeViewColumn *column =
645      gtk_tree_view_column_new_with_attributes(_("Name"), renderer,      gtk_tree_view_column_new_with_attributes(_("Name"), renderer,
646                   "text", RELITEM_COL_NAME, NULL);                       "text", MEMBER_COL_NAME,
647                         "foreground-set", MEMBER_COL_REF_ONLY,  NULL);
648    gtk_tree_view_column_set_expand(column, TRUE);    gtk_tree_view_column_set_expand(column, TRUE);
649    gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1);    gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1);
650    
651      /* --- "role" column --- */
652      renderer = gtk_cell_renderer_text_new();
653      g_object_set(renderer, "foreground", "grey", NULL);
654      gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view),
655            -1, _("Role"), renderer, "text", MEMBER_COL_ROLE,
656            "foreground-set", MEMBER_COL_REF_ONLY, NULL);
657    
658    /* build and fill the store */    /* build and fill the store */
659    context->store = gtk_list_store_new(RELITEM_NUM_COLS,    context->store = gtk_list_store_new(MEMBER_NUM_COLS,
660                  G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING,                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
661                  G_TYPE_STRING, G_TYPE_POINTER);                G_TYPE_BOOLEAN, G_TYPE_POINTER);
662    
663    gtk_tree_view_set_model(GTK_TREE_VIEW(context->view),    gtk_tree_view_set_model(GTK_TREE_VIEW(context->view),
664                            GTK_TREE_MODEL(context->store));                            GTK_TREE_MODEL(context->store));
665    
666    GtkTreeIter iter;    GtkTreeIter iter;
667    relation_t *relation = context->appdata->osm->relation;    member_t *member = context->relation->member;
668    while(relation) {    while(member) {
669        tag_t *tags = osm_object_get_tags(member->type, member->ptr);
670        char *id = osm_id_string(member->type, member->ptr);
671    
672      /* try to find something descriptive */      /* try to find something descriptive */
673      char *name = osm_tag_get_by_key(relation->tag, "name");      char *name = NULL;
674      if(!name) name = osm_tag_get_by_key(relation->tag, "ref");      if(tags)
675          name = osm_tag_get_by_key(tags, "name");
676    
677      /* Append a row and fill in some data */      /* Append a row and fill in some data */
678      gtk_list_store_append(context->store, &iter);      gtk_list_store_append(context->store, &iter);
679      gtk_list_store_set(context->store, &iter,      gtk_list_store_set(context->store, &iter,
680         RELITEM_COL_SELECTED, relitem_is_in_relation(context->item, relation),         MEMBER_COL_TYPE, osm_type_string(member->type),
681         RELITEM_COL_TYPE, osm_tag_get_by_key(relation->tag, "type"),         MEMBER_COL_ID,   id,
682         RELITEM_COL_ROLE, relitem_get_role_in_relation(context->item, relation),         MEMBER_COL_NAME, name,
683         RELITEM_COL_NAME, name,         MEMBER_COL_ROLE, member->role,
684         RELITEM_COL_DATA, relation,         MEMBER_COL_REF_ONLY, member->type >= NODE_ID,
685           MEMBER_COL_DATA, member,
686         -1);         -1);
687    
688      relation = relation->next;      g_free(id);
689        member = member->next;
690    }    }
691    
692    g_object_unref(context->store);    g_object_unref(context->store);
693    
694    /* put it into a scrolled window */    /* put it into a scrolled window */
# Line 442  static GtkWidget *relation_list(relitem_ Line 701  static GtkWidget *relation_list(relitem_
701    
702    gtk_box_pack_start_defaults(GTK_BOX(vbox), scrolled_window);    gtk_box_pack_start_defaults(GTK_BOX(vbox), scrolled_window);
703    
704    /* ------- button box ------------ */    return vbox;
705    }
706    
707    GtkWidget *hbox = gtk_hbox_new(TRUE,3);  /* user clicked "members..." button in relation list */
708    static void on_relation_members(GtkWidget *but, relation_context_t *context) {
709      member_context_t *mcontext = g_new0(member_context_t, 1);
710    
711      /* display members list */
712      mcontext->relation = get_selected_relation(context);
713      if(!mcontext->relation) return;
714    
715      char *str = osm_tag_get_by_key(mcontext->relation->tag, "name");
716      if(!str) str = osm_tag_get_by_key(mcontext->relation->tag, "ref");
717      if(!str)
718        str = g_strdup_printf(_("Members of relation #%ld"),
719                              mcontext->relation->id);
720      else
721        str = g_strdup_printf(_("Members of relation \"%s\""), str);
722    
723    context->but_add = gtk_button_new_with_label(_("Add..."));    mcontext->dialog =
724    //  gtk_widget_set_sensitive(context->but_add, FALSE);      gtk_dialog_new_with_buttons(str,
725    gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_add);          GTK_WINDOW(context->dialog), GTK_DIALOG_MODAL,
726    gtk_signal_connect(GTK_OBJECT(context->but_add), "clicked",          GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
727                       GTK_SIGNAL_FUNC(on_relation_add), context);          NULL);
728      g_free(str);
729    
730      gtk_dialog_set_default_response(GTK_DIALOG(mcontext->dialog),
731                                      GTK_RESPONSE_CLOSE);
732    
733    context->but_edit = gtk_button_new_with_label(_("Edit..."));    gtk_window_set_default_size(GTK_WINDOW(mcontext->dialog),
734    gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_edit);                                LIST_OF_MEMBERS_DIALOG_WIDTH,
735    gtk_signal_connect(GTK_OBJECT(context->but_edit), "clicked",                                LIST_OF_MEMBERS_DIALOG_HEIGHT);
                      GTK_SIGNAL_FUNC(on_relation_edit), context);  
736    
737    context->but_remove = gtk_button_new_with_label(_("Remove"));    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(mcontext->dialog)->vbox),
738    gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_remove);                       member_list_widget(mcontext), TRUE, TRUE, 0);
   gtk_signal_connect(GTK_OBJECT(context->but_remove), "clicked",  
                      GTK_SIGNAL_FUNC(on_relation_remove), context);  
739    
740    relation_list_selected(context, FALSE);    /* ----------------------------------- */
741    
742    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);    gtk_widget_show_all(mcontext->dialog);
743    return vbox;    gtk_dialog_run(GTK_DIALOG(mcontext->dialog));
744      gtk_widget_destroy(mcontext->dialog);
745    
746      g_free(mcontext);
747  }  }
748    
749  void relation_add_dialog(appdata_t *appdata, relation_item_t *relitem) {  static void on_relation_add(GtkWidget *but, relation_context_t *context) {
750    relitem_context_t *context = g_new0(relitem_context_t, 1);    /* create a new relation */
   map_t *map = appdata->map;  
   g_assert(map);  
751    
752    context->appdata = appdata;    relation_t *relation = osm_relation_new();
753    context->item = relitem;    if(!info_dialog(context->dialog, context->appdata, relation)) {
754        printf("tag edit cancelled\n");
755        osm_relation_free(relation);
756      } else {
757        osm_relation_attach(context->appdata->osm, relation);
758    
759    char *str = NULL;      /* append a row for the new data */
760    switch(relitem->type) {  
761    case NODE:      char *name = relation_get_descriptive_name(relation);
762      str = g_strdup_printf(_("Relations for node #%ld"), relitem->node->id);  
763      break;      guint num = osm_relation_members_num(relation);
764    case WAY:  
765      str = g_strdup_printf(_("Relations for way #%ld"), relitem->way->id);      /* Append a row and fill in some data */
766      break;      GtkTreeIter iter;
767    default:      gtk_list_store_append(context->store, &iter);
768      g_assert((relitem->type == NODE) || (relitem->type == WAY));      gtk_list_store_set(context->store, &iter,
769      break;                         RELATION_COL_ID, relation->id,
770                           RELATION_COL_TYPE,
771                           osm_tag_get_by_key(relation->tag, "type"),
772                           RELATION_COL_NAME, name,
773                           RELATION_COL_MEMBERS, num,
774                           RELATION_COL_DATA, relation,
775                           -1);
776    
777        gtk_tree_selection_select_iter(list_get_selection(context->list), &iter);
778    
779        /* scroll to end */
780        //    GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment();
781        /* xyz */
782      }
783    }
784    
785    /* user clicked "edit..." button in relation list */
786    static void on_relation_edit(GtkWidget *but, relation_context_t *context) {
787      relation_t *sel = get_selected_relation(context);
788      if(!sel) return;
789    
790      printf("edit relation #%ld\n", sel->id);
791    
792      if (!info_dialog(context->dialog, context->appdata, sel))
793        return;
794    
795      // Locate the changed item
796      GtkTreeIter iter;
797      gboolean valid = gtk_tree_model_get_iter_first(
798        GTK_TREE_MODEL(context->store), &iter);
799      while (valid) {
800        relation_t *row_rel;
801        gtk_tree_model_get(GTK_TREE_MODEL(context->store), &iter,
802                           RELATION_COL_DATA, &row_rel,
803                           -1);
804        if (row_rel == sel)
805          break;
806        valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(context->store), &iter);
807    }    }
808      if (!valid)
809        return;
810    
811      // Found it. Update all visible fields.
812      gtk_list_store_set(context->store, &iter,
813        RELATION_COL_ID,      sel->id,
814        RELATION_COL_TYPE,    osm_tag_get_by_key(sel->tag, "type"),
815        RELATION_COL_NAME,    relation_get_descriptive_name(sel),
816        RELATION_COL_MEMBERS, osm_relation_members_num(sel),
817        -1);
818    
819      // Order will probably have changed, so refocus
820      list_focus_on(context->list, &iter, TRUE);
821    }
822    
823    
824    /* remove the selected relation */
825    static void on_relation_remove(GtkWidget *but, relation_context_t *context) {
826      relation_t *sel = get_selected_relation(context);
827      if(!sel) return;
828    
829      printf("remove relation #%ld\n", sel->id);
830    
831      gint members = osm_relation_members_num(sel);
832    
833      if(members)
834        if(!yes_no_f(context->dialog, NULL, 0, 0,
835                     _("Delete non-empty relation?"),
836                     _("This relation still has %d members. "
837                       "Delete it anyway?"), members))
838          return;
839    
840    context->dialog = gtk_dialog_new_with_buttons(str,    /* first remove selected row from list */
841      GtkTreeIter       iter;
842      GtkTreeSelection *selection = list_get_selection(context->list);
843      if(gtk_tree_selection_get_selected(selection, NULL, &iter))
844        gtk_list_store_remove(context->store, &iter);
845    
846      /* then really delete it */
847      osm_relation_delete(context->appdata->osm, sel, FALSE);
848    
849      relation_list_selected(context, NULL);
850    }
851    
852    static GtkWidget *relation_list_widget(relation_context_t *context) {
853      context->list = list_new(LIST_HILDON_WITH_HEADERS);
854    
855      list_set_selection_function(context->list, relation_list_selection_func, context);
856    
857      list_set_columns(context->list,
858                       _("Id"),      RELATION_COL_ID, 0,
859                       _("Type"),    RELATION_COL_TYPE, 0,
860                       _("Name"),    RELATION_COL_NAME, LIST_FLAG_ELLIPSIZE,
861                       _("Members"), RELATION_COL_MEMBERS, 0,
862                       NULL);
863    
864      /* build and fill the store */
865      context->store = gtk_list_store_new(RELATION_NUM_COLS,
866                    G_TYPE_ITEM_ID_T, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT,
867                    G_TYPE_POINTER);
868    
869      list_set_store(context->list, context->store);
870    
871      // Sorting by ref/name by default is useful for places with lots of numbered
872      // bus routes. Especially for small screens.
873      gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(context->store),
874                                           RELATION_COL_NAME, GTK_SORT_ASCENDING);
875    
876      GtkTreeIter iter;
877      relation_t *relation = context->appdata->osm->relation;
878      while(relation) {
879        char *name = relation_get_descriptive_name(relation);
880    
881        guint num = osm_relation_members_num(relation);
882    
883        /* Append a row and fill in some data */
884        gtk_list_store_append(context->store, &iter);
885        gtk_list_store_set(context->store, &iter,
886                           RELATION_COL_ID, relation->id,
887                           RELATION_COL_TYPE,
888                           osm_tag_get_by_key(relation->tag, "type"),
889                           RELATION_COL_NAME, name,
890                           RELATION_COL_MEMBERS, num,
891                           RELATION_COL_DATA, relation,
892                           -1);
893    
894        relation = relation->next;
895      }
896    
897      g_object_unref(context->store);
898    
899      list_set_static_buttons(context->list, G_CALLBACK(on_relation_add),
900         G_CALLBACK(on_relation_edit), G_CALLBACK(on_relation_remove), context);
901    
902      list_set_user_buttons(context->list,
903            LIST_BUTTON_USER0, _("Members..."), G_CALLBACK(on_relation_members),
904            0);
905    
906      relation_list_selected(context, NULL);
907    
908      return context->list;
909    }
910    
911    /* a global view on all relations */
912    void relation_list(appdata_t *appdata) {
913      relation_context_t *context = g_new0(relation_context_t, 1);
914      context->appdata = appdata;
915    
916      printf("relation list\n");
917    
918      context->dialog =
919        gtk_dialog_new_with_buttons(_("All relations"),
920          GTK_WINDOW(appdata->window), GTK_DIALOG_MODAL,          GTK_WINDOW(appdata->window), GTK_DIALOG_MODAL,
921          GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,          GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
922          NULL);          NULL);
   g_free(str);  
923    
924    gtk_dialog_set_default_response(GTK_DIALOG(context->dialog),    gtk_dialog_set_default_response(GTK_DIALOG(context->dialog),
925                                    GTK_RESPONSE_ACCEPT);                                    GTK_RESPONSE_CLOSE);
926    
927    /* making the dialog a little wider makes it less "crowded" */    gtk_window_set_default_size(GTK_WINDOW(context->dialog),
928  #ifdef USE_HILDON                                LIST_OF_RELATIONS_DIALOG_WIDTH,
929    gtk_window_set_default_size(GTK_WINDOW(context->dialog), 500, 300);                                LIST_OF_RELATIONS_DIALOG_HEIGHT);
930  #else  
   gtk_window_set_default_size(GTK_WINDOW(context->dialog), 400, 200);  
 #endif  
931    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context->dialog)->vbox),    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context->dialog)->vbox),
932                       relation_list(context), TRUE, TRUE, 0);                       relation_list_widget(context), TRUE, TRUE, 0);
933    
934    /* ----------------------------------- */    /* ----------------------------------- */
935    
# Line 515  void relation_add_dialog(appdata_t *appd Line 939  void relation_add_dialog(appdata_t *appd
939    
940    g_free(context);    g_free(context);
941  }  }
942    
943    
944    // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.73  
changed lines
  Added in v.148