]>
Commit | Line | Data |
---|---|---|
9f58c4b4 GB |
1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ |
2 | /* | |
3 | * viking | |
4 | * Copyright (C) 2011, Guilhem Bonnefille <guilhem.bonnefille@gmail.com> | |
5 | * | |
6 | * viking is free software: you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
98264f5e | 8 | * Free Software Foundation, either version 2 of the License, or |
9f58c4b4 GB |
9 | * (at your option) any later version. |
10 | * | |
11 | * viking is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
14 | * See the GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along | |
17 | * with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | /** | |
21 | * SECTION:bingmapsource | |
22 | * @short_description: the class for Bing Maps | |
23 | * | |
24 | * The #BingMapSource class handles Bing map source. | |
25 | * | |
26 | * License and term of use are available here: | |
27 | * http://wiki.openstreetmap.org/wiki/File:Bing_license.pdf | |
28 | * | |
29 | * Technical details are available here: | |
30 | * http://msdn.microsoft.com/en-us/library/dd877180.aspx | |
31 | */ | |
32 | ||
33 | #ifdef HAVE_CONFIG_H | |
34 | #include "config.h" | |
35 | #endif | |
36 | ||
37 | #ifdef HAVE_MATH_H | |
38 | #include <math.h> | |
39 | #endif | |
40 | ||
41 | #ifdef HAVE_STDLIB_H | |
42 | #include <stdlib.h> | |
43 | #endif | |
44 | #include <glib.h> | |
45 | #include <glib/gstdio.h> | |
46 | #include <glib/gi18n.h> | |
47 | #include <gdk-pixbuf/gdk-pixdata.h> | |
48 | #include "globals.h" | |
9f58c4b4 | 49 | #include "bingmapsource.h" |
e1dde2a6 | 50 | #include "maputils.h" |
9f58c4b4 GB |
51 | #include "bbox.h" |
52 | #include "background.h" | |
53 | #include "icons/icons.h" | |
54 | ||
55 | /* Format for URL */ | |
56 | #define URL_ATTR_FMT "http://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/0,0?zl=1&mapVersion=v1&key=%s&include=ImageryProviders&output=xml" | |
57 | ||
23992e34 RN |
58 | static gchar *bget_uri ( VikMapSourceDefault *self, MapCoord *src ); |
59 | static gchar *bget_hostname ( VikMapSourceDefault *self ); | |
2f806387 | 60 | static void _get_copyright (VikMapSource * self, LatLonBBox bbox, gdouble zoom, void (*fct)(VikViewport*,const gchar*), void *data); |
9f58c4b4 GB |
61 | static const GdkPixbuf *_get_logo ( VikMapSource *self ); |
62 | static int _load_attributions ( BingMapSource *self ); | |
63 | static void _async_load_attributions ( BingMapSource *self ); | |
64 | ||
65 | struct _Attribution | |
66 | { | |
67 | gchar *attribution; | |
68 | int minZoom; | |
69 | int maxZoom; | |
70 | LatLonBBox bounds; | |
71 | }; | |
72 | ||
73 | typedef struct _BingMapSourcePrivate BingMapSourcePrivate; | |
74 | struct _BingMapSourcePrivate | |
75 | { | |
b39149e0 RN |
76 | gchar *hostname; |
77 | gchar *url; | |
9f58c4b4 GB |
78 | gchar *api_key; |
79 | GList *attributions; | |
80 | /* Current attribution, when parsing */ | |
81 | gchar *attribution; | |
a1ed03fb | 82 | gboolean loading_attributions; |
9f58c4b4 GB |
83 | }; |
84 | ||
85 | /* The pixbuf to store the logo */ | |
86 | static GdkPixbuf *pixbuf = NULL; | |
87 | ||
88 | #define BING_MAP_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BING_TYPE_MAP_SOURCE, BingMapSourcePrivate)) | |
89 | ||
90 | /* properties */ | |
91 | enum | |
92 | { | |
93 | PROP_0, | |
94 | ||
b39149e0 RN |
95 | PROP_HOSTNAME, |
96 | PROP_URL, | |
9f58c4b4 GB |
97 | PROP_API_KEY, |
98 | }; | |
99 | ||
100 | G_DEFINE_TYPE (BingMapSource, bing_map_source, VIK_TYPE_SLIPPY_MAP_SOURCE); | |
101 | ||
102 | static void | |
103 | bing_map_source_init (BingMapSource *self) | |
104 | { | |
105 | /* initialize the object here */ | |
106 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); | |
107 | ||
b39149e0 RN |
108 | priv->hostname = NULL; |
109 | priv->url = NULL; | |
9f58c4b4 GB |
110 | priv->api_key = NULL; |
111 | priv->attributions = NULL; | |
112 | priv->attribution = NULL; | |
a1ed03fb | 113 | priv->loading_attributions = FALSE; |
9f58c4b4 GB |
114 | } |
115 | ||
116 | static void | |
117 | bing_map_source_finalize (GObject *object) | |
118 | { | |
119 | BingMapSource *self = BING_MAP_SOURCE (object); | |
120 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); | |
121 | ||
b39149e0 RN |
122 | g_free (priv->hostname); |
123 | priv->hostname = NULL; | |
124 | g_free (priv->url); | |
125 | priv->url = NULL; | |
9f58c4b4 GB |
126 | g_free (priv->api_key); |
127 | priv->api_key = NULL; | |
128 | ||
129 | G_OBJECT_CLASS (bing_map_source_parent_class)->finalize (object); | |
130 | } | |
131 | ||
132 | static void | |
133 | _set_property (GObject *object, | |
134 | guint property_id, | |
135 | const GValue *value, | |
136 | GParamSpec *pspec) | |
137 | { | |
138 | BingMapSource *self = BING_MAP_SOURCE (object); | |
139 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); | |
140 | ||
141 | switch (property_id) | |
142 | { | |
b39149e0 RN |
143 | case PROP_HOSTNAME: |
144 | g_free (priv->hostname); | |
145 | priv->hostname = g_value_dup_string (value); | |
146 | break; | |
147 | ||
148 | case PROP_URL: | |
149 | g_free (priv->url); | |
150 | priv->url = g_value_dup_string (value); | |
151 | break; | |
152 | ||
9f58c4b4 GB |
153 | case PROP_API_KEY: |
154 | priv->api_key = g_strdup (g_value_get_string (value)); | |
155 | break; | |
156 | ||
157 | default: | |
158 | /* We don't have any other property... */ | |
159 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
160 | break; | |
161 | } | |
162 | } | |
163 | ||
164 | static void | |
165 | _get_property (GObject *object, | |
166 | guint property_id, | |
167 | GValue *value, | |
168 | GParamSpec *pspec) | |
169 | { | |
170 | BingMapSource *self = BING_MAP_SOURCE (object); | |
171 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); | |
172 | ||
173 | switch (property_id) | |
174 | { | |
b39149e0 RN |
175 | case PROP_HOSTNAME: |
176 | g_value_set_string (value, priv->hostname); | |
177 | break; | |
178 | ||
179 | case PROP_URL: | |
180 | g_value_set_string (value, priv->url); | |
181 | break; | |
182 | ||
9f58c4b4 GB |
183 | case PROP_API_KEY: |
184 | g_value_set_string (value, priv->api_key); | |
185 | break; | |
186 | ||
187 | default: | |
188 | /* We don't have any other property... */ | |
189 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); | |
190 | break; | |
191 | } | |
192 | } | |
193 | ||
194 | ||
195 | static void | |
196 | bing_map_source_class_init (BingMapSourceClass *klass) | |
197 | { | |
198 | GObjectClass* object_class = G_OBJECT_CLASS (klass); | |
199 | VikMapSourceDefaultClass* grandparent_class = VIK_MAP_SOURCE_DEFAULT_CLASS (klass); | |
200 | VikMapSourceClass* base_class = VIK_MAP_SOURCE_CLASS (klass); | |
201 | GParamSpec *pspec = NULL; | |
b39149e0 | 202 | |
9f58c4b4 GB |
203 | /* Overiding methods */ |
204 | object_class->set_property = _set_property; | |
205 | object_class->get_property = _get_property; | |
23992e34 RN |
206 | grandparent_class->get_uri = bget_uri; |
207 | grandparent_class->get_hostname = bget_hostname; | |
9f58c4b4 GB |
208 | base_class->get_logo = _get_logo; |
209 | base_class->get_copyright = _get_copyright; | |
210 | ||
b39149e0 RN |
211 | pspec = g_param_spec_string ("hostname", |
212 | "Hostname", | |
213 | "The hostname of the map server", | |
214 | "<no-set>" /* default value */, | |
215 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); | |
216 | g_object_class_install_property (object_class, PROP_HOSTNAME, pspec); | |
217 | ||
218 | pspec = g_param_spec_string ("url", | |
219 | "URL", | |
220 | "The template of the tiles' URL", | |
221 | "<no-set>" /* default value */, | |
222 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); | |
223 | g_object_class_install_property (object_class, PROP_URL, pspec); | |
224 | ||
9f58c4b4 GB |
225 | pspec = g_param_spec_string ("api-key", |
226 | "API key", | |
227 | "The API key to access Bing", | |
228 | "<no-set>" /* default value */, | |
229 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); | |
230 | g_object_class_install_property (object_class, PROP_API_KEY, pspec); | |
231 | ||
232 | g_type_class_add_private (klass, sizeof (BingMapSourcePrivate)); | |
233 | ||
234 | object_class->finalize = bing_map_source_finalize; | |
235 | ||
236 | pixbuf = gdk_pixbuf_from_pixdata ( &bing_maps_pixbuf, TRUE, NULL ); | |
237 | } | |
238 | ||
239 | static gchar * | |
240 | compute_quad_tree(int zoom, int tilex, int tiley) | |
241 | { | |
242 | /* Picked from http://trac.openstreetmap.org/browser/applications/editors/josm/plugins/slippymap/src/org/openstreetmap/josm/plugins/slippymap/SlippyMapPreferences.java?rev=24486 */ | |
243 | gchar k[20]; | |
244 | int ik = 0; | |
245 | int i = 0; | |
246 | for(i = zoom; i > 0; i--) | |
247 | { | |
248 | char digit = 48; | |
249 | int mask = 1 << (i - 1); | |
250 | if ((tilex & mask) != 0) { | |
251 | digit += 1; | |
252 | } | |
253 | if ((tiley & mask) != 0) { | |
254 | digit += 2; | |
255 | } | |
256 | k[ik++] = digit; | |
257 | } | |
258 | k[ik] = '\0'; | |
259 | return g_strdup(k); | |
260 | } | |
261 | ||
262 | static gchar * | |
23992e34 | 263 | bget_uri( VikMapSourceDefault *self, MapCoord *src ) |
9f58c4b4 GB |
264 | { |
265 | g_return_val_if_fail (BING_IS_MAP_SOURCE(self), NULL); | |
266 | ||
b39149e0 | 267 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE(self); |
9f58c4b4 | 268 | gchar *quadtree = compute_quad_tree (17 - src->scale, src->x, src->y); |
b39149e0 | 269 | gchar *uri = g_strdup_printf ( priv->url, quadtree ); |
9f58c4b4 GB |
270 | g_free (quadtree); |
271 | return uri; | |
272 | } | |
273 | ||
b39149e0 | 274 | static gchar * |
23992e34 | 275 | bget_hostname( VikMapSourceDefault *self ) |
b39149e0 RN |
276 | { |
277 | g_return_val_if_fail (BING_IS_MAP_SOURCE(self), NULL); | |
278 | ||
279 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE(self); | |
280 | return g_strdup( priv->hostname ); | |
281 | } | |
282 | ||
9f58c4b4 GB |
283 | static const GdkPixbuf * |
284 | _get_logo( VikMapSource *self ) | |
285 | { | |
286 | return pixbuf; | |
287 | } | |
288 | ||
289 | static void | |
2f806387 | 290 | _get_copyright(VikMapSource * self, LatLonBBox bbox, gdouble zoom, void (*fct)(VikViewport*,const gchar*), void *data) |
9f58c4b4 GB |
291 | { |
292 | g_return_if_fail (BING_IS_MAP_SOURCE(self)); | |
293 | g_debug("%s: looking for %g %g %g %g at %g", __FUNCTION__, bbox.south, bbox.north, bbox.east, bbox.west, zoom); | |
294 | ||
295 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE(self); | |
296 | ||
e1dde2a6 | 297 | int level = map_utils_mpp_to_scale (zoom); |
9f58c4b4 GB |
298 | |
299 | /* Loop over all known attributions */ | |
300 | GList *attribution = priv->attributions; | |
b39149e0 | 301 | if (attribution == NULL && g_strcmp0 ("<no-set>", priv->api_key)) { |
a1ed03fb RN |
302 | if ( ! priv->loading_attributions ) |
303 | _async_load_attributions (BING_MAP_SOURCE (self)); | |
304 | else | |
305 | // Wait until attributions loaded before processing them | |
306 | return; | |
9f58c4b4 GB |
307 | } |
308 | while (attribution != NULL) { | |
309 | struct _Attribution *current = (struct _Attribution*)attribution->data; | |
310 | /* g_debug("%s %g %g %g %g %d %d", __FUNCTION__, current->bounds.south, current->bounds.north, current->bounds.east, current->bounds.west, current->minZoom, current->maxZoom); */ | |
311 | if (BBOX_INTERSECT(bbox, current->bounds) && | |
312 | (17 - level) > current->minZoom && | |
313 | (17 - level) < current->maxZoom) { | |
314 | (*fct)(data, current->attribution); | |
315 | g_debug("%s: found match %s", __FUNCTION__, current->attribution); | |
316 | } | |
317 | attribution = attribution->next; | |
318 | } | |
319 | } | |
320 | ||
321 | /* Called for open tags <foo bar="baz"> */ | |
322 | static void | |
23992e34 | 323 | bstart_element (GMarkupParseContext *context, |
9f58c4b4 GB |
324 | const gchar *element_name, |
325 | const gchar **attribute_names, | |
326 | const gchar **attribute_values, | |
327 | gpointer user_data, | |
328 | GError **error) | |
329 | { | |
330 | BingMapSource *self = BING_MAP_SOURCE (user_data); | |
331 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); | |
332 | const gchar *element = g_markup_parse_context_get_element (context); | |
333 | if (strcmp (element, "CoverageArea") == 0) { | |
334 | /* New Attribution */ | |
75ea29f0 | 335 | struct _Attribution *attribution = g_malloc0 (sizeof(struct _Attribution)); |
9f58c4b4 GB |
336 | priv->attributions = g_list_append (priv->attributions, attribution); |
337 | attribution->attribution = g_strdup (priv->attribution); | |
338 | } | |
339 | } | |
340 | ||
341 | /* Called for character data */ | |
342 | /* text is not nul-terminated */ | |
343 | static void | |
23992e34 | 344 | btext (GMarkupParseContext *context, |
9f58c4b4 GB |
345 | const gchar *text, |
346 | gsize text_len, | |
347 | gpointer user_data, | |
348 | GError **error) | |
349 | { | |
350 | BingMapSource *self = BING_MAP_SOURCE (user_data); | |
351 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); | |
352 | ||
353 | struct _Attribution *attribution = priv->attributions == NULL ? NULL : g_list_last (priv->attributions)->data; | |
354 | const gchar *element = g_markup_parse_context_get_element (context); | |
355 | gchar *textl = g_strndup (text, text_len); | |
356 | const GSList *stack = g_markup_parse_context_get_element_stack (context); | |
357 | int len = g_slist_length ((GSList *)stack); | |
358 | ||
359 | const gchar *parent = len > 1 ? g_slist_nth_data ((GSList *)stack, 1) : NULL; | |
9f58c4b4 GB |
360 | if (strcmp (element, "Attribution") == 0) { |
361 | g_free (priv->attribution); | |
362 | priv->attribution = g_strdup (textl); | |
327cc190 RN |
363 | } |
364 | else { | |
365 | if ( attribution ) { | |
366 | if (parent != NULL && strcmp (parent, "CoverageArea") == 0) { | |
367 | if (strcmp (element, "ZoomMin") == 0) { | |
368 | attribution->minZoom = atoi (textl); | |
369 | } else if (strcmp (element, "ZoomMax") == 0) { | |
370 | attribution->maxZoom = atoi (textl); | |
371 | } | |
372 | } else if (parent != NULL && strcmp (parent, "BoundingBox") == 0) { | |
373 | if (strcmp (element, "SouthLatitude") == 0) { | |
374 | attribution->bounds.south = g_ascii_strtod (textl, NULL); | |
375 | } else if (strcmp (element, "WestLongitude") == 0) { | |
376 | attribution->bounds.west = g_ascii_strtod (textl, NULL); | |
377 | } else if (strcmp (element, "NorthLatitude") == 0) { | |
378 | attribution->bounds.north = g_ascii_strtod (textl, NULL); | |
379 | } else if (strcmp (element, "EastLongitude") == 0) { | |
380 | attribution->bounds.east = g_ascii_strtod (textl, NULL); | |
381 | } | |
382 | } | |
9f58c4b4 GB |
383 | } |
384 | } | |
9f58c4b4 GB |
385 | g_free(textl); |
386 | } | |
387 | ||
388 | static gboolean | |
389 | _parse_file_for_attributions(BingMapSource *self, gchar *filename) | |
390 | { | |
391 | GMarkupParser xml_parser; | |
392 | GMarkupParseContext *xml_context = NULL; | |
393 | GError *error = NULL; | |
394 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); | |
395 | g_return_val_if_fail(priv != NULL, FALSE); | |
396 | ||
397 | FILE *file = g_fopen (filename, "r"); | |
398 | if (file == NULL) | |
399 | /* TODO emit warning */ | |
400 | return FALSE; | |
401 | ||
402 | /* setup context parse (ie callbacks) */ | |
23992e34 | 403 | xml_parser.start_element = &bstart_element; |
9f58c4b4 | 404 | xml_parser.end_element = NULL; |
23992e34 | 405 | xml_parser.text = &btext; |
9f58c4b4 GB |
406 | xml_parser.passthrough = NULL; |
407 | xml_parser.error = NULL; | |
408 | ||
409 | xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL); | |
410 | ||
411 | gchar buff[BUFSIZ]; | |
412 | size_t nb; | |
413 | size_t offset = -1; | |
414 | while (xml_context && | |
415 | (nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0) | |
416 | { | |
417 | if (offset == -1) | |
418 | /* first run */ | |
419 | /* Avoid possible BOM at begining of the file */ | |
420 | offset = buff[0] == '<' ? 0 : 3; | |
421 | else | |
422 | /* reset offset */ | |
423 | offset = 0; | |
424 | if (!g_markup_parse_context_parse(xml_context, buff+offset, nb-offset, &error)) | |
425 | { | |
426 | fprintf(stderr, "%s: parsing error: %s.\n", | |
427 | __FUNCTION__, error->message); | |
428 | g_markup_parse_context_free(xml_context); | |
429 | xml_context = NULL; | |
430 | } | |
431 | g_clear_error (&error); | |
432 | } | |
433 | /* cleanup */ | |
434 | if (xml_context && | |
435 | !g_markup_parse_context_end_parse(xml_context, &error)) | |
436 | fprintf(stderr, "%s: errors occurred while reading file: %s.\n", | |
437 | __FUNCTION__, error->message); | |
438 | g_clear_error (&error); | |
439 | ||
440 | if (xml_context) | |
441 | g_markup_parse_context_free(xml_context); | |
442 | xml_context = NULL; | |
443 | fclose (file); | |
444 | ||
75ea29f0 RN |
445 | if (vik_debug) { |
446 | GList *attribution = priv->attributions; | |
447 | while (attribution != NULL) { | |
448 | struct _Attribution *aa = (struct _Attribution*)attribution->data; | |
449 | g_debug ("Bing Attribution: %s from %d to %d %g %g %g %g", aa->attribution, aa->minZoom, aa->maxZoom, aa->bounds.south, aa->bounds.north, aa->bounds.east, aa->bounds.west); | |
450 | attribution = attribution->next; | |
451 | } | |
452 | } | |
453 | ||
9f58c4b4 GB |
454 | return TRUE; |
455 | } | |
456 | ||
457 | static int | |
458 | _load_attributions ( BingMapSource *self ) | |
459 | { | |
9f58c4b4 GB |
460 | int ret = 0; /* OK */ |
461 | ||
462 | BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self); | |
75ea29f0 | 463 | priv->loading_attributions = TRUE; |
e09b94fe | 464 | gchar *uri = g_strdup_printf(URL_ATTR_FMT, priv->api_key); |
9f58c4b4 | 465 | |
e09b94fe | 466 | gchar *tmpname = a_download_uri_to_tmp_file ( uri, vik_map_source_default_get_download_options(VIK_MAP_SOURCE_DEFAULT(self)) ); |
0f7bd013 RN |
467 | if ( !tmpname ) { |
468 | ret = -1; | |
469 | goto done; | |
470 | } | |
9f58c4b4 GB |
471 | |
472 | g_debug("%s: %s", __FUNCTION__, tmpname); | |
473 | if (!_parse_file_for_attributions(self, tmpname)) { | |
474 | ret = -1; | |
9f58c4b4 GB |
475 | } |
476 | ||
0f7bd013 RN |
477 | (void)g_remove(tmpname); |
478 | g_free(tmpname); | |
9f58c4b4 | 479 | done: |
a1ed03fb | 480 | priv->loading_attributions = FALSE; |
9f58c4b4 | 481 | g_free(uri); |
9f58c4b4 GB |
482 | return ret; |
483 | } | |
484 | ||
d3b7baa7 | 485 | static gboolean |
9f58c4b4 GB |
486 | _emit_update ( gpointer data ) |
487 | { | |
d3b7baa7 RN |
488 | //if ( data ) |
489 | // vik_layers_panel_emit_update ( VIK_LAYERS_PANEL (data) ); | |
490 | return FALSE; | |
9f58c4b4 GB |
491 | } |
492 | ||
493 | static int | |
494 | _load_attributions_thread ( BingMapSource *self, gpointer threaddata ) | |
495 | { | |
496 | _load_attributions ( self ); | |
497 | int result = a_background_thread_progress ( threaddata, 1.0 ); | |
498 | if ( result != 0 ) | |
499 | return -1; /* Abort thread */ | |
500 | ||
501 | /* Emit update */ | |
d3b7baa7 RN |
502 | // As we are on a download thread, must the update GUI from the main loop |
503 | // TODO: have reference to the window/viewport/layerspanel to update... | |
504 | (void)gdk_threads_add_idle ( _emit_update, NULL ); | |
9f58c4b4 GB |
505 | |
506 | return 0; | |
507 | } | |
508 | ||
509 | static void | |
510 | _async_load_attributions ( BingMapSource *self ) | |
511 | { | |
c75da936 RN |
512 | a_background_thread ( BACKGROUND_POOL_REMOTE, |
513 | /*VIK_GTK_WINDOW_FROM_WIDGET(vp)*/NULL, | |
514 | _("Bing attribution Loading"), | |
515 | (vik_thr_func) _load_attributions_thread, | |
516 | self, | |
517 | NULL, | |
518 | NULL, | |
519 | 1 ); | |
9f58c4b4 GB |
520 | |
521 | } | |
522 | ||
523 | /** | |
524 | * bing_map_source_new_with_id: | |
525 | * @id: internal identifier. | |
526 | * @label: the label to display in map provider selector. | |
527 | * @key: the API key to access Bing's services. | |
528 | * | |
529 | * Constructor for Bing map source. | |
530 | * | |
531 | * Returns: a newly allocated BingMapSource GObject. | |
532 | */ | |
533 | BingMapSource * | |
d7e495b2 | 534 | bing_map_source_new_with_id (guint16 id, const gchar *label, const gchar *key) |
9f58c4b4 GB |
535 | { |
536 | /* initialize settings here */ | |
537 | return g_object_new(BING_TYPE_MAP_SOURCE, | |
538 | "id", id, | |
539 | "label", label, | |
2eb18edc | 540 | "name", "Bing-Aerial", |
9f58c4b4 | 541 | "hostname", "ecn.t2.tiles.virtualearth.net", |
b39149e0 | 542 | "url", "/tiles/a%s.jpeg?g=587", |
9f58c4b4 GB |
543 | "api-key", key, |
544 | "check-file-server-time", TRUE, | |
e633ddef RN |
545 | "zoom-min", 0, |
546 | "zoom-max", 19, // NB: Might be regionally different rather than the same across the world | |
9f58c4b4 GB |
547 | "copyright", "© 2011 Microsoft Corporation and/or its suppliers", |
548 | "license", "Microsoft Bing Maps Specific", | |
549 | "license-url", "http://www.microsoft.com/maps/assets/docs/terms.aspx", | |
550 | NULL); | |
551 | } |