static void layers_item_toggled (VikLayersPanel *vlp, GtkTreeIter *iter) { gboolean visible; gpointer p; gint type; /* get type and data */ type = vik_treeview_item_get_type ( vlp->vt, iter ); p = vik_treeview_item_get_pointer ( vlp->vt, iter ); switch ( type ) { case VIK_TREEVIEW_TYPE_LAYER: visible = (VIK_LAYER(p)->visible ^= 1); vik_layer_emit_update_although_invisible ( VIK_LAYER(p) ); /* set trigger for half-drawn */ break; case VIK_TREEVIEW_TYPE_SUBLAYER: visible = vik_layer_sublayer_toggle_visible ( VIK_LAYER(vik_treeview_item_get_parent(vlp->vt, iter)), vik_treeview_item_get_data(vlp->vt, iter), p); vik_layer_emit_update_although_invisible ( VIK_LAYER(vik_treeview_item_get_parent(vlp->vt, iter)) ); break; default: return; } vik_treeview_item_set_visible ( vlp->vt, iter, visible ); }
/** * vik_aggregate_layer_add_layer: * @allow_reordering: should be set for GUI interactions, * whereas loading from a file needs strict ordering and so should be FALSE */ void vik_aggregate_layer_add_layer ( VikAggregateLayer *val, VikLayer *l, gboolean allow_reordering ) { GtkTreeIter iter; VikLayer *vl = VIK_LAYER(val); // By default layers go to the top gboolean put_above = TRUE; if ( allow_reordering ) { // These types are 'base' types in that you what other information on top if ( l->type == VIK_LAYER_MAPS || l->type == VIK_LAYER_DEM || l->type == VIK_LAYER_GEOREF ) put_above = FALSE; } if ( vl->realized ) { vik_treeview_add_layer ( vl->vt, &(vl->iter), &iter, l->name, val, put_above, l, l->type, l->type); if ( ! l->visible ) vik_treeview_item_set_visible ( vl->vt, &iter, FALSE ); vik_layer_realize ( l, vl->vt, &iter ); if ( val->children == NULL ) vik_treeview_expand ( vl->vt, &(vl->iter) ); } if ( put_above ) val->children = g_list_append ( val->children, l ); else val->children = g_list_prepend ( val->children, l ); g_signal_connect_swapped ( G_OBJECT(l), "update", G_CALLBACK(vik_layer_emit_update_secondary), val ); }
void vik_aggregate_layer_insert_layer ( VikAggregateLayer *val, VikLayer *l, GtkTreeIter *replace_iter ) { GtkTreeIter iter; VikLayer *vl = VIK_LAYER(val); if ( vl->realized ) { vik_treeview_insert_layer ( vl->vt, &(vl->iter), &iter, l->name, val, l, l->type, l->type, replace_iter ); if ( ! l->visible ) vik_treeview_item_set_visible ( vl->vt, &iter, FALSE ); vik_layer_realize ( l, vl->vt, &iter ); if ( val->children == NULL ) vik_treeview_expand ( vl->vt, &(vl->iter) ); } if (replace_iter) { GList *theone = g_list_find ( val->children, vik_treeview_item_get_pointer ( vl->vt, replace_iter ) ); val->children = g_list_insert ( val->children, l, g_list_position(val->children,theone)+1 ); } else { // Effectively insert at 'end' of the list to match how displayed in the treeview // - but since it is drawn from 'bottom first' it is actually the first in the child list // This ordering is especially important if it is a map or similar type, // which needs be drawn first for the layering draw method to work properly. // ATM this only happens when a layer is drag/dropped to the end of an aggregate layer val->children = g_list_prepend ( val->children, l ); } g_signal_connect_swapped ( G_OBJECT(l), "update", G_CALLBACK(vik_layer_emit_update_secondary), val ); }
void vik_aggregate_layer_realize ( VikAggregateLayer *val, VikTreeview *vt, GtkTreeIter *layer_iter ) { GList *i = val->children; GtkTreeIter iter; VikLayer *vl = VIK_LAYER(val); VikLayer *vli; while ( i ) { vli = VIK_LAYER(i->data); vik_treeview_add_layer ( vl->vt, layer_iter, &iter, vli->name, val, TRUE, vli, vli->type, vli->type ); if ( ! vli->visible ) vik_treeview_item_set_visible ( vl->vt, &iter, FALSE ); vik_layer_realize ( vli, vl->vt, &iter ); i = i->next; } }
void vik_aggregate_layer_add_layer ( VikAggregateLayer *val, VikLayer *l ) { GtkTreeIter iter; VikLayer *vl = VIK_LAYER(val); if ( vl->realized ) { vik_treeview_add_layer ( vl->vt, &(vl->iter), &iter, l->name, val, l, l->type, l->type); if ( ! l->visible ) vik_treeview_item_set_visible ( vl->vt, &iter, FALSE ); vik_layer_realize ( l, vl->vt, &iter ); if ( val->children == NULL ) vik_treeview_expand ( vl->vt, &(vl->iter) ); } val->children = g_list_append ( val->children, l ); g_signal_connect_swapped ( G_OBJECT(l), "update", G_CALLBACK(vik_layer_emit_update_secondary), val ); }
static void aggregate_layer_child_visible ( gpointer data[2], gboolean on_off) { // Convert data back to correct types VikAggregateLayer *val = VIK_AGGREGATE_LAYER ( data[0] ); VikLayersPanel *vlp = VIK_LAYERS_PANEL ( data[1] ); VikLayer *vl; // Loop around all (child) layers applying visibility setting // This does not descend the tree if there are aggregates within aggregrate - just the first level of layers held GList *iter = val->children; while ( iter ) { vl = VIK_LAYER ( iter->data ); vl->visible = on_off; // Also set checkbox on_off vik_treeview_item_set_visible ( vik_layers_panel_get_treeview ( vlp ), &(vl->iter), on_off ); iter = iter->next; } // Redraw as view may have changed vik_layer_emit_update ( VIK_LAYER ( val ) ); }
void vik_aggregate_layer_insert_layer ( VikAggregateLayer *val, VikLayer *l, GtkTreeIter *replace_iter ) { GtkTreeIter iter; VikLayer *vl = VIK_LAYER(val); // By default layers are inserted above the selected layer gboolean put_above = TRUE; // These types are 'base' types in that you what other information on top if ( l->type == VIK_LAYER_MAPS || l->type == VIK_LAYER_DEM || l->type == VIK_LAYER_GEOREF ) put_above = FALSE; if ( vl->realized ) { vik_treeview_insert_layer ( vl->vt, &(vl->iter), &iter, l->name, val, put_above, l, l->type, l->type, replace_iter ); if ( ! l->visible ) vik_treeview_item_set_visible ( vl->vt, &iter, FALSE ); vik_layer_realize ( l, vl->vt, &iter ); if ( val->children == NULL ) vik_treeview_expand ( vl->vt, &(vl->iter) ); } if (replace_iter) { GList *theone = g_list_find ( val->children, vik_treeview_item_get_pointer ( vl->vt, replace_iter ) ); if ( put_above ) val->children = g_list_insert ( val->children, l, g_list_position(val->children,theone)+1 ); else // Thus insert 'here' (so don't add 1) val->children = g_list_insert ( val->children, l, g_list_position(val->children,theone) ); } else { // Effectively insert at 'end' of the list to match how displayed in the treeview // - but since it is drawn from 'bottom first' it is actually the first in the child list // This ordering is especially important if it is a map or similar type, // which needs be drawn first for the layering draw method to work properly. // ATM this only happens when a layer is drag/dropped to the end of an aggregate layer val->children = g_list_prepend ( val->children, l ); } g_signal_connect_swapped ( G_OBJECT(l), "update", G_CALLBACK(vik_layer_emit_update_secondary), val ); }
/** * Read in a Viking file and return how successful the parsing was * ATM this will always work, in that even if there are parsing problems * then there will be no new values to override the defaults * * TODO flow up line number(s) / error messages of problems encountered... * */ static gboolean file_read ( VikAggregateLayer *top, FILE *f, const gchar *dirpath, VikViewport *vp ) { Stack *stack; struct LatLon ll = { 0.0, 0.0 }; gchar buffer[4096]; gchar *line; guint16 len; long line_num = 0; VikLayerParam *params = NULL; /* for current layer, so we don't have to keep on looking up interface */ guint8 params_count = 0; GHashTable *string_lists = g_hash_table_new(g_direct_hash,g_direct_equal); gboolean successful_read = TRUE; push(&stack); stack->under = NULL; stack->data = (gpointer) top; while ( fgets ( buffer, 4096, f ) ) { line_num++; line = buffer; while ( *line == ' ' || *line =='\t' ) line++; if ( line[0] == '#' ) continue; len = strlen(line); if ( len > 0 && line[len-1] == '\n' ) line[--len] = '\0'; if ( len > 0 && line[len-1] == '\r' ) line[--len] = '\0'; if ( len == 0 ) continue; if ( line[0] == '~' ) { line++; len--; if ( *line == '\0' ) continue; else if ( str_starts_with ( line, "Layer ", 6, TRUE ) ) { int parent_type = VIK_LAYER(stack->data)->type; if ( ( ! stack->data ) || ((parent_type != VIK_LAYER_AGGREGATE) && (parent_type != VIK_LAYER_GPS)) ) { successful_read = FALSE; g_warning ( "Line %ld: Layer command inside non-Aggregate Layer (type %d)", line_num, parent_type ); push(&stack); /* inside INVALID layer */ stack->data = NULL; continue; } else { VikLayerTypeEnum type = vik_layer_type_from_string ( line+6 ); push(&stack); if ( type == VIK_LAYER_NUM_TYPES ) { successful_read = FALSE; g_warning ( "Line %ld: Unknown type %s", line_num, line+6 ); stack->data = NULL; } else if (parent_type == VIK_LAYER_GPS) { stack->data = (gpointer) vik_gps_layer_get_a_child(VIK_GPS_LAYER(stack->under->data)); params = vik_layer_get_interface(type)->params; params_count = vik_layer_get_interface(type)->params_count; } else { stack->data = (gpointer) vik_layer_create ( type, vp, FALSE ); params = vik_layer_get_interface(type)->params; params_count = vik_layer_get_interface(type)->params_count; } } } else if ( str_starts_with ( line, "EndLayer", 8, FALSE ) ) { if ( stack->under == NULL ) { successful_read = FALSE; g_warning ( "Line %ld: Mismatched ~EndLayer command", line_num ); } else { /* add any string lists we've accumulated */ gpointer layer_and_vp[2]; layer_and_vp[0] = stack->data; layer_and_vp[1] = vp; g_hash_table_foreach ( string_lists, (GHFunc) string_list_set_param, layer_and_vp ); g_hash_table_remove_all ( string_lists ); if ( stack->data && stack->under->data ) { if (VIK_LAYER(stack->under->data)->type == VIK_LAYER_AGGREGATE) { vik_aggregate_layer_add_layer ( VIK_AGGREGATE_LAYER(stack->under->data), VIK_LAYER(stack->data), FALSE ); vik_layer_post_read ( VIK_LAYER(stack->data), vp, TRUE ); } else if (VIK_LAYER(stack->under->data)->type == VIK_LAYER_GPS) { /* TODO: anything else needs to be done here ? */ } else { successful_read = FALSE; g_warning ( "Line %ld: EndLayer command inside non-Aggregate Layer (type %d)", line_num, VIK_LAYER(stack->data)->type ); } } pop(&stack); } } else if ( str_starts_with ( line, "LayerData", 9, FALSE ) ) { if ( stack->data && vik_layer_get_interface(VIK_LAYER(stack->data)->type)->read_file_data ) { /* must read until hits ~EndLayerData */ if ( ! vik_layer_get_interface(VIK_LAYER(stack->data)->type)->read_file_data ( VIK_LAYER(stack->data), f, dirpath ) ) successful_read = FALSE; } else { /* simply skip layer data over */ while ( fgets ( buffer, 4096, f ) ) { line_num++; line = buffer; len = strlen(line); if ( len > 0 && line[len-1] == '\n' ) line[--len] = '\0'; if ( len > 0 && line[len-1] == '\r' ) line[--len] = '\0'; if ( strcasecmp ( line, "~EndLayerData" ) == 0 ) break; } continue; } } else { successful_read = FALSE; g_warning ( "Line %ld: Unknown tilde command", line_num ); } } else { gint32 eq_pos = -1; guint16 i; if ( ! stack->data ) continue; for ( i = 0; i < len; i++ ) if ( line[i] == '=' ) eq_pos = i; if ( stack->under == NULL && eq_pos == 12 && strncasecmp ( line, "FILE_VERSION", eq_pos ) == 0) { gint version = strtol(line+13, NULL, 10); g_debug ( "%s: reading file version %d", __FUNCTION__, version ); if ( version > VIKING_FILE_VERSION ) successful_read = FALSE; // However we'll still carry and attempt to read whatever we can } else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "xmpp", eq_pos ) == 0) /* "hard coded" params: global & for all layer-types */ vik_viewport_set_xmpp ( VIK_VIEWPORT(vp), strtod ( line+5, NULL ) ); else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "ympp", eq_pos ) == 0) vik_viewport_set_ympp ( VIK_VIEWPORT(vp), strtod ( line+5, NULL ) ); else if ( stack->under == NULL && eq_pos == 3 && strncasecmp ( line, "lat", eq_pos ) == 0 ) ll.lat = strtod ( line+4, NULL ); else if ( stack->under == NULL && eq_pos == 3 && strncasecmp ( line, "lon", eq_pos ) == 0 ) ll.lon = strtod ( line+4, NULL ); else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "mode", eq_pos ) == 0 && strcasecmp ( line+5, "utm" ) == 0) vik_viewport_set_drawmode ( VIK_VIEWPORT(vp), VIK_VIEWPORT_DRAWMODE_UTM); else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "mode", eq_pos ) == 0 && strcasecmp ( line+5, "expedia" ) == 0) vik_viewport_set_drawmode ( VIK_VIEWPORT(vp), VIK_VIEWPORT_DRAWMODE_EXPEDIA ); else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "mode", eq_pos ) == 0 && strcasecmp ( line+5, "google" ) == 0) { successful_read = FALSE; g_warning ( _("Draw mode '%s' no more supported"), "google" ); } else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "mode", eq_pos ) == 0 && strcasecmp ( line+5, "kh" ) == 0) { successful_read = FALSE; g_warning ( _("Draw mode '%s' no more supported"), "kh" ); } else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "mode", eq_pos ) == 0 && strcasecmp ( line+5, "mercator" ) == 0) vik_viewport_set_drawmode ( VIK_VIEWPORT(vp), VIK_VIEWPORT_DRAWMODE_MERCATOR ); else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "mode", eq_pos ) == 0 && strcasecmp ( line+5, "latlon" ) == 0) vik_viewport_set_drawmode ( VIK_VIEWPORT(vp), VIK_VIEWPORT_DRAWMODE_LATLON ); else if ( stack->under == NULL && eq_pos == 5 && strncasecmp ( line, "color", eq_pos ) == 0 ) vik_viewport_set_background_color ( VIK_VIEWPORT(vp), line+6 ); else if ( stack->under == NULL && eq_pos == 14 && strncasecmp ( line, "highlightcolor", eq_pos ) == 0 ) vik_viewport_set_highlight_color ( VIK_VIEWPORT(vp), line+15 ); else if ( stack->under == NULL && eq_pos == 9 && strncasecmp ( line, "drawscale", eq_pos ) == 0 ) vik_viewport_set_draw_scale ( VIK_VIEWPORT(vp), TEST_BOOLEAN(line+10) ); else if ( stack->under == NULL && eq_pos == 14 && strncasecmp ( line, "drawcentermark", eq_pos ) == 0 ) vik_viewport_set_draw_centermark ( VIK_VIEWPORT(vp), TEST_BOOLEAN(line+15) ); else if ( stack->under == NULL && eq_pos == 13 && strncasecmp ( line, "drawhighlight", eq_pos ) == 0 ) vik_viewport_set_draw_highlight ( VIK_VIEWPORT(vp), TEST_BOOLEAN(line+14) ); else if ( stack->under && eq_pos == 4 && strncasecmp ( line, "name", eq_pos ) == 0 ) vik_layer_rename ( VIK_LAYER(stack->data), line+5 ); else if ( eq_pos == 7 && strncasecmp ( line, "visible", eq_pos ) == 0 ) VIK_LAYER(stack->data)->visible = TEST_BOOLEAN(line+8); else if ( eq_pos != -1 && stack->under ) { gboolean found_match = FALSE; /* go thru layer params. if len == eq_pos && starts_with jazz, set it. */ /* also got to check for name and visible. */ if ( ! params ) { successful_read = FALSE; g_warning ( "Line %ld: No options for this kind of layer", line_num ); continue; } for ( i = 0; i < params_count; i++ ) if ( strlen(params[i].name) == eq_pos && strncasecmp ( line, params[i].name, eq_pos ) == 0 ) { VikLayerParamData x; line += eq_pos+1; if ( params[i].type == VIK_LAYER_PARAM_STRING_LIST ) { GList *l = g_list_append ( g_hash_table_lookup ( string_lists, GINT_TO_POINTER ((gint) i) ), g_strdup(line) ); g_hash_table_replace ( string_lists, GINT_TO_POINTER ((gint)i), l ); /* add the value to a list, possibly making a new list. * this will be passed to the layer when we read an ~EndLayer */ } else { switch ( params[i].type ) { case VIK_LAYER_PARAM_DOUBLE: x.d = strtod(line, NULL); break; case VIK_LAYER_PARAM_UINT: x.u = strtoul(line, NULL, 10); break; case VIK_LAYER_PARAM_INT: x.i = strtol(line, NULL, 10); break; case VIK_LAYER_PARAM_BOOLEAN: x.b = TEST_BOOLEAN(line); break; case VIK_LAYER_PARAM_COLOR: memset(&(x.c), 0, sizeof(x.c)); /* default: black */ gdk_color_parse ( line, &(x.c) ); break; /* STRING or STRING_LIST -- if STRING_LIST, just set param to add a STRING */ default: x.s = line; } vik_layer_set_param ( VIK_LAYER(stack->data), i, x, vp, TRUE ); } found_match = TRUE; break; } if ( ! found_match ) { // ATM don't flow up this issue because at least one internal parameter has changed from version 1.3 // and don't what to worry users about raising such issues // TODO Maybe hold old values here - compare the line value against them and if a match // generate a different style of message in the GUI... // successful_read = FALSE; g_warning ( "Line %ld: Unknown parameter. Line:\n%s", line_num, line ); } } else { successful_read = FALSE; g_warning ( "Line %ld: Invalid parameter or parameter outside of layer.", line_num ); } } /* could be: [Layer Type=Bla] [EndLayer] [LayerData] name=this #comment */ } while ( stack ) { if ( stack->under && stack->under->data && stack->data ) { vik_aggregate_layer_add_layer ( VIK_AGGREGATE_LAYER(stack->under->data), VIK_LAYER(stack->data), FALSE ); vik_layer_post_read ( VIK_LAYER(stack->data), vp, TRUE ); } pop(&stack); } if ( ll.lat != 0.0 || ll.lon != 0.0 ) vik_viewport_set_center_latlon ( VIK_VIEWPORT(vp), &ll, TRUE ); if ( ( ! VIK_LAYER(top)->visible ) && VIK_LAYER(top)->realized ) vik_treeview_item_set_visible ( VIK_LAYER(top)->vt, &(VIK_LAYER(top)->iter), FALSE ); /* delete anything we've forgotten about -- should only happen when file ends before an EndLayer */ g_hash_table_foreach ( string_lists, string_list_delete, NULL ); g_hash_table_destroy ( string_lists ); return successful_read; }