コード例 #1
0
ファイル: vikgeoreflayer.c プロジェクト: rpeyron/viking
static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
{
  if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
    return FALSE;
  if ( event->button == 1 )
  {
    if ( vgl->mpp_easting < (VIK_VIEWPORT_MAX_ZOOM / 1.05) && vgl->mpp_northing < (VIK_VIEWPORT_MAX_ZOOM / 1.05) )
    {
      vgl->mpp_easting *= 1.01;
      vgl->mpp_northing *= 1.01;
    }
  }
  else
  {
    if ( vgl->mpp_easting > (VIK_VIEWPORT_MIN_ZOOM * 1.05) && vgl->mpp_northing > (VIK_VIEWPORT_MIN_ZOOM * 1.05) )
    {
      vgl->mpp_easting /= 1.01;
      vgl->mpp_northing /= 1.01;
    }
  }
  vik_viewport_set_xmpp ( vvp, vgl->mpp_easting );
  vik_viewport_set_ympp ( vvp, vgl->mpp_northing );
  vik_layer_emit_update ( VIK_LAYER(vgl) );
  return TRUE;
}
コード例 #2
0
/**
 * Run geotagging process in a separate thread
 */
static int trw_layer_geotag_thread ( geotag_options_t *options, gpointer threaddata )
{
	guint total = g_list_length(options->files), done = 0;

	// TODO decide how to report any issues to the user ...

	// Foreach file attempt to geotag it
	while ( options->files ) {
		options->image = (gchar *) ( options->files->data );
		trw_layer_geotag_process ( options );
		options->files = options->files->next;

		// Update thread progress and detect stop requests
		int result = a_background_thread_progress ( threaddata, ((gdouble) ++done) / total );
		if ( result != 0 )
			return -1; /* Abort thread */
	}

	if ( options->redraw ) {
		if ( IS_VIK_LAYER(options->vtl) ) {
			// Ensure any new images get shown
			trw_layer_verify_thumbnails ( options->vtl, NULL ); // NB second parameter not used ATM
			// Force redraw as verify only redraws if there are new thumbnails (they may already exist)
			vik_layer_emit_update ( VIK_LAYER(options->vtl), TRUE ); // Update from background
		}
	}

	return 0;
}
コード例 #3
0
static void trw_layer_waypoint_view ( menu_array_values values )
{
	VikTrwLayer *vtl = VIK_TRW_LAYER(values[MA_VTL]);
	VikWaypoint *wpt = VIK_WAYPOINT(values[MA_WPT]);
	VikViewport *vvp = VIK_VIEWPORT(values[MA_VVP]);

	vik_viewport_set_center_coord ( vvp, &(wpt->coord), TRUE );

	trw_layer_waypoint_select (values);

	vik_layer_emit_update ( VIK_LAYER(vtl) );
}
コード例 #4
0
ファイル: vikgeoreflayer.c プロジェクト: rpeyron/viking
static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
{
  if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
    return FALSE;

  if ( vgl->click_x != -1 )
  {
    vgl->corner.easting += (event->x - vgl->click_x) * vik_viewport_get_xmpp (vvp);
    vgl->corner.northing -= (event->y - vgl->click_y) * vik_viewport_get_ympp (vvp);
    vik_layer_emit_update ( VIK_LAYER(vgl) );
    return TRUE;
  }
  return FALSE; /* I didn't move anything on this layer! */
}
コード例 #5
0
ファイル: viklayerspanel.c プロジェクト: evanbattaglia/viking
gboolean vik_layers_panel_properties ( VikLayersPanel *vlp )
{
  GtkTreeIter iter;
  g_assert ( vlp->vvp );

  if ( vik_treeview_get_selected_iter ( vlp->vt, &iter ) && vik_treeview_item_get_type ( vlp->vt, &iter ) == VIK_TREEVIEW_TYPE_LAYER )
  {
    if ( vik_treeview_item_get_data ( vlp->vt, &iter ) == VIK_LAYER_AGGREGATE )
      a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vlp), _("Aggregate Layers have no settable properties.") );
    VikLayer *layer = VIK_LAYER( vik_treeview_item_get_pointer ( vlp->vt, &iter ) );
    if (vik_layer_properties ( layer, vlp->vvp ))
      vik_layer_emit_update ( layer, FALSE );
    return TRUE;
  }
  else
    return FALSE;
}
コード例 #6
0
/*
 * Function for starting the DEM file loading as a background thread
 */
static int dem_layer_load_list_thread ( dem_load_thread_data *dltd, gpointer threaddata )
{
  int result = 0; // Default to good
  // Actual Load
  if ( a_dems_load_list ( &(dltd->vdl->files), threaddata ) ) {
    // Thread cancelled
    result = -1;
  }

  // ATM as each file is processed the screen is not updated (no mechanism exposed to a_dems_load_list)
  // Thus force draw only at the end, as loading is complete/aborted
  //gdk_threads_enter();
  // Test is helpful to prevent Gtk-CRITICAL warnings if the program is exitted whilst loading
  if ( IS_VIK_LAYER(dltd->vdl) )
    vik_layer_emit_update ( VIK_LAYER(dltd->vdl) ); // NB update from background thread
  //gdk_threads_leave();

  return result;
}
コード例 #7
0
ファイル: vikaggregatelayer.c プロジェクト: rnorris/viking
static void aggregate_layer_child_visible_toggle ( menu_array_values values )
{
  VikAggregateLayer *val = VIK_AGGREGATE_LAYER ( values[MA_VAL] );
  VikLayersPanel *vlp = VIK_LAYERS_PANEL ( values[MA_VLP] );
  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 = !vl->visible;
    // Also set checkbox on/off
    vik_treeview_item_toggle_visible ( vik_layers_panel_get_treeview ( vlp ), &(vl->iter) );
    iter = iter->next;
  }
  // Redraw as view may have changed
  vik_layer_emit_update ( VIK_LAYER ( val ) );
}
コード例 #8
0
ファイル: vikaggregatelayer.c プロジェクト: gdt/viking
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 ) );
}
コード例 #9
0
static void dem_download_thread ( DEMDownloadParams *p, gpointer threaddata )
{
  if ( p->source == DEM_SOURCE_SRTM )
    srtm_dem_download_thread ( p, threaddata );
#ifdef VIK_CONFIG_DEM24K
  else if ( p->source == DEM_SOURCE_DEM24K )
    dem24k_dem_download_thread ( p, threaddata );
#endif
  else
    return;

  //gdk_threads_enter();
  g_mutex_lock ( p->mutex );
  if ( p->vdl ) {
    g_object_weak_unref ( G_OBJECT(p->vdl), weak_ref_cb, p );

    if ( dem_layer_add_file ( p->vdl, p->dest ) )
      vik_layer_emit_update ( VIK_LAYER(p->vdl) ); // NB update from background thread
  }
  g_mutex_unlock ( p->mutex );
  //gdk_threads_leave();
}
コード例 #10
0
static void trw_layer_waypoint_properties ( menu_array_values values )
{
	VikTrwLayer *vtl = VIK_TRW_LAYER(values[MA_VTL]);
	VikWaypoint *wpt = VIK_WAYPOINT(values[MA_WPT]);

	if ( wpt && wpt->name ) {
		// Kill off this dialog to allow interaction with properties window
		//  since the properties also allows waypoint manipulations it won't cause conflicts here.
		GtkWidget *gw = gtk_widget_get_toplevel ( values[MA_TREEVIEW] );
		waypoint_close_cb ( gw, 0, values[MA_WPTS_LIST] );

		gboolean updated = FALSE;
		gchar *new_name = a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), wpt->name, vtl, wpt, vik_trw_layer_get_coord_mode(vtl), FALSE, &updated );
		if ( new_name )
			trw_layer_waypoint_rename ( vtl, wpt, new_name );

		if ( updated )
			trw_layer_waypoint_reset_icon ( vtl, wpt );

		if ( updated && VIK_LAYER(vtl)->visible )
			vik_layer_emit_update ( VIK_LAYER(vtl) );
	}
}
コード例 #11
0
static gboolean datasource_osm_my_traces_process ( VikTrwLayer *vtl, const gchar *cmd, const gchar *extra, BabelStatusFunc status_cb, acq_dialog_widgets_t *adw, DownloadMapOptions *options_unused )
{
    //datasource_osm_my_traces_t *data = (datasource_osm_my_traces_t *)adw->user_data;

    gboolean result;

    gchar *user_pass = osm_get_login();

    DownloadMapOptions options = { FALSE, FALSE, NULL, 2, NULL, user_pass }; // Allow a couple of redirects

    xml_data *xd = g_malloc ( sizeof (xml_data) );
    //xd->xpath = g_string_new ( "" );
    xd->c_cdata = g_string_new ( "" );
    xd->current_tag = tt_unknown;
    xd->current_gpx_meta_data = new_gpx_meta_data_t();
    xd->list_of_gpx_meta_data = NULL;

    gchar *tmpname = a_download_uri_to_tmp_file ( DS_OSM_TRACES_GPX_FILES, &options );
    result = read_gpx_files_metadata_xml ( tmpname, xd );
    // Test already downloaded metadata file: eg:
    //result = read_gpx_files_metadata_xml ( "/tmp/viking-download.GI47PW", xd );

    if ( tmpname ) {
        g_remove ( tmpname );
        g_free ( tmpname );
    }

    if ( ! result )
        return FALSE;

    if ( g_list_length ( xd->list_of_gpx_meta_data ) == 0 ) {
        if (!vik_datasource_osm_my_traces_interface.is_thread)
            none_found ( GTK_WINDOW(adw->vw) );
        return FALSE;
    }

    xd->list_of_gpx_meta_data = g_list_reverse ( xd->list_of_gpx_meta_data );

    set_in_current_view_property ( vtl, adw->user_data, xd->list_of_gpx_meta_data );

    if (vik_datasource_osm_my_traces_interface.is_thread) gdk_threads_enter();
    GList *selected = select_from_list ( GTK_WINDOW(adw->vw), xd->list_of_gpx_meta_data, "Select GPS Traces", "Select the GPS traces you want to add." );
    if (vik_datasource_osm_my_traces_interface.is_thread) gdk_threads_leave();

    // If passed in on an existing layer - we will create everything into that.
    //  thus with many differing gpx's - this will combine all waypoints into this single layer!
    // Hence the preference is to create multiple layers
    //  and so this creation of the layers must be managed here

    gboolean create_new_layer = ( !vtl );

    // Only update the screen on the last layer acquired
    VikTrwLayer *vtl_last = vtl;
    gboolean got_something = FALSE;

    GList *selected_iterator = selected;
    while ( selected_iterator ) {

        VikTrwLayer *vtlX = vtl;

        if ( create_new_layer ) {
            // Have data but no layer - so create one
            vtlX = VIK_TRW_LAYER ( vik_layer_create ( VIK_LAYER_TRW, vik_window_viewport(adw->vw), NULL, FALSE ) );
            if ( ((gpx_meta_data_t*)selected_iterator->data)->name )
                vik_layer_rename ( VIK_LAYER ( vtlX ), ((gpx_meta_data_t*)selected_iterator->data)->name );
            else
                vik_layer_rename ( VIK_LAYER ( vtlX ), _("My OSM Traces") );
            vik_aggregate_layer_add_layer ( vik_layers_panel_get_top_layer (adw->vlp), VIK_LAYER(vtlX) );
        }

        result = FALSE;
        gint gpx_id = ((gpx_meta_data_t*)selected_iterator->data)->id;
        if ( gpx_id ) {
            gchar *url = g_strdup_printf ( DS_OSM_TRACES_GPX_URL_FMT, gpx_id );

            result = a_babel_convert_from_url ( vtlX, url, "gpx", status_cb, adw, &options );
            // TODO investigate using a progress bar:
            // http://developer.gnome.org/gtk/2.24/GtkProgressBar.html

            got_something = got_something || result;
            // TODO feedback to UI to inform which traces failed
            if ( !result )
                g_warning ( _("Unable to get trace: %s"), url );
        }

        if ( result ) {
            // Move to area of the track
            vik_trw_layer_auto_set_view ( vtlX, vik_window_viewport(adw->vw) );
            vik_layer_post_read ( VIK_LAYER(vtlX), vik_window_viewport(adw->vw), TRUE );
            vtl_last = vtlX;
        }
        else if ( create_new_layer ) {
            // Layer not needed as no data has been acquired
            g_object_unref ( vtlX );
        }

        selected_iterator = g_list_next ( selected_iterator );
    }

    // Free memory
    if ( xd->current_gpx_meta_data )
        free_gpx_meta_data ( xd->current_gpx_meta_data, NULL );
    g_free ( xd->current_gpx_meta_data );
    free_gpx_meta_data_list ( xd->list_of_gpx_meta_data );
    free_gpx_meta_data_list ( selected );
    g_free ( xd );
    g_free ( user_pass );

    // Would prefer to keep the update in acquire.c,
    //  however since we may create the layer - need to do the update here
    if ( got_something )
        vik_layer_emit_update ( VIK_LAYER(vtl_last) );

    // ATM The user is only informed if all getting *all* of the traces failed
    if ( selected )
        result = got_something;
    else
        // Process was cancelled but need to return that it proceeded as expected
        result = TRUE;

    return result;
}
コード例 #12
0
static gboolean dem_layer_download_release ( VikDEMLayer *vdl, GdkEventButton *event, VikViewport *vvp )
{
  VikCoord coord;
  static struct LatLon ll;

  gchar *full_path;
  gchar *dem_file = NULL;

  vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
  vik_coord_to_latlon ( &coord, &ll );

  
  if ( vdl->source == DEM_SOURCE_SRTM )
    dem_file = srtm_lat_lon_to_dest_fn ( ll.lat, ll.lon );
#ifdef VIK_CONFIG_DEM24K
  else if ( vdl->source == DEM_SOURCE_DEM24K )
    dem_file = dem24k_lat_lon_to_dest_fn ( ll.lat, ll.lon );
#endif

  if ( ! dem_file )
    return TRUE;

  full_path = g_strdup_printf("%s%s", MAPS_CACHE_DIR, dem_file );

  g_debug("%s: %s", __FUNCTION__, full_path);

  if ( event->button == 1 ) {
    // TODO: check if already in filelist
    if ( ! dem_layer_add_file(vdl, full_path) ) {
      gchar *tmp = g_strdup_printf ( _("Downloading DEM %s"), dem_file );
      DEMDownloadParams *p = g_malloc(sizeof(DEMDownloadParams));
      p->dest = g_strdup(full_path);
      p->lat = ll.lat;
      p->lon = ll.lon;
      p->vdl = vdl;
      p->mutex = g_mutex_new();
      p->source = vdl->source;
      g_object_weak_ref(G_OBJECT(p->vdl), weak_ref_cb, p );

      a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vdl), tmp,
                            (vik_thr_func) dem_download_thread, p,
                            (vik_thr_free_func) free_dem_download_params, NULL, 1 );

      g_free ( tmp );
    }
    else
      vik_layer_emit_update ( VIK_LAYER(vdl) );
  }
  else {
    if ( !vdl->right_click_menu ) {
      GtkWidget *item;
      vdl->right_click_menu = GTK_MENU ( gtk_menu_new () );

      item = gtk_image_menu_item_new_with_mnemonic ( _("_Show DEM File Information") );
      gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU) );
      g_signal_connect ( G_OBJECT(item), "activate", G_CALLBACK(dem_layer_file_info), &ll );
      gtk_menu_shell_append (GTK_MENU_SHELL(vdl->right_click_menu), item);
    }

    gtk_menu_popup ( vdl->right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
    gtk_widget_show_all ( GTK_WIDGET(vdl->right_click_menu) );
  }

  g_free ( dem_file );
  g_free ( full_path );

  return TRUE;
}
コード例 #13
0
ファイル: vikgeoreflayer.c プロジェクト: guyou/viking
/* returns TRUE if OK was pressed. */
static gboolean georef_layer_dialog ( VikGeorefLayer *vgl, gpointer vp, GtkWindow *w, gboolean have_apply_button )
{
  GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Layer Properties"), w,
                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                                   GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,  NULL );
  if ( have_apply_button )
    gtk_dialog_add_button ( GTK_DIALOG(dialog), GTK_STOCK_APPLY, GTK_RESPONSE_APPLY );
  gtk_dialog_add_button ( GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT );

  /* Default to reject as user really needs to specify map file first */
  gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
  GtkWidget *response_w = NULL;
#if GTK_CHECK_VERSION (2, 20, 0)
  response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
#endif
  GtkWidget *table, *wfp_hbox, *wfp_label, *wfp_button, *ce_label, *cn_label, *xlabel, *ylabel, *imagelabel;
  changeable_widgets cw;

  GtkBox *dgbox = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
  table = gtk_table_new ( 4, 2, FALSE );
  gtk_box_pack_start ( dgbox, table, TRUE, TRUE, 0 );

  wfp_hbox = gtk_hbox_new ( FALSE, 0 );
  wfp_label = gtk_label_new ( _("World File Parameters:") );
  wfp_button = gtk_button_new_with_label ( _("Load From File...") );

  gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_label, TRUE, TRUE, 0 );
  gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_button, FALSE, FALSE, 3 );

  ce_label = gtk_label_new ( _("Corner pixel easting:") );
  cw.ce_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, -15000000.0, 1500000.0, 1, 5, 0 ), 1, 4 );
  gtk_widget_set_tooltip_text ( GTK_WIDGET(cw.ce_spin), _("the UTM \"easting\" value of the upper-left corner pixel of the map") );

  cn_label = gtk_label_new ( _("Corner pixel northing:") );
  cw.cn_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, -15000000.0, 15000000.0, 1, 5, 0 ), 1, 4 );
  gtk_widget_set_tooltip_text ( GTK_WIDGET(cw.cn_spin), _("the UTM \"northing\" value of the upper-left corner pixel of the map") );

  xlabel = gtk_label_new ( _("X (easting) scale (mpp): "));
  ylabel = gtk_label_new ( _("Y (northing) scale (mpp): "));

  cw.x_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
  gtk_widget_set_tooltip_text ( GTK_WIDGET(cw.x_spin), _("the scale of the map in the X direction (meters per pixel)") );
  cw.y_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
  gtk_widget_set_tooltip_text ( GTK_WIDGET(cw.y_spin), _("the scale of the map in the Y direction (meters per pixel)") );

  imagelabel = gtk_label_new ( _("Map Image:") );
  cw.imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN, VF_FILTER_IMAGE, maybe_read_world_file, &cw);

  gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cw.ce_spin), vgl->corner.easting );
  gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cw.cn_spin), vgl->corner.northing );
  gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cw.x_spin), vgl->mpp_easting );
  gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cw.y_spin), vgl->mpp_northing );
  if ( vgl->image )
    vik_file_entry_set_filename ( VIK_FILE_ENTRY(cw.imageentry), vgl->image );

  gtk_table_attach_defaults ( GTK_TABLE(table), imagelabel, 0, 1, 0, 1 );
  gtk_table_attach_defaults ( GTK_TABLE(table), cw.imageentry, 1, 2, 0, 1 );
  gtk_table_attach_defaults ( GTK_TABLE(table), wfp_hbox, 0, 2, 1, 2 );
  gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 2, 3 );
  gtk_table_attach_defaults ( GTK_TABLE(table), cw.x_spin, 1, 2, 2, 3 );
  gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 3, 4 );
  gtk_table_attach_defaults ( GTK_TABLE(table), cw.y_spin, 1, 2, 3, 4 );

  cw.tabs = gtk_notebook_new();
  GtkWidget *table_utm = gtk_table_new ( 3, 2, FALSE );

  gtk_table_attach_defaults ( GTK_TABLE(table_utm), ce_label, 0, 1, 0, 1 );
  gtk_table_attach_defaults ( GTK_TABLE(table_utm), cw.ce_spin, 1, 2, 0, 1 );
  gtk_table_attach_defaults ( GTK_TABLE(table_utm), cn_label, 0, 1, 1, 2 );
  gtk_table_attach_defaults ( GTK_TABLE(table_utm), cw.cn_spin, 1, 2, 1, 2 );

  GtkWidget *utm_hbox = gtk_hbox_new ( FALSE, 0 );
  cw.utm_zone_spin = gtk_spin_button_new ((GtkAdjustment*)gtk_adjustment_new( vgl->corner.zone, 1, 60, 1, 5, 0 ), 1, 0 );
  gtk_box_pack_start ( GTK_BOX(utm_hbox), gtk_label_new(_("Zone:")), TRUE, TRUE, 0 );
  gtk_box_pack_start ( GTK_BOX(utm_hbox), cw.utm_zone_spin, TRUE, TRUE, 0 );
  gtk_box_pack_start ( GTK_BOX(utm_hbox), gtk_label_new(_("Letter:")), TRUE, TRUE, 0 );
  cw.utm_letter_entry = gtk_entry_new ();
  gtk_entry_set_max_length ( GTK_ENTRY(cw.utm_letter_entry), 1 );
  gtk_entry_set_width_chars ( GTK_ENTRY(cw.utm_letter_entry), 2 );
  gchar tmp_letter[2];
  tmp_letter[0] = vgl->corner.letter;
  tmp_letter[1] = '\0';
  gtk_entry_set_text ( GTK_ENTRY(cw.utm_letter_entry), tmp_letter );
  gtk_box_pack_start ( GTK_BOX(utm_hbox), cw.utm_letter_entry, TRUE, TRUE, 0 );

  gtk_table_attach_defaults ( GTK_TABLE(table_utm), utm_hbox, 0, 2, 2, 3 );

  // Lat/Lon
  GtkWidget *table_ll = gtk_table_new ( 5, 2, FALSE );

  GtkWidget *lat_tl_label = gtk_label_new ( _("Upper left latitude:") );
  cw.lat_tl_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new (0.0,-90,90.0,0.05,0.1,0), 0.1, 6 );
  GtkWidget *lon_tl_label = gtk_label_new ( _("Upper left longitude:") );
  cw.lon_tl_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new (0.0,-180,180.0,0.05,0.1,0), 0.1, 6 );
  GtkWidget *lat_br_label = gtk_label_new ( _("Lower right latitude:") );
  cw.lat_br_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new (0.0,-90,90.0,0.05,0.1,0), 0.1, 6 );
  GtkWidget *lon_br_label = gtk_label_new ( _("Lower right longitude:") );
  cw.lon_br_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new (0.0,-180.0,180.0,0.05,0.1,0), 0.1, 6 );

  gtk_table_attach_defaults ( GTK_TABLE(table_ll), lat_tl_label, 0, 1, 0, 1 );
  gtk_table_attach_defaults ( GTK_TABLE(table_ll), cw.lat_tl_spin, 1, 2, 0, 1 );
  gtk_table_attach_defaults ( GTK_TABLE(table_ll), lon_tl_label, 0, 1, 1, 2 );
  gtk_table_attach_defaults ( GTK_TABLE(table_ll), cw.lon_tl_spin, 1, 2, 1, 2 );
  gtk_table_attach_defaults ( GTK_TABLE(table_ll), lat_br_label, 0, 1, 2, 3 );
  gtk_table_attach_defaults ( GTK_TABLE(table_ll), cw.lat_br_spin, 1, 2, 2, 3 );
  gtk_table_attach_defaults ( GTK_TABLE(table_ll), lon_br_label, 0, 1, 3, 4 );
  gtk_table_attach_defaults ( GTK_TABLE(table_ll), cw.lon_br_spin, 1, 2, 3, 4 );

  GtkWidget *calc_mpp_button = gtk_button_new_with_label ( _("Calculate MPP values from coordinates") );
  gtk_widget_set_tooltip_text ( calc_mpp_button, _("Enter all corner coordinates before calculating the MPP values from the image size") );
  gtk_table_attach_defaults ( GTK_TABLE(table_ll), calc_mpp_button, 0, 2, 4, 5 );

  VikCoord vc;
  vik_coord_load_from_utm (&vc, VIK_COORD_LATLON, &(vgl->corner));
  gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cw.lat_tl_spin), vc.north_south );
  gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cw.lon_tl_spin), vc.east_west );
  gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cw.lat_br_spin), vgl->ll_br.lat );
  gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cw.lon_br_spin), vgl->ll_br.lon );

  gtk_notebook_append_page(GTK_NOTEBOOK(cw.tabs), GTK_WIDGET(table_utm), gtk_label_new(_("UTM")));
  gtk_notebook_append_page(GTK_NOTEBOOK(cw.tabs), GTK_WIDGET(table_ll), gtk_label_new(_("Latitude/Longitude")));
  gtk_box_pack_start ( dgbox, cw.tabs, TRUE, TRUE, 0 );

  GtkWidget *alpha_hbox = gtk_hbox_new ( FALSE, 0 );
  // GTK3 => GtkWidget *alpha_scale = gtk_scale_new_with_range ( GTK_ORIENTATION_HORIZONTAL, 0, 255, 1 );
  GtkWidget *alpha_scale = gtk_hscale_new_with_range ( 0, 255, 1 );
  gtk_scale_set_digits ( GTK_SCALE(alpha_scale), 0 );
  gtk_range_set_value ( GTK_RANGE(alpha_scale), vgl->alpha );
  gtk_box_pack_start ( GTK_BOX(alpha_hbox), gtk_label_new(_("Alpha:")), TRUE, TRUE, 0 );
  gtk_box_pack_start ( GTK_BOX(alpha_hbox), alpha_scale, TRUE, TRUE, 0 );
  gtk_box_pack_start ( dgbox, alpha_hbox, TRUE, TRUE, 0 );

  vgl->cw = cw;

  g_signal_connect ( G_OBJECT(vgl->cw.tabs), "switch-page", G_CALLBACK(switch_tab), vgl );
  g_signal_connect ( G_OBJECT(calc_mpp_button), "clicked", G_CALLBACK(calculate_mpp_from_coords), vgl );

  g_signal_connect_swapped ( G_OBJECT(wfp_button), "clicked", G_CALLBACK(georef_layer_dialog_load), &cw );

  if ( response_w )
    gtk_widget_grab_focus ( response_w );

  gtk_widget_show_all ( dialog );

  // Remember setting the notebook page must be done after the widget is visible.
  gint page_num = 0;
  if ( a_settings_get_integer ( VIK_SETTINGS_GEOREF_TAB, &page_num ) )
    if ( page_num < 0 || page_num > 1 )
      page_num = 0;
  gtk_notebook_set_current_page ( GTK_NOTEBOOK(cw.tabs), page_num );

  gboolean answer = FALSE;
  gint resp = GTK_RESPONSE_APPLY;
  while ( resp == GTK_RESPONSE_APPLY )  {
    resp = gtk_dialog_run ( GTK_DIALOG(dialog) );
    if ( resp == GTK_RESPONSE_ACCEPT || resp == GTK_RESPONSE_APPLY ) {
      align_coords ( vgl );

      vgl->corner.easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cw.ce_spin) );
      vgl->corner.northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cw.cn_spin) );
      vgl->corner.zone = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(cw.utm_zone_spin) );
      const gchar *letter = gtk_entry_get_text ( GTK_ENTRY(cw.utm_letter_entry) );
      if (*letter)
         vgl->corner.letter = toupper(*letter);
      vgl->mpp_easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cw.x_spin) );
      vgl->mpp_northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cw.y_spin) );
      vgl->ll_br = get_ll_br (vgl);
      check_br_is_good_or_msg_user ( vgl );
      // TODO check if image has changed otherwise no need to regenerate pixbuf
      if ( !vgl->pixbuf ) {
        if ( g_strcmp0 (vgl->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(cw.imageentry)) ) != 0 ) {
          georef_layer_set_image ( vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(cw.imageentry)) );
          georef_layer_load_image ( vgl, VIK_VIEWPORT(vp), FALSE );
        }
      }

      vgl->alpha = (guint8) gtk_range_get_value ( GTK_RANGE(alpha_scale) );
      if ( vgl->pixbuf && vgl->alpha <= 255 )
        vgl->pixbuf = ui_pixbuf_set_alpha ( vgl->pixbuf, vgl->alpha );
      if ( vgl->scaled && vgl->alpha <= 255 )
        vgl->scaled = ui_pixbuf_set_alpha ( vgl->scaled, vgl->alpha );

      a_settings_set_integer ( VIK_SETTINGS_GEOREF_TAB, gtk_notebook_get_current_page(GTK_NOTEBOOK(cw.tabs)) );

      if ( resp == GTK_RESPONSE_APPLY ) {
        vik_layer_emit_update ( VIK_LAYER(vgl) );
        answer = FALSE;
      }
      else
        answer = TRUE;
    }
  }
  gtk_widget_destroy ( GTK_WIDGET(dialog) );
  return answer;
}