22 |
/* --------------- relation dialog for an item (node or way) ----------- */ |
/* --------------- relation dialog for an item (node or way) ----------- */ |
23 |
|
|
24 |
typedef struct { |
typedef struct { |
25 |
relation_item_t *item; |
object_t *item; |
26 |
appdata_t *appdata; |
appdata_t *appdata; |
27 |
GtkWidget *dialog, *view; |
GtkWidget *dialog, *list; |
28 |
GtkListStore *store; |
GtkListStore *store; |
|
GtkWidget *but_add, *but_edit, *but_remove; |
|
29 |
} relitem_context_t; |
} relitem_context_t; |
30 |
|
|
31 |
enum { |
enum { |
43 |
} role_chain_t; |
} role_chain_t; |
44 |
|
|
45 |
static gboolean relation_add_item(GtkWidget *parent, |
static gboolean relation_add_item(GtkWidget *parent, |
46 |
relation_t *relation, relation_item_t *item) { |
relation_t *relation, object_t *object) { |
47 |
role_chain_t *chain = NULL, **chainP = &chain; |
role_chain_t *chain = NULL, **chainP = &chain; |
48 |
|
|
49 |
printf("add item of type %d to relation #%ld\n", |
printf("add object of type %d to relation #" ITEM_ID_FORMAT "\n", |
50 |
item->type, relation->id); |
object->type, relation->id); |
51 |
|
|
52 |
/* ask the user for the role of the new item in this relation */ |
/* ask the user for the role of the new object in this relation */ |
53 |
|
|
54 |
/* collect roles first */ |
/* collect roles first */ |
55 |
member_t *member = relation->member; |
member_t *member = relation->member; |
74 |
} |
} |
75 |
|
|
76 |
/* ------------------ role dialog ---------------- */ |
/* ------------------ role dialog ---------------- */ |
77 |
GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Select role"), |
GtkWidget *dialog = |
78 |
GTK_WINDOW(parent), GTK_DIALOG_MODAL, |
misc_dialog_new(MISC_DIALOG_NOSIZE,_("Select role"), |
79 |
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, |
GTK_WINDOW(parent), |
80 |
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, |
81 |
NULL); |
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
82 |
|
NULL); |
83 |
|
|
84 |
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); |
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); |
85 |
|
|
87 |
|
|
88 |
char *info_str = NULL; |
char *info_str = NULL; |
89 |
if(type) info_str = g_strdup_printf(_("In relation of type: %s"), type); |
if(type) info_str = g_strdup_printf(_("In relation of type: %s"), type); |
90 |
else info_str = g_strdup_printf(_("In relation #%ld"), relation->id); |
else info_str = g_strdup_printf(_("In relation #" ITEM_ID_FORMAT), |
91 |
|
relation->id); |
92 |
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), |
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), |
93 |
gtk_label_new(info_str)); |
gtk_label_new(info_str)); |
94 |
g_free(info_str); |
g_free(info_str); |
144 |
member_t **memberP = &relation->member; |
member_t **memberP = &relation->member; |
145 |
while(*memberP) memberP = &(*memberP)->next; |
while(*memberP) memberP = &(*memberP)->next; |
146 |
|
|
147 |
|
g_assert((object->type == NODE)||(object->type == WAY)|| |
148 |
|
(object->type == RELATION)); |
149 |
|
|
150 |
/* create new member */ |
/* create new member */ |
151 |
*memberP = g_new0(member_t, 1); |
*memberP = g_new0(member_t, 1); |
152 |
(*memberP)->type = item->type; |
(*memberP)->object = *object; |
153 |
(*memberP)->role = role; |
(*memberP)->role = role; |
|
switch(item->type) { |
|
|
case NODE: |
|
|
(*memberP)->node = item->node; |
|
|
break; |
|
|
case WAY: |
|
|
(*memberP)->way = item->way; |
|
|
break; |
|
|
case RELATION: |
|
|
(*memberP)->relation = item->relation; |
|
|
break; |
|
|
default: |
|
|
g_assert((item->type == NODE)||(item->type == WAY)|| |
|
|
(item->type == RELATION)); |
|
|
break; |
|
|
} |
|
154 |
|
|
155 |
relation->flags |= OSM_FLAG_DIRTY; |
relation->flags |= OSM_FLAG_DIRTY; |
156 |
return TRUE; |
return TRUE; |
157 |
} |
} |
158 |
|
|
159 |
static void relation_remove_item(relation_t *relation, relation_item_t *item) { |
static void relation_remove_item(relation_t *relation, object_t *object) { |
160 |
|
|
161 |
printf("remove item of type %d from relation #%ld\n", |
printf("remove object of type %d from relation #" ITEM_ID_FORMAT "\n", |
162 |
item->type, relation->id); |
object->type, relation->id); |
163 |
|
|
164 |
member_t **member = &relation->member; |
member_t **member = &relation->member; |
165 |
while(*member) { |
while(*member) { |
166 |
if(((*member)->type == item->type) && |
if(((*member)->object.type == object->type) && |
167 |
(((item->type == NODE) && (item->node == (*member)->node)) || |
(((object->type == NODE) && |
168 |
((item->type == WAY) && (item->way == (*member)->way)) || |
(object->node == (*member)->object.node)) || |
169 |
((item->type == RELATION) && (item->relation == (*member)->relation)))) { |
((object->type == WAY) && |
170 |
|
(object->way == (*member)->object.way)) || |
171 |
|
((object->type == RELATION) && |
172 |
|
(object->relation == (*member)->object.relation)))) { |
173 |
|
|
174 |
member_t *next = (*member)->next; |
member_t *next = (*member)->next; |
175 |
osm_member_free(*member); |
osm_member_free(*member); |
187 |
static void relation_item_list_selected(relitem_context_t *context, |
static void relation_item_list_selected(relitem_context_t *context, |
188 |
gboolean selected) { |
gboolean selected) { |
189 |
|
|
190 |
if(context->but_remove) |
list_button_enable(context->list, LIST_BUTTON_REMOVE, selected); |
191 |
gtk_widget_set_sensitive(context->but_remove, selected); |
list_button_enable(context->list, LIST_BUTTON_EDIT, selected); |
|
if(context->but_edit) |
|
|
gtk_widget_set_sensitive(context->but_edit, selected); |
|
192 |
} |
} |
193 |
|
|
194 |
static gboolean |
/* try to find something descriptive */ |
195 |
relation_item_list_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, |
static char *relation_get_descriptive_name(relation_t *relation) { |
196 |
GtkTreePath *path, gboolean path_currently_selected, |
char *name = osm_tag_get_by_key(relation->tag, "ref"); |
197 |
gpointer userdata) { |
if (!name) |
198 |
relitem_context_t *context = (relitem_context_t*)userdata; |
name = osm_tag_get_by_key(relation->tag, "name"); |
199 |
GtkTreeIter iter; |
if (!name) |
200 |
|
name = osm_tag_get_by_key(relation->tag, "note"); |
201 |
if(gtk_tree_model_get_iter(model, &iter, path)) { |
if (!name) |
202 |
g_assert(gtk_tree_path_get_depth(path) == 1); |
name = osm_tag_get_by_key(relation->tag, "fix" "me"); |
203 |
relation_item_list_selected(context, TRUE); |
return name; |
204 |
} |
} |
205 |
|
|
206 |
return TRUE; /* allow selection state to change */ |
static gboolean relation_info_dialog(GtkWidget *parent, appdata_t *appdata, |
207 |
} |
relation_t *relation) { |
208 |
|
|
209 |
|
object_t object = { .type = RELATION }; |
210 |
|
object.relation = relation; |
211 |
|
return info_dialog(parent, appdata, &object); |
212 |
|
} |
213 |
|
|
214 |
static void on_relation_item_add(GtkWidget *but, relitem_context_t *context) { |
static void on_relation_item_add(GtkWidget *but, relitem_context_t *context) { |
215 |
/* create a new relation */ |
/* create a new relation */ |
216 |
|
|
217 |
relation_t *relation = osm_relation_new(); |
relation_t *relation = osm_relation_new(); |
218 |
if(!info_dialog(context->dialog, context->appdata, relation)) { |
if(!relation_info_dialog(context->dialog, context->appdata, relation)) { |
219 |
printf("tag edit cancelled\n"); |
printf("tag edit cancelled\n"); |
220 |
osm_relation_free(relation); |
osm_relation_free(relation); |
221 |
} else { |
} else { |
224 |
/* add to list */ |
/* add to list */ |
225 |
|
|
226 |
/* append a row for the new data */ |
/* append a row for the new data */ |
227 |
/* 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"); |
|
228 |
|
|
229 |
GtkTreeIter iter; |
GtkTreeIter iter; |
230 |
gtk_list_store_append(context->store, &iter); |
gtk_list_store_append(context->store, &iter); |
236 |
RELITEM_COL_DATA, relation, |
RELITEM_COL_DATA, relation, |
237 |
-1); |
-1); |
238 |
|
|
239 |
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); |
|
|
|
|
|
/* scroll to end */ |
|
|
// GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(); |
|
|
/* xyz */ |
|
240 |
} |
} |
241 |
} |
} |
242 |
|
|
245 |
GtkTreeModel *model; |
GtkTreeModel *model; |
246 |
GtkTreeIter iter; |
GtkTreeIter iter; |
247 |
|
|
248 |
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)); |
selection = list_get_selection(context->list); |
249 |
if(gtk_tree_selection_get_selected(selection, &model, &iter)) { |
if(gtk_tree_selection_get_selected(selection, &model, &iter)) { |
250 |
relation_t *relation; |
relation_t *relation; |
251 |
gtk_tree_model_get(model, &iter, RELITEM_COL_DATA, &relation, -1); |
gtk_tree_model_get(model, &iter, RELITEM_COL_DATA, &relation, -1); |
258 |
relation_t *sel = get_selection(context); |
relation_t *sel = get_selection(context); |
259 |
if(!sel) return; |
if(!sel) return; |
260 |
|
|
261 |
printf("edit relation #%ld\n", sel->id); |
printf("edit relation item #" ITEM_ID_FORMAT "\n", sel->id); |
262 |
|
|
263 |
|
if (!relation_info_dialog(context->dialog, context->appdata, sel)) |
264 |
|
return; |
265 |
|
|
266 |
|
// Locate the changed item |
267 |
|
GtkTreeIter iter; |
268 |
|
gboolean valid = gtk_tree_model_get_iter_first( |
269 |
|
GTK_TREE_MODEL(context->store), &iter); |
270 |
|
while (valid) { |
271 |
|
relation_t *row_rel; |
272 |
|
gtk_tree_model_get(GTK_TREE_MODEL(context->store), &iter, |
273 |
|
RELITEM_COL_DATA, &row_rel, |
274 |
|
-1); |
275 |
|
if (row_rel == sel) |
276 |
|
break; |
277 |
|
valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(context->store), &iter); |
278 |
|
} |
279 |
|
if (!valid) |
280 |
|
return; |
281 |
|
|
282 |
info_dialog(context->dialog, context->appdata, sel); |
// Found it. Update all visible fields that belong to the relation iself. |
283 |
|
gtk_list_store_set(context->store, &iter, |
284 |
|
RELITEM_COL_TYPE, osm_tag_get_by_key(sel->tag, "type"), |
285 |
|
RELITEM_COL_NAME, relation_get_descriptive_name(sel), |
286 |
|
-1); |
287 |
|
|
288 |
|
// Order will probably have changed, so refocus |
289 |
|
list_focus_on(context->list, &iter, TRUE); |
290 |
} |
} |
291 |
|
|
292 |
/* remove the selected relation */ |
/* remove the selected relation */ |
294 |
relation_t *sel = get_selection(context); |
relation_t *sel = get_selection(context); |
295 |
if(!sel) return; |
if(!sel) return; |
296 |
|
|
297 |
printf("remove relation #%ld\n", sel->id); |
printf("remove relation #" ITEM_ID_FORMAT "\n", sel->id); |
298 |
|
|
299 |
int members = 0; |
gint members = osm_relation_members_num(sel); |
|
member_t *member = sel->member; |
|
|
while(member) { |
|
|
members++; |
|
|
member = member->next; |
|
|
} |
|
300 |
|
|
301 |
if(members) |
if(members) |
302 |
if(!yes_no_f(context->dialog, NULL, 0, 0, |
if(!yes_no_f(context->dialog, NULL, 0, 0, |
307 |
|
|
308 |
/* first remove selected row from list */ |
/* first remove selected row from list */ |
309 |
GtkTreeIter iter; |
GtkTreeIter iter; |
310 |
GtkTreeSelection *selection = |
GtkTreeSelection *selection = list_get_selection(context->list); |
|
gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)); |
|
311 |
if(gtk_tree_selection_get_selected(selection, NULL, &iter)) |
if(gtk_tree_selection_get_selected(selection, NULL, &iter)) |
312 |
gtk_list_store_remove(context->store, &iter); |
gtk_list_store_remove(context->store, &iter); |
313 |
|
|
317 |
relation_item_list_selected(context, FALSE); |
relation_item_list_selected(context, FALSE); |
318 |
} |
} |
319 |
|
|
320 |
static char *relitem_get_role_in_relation(relation_item_t *item, relation_t *relation) { |
static char *relitem_get_role_in_relation(object_t *item, relation_t *relation) { |
321 |
member_t *member = relation->member; |
member_t *member = relation->member; |
322 |
while(member) { |
while(member) { |
323 |
switch(member->type) { |
switch(member->object.type) { |
324 |
|
|
325 |
case NODE: |
case NODE: |
326 |
if((item->type == NODE) && (item->node == member->node)) |
if((item->type == NODE) && (item->node == member->object.node)) |
327 |
return member->role; |
return member->role; |
328 |
break; |
break; |
329 |
|
|
330 |
case WAY: |
case WAY: |
331 |
if((item->type == WAY) && (item->way == member->way)) |
if((item->type == WAY) && (item->way == member->object.way)) |
332 |
return member->role; |
return member->role; |
333 |
break; |
break; |
334 |
|
|
358 |
RELITEM_COL_DATA, &relation, |
RELITEM_COL_DATA, &relation, |
359 |
-1); |
-1); |
360 |
|
|
361 |
|
list_pre_inplace_edit_tweak(GTK_TREE_MODEL(context->store)); |
362 |
|
|
363 |
if(!enabled) { |
if(!enabled) { |
364 |
printf("will now become be part of this relation\n"); |
printf("will now become be part of this relation\n"); |
365 |
if(relation_add_item(context->dialog, relation, context->item)) |
if(relation_add_item(context->dialog, relation, context->item)) |
376 |
RELITEM_COL_ROLE, NULL, |
RELITEM_COL_ROLE, NULL, |
377 |
-1); |
-1); |
378 |
} |
} |
379 |
|
|
380 |
} |
} |
381 |
|
|
382 |
static gboolean relitem_is_in_relation(relation_item_t *item, relation_t *relation) { |
static gboolean relitem_is_in_relation(object_t *item, relation_t *relation) { |
383 |
member_t *member = relation->member; |
member_t *member = relation->member; |
384 |
while(member) { |
while(member) { |
385 |
switch(member->type) { |
switch(member->object.type) { |
386 |
|
|
387 |
case NODE: |
case NODE: |
388 |
if((item->type == NODE) && (item->node == member->node)) |
if((item->type == NODE) && (item->node == member->object.node)) |
389 |
return TRUE; |
return TRUE; |
390 |
break; |
break; |
391 |
|
|
392 |
case WAY: |
case WAY: |
393 |
if((item->type == WAY) && (item->way == member->way)) |
if((item->type == WAY) && (item->way == member->object.way)) |
394 |
return TRUE; |
return TRUE; |
395 |
break; |
break; |
396 |
|
|
403 |
} |
} |
404 |
|
|
405 |
static GtkWidget *relation_item_list_widget(relitem_context_t *context) { |
static GtkWidget *relation_item_list_widget(relitem_context_t *context) { |
406 |
GtkWidget *vbox = gtk_vbox_new(FALSE,3); |
context->list = list_new(LIST_HILDON_WITH_HEADERS); |
|
context->view = gtk_tree_view_new(); |
|
|
|
|
|
gtk_tree_selection_set_select_function( |
|
|
gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)), |
|
|
relation_item_list_selection_func, |
|
|
context, NULL); |
|
|
|
|
|
|
|
|
/* --- "selected" column --- */ |
|
|
GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new(); |
|
|
g_signal_connect(renderer, "toggled", G_CALLBACK(relitem_toggled), context); |
|
|
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view), |
|
|
-1, _(""), renderer, |
|
|
"active", RELITEM_COL_SELECTED, |
|
|
NULL); |
|
|
|
|
|
/* --- "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); |
|
|
|
|
|
/* --- "Role" column --- */ |
|
|
renderer = gtk_cell_renderer_text_new(); |
|
|
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view), |
|
|
-1, _("Role"), renderer, "text", RELITEM_COL_ROLE, NULL); |
|
|
|
|
|
/* --- "Name" column --- */ |
|
|
renderer = gtk_cell_renderer_text_new(); |
|
|
g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
|
|
GtkTreeViewColumn *column = |
|
|
gtk_tree_view_column_new_with_attributes(_("Name"), renderer, |
|
|
"text", RELITEM_COL_NAME, NULL); |
|
|
gtk_tree_view_column_set_expand(column, TRUE); |
|
|
gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1); |
|
407 |
|
|
408 |
|
list_set_columns(context->list, |
409 |
|
_(""), RELITEM_COL_SELECTED, LIST_FLAG_TOGGLE, |
410 |
|
G_CALLBACK(relitem_toggled), context, |
411 |
|
_("Type"), RELITEM_COL_TYPE, 0, |
412 |
|
_("Role"), RELITEM_COL_ROLE, 0, |
413 |
|
_("Name"), RELITEM_COL_NAME, LIST_FLAG_ELLIPSIZE, |
414 |
|
NULL); |
415 |
|
|
416 |
/* build and fill the store */ |
/* build and fill the store */ |
417 |
context->store = gtk_list_store_new(RELITEM_NUM_COLS, |
context->store = gtk_list_store_new(RELITEM_NUM_COLS, |
418 |
G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, |
G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, |
419 |
G_TYPE_STRING, G_TYPE_POINTER); |
G_TYPE_STRING, G_TYPE_POINTER); |
420 |
|
|
421 |
gtk_tree_view_set_model(GTK_TREE_VIEW(context->view), |
list_set_store(context->list, context->store); |
422 |
GTK_TREE_MODEL(context->store)); |
|
423 |
|
// Debatable whether to sort by the "selected" or the "Name" column by |
424 |
|
// default. Both are be useful, in different ways. |
425 |
|
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(context->store), |
426 |
|
RELITEM_COL_NAME, GTK_SORT_ASCENDING); |
427 |
|
|
428 |
GtkTreeIter iter; |
GtkTreeIter iter; |
429 |
relation_t *relation = context->appdata->osm->relation; |
relation_t *relation = context->appdata->osm->relation; |
430 |
while(relation) { |
while(relation) { |
431 |
/* try to find something descriptive */ |
/* try to find something descriptive */ |
432 |
char *name = osm_tag_get_by_key(relation->tag, "name"); |
char *name = relation_get_descriptive_name(relation); |
|
if(!name) name = osm_tag_get_by_key(relation->tag, "ref"); |
|
433 |
|
|
434 |
/* Append a row and fill in some data */ |
/* Append a row and fill in some data */ |
435 |
gtk_list_store_append(context->store, &iter); |
gtk_list_store_append(context->store, &iter); |
446 |
|
|
447 |
g_object_unref(context->store); |
g_object_unref(context->store); |
448 |
|
|
449 |
/* put it into a scrolled window */ |
list_set_static_buttons(context->list, G_CALLBACK(on_relation_item_add), |
450 |
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
G_CALLBACK(on_relation_item_edit),G_CALLBACK(on_relation_item_remove), |
451 |
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), |
context); |
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
|
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), |
|
|
GTK_SHADOW_ETCHED_IN); |
|
|
gtk_container_add(GTK_CONTAINER(scrolled_window), context->view); |
|
|
|
|
|
gtk_box_pack_start_defaults(GTK_BOX(vbox), scrolled_window); |
|
|
|
|
|
/* ------- button box ------------ */ |
|
|
|
|
|
GtkWidget *hbox = gtk_hbox_new(TRUE,3); |
|
|
|
|
|
context->but_add = gtk_button_new_with_label(_("Add...")); |
|
|
// gtk_widget_set_sensitive(context->but_add, FALSE); |
|
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_add); |
|
|
gtk_signal_connect(GTK_OBJECT(context->but_add), "clicked", |
|
|
GTK_SIGNAL_FUNC(on_relation_item_add), context); |
|
|
|
|
|
context->but_edit = gtk_button_new_with_label(_("Edit...")); |
|
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_edit); |
|
|
gtk_signal_connect(GTK_OBJECT(context->but_edit), "clicked", |
|
|
GTK_SIGNAL_FUNC(on_relation_item_edit), context); |
|
|
|
|
|
context->but_remove = gtk_button_new_with_label(_("Remove")); |
|
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_remove); |
|
|
gtk_signal_connect(GTK_OBJECT(context->but_remove), "clicked", |
|
|
GTK_SIGNAL_FUNC(on_relation_item_remove), context); |
|
452 |
|
|
453 |
relation_item_list_selected(context, FALSE); |
relation_item_list_selected(context, FALSE); |
454 |
|
|
455 |
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
return context->list; |
|
return vbox; |
|
456 |
} |
} |
457 |
|
|
458 |
void relation_add_dialog(appdata_t *appdata, relation_item_t *relitem) { |
void relation_add_dialog(appdata_t *appdata, object_t *object) { |
459 |
relitem_context_t *context = g_new0(relitem_context_t, 1); |
relitem_context_t *context = g_new0(relitem_context_t, 1); |
460 |
map_t *map = appdata->map; |
map_t *map = appdata->map; |
461 |
g_assert(map); |
g_assert(map); |
462 |
|
|
463 |
context->appdata = appdata; |
context->appdata = appdata; |
464 |
context->item = relitem; |
context->item = object; |
465 |
|
|
466 |
char *str = NULL; |
char *str = NULL; |
467 |
switch(relitem->type) { |
switch(object->type) { |
468 |
case NODE: |
case NODE: |
469 |
str = g_strdup_printf(_("Relations for node #%ld"), relitem->node->id); |
str = g_strdup_printf(_("Relations for node #" ITEM_ID_FORMAT), |
470 |
|
object->node->id); |
471 |
break; |
break; |
472 |
case WAY: |
case WAY: |
473 |
str = g_strdup_printf(_("Relations for way #%ld"), relitem->way->id); |
str = g_strdup_printf(_("Relations for way #" ITEM_ID_FORMAT), |
474 |
|
object->way->id); |
475 |
break; |
break; |
476 |
default: |
default: |
477 |
g_assert((relitem->type == NODE) || (relitem->type == WAY)); |
g_assert((object->type == NODE) || (object->type == WAY)); |
478 |
break; |
break; |
479 |
} |
} |
480 |
|
|
481 |
context->dialog = gtk_dialog_new_with_buttons(str, |
context->dialog = |
482 |
GTK_WINDOW(appdata->window), GTK_DIALOG_MODAL, |
misc_dialog_new(MISC_DIALOG_LARGE, str, |
483 |
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, |
GTK_WINDOW(appdata->window), |
484 |
NULL); |
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, |
485 |
|
NULL); |
486 |
g_free(str); |
g_free(str); |
487 |
|
|
488 |
gtk_dialog_set_default_response(GTK_DIALOG(context->dialog), |
gtk_dialog_set_default_response(GTK_DIALOG(context->dialog), |
489 |
GTK_RESPONSE_CLOSE); |
GTK_RESPONSE_CLOSE); |
490 |
|
|
|
/* making the dialog a little wider makes it less "crowded" */ |
|
|
#ifdef USE_HILDON |
|
|
gtk_window_set_default_size(GTK_WINDOW(context->dialog), 500, 300); |
|
|
#else |
|
|
gtk_window_set_default_size(GTK_WINDOW(context->dialog), 400, 200); |
|
|
#endif |
|
491 |
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), |
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), |
492 |
relation_item_list_widget(context), TRUE, TRUE, 0); |
relation_item_list_widget(context), TRUE, TRUE, 0); |
493 |
|
|
504 |
|
|
505 |
typedef struct { |
typedef struct { |
506 |
appdata_t *appdata; |
appdata_t *appdata; |
507 |
GtkWidget *dialog, *view; |
GtkWidget *dialog, *list, *show_btn; |
|
GtkWidget *but_members, *but_add, *but_edit, *but_remove; |
|
508 |
GtkListStore *store; |
GtkListStore *store; |
509 |
|
object_t *object; /* object this list relates to, NULL if global */ |
510 |
} relation_context_t; |
} relation_context_t; |
511 |
|
|
512 |
enum { |
enum { |
518 |
RELATION_NUM_COLS |
RELATION_NUM_COLS |
519 |
}; |
}; |
520 |
|
|
521 |
|
static relation_t *get_selected_relation(relation_context_t *context) { |
522 |
|
GtkTreeSelection *selection; |
523 |
|
GtkTreeModel *model; |
524 |
|
GtkTreeIter iter; |
525 |
|
|
526 |
|
selection = list_get_selection(context->list); |
527 |
|
if(gtk_tree_selection_get_selected(selection, &model, &iter)) { |
528 |
|
relation_t *relation; |
529 |
|
gtk_tree_model_get(model, &iter, RELATION_COL_DATA, &relation, -1); |
530 |
|
return(relation); |
531 |
|
} |
532 |
|
return NULL; |
533 |
|
} |
534 |
|
|
535 |
static void relation_list_selected(relation_context_t *context, |
static void relation_list_selected(relation_context_t *context, |
536 |
gboolean selected) { |
relation_t *selected) { |
537 |
|
|
538 |
|
list_button_enable(context->list, LIST_BUTTON_USER0, |
539 |
|
(selected != NULL) && (selected->member != NULL)); |
540 |
|
gtk_widget_set_sensitive(context->show_btn, |
541 |
|
(selected != NULL) && (selected->member != NULL)); |
542 |
|
|
543 |
if(context->but_members) |
list_button_enable(context->list, LIST_BUTTON_REMOVE, selected != NULL); |
544 |
gtk_widget_set_sensitive(context->but_members, selected); |
list_button_enable(context->list, LIST_BUTTON_EDIT, selected != NULL); |
545 |
} |
} |
546 |
|
|
547 |
static gboolean |
static gboolean |
553 |
|
|
554 |
if(gtk_tree_model_get_iter(model, &iter, path)) { |
if(gtk_tree_model_get_iter(model, &iter, path)) { |
555 |
g_assert(gtk_tree_path_get_depth(path) == 1); |
g_assert(gtk_tree_path_get_depth(path) == 1); |
556 |
relation_list_selected(context, TRUE); |
|
557 |
|
relation_t *relation = NULL; |
558 |
|
gtk_tree_model_get(model, &iter, RELATION_COL_DATA, &relation, -1); |
559 |
|
relation_list_selected(context, relation); |
560 |
} |
} |
561 |
|
|
562 |
return TRUE; /* allow selection state to change */ |
return TRUE; /* allow selection state to change */ |
563 |
} |
} |
564 |
|
|
|
static relation_t *get_selected_relation(relation_context_t *context) { |
|
|
GtkTreeSelection *selection; |
|
|
GtkTreeModel *model; |
|
|
GtkTreeIter iter; |
|
|
|
|
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)); |
|
|
if(gtk_tree_selection_get_selected(selection, &model, &iter)) { |
|
|
relation_t *relation; |
|
|
gtk_tree_model_get(model, &iter, RELATION_COL_DATA, &relation, -1); |
|
|
return(relation); |
|
|
} |
|
|
return NULL; |
|
|
} |
|
|
|
|
565 |
typedef struct { |
typedef struct { |
566 |
relation_t *relation; |
relation_t *relation; |
567 |
GtkWidget *dialog, *view; |
GtkWidget *dialog, *view; |
589 |
|
|
590 |
member_t *member = NULL; |
member_t *member = NULL; |
591 |
gtk_tree_model_get(model, &iter, MEMBER_COL_DATA, &member, -1); |
gtk_tree_model_get(model, &iter, MEMBER_COL_DATA, &member, -1); |
592 |
if(member && member->type < NODE_ID) |
if(member && member->object.type < NODE_ID) |
593 |
return TRUE; |
return TRUE; |
594 |
} |
} |
595 |
|
|
609 |
/* --- "type" column --- */ |
/* --- "type" column --- */ |
610 |
GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); |
GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); |
611 |
g_object_set(renderer, "foreground", "grey", NULL); |
g_object_set(renderer, "foreground", "grey", NULL); |
612 |
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view), |
GtkTreeViewColumn *column = |
613 |
-1, _("Type"), renderer, "text", MEMBER_COL_TYPE, |
gtk_tree_view_column_new_with_attributes(_("Type"), renderer, |
614 |
"foreground-set", MEMBER_COL_REF_ONLY, NULL); |
"text", MEMBER_COL_TYPE, |
615 |
|
"foreground-set", MEMBER_COL_REF_ONLY, NULL); |
616 |
|
gtk_tree_view_column_set_sort_column_id(column, MEMBER_COL_TYPE); |
617 |
|
gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1); |
618 |
|
|
619 |
/* --- "id" column --- */ |
/* --- "id" column --- */ |
620 |
renderer = gtk_cell_renderer_text_new(); |
renderer = gtk_cell_renderer_text_new(); |
621 |
g_object_set(renderer, "foreground", "grey", NULL); |
g_object_set(renderer, "foreground", "grey", NULL); |
622 |
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view), |
column = gtk_tree_view_column_new_with_attributes(_("Id"), renderer, |
623 |
-1, _("Id"), renderer, "text", MEMBER_COL_ID, |
"text", MEMBER_COL_ID, |
624 |
"foreground-set", MEMBER_COL_REF_ONLY, NULL); |
"foreground-set", MEMBER_COL_REF_ONLY, NULL); |
625 |
|
gtk_tree_view_column_set_sort_column_id(column, MEMBER_COL_ID); |
626 |
|
gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1); |
627 |
|
|
628 |
|
|
629 |
/* --- "Name" column --- */ |
/* --- "Name" column --- */ |
630 |
renderer = gtk_cell_renderer_text_new(); |
renderer = gtk_cell_renderer_text_new(); |
631 |
g_object_set(renderer, "foreground", "grey", NULL); |
g_object_set(renderer, "foreground", "grey", NULL); |
632 |
g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
633 |
GtkTreeViewColumn *column = |
column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, |
|
gtk_tree_view_column_new_with_attributes(_("Name"), renderer, |
|
634 |
"text", MEMBER_COL_NAME, |
"text", MEMBER_COL_NAME, |
635 |
"foreground-set", MEMBER_COL_REF_ONLY, NULL); |
"foreground-set", MEMBER_COL_REF_ONLY, NULL); |
636 |
gtk_tree_view_column_set_expand(column, TRUE); |
gtk_tree_view_column_set_expand(column, TRUE); |
637 |
|
gtk_tree_view_column_set_sort_column_id(column, MEMBER_COL_NAME); |
638 |
gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1); |
gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1); |
639 |
|
|
640 |
/* --- "role" column --- */ |
/* --- "role" column --- */ |
641 |
renderer = gtk_cell_renderer_text_new(); |
renderer = gtk_cell_renderer_text_new(); |
642 |
g_object_set(renderer, "foreground", "grey", NULL); |
g_object_set(renderer, "foreground", "grey", NULL); |
643 |
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view), |
column = gtk_tree_view_column_new_with_attributes(_("Role"), renderer, |
644 |
-1, _("Role"), renderer, "text", MEMBER_COL_ROLE, |
"text", MEMBER_COL_ROLE, |
645 |
"foreground-set", MEMBER_COL_REF_ONLY, NULL); |
"foreground-set", MEMBER_COL_REF_ONLY, NULL); |
646 |
|
gtk_tree_view_column_set_sort_column_id(column, MEMBER_COL_ROLE); |
647 |
|
gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1); |
648 |
|
|
649 |
|
|
650 |
/* build and fill the store */ |
/* build and fill the store */ |
651 |
context->store = gtk_list_store_new(MEMBER_NUM_COLS, |
context->store = gtk_list_store_new(MEMBER_NUM_COLS, |
658 |
GtkTreeIter iter; |
GtkTreeIter iter; |
659 |
member_t *member = context->relation->member; |
member_t *member = context->relation->member; |
660 |
while(member) { |
while(member) { |
661 |
tag_t *tags = osm_object_get_tags(member->type, member->ptr); |
tag_t *tags = osm_object_get_tags(&member->object); |
662 |
char *id = osm_id_string(member->type, member->ptr); |
char *id = osm_object_id_string(&member->object); |
663 |
|
|
664 |
/* try to find something descriptive */ |
/* try to find something descriptive */ |
665 |
char *name = NULL; |
char *name = NULL; |
669 |
/* Append a row and fill in some data */ |
/* Append a row and fill in some data */ |
670 |
gtk_list_store_append(context->store, &iter); |
gtk_list_store_append(context->store, &iter); |
671 |
gtk_list_store_set(context->store, &iter, |
gtk_list_store_set(context->store, &iter, |
672 |
MEMBER_COL_TYPE, osm_type_string(member->type), |
MEMBER_COL_TYPE, osm_object_type_string(&member->object), |
673 |
MEMBER_COL_ID, id, |
MEMBER_COL_ID, id, |
674 |
MEMBER_COL_NAME, name, |
MEMBER_COL_NAME, name, |
675 |
MEMBER_COL_ROLE, member->role, |
MEMBER_COL_ROLE, member->role, |
676 |
MEMBER_COL_REF_ONLY, member->type >= NODE_ID, |
MEMBER_COL_REF_ONLY, member->object.type >= NODE_ID, |
677 |
MEMBER_COL_DATA, member, |
MEMBER_COL_DATA, member, |
678 |
-1); |
-1); |
679 |
|
|
696 |
return vbox; |
return vbox; |
697 |
} |
} |
698 |
|
|
699 |
/* user clicked "members..." button in relation list */ |
void relation_show_members(GtkWidget *parent, relation_t *relation) { |
|
static void on_relation_members(GtkWidget *but, relation_context_t *context) { |
|
700 |
member_context_t *mcontext = g_new0(member_context_t, 1); |
member_context_t *mcontext = g_new0(member_context_t, 1); |
701 |
|
mcontext->relation = relation; |
|
/* display members list */ |
|
|
mcontext->relation = get_selected_relation(context); |
|
|
if(!mcontext->relation) return; |
|
702 |
|
|
703 |
char *str = osm_tag_get_by_key(mcontext->relation->tag, "name"); |
char *str = osm_tag_get_by_key(mcontext->relation->tag, "name"); |
704 |
if(!str) str = osm_tag_get_by_key(mcontext->relation->tag, "ref"); |
if(!str) str = osm_tag_get_by_key(mcontext->relation->tag, "ref"); |
705 |
if(!str) |
if(!str) |
706 |
str = g_strdup_printf(_("Members of relation #%ld"), |
str = g_strdup_printf(_("Members of relation #" ITEM_ID_FORMAT), |
707 |
mcontext->relation->id); |
mcontext->relation->id); |
708 |
else |
else |
709 |
str = g_strdup_printf(_("Members of relation \"%s\""), str); |
str = g_strdup_printf(_("Members of relation \"%s\""), str); |
710 |
|
|
711 |
mcontext->dialog = |
mcontext->dialog = |
712 |
gtk_dialog_new_with_buttons(str, |
misc_dialog_new(MISC_DIALOG_MEDIUM, str, |
713 |
GTK_WINDOW(context->dialog), GTK_DIALOG_MODAL, |
GTK_WINDOW(parent), |
714 |
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, |
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, |
715 |
NULL); |
NULL); |
716 |
g_free(str); |
g_free(str); |
717 |
|
|
718 |
gtk_dialog_set_default_response(GTK_DIALOG(mcontext->dialog), |
gtk_dialog_set_default_response(GTK_DIALOG(mcontext->dialog), |
719 |
GTK_RESPONSE_CLOSE); |
GTK_RESPONSE_CLOSE); |
720 |
|
|
|
/* making the dialog a little wider makes it less "crowded" */ |
|
|
#ifdef USE_HILDON |
|
|
gtk_window_set_default_size(GTK_WINDOW(mcontext->dialog), 500, 300); |
|
|
#else |
|
|
gtk_window_set_default_size(GTK_WINDOW(mcontext->dialog), 400, 200); |
|
|
#endif |
|
|
|
|
721 |
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(mcontext->dialog)->vbox), |
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(mcontext->dialog)->vbox), |
722 |
member_list_widget(mcontext), TRUE, TRUE, 0); |
member_list_widget(mcontext), TRUE, TRUE, 0); |
723 |
|
|
730 |
g_free(mcontext); |
g_free(mcontext); |
731 |
} |
} |
732 |
|
|
733 |
static GtkWidget *relation_list_widget(relation_context_t *context) { |
/* user clicked "members..." button in relation list */ |
734 |
GtkWidget *vbox = gtk_vbox_new(FALSE,3); |
static void on_relation_members(GtkWidget *but, relation_context_t *context) { |
735 |
context->view = gtk_tree_view_new(); |
relation_t *sel = get_selected_relation(context); |
736 |
|
|
737 |
|
if(sel) |
738 |
|
relation_show_members(context->dialog, sel); |
739 |
|
} |
740 |
|
|
|
gtk_tree_selection_set_select_function( |
|
|
gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)), |
|
|
relation_list_selection_func, |
|
|
context, NULL); |
|
741 |
|
|
742 |
/* --- "id" column --- */ |
static void on_relation_add(GtkWidget *but, relation_context_t *context) { |
743 |
GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); |
/* create a new relation */ |
|
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view), |
|
|
-1, _("Id"), renderer, "text", RELATION_COL_ID, NULL); |
|
744 |
|
|
745 |
/* --- "Type" column --- */ |
relation_t *relation = osm_relation_new(); |
746 |
renderer = gtk_cell_renderer_text_new(); |
if(!relation_info_dialog(context->dialog, context->appdata, relation)) { |
747 |
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view), |
printf("tag edit cancelled\n"); |
748 |
-1, _("Type"), renderer, "text", RELATION_COL_TYPE, NULL); |
osm_relation_free(relation); |
749 |
|
} else { |
750 |
|
osm_relation_attach(context->appdata->osm, relation); |
751 |
|
|
752 |
/* --- "Name" column --- */ |
/* append a row for the new data */ |
|
renderer = gtk_cell_renderer_text_new(); |
|
|
g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); |
|
|
GtkTreeViewColumn *column = |
|
|
gtk_tree_view_column_new_with_attributes(_("Name"), renderer, |
|
|
"text", RELATION_COL_NAME, NULL); |
|
|
gtk_tree_view_column_set_expand(column, TRUE); |
|
|
gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1); |
|
753 |
|
|
754 |
/* --- "members" column --- */ |
char *name = relation_get_descriptive_name(relation); |
755 |
renderer = gtk_cell_renderer_text_new(); |
|
756 |
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view), |
guint num = osm_relation_members_num(relation); |
757 |
-1, _("Members"), renderer, "text", RELATION_COL_MEMBERS, NULL); |
|
758 |
|
/* Append a row and fill in some data */ |
759 |
|
GtkTreeIter iter; |
760 |
|
gtk_list_store_append(context->store, &iter); |
761 |
|
gtk_list_store_set(context->store, &iter, |
762 |
|
RELATION_COL_ID, relation->id, |
763 |
|
RELATION_COL_TYPE, |
764 |
|
osm_tag_get_by_key(relation->tag, "type"), |
765 |
|
RELATION_COL_NAME, name, |
766 |
|
RELATION_COL_MEMBERS, num, |
767 |
|
RELATION_COL_DATA, relation, |
768 |
|
-1); |
769 |
|
|
770 |
|
gtk_tree_selection_select_iter(list_get_selection(context->list), &iter); |
771 |
|
|
772 |
|
/* scroll to end */ |
773 |
|
// GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(); |
774 |
|
/* xyz */ |
775 |
|
} |
776 |
|
} |
777 |
|
|
778 |
|
/* user clicked "edit..." button in relation list */ |
779 |
|
static void on_relation_edit(GtkWidget *but, relation_context_t *context) { |
780 |
|
relation_t *sel = get_selected_relation(context); |
781 |
|
if(!sel) return; |
782 |
|
|
783 |
|
printf("edit relation #" ITEM_ID_FORMAT "\n", sel->id); |
784 |
|
|
785 |
|
if (!relation_info_dialog(context->dialog, context->appdata, sel)) |
786 |
|
return; |
787 |
|
|
788 |
|
// Locate the changed item |
789 |
|
GtkTreeIter iter; |
790 |
|
gboolean valid = gtk_tree_model_get_iter_first( |
791 |
|
GTK_TREE_MODEL(context->store), &iter); |
792 |
|
while (valid) { |
793 |
|
relation_t *row_rel; |
794 |
|
gtk_tree_model_get(GTK_TREE_MODEL(context->store), &iter, |
795 |
|
RELATION_COL_DATA, &row_rel, |
796 |
|
-1); |
797 |
|
if (row_rel == sel) |
798 |
|
break; |
799 |
|
valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(context->store), &iter); |
800 |
|
} |
801 |
|
if (!valid) |
802 |
|
return; |
803 |
|
|
804 |
|
// Found it. Update all visible fields. |
805 |
|
gtk_list_store_set(context->store, &iter, |
806 |
|
RELATION_COL_ID, sel->id, |
807 |
|
RELATION_COL_TYPE, osm_tag_get_by_key(sel->tag, "type"), |
808 |
|
RELATION_COL_NAME, relation_get_descriptive_name(sel), |
809 |
|
RELATION_COL_MEMBERS, osm_relation_members_num(sel), |
810 |
|
-1); |
811 |
|
|
812 |
|
// Order will probably have changed, so refocus |
813 |
|
list_focus_on(context->list, &iter, TRUE); |
814 |
|
} |
815 |
|
|
816 |
|
|
817 |
|
/* remove the selected relation */ |
818 |
|
static void on_relation_remove(GtkWidget *but, relation_context_t *context) { |
819 |
|
relation_t *sel = get_selected_relation(context); |
820 |
|
if(!sel) return; |
821 |
|
|
822 |
|
printf("remove relation #" ITEM_ID_FORMAT "\n", sel->id); |
823 |
|
|
824 |
|
gint members = osm_relation_members_num(sel); |
825 |
|
|
826 |
|
if(members) |
827 |
|
if(!yes_no_f(context->dialog, NULL, 0, 0, |
828 |
|
_("Delete non-empty relation?"), |
829 |
|
_("This relation still has %d members. " |
830 |
|
"Delete it anyway?"), members)) |
831 |
|
return; |
832 |
|
|
833 |
|
/* first remove selected row from list */ |
834 |
|
GtkTreeIter iter; |
835 |
|
GtkTreeSelection *selection = list_get_selection(context->list); |
836 |
|
if(gtk_tree_selection_get_selected(selection, NULL, &iter)) |
837 |
|
gtk_list_store_remove(context->store, &iter); |
838 |
|
|
839 |
|
/* then really delete it */ |
840 |
|
osm_relation_delete(context->appdata->osm, sel, FALSE); |
841 |
|
|
842 |
|
relation_list_selected(context, NULL); |
843 |
|
} |
844 |
|
|
845 |
|
static GtkWidget *relation_list_widget(relation_context_t *context) { |
846 |
|
context->list = list_new(LIST_HILDON_WITH_HEADERS); |
847 |
|
|
848 |
|
list_set_selection_function(context->list, relation_list_selection_func, |
849 |
|
context); |
850 |
|
|
851 |
|
list_set_columns(context->list, |
852 |
|
_("Id"), RELATION_COL_ID, 0, |
853 |
|
_("Type"), RELATION_COL_TYPE, 0, |
854 |
|
_("Name"), RELATION_COL_NAME, LIST_FLAG_ELLIPSIZE, |
855 |
|
_("Members"), RELATION_COL_MEMBERS, 0, |
856 |
|
NULL); |
857 |
|
|
858 |
/* build and fill the store */ |
/* build and fill the store */ |
859 |
context->store = gtk_list_store_new(RELATION_NUM_COLS, |
context->store = gtk_list_store_new(RELATION_NUM_COLS, |
860 |
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, |
G_TYPE_ITEM_ID_T, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, |
861 |
G_TYPE_POINTER); |
G_TYPE_POINTER); |
862 |
|
|
863 |
gtk_tree_view_set_model(GTK_TREE_VIEW(context->view), |
list_set_store(context->list, context->store); |
|
GTK_TREE_MODEL(context->store)); |
|
864 |
|
|
865 |
|
// Sorting by ref/name by default is useful for places with lots of numbered |
866 |
|
// bus routes. Especially for small screens. |
867 |
|
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(context->store), |
868 |
|
RELATION_COL_NAME, GTK_SORT_ASCENDING); |
869 |
|
|
870 |
GtkTreeIter iter; |
GtkTreeIter iter; |
871 |
relation_t *relation = context->appdata->osm->relation; |
relation_t *relation = NULL; |
872 |
while(relation) { |
relation_chain_t *rchain = NULL; |
|
char *id = g_strdup_printf("#%ld", relation->id); |
|
873 |
|
|
874 |
/* try to find something descriptive */ |
if(context->object) |
875 |
char *name = osm_tag_get_by_key(relation->tag, "name"); |
rchain = osm_object_to_relation(context->appdata->osm, context->object); |
876 |
if(!name) name = osm_tag_get_by_key(relation->tag, "ref"); |
else |
877 |
|
relation = context->appdata->osm->relation; |
878 |
|
|
879 |
char *num = g_strdup_printf("%d", osm_relation_members_num(relation)); |
while(relation || rchain) { |
880 |
|
relation_t *rel = relation?relation:rchain->relation; |
881 |
|
|
882 |
|
char *name = relation_get_descriptive_name(rel); |
883 |
|
guint num = osm_relation_members_num(rel); |
884 |
|
|
885 |
/* Append a row and fill in some data */ |
/* Append a row and fill in some data */ |
886 |
gtk_list_store_append(context->store, &iter); |
gtk_list_store_append(context->store, &iter); |
887 |
gtk_list_store_set(context->store, &iter, |
gtk_list_store_set(context->store, &iter, |
888 |
RELATION_COL_ID, id, |
RELATION_COL_ID, rel->id, |
889 |
RELATION_COL_TYPE, |
RELATION_COL_TYPE, |
890 |
osm_tag_get_by_key(relation->tag, "type"), |
osm_tag_get_by_key(rel->tag, "type"), |
891 |
RELATION_COL_NAME, name, |
RELATION_COL_NAME, name, |
892 |
RELATION_COL_MEMBERS, num, |
RELATION_COL_MEMBERS, num, |
893 |
RELATION_COL_DATA, relation, |
RELATION_COL_DATA, rel, |
894 |
-1); |
-1); |
895 |
|
|
896 |
g_free(id); |
if(relation) relation = relation->next; |
897 |
g_free(num); |
if(rchain) rchain = rchain->next; |
|
relation = relation->next; |
|
898 |
} |
} |
899 |
|
|
900 |
|
if(rchain) |
901 |
|
osm_relation_chain_free(rchain); |
902 |
|
|
903 |
g_object_unref(context->store); |
g_object_unref(context->store); |
904 |
|
|
905 |
/* put it into a scrolled window */ |
list_set_static_buttons(context->list, G_CALLBACK(on_relation_add), |
906 |
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); |
G_CALLBACK(on_relation_edit), G_CALLBACK(on_relation_remove), context); |
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), |
|
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
|
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), |
|
|
GTK_SHADOW_ETCHED_IN); |
|
|
gtk_container_add(GTK_CONTAINER(scrolled_window), context->view); |
|
|
|
|
|
gtk_box_pack_start_defaults(GTK_BOX(vbox), scrolled_window); |
|
|
|
|
|
/* ------- button box ------------ */ |
|
|
|
|
|
GtkWidget *hbox = gtk_hbox_new(TRUE,3); |
|
|
|
|
|
context->but_add = gtk_button_new_with_label(_("Add...")); |
|
|
gtk_widget_set_sensitive(context->but_add, FALSE); |
|
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_add); |
|
|
// gtk_signal_connect(GTK_OBJECT(context->but_add), "clicked", |
|
|
// GTK_SIGNAL_FUNC(on_relation_add), context); |
|
|
|
|
|
context->but_edit = gtk_button_new_with_label(_("Edit...")); |
|
|
gtk_widget_set_sensitive(context->but_edit, FALSE); |
|
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_edit); |
|
|
// gtk_signal_connect(GTK_OBJECT(context->but_edit), "clicked", |
|
|
// GTK_SIGNAL_FUNC(on_relation_edit), context); |
|
|
|
|
|
context->but_members = gtk_button_new_with_label(_("Members...")); |
|
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_members); |
|
|
gtk_signal_connect(GTK_OBJECT(context->but_members), "clicked", |
|
|
GTK_SIGNAL_FUNC(on_relation_members), context); |
|
|
|
|
|
context->but_remove = gtk_button_new_with_label(_("Remove")); |
|
|
gtk_widget_set_sensitive(context->but_remove, FALSE); |
|
|
gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_remove); |
|
|
// gtk_signal_connect(GTK_OBJECT(context->but_remove), "clicked", |
|
|
// GTK_SIGNAL_FUNC(on_relation_remove), context); |
|
907 |
|
|
908 |
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); |
list_set_user_buttons(context->list, |
909 |
|
LIST_BUTTON_USER0, _("Members"), G_CALLBACK(on_relation_members), |
910 |
|
0); |
911 |
|
|
912 |
relation_list_selected(context, FALSE); |
relation_list_selected(context, NULL); |
913 |
|
|
914 |
return vbox; |
return context->list; |
915 |
} |
} |
916 |
|
|
917 |
/* a global view on all relations */ |
/* a global view on all relations */ |
918 |
void relation_list(appdata_t *appdata) { |
void relation_list(GtkWidget *parent, appdata_t *appdata, object_t *object) { |
919 |
relation_context_t *context = g_new0(relation_context_t, 1); |
relation_context_t *context = g_new0(relation_context_t, 1); |
920 |
context->appdata = appdata; |
context->appdata = appdata; |
921 |
|
|
922 |
printf("relation list\n"); |
char *str = NULL; |
923 |
|
if(!object) |
924 |
|
str = g_strdup(_("All relations")); |
925 |
|
else { |
926 |
|
str = g_strdup_printf(_("Relations of %s"), osm_object_string(object)); |
927 |
|
context->object = object; |
928 |
|
} |
929 |
|
|
930 |
context->dialog = |
context->dialog = |
931 |
gtk_dialog_new_with_buttons(_("All relations"), |
misc_dialog_new(MISC_DIALOG_LARGE, str, |
932 |
GTK_WINDOW(appdata->window), GTK_DIALOG_MODAL, |
GTK_WINDOW(parent), |
933 |
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, |
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, |
934 |
NULL); |
NULL); |
935 |
|
|
936 |
|
g_free(str); |
937 |
|
|
938 |
gtk_dialog_set_default_response(GTK_DIALOG(context->dialog), |
gtk_dialog_set_default_response(GTK_DIALOG(context->dialog), |
939 |
GTK_RESPONSE_CLOSE); |
GTK_RESPONSE_CLOSE); |
940 |
|
|
941 |
/* making the dialog a little wider makes it less "crowded" */ |
context->show_btn = gtk_dialog_add_button(GTK_DIALOG(context->dialog), |
942 |
#ifdef USE_HILDON |
_("Select"), GTK_RESPONSE_HELP); |
943 |
gtk_window_set_default_size(GTK_WINDOW(context->dialog), 500, 300); |
|
|
#else |
|
|
gtk_window_set_default_size(GTK_WINDOW(context->dialog), 400, 200); |
|
|
#endif |
|
944 |
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), |
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), |
945 |
relation_list_widget(context), TRUE, TRUE, 0); |
relation_list_widget(context), TRUE, TRUE, 0); |
946 |
|
|
947 |
/* ----------------------------------- */ |
/* ----------------------------------- */ |
948 |
|
|
949 |
|
|
950 |
gtk_widget_show_all(context->dialog); |
gtk_widget_show_all(context->dialog); |
951 |
gtk_dialog_run(GTK_DIALOG(context->dialog)); |
if(gtk_dialog_run(GTK_DIALOG(context->dialog)) == GTK_RESPONSE_HELP) { |
952 |
gtk_widget_destroy(context->dialog); |
map_item_deselect(appdata); |
953 |
|
|
954 |
|
relation_t *sel = get_selected_relation(context); |
955 |
|
if(sel) map_relation_select(appdata, sel); |
956 |
|
} |
957 |
|
|
958 |
|
gtk_widget_destroy(context->dialog); |
959 |
g_free(context); |
g_free(context); |
960 |
} |
} |
961 |
|
|
962 |
|
// vim:et:ts=8:sw=2:sts=2:ai |