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