#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixdata.h>
+#include <glib.h>
+#include <glib/gstdio.h>
#include <glib/gi18n.h>
-#include <stdio.h>
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+#ifdef HAVE_MATH_H
#include <math.h>
+#endif
+
#include "globals.h"
#include "coords.h"
#include "vikcoord.h"
#include "vikviewport.h"
#include "viklayer.h"
#include "vikmapslayer.h"
-#include "vikmapslayer_pixmap.h"
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+#endif
#include "mapcache.h"
/* only for dialog.h -- ugh */
VikLayerParam maps_layer_params[] = {
{ "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Map Type:"), VIK_LAYER_WIDGET_RADIOGROUP, NULL, NULL },
- { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory (Optional):"), VIK_LAYER_WIDGET_FILEENTRY },
+ { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("Maps Directory:"), VIK_LAYER_WIDGET_FOLDERENTRY },
{ "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales },
{ "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, N_("Autodownload maps:"), VIK_LAYER_WIDGET_CHECKBUTTON },
{ "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Zoom Level:"), VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms },
static VikToolInterface maps_tools[] = {
{ N_("Maps Download"), (VikToolConstructorFunc) maps_layer_download_create, NULL, NULL, NULL,
(VikToolMouseFunc) maps_layer_download_click, NULL, (VikToolMouseFunc) maps_layer_download_release,
- (VikToolKeyFunc) NULL, &cursor_mapdl },
+ (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_mapdl_pixbuf },
};
VikLayerInterface vik_maps_layer_interface = {
N_("Map"),
- &mapslayer_pixbuf,
+ &vikmapslayer_pixbuf,
maps_tools,
sizeof(maps_tools) / sizeof(maps_tools[0]),
(VikLayerFuncCreate) maps_layer_new,
(VikLayerFuncRealize) NULL,
- maps_layer_post_read,
+ (VikLayerFuncPostRead) maps_layer_post_read,
(VikLayerFuncFree) maps_layer_free,
(VikLayerFuncProperties) NULL,
VikViewport *redownload_vvp;
};
-enum { REDOWNLOAD_NONE = 0, REDOWNLOAD_BAD, REDOWNLOAD_ALL, DOWNLOAD_OR_REFRESH };
+enum { REDOWNLOAD_NONE = 0, /* download only missing maps */
+ REDOWNLOAD_BAD, /* download missing and bad maps */
+ REDOWNLOAD_NEW, /* download missing maps that are newer on server only */
+ REDOWNLOAD_ALL, /* download all maps */
+ DOWNLOAD_OR_REFRESH }; /* download missing maps and refresh cache */
/****************************************/
params_maptypes = g_list_append(params_maptypes, g_strdup(label));
/* Add the id */
- params_maptypes_ids = g_list_append(params_maptypes_ids, (gpointer)id);
+ params_maptypes_ids = g_list_append(params_maptypes_ids, GUINT_TO_POINTER (id));
/* We have to clone */
VikMapsLayer_MapType *clone = g_memdup(map_type, sizeof(VikMapsLayer_MapType));
/****************************************/
#define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
+#define MAPS_CACHE_DIR maps_layer_default_dir()
+
#ifdef WINDOWS
-#define MAPS_CACHE_DIR "C:\\VIKING-MAPS\\"
+#include <io.h>
+#define GLOBAL_MAPS_DIR "C:\\VIKING-MAPS\\"
+#define LOCAL_MAPS_DIR "VIKING-MAPS"
#else /* POSIX */
-
#include <stdlib.h>
-
-#define MAPS_CACHE_DIR maps_layer_default_dir()
#define GLOBAL_MAPS_DIR "/var/cache/maps/"
+#define LOCAL_MAPS_DIR ".viking-maps"
+#endif
gchar *maps_layer_default_dir ()
{
const gchar *mapdir = g_getenv("VIKING_MAPS");
if ( mapdir ) {
defaultdir = g_strdup ( mapdir );
- } else if ( access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
+ } else if ( g_access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
} else {
- const gchar *home = g_getenv("HOME");
- if (!home || access(home, W_OK))
+ const gchar *home = g_get_home_dir();
+ if (!home || g_access(home, W_OK))
home = g_get_home_dir ();
if ( home )
- defaultdir = g_build_filename ( home, ".viking-maps", NULL );
+ defaultdir = g_build_filename ( home, LOCAL_MAPS_DIR, NULL );
else
- defaultdir = g_strdup ( ".viking-maps" );
+ defaultdir = g_strdup ( LOCAL_MAPS_DIR );
}
if (defaultdir && (defaultdir[strlen(defaultdir)-1] != G_DIR_SEPARATOR))
{
return defaultdir;
}
-#endif
-
static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
{
- if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && access ( vml->cache_dir, F_OK ) != 0 )
+ if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && g_file_test ( vml->cache_dir, G_FILE_TEST_EXISTS ) == FALSE )
{
-#ifdef WINDOWS
- mkdir ( vml->cache_dir );
-#else
- mkdir ( vml->cache_dir, 0777 );
-#endif
+ g_mkdir ( vml->cache_dir, 0777 );
}
}
VikLayerParamData rv;
switch ( id )
{
- case PARAM_CACHE_DIR: rv.s = (vml->cache_dir && strcmp(vml->cache_dir, MAPS_CACHE_DIR) != 0) ? vml->cache_dir : ""; break;
+ case PARAM_CACHE_DIR: rv.s = vml->cache_dir ? vml->cache_dir : ""; break;
case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
case PARAM_ALPHA: rv.u = vml->alpha; break;
case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
{
GdkPixbuf *tmp;
guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
- tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_BILINEAR);
+ tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_NEAREST);
g_object_unref ( G_OBJECT(pixbuf) );
return tmp;
}
g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
vml->cache_dir, mode,
mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
- if ( access ( filename_buf, R_OK ) == 0) {
+ if ( g_file_test ( filename_buf, G_FILE_TEST_EXISTS ) == TRUE) {
{
GError *gx = NULL;
pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
#ifdef DEBUG
fputs(stderr, "DEBUG: Starting autodownload\n");
#endif
- start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
+ if ( map_type->options != NULL && map_type->options->check_file_server_time )
+ // Try to download newer tiles
+ start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NEW );
+ else
+ // Download only missing tiles
+ start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
}
if ( map_type->tilesize_x == 0 && !existence_only ) {
g_snprintf ( path_buf, max_path_len, DIRSTRUCTURE,
vml->cache_dir, mode,
ulm.scale, ulm.z, ulm.x, ulm.y );
- if ( access ( path_buf, F_OK ) == 0 ) {
+ if ( g_file_test ( path_buf, G_FILE_TEST_EXISTS ) == TRUE ) {
vik_viewport_draw_line ( vvp, black_gc, xx+tilesize_x_ceil, yy, xx, yy+tilesize_y_ceil );
}
} else {
pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
if ( pixbuf )
vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
+ else {
+ /* retry with bigger shrinkfactor */
+ int scale_inc;
+ for (scale_inc = 1; scale_inc < 4; scale_inc ++) {
+ int scale_factor = 1 << scale_inc; /* 2^scale_inc */
+ MapCoord ulm2 = ulm;
+ ulm2.x = ulm.x / scale_factor;
+ ulm2.y = ulm.y / scale_factor;
+ ulm2.scale = ulm.scale + scale_inc;
+ pixbuf = get_pixbuf ( vml, mode, &ulm2, path_buf, max_path_len, xshrinkfactor * scale_factor, yshrinkfactor * scale_factor );
+ if ( pixbuf ) {
+ gint src_x = (ulm.x % scale_factor) * tilesize_x_ceil;
+ gint src_y = (ulm.y % scale_factor) * tilesize_y_ceil;
+ vik_viewport_draw_pixbuf ( vvp, pixbuf, src_x, src_y, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
+ break;
+ }
+ }
+ }
}
yy += tilesize_y;
g_mutex_unlock(mdi->mutex);
}
-static void map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
+static int map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
{
guint donemaps = 0;
gint x, y;
mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
donemaps++;
- a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
+ int res = a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
+ if (res != 0)
+ return -1;
if ( mdi->redownload == REDOWNLOAD_ALL)
- remove ( mdi->filename_buf );
+ g_remove ( mdi->filename_buf );
- else if ( (mdi->redownload == REDOWNLOAD_BAD) && (access ( mdi->filename_buf, F_OK ) == 0) )
+ else if ( (mdi->redownload == REDOWNLOAD_BAD) && (g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE) )
{
/* see if this one is bad or what */
GError *gx = NULL;
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
if (gx || (!pixbuf))
- remove ( mdi->filename_buf );
+ g_remove ( mdi->filename_buf );
if ( pixbuf )
g_object_unref ( pixbuf );
if ( gx )
g_error_free ( gx );
}
- if ( access ( mdi->filename_buf, F_OK ) != 0 )
+ if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
{
need_download = TRUE;
if (( mdi->redownload != REDOWNLOAD_NONE ) &&
remove_mem_cache = TRUE;
} else if ( mdi->redownload == DOWNLOAD_OR_REFRESH ) {
remove_mem_cache = TRUE;
+ } else if ( mdi->redownload == REDOWNLOAD_NEW) {
+ need_download = TRUE;
+ remove_mem_cache = TRUE;
} else
continue;
if (mdi->map_layer_alive)
g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
g_mutex_unlock(mdi->mutex);
+ return 0;
}
static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
mdi->cache_dir, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id,
mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
- if ( access ( mdi->filename_buf, F_OK ) == 0)
+ if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == TRUE)
{
- remove ( mdi->filename_buf );
+ g_remove ( mdi->filename_buf );
}
}
}
g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
vml->cache_dir, map_type->uniq_id, ulm.scale,
ulm.z, a, b );
- if ( access ( mdi->filename_buf, F_OK ) != 0)
+ if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
mdi->mapstoget++;
}
}
if ( mdi->mapstoget )
{
- gchar *tmp = g_strdup_printf ( "%s %s%d %s %s...", redownload ? _("Redownloading") : _("Downloading"), redownload == REDOWNLOAD_BAD ? _("up to ") : "", mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype), ngettext("map", "maps", mdi->mapstoget) );
+ const gchar *tmp_str;
+ gchar *tmp;
+ if (redownload)
+ {
+ if (redownload == REDOWNLOAD_BAD)
+ tmp_str = ngettext("Redownloading up to %d %s map...", "Redownloading up to %d %s maps...", mdi->mapstoget);
+ else
+ tmp_str = ngettext("Redownloading %d %s map...", "Redownloading %d %s maps...", mdi->mapstoget);
+ }
+ else
+ {
+ tmp_str = ngettext("Downloading %d %s map...", "Downloading %d %s maps...", mdi->mapstoget);
+ }
+ tmp = g_strdup_printf ( tmp_str, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype));
+
g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
/* launch the thread */
a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
if (!map_type->coord_to_mapcoord(ul, zoom, zoom, &ulm)
|| !map_type->coord_to_mapcoord(br, zoom, zoom, &brm)) {
- g_warning("%s() coord_to_mapcoord() failed\n", __PRETTY_FUNCTION__);
+ g_warning("%s() coord_to_mapcoord() failed", __PRETTY_FUNCTION__);
return;
}
g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
vml->cache_dir, map_type->uniq_id, ulm.scale,
ulm.z, i, j );
- if ( access ( mdi->filename_buf, F_OK ) != 0)
+ if ( g_file_test ( mdi->filename_buf, G_FILE_TEST_EXISTS ) == FALSE )
mdi->mapstoget++;
}
}
if (mdi->mapstoget) {
gchar *tmp;
const gchar *fmt;
- if (mdi->mapstoget == 1)
- fmt = _("Downloading %d %s map...");
- else
- fmt = _("Downloading %d %s maps...");
+ fmt = ngettext("Downloading %d %s map...",
+ "Downloading %d %s maps...",
+ mdi->mapstoget);
tmp = g_strdup_printf ( fmt, mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype) );
g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
{
start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
}
+
static void maps_layer_redownload_all ( VikMapsLayer *vml )
{
start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
}
+static void maps_layer_redownload_new ( VikMapsLayer *vml )
+{
+ start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_NEW );
+}
+
static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
{
if (!vml || vml->vl.type != VIK_LAYER_MAPS)
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
+ item = gtk_menu_item_new_with_label ( _("Redownload new map(s)") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_new), vml );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
+
item = gtk_menu_item_new_with_label ( _("Redownload all map(s)") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
}
-static void maps_layer_download_onscreen_maps ( gpointer vml_vvp[2] )
+static void maps_layer_download_missing_onscreen_maps ( gpointer vml_vvp[2] )
{
download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
}
+static void maps_layer_download_new_onscreen_maps ( gpointer vml_vvp[2] )
+{
+ download_onscreen_maps( vml_vvp, REDOWNLOAD_NEW);
+}
+
static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
{
download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( _("Download Onscreen Maps") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_onscreen_maps), pass_along );
+ item = gtk_menu_item_new_with_label ( _("Download missing Onscreen Maps") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_missing_onscreen_maps), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
+ if ( MAPS_LAYER_NTH_TYPE(vml->maptype)->options != NULL &&
+ MAPS_LAYER_NTH_TYPE(vml->maptype)->options->check_file_server_time ) {
+ item = gtk_menu_item_new_with_label ( _("Download new Onscreen Maps from server") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_new_onscreen_maps), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ }
+
+ /* TODO Add GTK_STOCK_REFRESH icon */
item = gtk_menu_item_new_with_label ( _("Refresh Onscreen Tiles") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);