]>
Commit | Line | Data |
---|---|---|
7d02a0b0 GB |
1 | /* |
2 | * Viking - GPS data editor | |
a482007a | 3 | * Copyright (C) 2007, Guilhem Bonnefille <guilhem.bonnefille@gmail.com> |
7d02a0b0 | 4 | * Based on: |
a482007a | 5 | * Copyright (C) 2003-2007, Leandro A. F. Pereira <leandro@linuxmag.com.br> |
7d02a0b0 GB |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation, version 2. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | */ | |
4c77d5e0 GB |
20 | #ifdef HAVE_CONFIG_H |
21 | #include "config.h" | |
22 | #endif | |
23 | ||
91c46f90 | 24 | #include <glib/gstdio.h> |
4c77d5e0 | 25 | #include <glib/gi18n.h> |
c612e922 | 26 | #include <glib/gprintf.h> |
7d02a0b0 | 27 | |
8e562a70 | 28 | #include "util.h" |
7d02a0b0 | 29 | #include "dialog.h" |
91c46f90 RN |
30 | #include "globals.h" |
31 | #include "download.h" | |
0d66c56c RN |
32 | #include "preferences.h" |
33 | #include "vikmapslayer.h" | |
91fc9c76 | 34 | #include "settings.h" |
7d02a0b0 | 35 | |
7d384035 RN |
36 | /* |
37 | #ifdef WINDOWS | |
38 | #include <windows.h> | |
39 | #endif | |
40 | ||
02d0c367 | 41 | #ifndef WINDOWS |
3530c91e GB |
42 | static gboolean spawn_command_line_async(const gchar * cmd, |
43 | const gchar * arg) | |
44 | { | |
45 | gchar *cmdline = NULL; | |
46 | gboolean status; | |
47 | ||
48 | cmdline = g_strdup_printf("%s '%s'", cmd, arg); | |
49 | g_debug("Running: %s", cmdline); | |
50 | ||
51 | status = g_spawn_command_line_async(cmdline, NULL); | |
52 | ||
53 | g_free(cmdline); | |
54 | ||
a0f4c917 | 55 | return status; |
3530c91e | 56 | } |
02d0c367 | 57 | #endif |
7d384035 | 58 | */ |
3530c91e | 59 | |
7d02a0b0 GB |
60 | void open_url(GtkWindow *parent, const gchar * url) |
61 | { | |
7d384035 RN |
62 | GError *error = NULL; |
63 | gtk_show_uri ( gtk_widget_get_screen (GTK_WIDGET(parent)), url, GDK_CURRENT_TIME, &error ); | |
64 | if ( error ) { | |
65 | a_dialog_error_msg_extra ( parent, _("Could not launch web browser. %s"), error->message ); | |
66 | g_error_free ( error ); | |
7d02a0b0 | 67 | } |
7d02a0b0 | 68 | } |
3530c91e GB |
69 | |
70 | void new_email(GtkWindow *parent, const gchar * address) | |
71 | { | |
72 | gchar *uri = g_strdup_printf("mailto:%s", address); | |
7d384035 RN |
73 | GError *error = NULL; |
74 | gtk_show_uri ( gtk_widget_get_screen (GTK_WIDGET(parent)), uri, GDK_CURRENT_TIME, &error ); | |
75 | if ( error ) { | |
76 | a_dialog_error_msg_extra ( parent, _("Could not create new email. %s"), error->message ); | |
77 | g_error_free ( error ); | |
78 | } | |
79 | /* | |
3530c91e GB |
80 | #ifdef WINDOWS |
81 | ShellExecute(NULL, NULL, (char *) uri, NULL, ".\\", 0); | |
7d384035 | 82 | #else |
3530c91e GB |
83 | if (!spawn_command_line_async("xdg-email", uri)) |
84 | a_dialog_error_msg ( parent, _("Could not create new email.") ); | |
7d384035 RN |
85 | #endif |
86 | */ | |
3530c91e GB |
87 | g_free(uri); |
88 | uri = NULL; | |
89 | } | |
ba4a5e11 GB |
90 | gchar *uri_escape(gchar *str) |
91 | { | |
92 | gchar *esc_str = g_malloc(3*strlen(str)); | |
93 | gchar *dst = esc_str; | |
94 | gchar *src; | |
95 | ||
96 | for (src = str; *src; src++) { | |
97 | if (*src == ' ') | |
98 | *dst++ = '+'; | |
99 | else if (g_ascii_isalnum(*src)) | |
100 | *dst++ = *src; | |
101 | else { | |
7705a76f | 102 | g_sprintf(dst, "%%%02hhX", *src); |
ba4a5e11 GB |
103 | dst += 3; |
104 | } | |
105 | } | |
106 | *dst = '\0'; | |
107 | ||
108 | return(esc_str); | |
109 | } | |
110 | ||
70434be3 GB |
111 | |
112 | GList * str_array_to_glist(gchar* data[]) | |
113 | { | |
114 | GList *gl = NULL; | |
115 | gpointer * p; | |
116 | for (p = (gpointer)data; *p; p++) | |
117 | gl = g_list_prepend(gl, *p); | |
118 | return g_list_reverse(gl); | |
119 | } | |
9106934d | 120 | |
0da89d90 RN |
121 | /** |
122 | * split_string_from_file_on_equals: | |
123 | * | |
124 | * @buf: the input string | |
125 | * @key: newly allocated string that is before the '=' | |
126 | * @val: newly allocated string after the '=' | |
127 | * | |
128 | * Designed for file line processing, so it ignores strings beginning with special | |
129 | * characters, such as '#'; returns false in such situations. | |
130 | * Also returns false if no equals character is found | |
131 | * | |
132 | * e.g. if buf = "GPS.parameter=42" | |
133 | * key = "GPS.parameter" | |
134 | * val = "42" | |
135 | */ | |
136 | gboolean split_string_from_file_on_equals ( const gchar *buf, gchar **key, gchar **val ) | |
9106934d | 137 | { |
9106934d RN |
138 | // comments, special characters in viking file format |
139 | if ( buf == NULL || buf[0] == '\0' || buf[0] == '~' || buf[0] == '=' || buf[0] == '#' ) | |
140 | return FALSE; | |
0da89d90 RN |
141 | |
142 | if ( ! strchr ( buf, '=' ) ) | |
9106934d | 143 | return FALSE; |
0da89d90 RN |
144 | |
145 | gchar **strv = g_strsplit ( buf, "=", 2 ); | |
146 | ||
147 | gint gi = 0; | |
148 | gchar *str = strv[gi]; | |
149 | while ( str ) { | |
150 | if ( gi == 0 ) | |
151 | *key = g_strdup ( str ); | |
152 | else | |
153 | *val = g_strdup ( str ); | |
154 | gi++; | |
155 | str = strv[gi]; | |
156 | } | |
157 | ||
158 | g_strfreev ( strv ); | |
159 | ||
160 | // Remove newline from val and also any other whitespace | |
161 | *key = g_strstrip ( *key ); | |
162 | *val = g_strstrip ( *val ); | |
163 | ||
9106934d RN |
164 | return TRUE; |
165 | } | |
f05ecca4 RN |
166 | |
167 | /* 1 << (x) is like a 2**(x) */ | |
168 | #define GZ(x) (1<<(x)) | |
169 | ||
4b4b5bc4 | 170 | static const gdouble scale_mpps[] = { 0.125, 0.25, 0.5, GZ(0), GZ(1), GZ(2), GZ(3), GZ(4), GZ(5), GZ(6), GZ(7), GZ(8), GZ(9), |
f05ecca4 RN |
171 | GZ(10), GZ(11), GZ(12), GZ(13), GZ(14), GZ(15), GZ(16), GZ(17) }; |
172 | ||
173 | static const gint num_scales = (sizeof(scale_mpps) / sizeof(scale_mpps[0])); | |
174 | ||
175 | #define ERROR_MARGIN 0.01 | |
4b4b5bc4 RN |
176 | /** |
177 | * mpp_to_zoom: | |
178 | * | |
179 | * Returns: a zoom level. see : http://wiki.openstreetmap.org/wiki/Zoom_levels | |
180 | */ | |
f05ecca4 RN |
181 | guint8 mpp_to_zoom ( gdouble mpp ) |
182 | { | |
183 | gint i; | |
184 | for ( i = 0; i < num_scales; i++ ) { | |
185 | if ( ABS(scale_mpps[i] - mpp) < ERROR_MARGIN ) { | |
186 | g_debug ( "mpp_to_zoom: %f -> %d", mpp, i ); | |
4b4b5bc4 | 187 | return 20-i; |
f05ecca4 RN |
188 | } |
189 | } | |
4b4b5bc4 | 190 | return 17; // a safe zoomed in default |
f05ecca4 | 191 | } |
91c46f90 RN |
192 | |
193 | typedef struct { | |
194 | GtkWindow *window; // Layer needed for redrawing | |
195 | gchar *version; // Image list | |
196 | } new_version_thread_data; | |
197 | ||
198 | static gboolean new_version_available_message ( new_version_thread_data *nvtd ) | |
199 | { | |
200 | // Only a simple goto website option is offered | |
201 | // Trying to do an installation update is platform specific | |
202 | if ( a_dialog_yes_or_no ( nvtd->window, | |
203 | _("There is a newer version of Viking available: %s\n\nDo you wish to go to Viking's website now?"), nvtd->version ) ) | |
204 | // NB 'VIKING_URL' redirects to the Wiki, here we want to go the main site. | |
205 | open_url ( nvtd->window, "http://sourceforge.net/projects/viking/" ); | |
91fc9c76 | 206 | |
91c46f90 RN |
207 | g_free ( nvtd->version ); |
208 | g_free ( nvtd ); | |
209 | return FALSE; | |
210 | } | |
211 | ||
91fc9c76 RN |
212 | #define VIK_SETTINGS_VERSION_CHECKED_DATE "version_checked_date" |
213 | ||
91c46f90 RN |
214 | static void latest_version_thread ( GtkWindow *window ) |
215 | { | |
91fc9c76 | 216 | // Need to allow a few redirects, as SF file is often served from different server |
a3697549 | 217 | DownloadMapOptions options = { FALSE, FALSE, NULL, 5, NULL, NULL, NULL }; |
91c46f90 RN |
218 | gchar *filename = a_download_uri_to_tmp_file ( "http://sourceforge.net/projects/viking/files/VERSION", &options ); |
219 | //gchar *filename = g_strdup ( "VERSION" ); | |
220 | if ( !filename ) { | |
221 | return; | |
222 | } | |
223 | ||
224 | GMappedFile *mf = g_mapped_file_new ( filename, FALSE, NULL ); | |
225 | if ( !mf ) | |
226 | return; | |
227 | ||
228 | gchar *text = g_mapped_file_get_contents ( mf ); | |
229 | ||
230 | gint latest_version = viking_version_to_number ( text ); | |
231 | gint my_version = viking_version_to_number ( VIKING_VERSION ); | |
232 | ||
233 | g_debug ( "The lastest version is: %s", text ); | |
234 | ||
235 | if ( my_version < latest_version ) { | |
236 | new_version_thread_data *nvtd = g_malloc ( sizeof(new_version_thread_data) ); | |
237 | nvtd->window = window; | |
238 | nvtd->version = g_strdup ( text ); | |
239 | gdk_threads_add_idle ( (GSourceFunc) new_version_available_message, nvtd ); | |
240 | } | |
241 | else | |
242 | g_debug ( "Running the lastest version: %s", VIKING_VERSION ); | |
243 | ||
244 | g_mapped_file_unref ( mf ); | |
245 | if ( filename ) { | |
246 | g_remove ( filename ); | |
247 | g_free ( filename ); | |
248 | } | |
91fc9c76 RN |
249 | |
250 | // Update last checked time | |
251 | GTimeVal time; | |
252 | g_get_current_time ( &time ); | |
253 | a_settings_set_string ( VIK_SETTINGS_VERSION_CHECKED_DATE, g_time_val_to_iso8601(&time) ); | |
91c46f90 RN |
254 | } |
255 | ||
91fc9c76 RN |
256 | #define VIK_SETTINGS_VERSION_CHECK_PERIOD "version_check_period_days" |
257 | ||
0d66c56c | 258 | /** |
91c46f90 RN |
259 | * check_latest_version: |
260 | * @window: Somewhere where we may need use the display to inform the user about the version status | |
261 | * | |
262 | * Periodically checks the released latest VERSION file on the website to compare with the running version | |
263 | * | |
91c46f90 RN |
264 | */ |
265 | void check_latest_version ( GtkWindow *window ) | |
266 | { | |
91fc9c76 RN |
267 | if ( ! a_vik_get_check_version () ) |
268 | return; | |
269 | ||
270 | gboolean do_check = FALSE; | |
271 | ||
272 | gint check_period; | |
273 | if ( ! a_settings_get_integer ( VIK_SETTINGS_VERSION_CHECK_PERIOD, &check_period ) ) { | |
274 | check_period = 14; | |
275 | } | |
276 | ||
277 | // Get last checked date... | |
278 | GDate *gdate_last = g_date_new(); | |
279 | GDate *gdate_now = g_date_new(); | |
280 | GTimeVal time_last; | |
281 | gchar *last_checked_date = NULL; | |
282 | ||
283 | // When no previous date available - set to do the version check | |
284 | if ( a_settings_get_string ( VIK_SETTINGS_VERSION_CHECKED_DATE, &last_checked_date) ) { | |
285 | if ( g_time_val_from_iso8601 ( last_checked_date, &time_last ) ) { | |
286 | g_date_set_time_val ( gdate_last, &time_last ); | |
287 | } | |
288 | else | |
289 | do_check = TRUE; | |
290 | } | |
291 | else | |
292 | do_check = TRUE; | |
293 | ||
294 | GTimeVal time_now; | |
295 | g_get_current_time ( &time_now ); | |
296 | g_date_set_time_val ( gdate_now, &time_now ); | |
297 | ||
298 | if ( ! do_check ) { | |
299 | // Dates available so do the comparison | |
300 | g_date_add_days ( gdate_last, check_period ); | |
301 | if ( g_date_compare ( gdate_last, gdate_now ) < 0 ) | |
302 | do_check = TRUE; | |
303 | } | |
304 | ||
305 | g_date_free ( gdate_last ); | |
306 | g_date_free ( gdate_now ); | |
307 | ||
308 | if ( do_check ) { | |
91c46f90 | 309 | #if GLIB_CHECK_VERSION (2, 32, 0) |
91fc9c76 | 310 | g_thread_try_new ( "latest_version_thread", (GThreadFunc)latest_version_thread, window, NULL ); |
91c46f90 | 311 | #else |
91fc9c76 | 312 | g_thread_create ( (GThreadFunc)latest_version_thread, window, FALSE, NULL ); |
91c46f90 | 313 | #endif |
91fc9c76 | 314 | } |
91c46f90 | 315 | } |
0d66c56c RN |
316 | |
317 | /** | |
318 | * set_auto_features_on_first_run: | |
319 | * | |
320 | * Ask the user's opinion to set some of Viking's default behaviour | |
321 | */ | |
322 | void set_auto_features_on_first_run ( void ) | |
323 | { | |
324 | gboolean auto_features = FALSE; | |
325 | if ( a_vik_very_first_run () ) { | |
326 | ||
327 | GtkWidget *win = gtk_window_new ( GTK_WINDOW_TOPLEVEL ); | |
328 | ||
329 | if ( a_dialog_yes_or_no ( GTK_WINDOW(win), | |
330 | _("This appears to be Viking's very first run.\n\nDo you wish to enable automatic internet features?\n\nIndividual settings can be controlled in the Preferences."), NULL ) ) | |
331 | auto_features = TRUE; | |
332 | } | |
333 | ||
334 | if ( auto_features ) { | |
335 | // Set Maps to autodownload | |
336 | // Ensure the default is true | |
337 | maps_layer_set_autodownload_default ( TRUE ); | |
338 | ||
339 | // Simplistic repeat of preference settings | |
340 | // Only the name & type are important for setting a preference via this 'external' way | |
341 | ||
342 | // Enable auto add map + | |
343 | // Enable IP lookup | |
a87f8fa1 RN |
344 | VikLayerParam pref_add_map[] = { { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_STARTUP_NAMESPACE "add_default_map_layer", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, NULL, VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, NULL, NULL, NULL, }, }; |
345 | VikLayerParam pref_startup_method[] = { { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_STARTUP_NAMESPACE "startup_method", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, NULL, VIK_LAYER_WIDGET_COMBOBOX, NULL, NULL, NULL, NULL, NULL, NULL}, }; | |
0d66c56c RN |
346 | |
347 | VikLayerParamData vlp_data; | |
348 | vlp_data.b = TRUE; | |
349 | a_preferences_run_setparam ( vlp_data, pref_add_map ); | |
350 | ||
351 | vlp_data.u = VIK_STARTUP_METHOD_AUTO_LOCATION; | |
352 | a_preferences_run_setparam ( vlp_data, pref_startup_method ); | |
353 | ||
91fc9c76 RN |
354 | // Only on Windows make checking for the latest version on by default |
355 | // For other systems it's expected a Package manager or similar controls the installation, so leave it off | |
356 | #ifdef WINDOWS | |
357 | VikLayerParam pref_startup_version_check[] = { { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_STARTUP_NAMESPACE "check_version", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, NULL, VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, NULL, }, }; | |
358 | vlp_data.b = TRUE; | |
359 | a_preferences_run_setparam ( vlp_data, pref_startup_version_check ); | |
360 | #endif | |
361 | ||
0d66c56c RN |
362 | // Ensure settings are saved for next time |
363 | a_preferences_save_to_file (); | |
364 | } | |
365 | } |