Contents of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 164 - (hide annotations)
Thu Nov 5 20:37:16 2009 UTC (14 years, 6 months ago) by harbaum
File MIME type: text/plain
File size: 70301 byte(s)
Fremantleized message boxes
1 harbaum 1 /*
2     * This file is part of GPXView.
3     *
4     * GPXView is free software: you can redistribute it and/or modify
5     * it under the terms of the GNU General Public License as published by
6     * the Free Software Foundation, either version 3 of the License, or
7     * (at your option) any later version.
8     *
9     * GPXView is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with GPXView. If not, see <http://www.gnu.org/licenses/>.
16     */
17    
18     #include <stdio.h>
19     #include <string.h>
20     #include <math.h>
21    
22 harbaum 157 #include <curl/curl.h>
23    
24 harbaum 1 #include <time.h>
25     #include <sys/time.h>
26    
27     #include "gpxview.h"
28     #include "custom_size_renderer.h"
29     #include "custom_rating_renderer.h"
30     #include "custom_type_renderer.h"
31    
32     #ifdef USE_MAEMO
33     #include <hildon/hildon-banner.h>
34 harbaum 164 #if MAEMO_VERSION_MAJOR >= 5
35     #include <hildon/hildon-note.h>
36 harbaum 1 #endif
37 harbaum 164 #endif
38 harbaum 1
39     #include <locale.h>
40    
41     extern char *strcasestr (__const char *__haystack, __const char *__needle);
42    
43 harbaum 128 #if defined(USE_BREAD_CRUMB_TRAIL) || defined(BCT)
44 harbaum 1 static void crumb_add(appdata_t *appdata, char *name, int level,
45     gpointer user_data);
46    
47     enum {
48     CRUMB_GPXLIST = 0,
49     CRUMB_CACHELIST,
50     CRUMB_SEARCH_GLOBAL,
51     CRUMB_SEARCH_GPX,
52     CRUMB_CACHE,
53     };
54     #endif
55    
56     /* size of first buffer malloc; start small to exercise grow routines */
57     #define FIRSTSIZE 1
58    
59     void errorf(const char *fmt, ...) {
60     va_list args;
61     char *buf = NULL;
62     size_t bufsize;
63     char *newbuf;
64     size_t nextsize = 0;
65     int outsize;
66    
67     bufsize = 0;
68     for (;;) {
69     if (bufsize == 0) {
70     if ((buf = (char *)malloc(FIRSTSIZE)) == NULL)
71     return;
72    
73     bufsize = 1;
74     } else if ((newbuf = (char *)realloc(buf, nextsize)) != NULL) {
75     buf = newbuf;
76     bufsize = nextsize;
77     } else {
78     free(buf);
79     return;
80     }
81    
82     va_start(args, fmt);
83     outsize = vsnprintf(buf, bufsize, fmt, args);
84     va_end(args);
85    
86     if (outsize == -1) {
87     nextsize = bufsize * 2;
88     } else if (outsize == bufsize) {
89     nextsize = bufsize * 2;
90     } else if (outsize > bufsize) {
91     nextsize = outsize + 2; // Linux!
92     } else if (outsize == bufsize - 1) {
93     nextsize = bufsize * 2;
94     } else {
95     /* Output was not truncated */
96     break;
97     }
98     }
99    
100 harbaum 164 #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
101 harbaum 1 GtkWidget *dialog = gtk_message_dialog_new(
102     GTK_WINDOW(NULL),
103     GTK_DIALOG_DESTROY_WITH_PARENT,
104 harbaum 123 GTK_MESSAGE_ERROR,
105     GTK_BUTTONS_CLOSE, buf);
106 harbaum 1
107     gtk_window_set_title(GTK_WINDOW(dialog), _("ERROR"));
108 harbaum 164 #else
109     GtkWidget *dialog =
110     hildon_note_new_information(GTK_WINDOW(NULL), buf);
111     #endif
112 harbaum 1
113     gtk_dialog_run(GTK_DIALOG(dialog));
114     gtk_widget_destroy(dialog);
115    
116     free(buf);
117     }
118    
119     gpx_t *choose_file(appdata_t *appdata, gboolean whole_dir) {
120     GtkWidget *dialog;
121     gpx_t *gpx = NULL;
122    
123     #ifdef USE_MAEMO
124     dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(appdata->window),
125     whole_dir?GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER :
126     GTK_FILE_CHOOSER_ACTION_OPEN);
127    
128     #ifdef HILDON_HELP
129     hildon_help_dialog_help_enable(GTK_DIALOG(dialog),
130     HELP_ID_IMPORT, appdata->osso_context);
131     #endif
132     #else
133 harbaum 11 dialog = gtk_file_chooser_dialog_new (whole_dir?_("Import directory"):
134     _("Import file"),
135 harbaum 1 GTK_WINDOW(appdata->window),
136     whole_dir?GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER :
137     GTK_FILE_CHOOSER_ACTION_OPEN,
138     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
139     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
140     NULL);
141     #endif
142    
143     /* use path if one is present */
144     if(appdata->path)
145     gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
146     appdata->path);
147    
148     gtk_widget_show_all (GTK_WIDGET(dialog));
149     if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) {
150     char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
151 harbaum 107
152     if(filename) {
153     gpx_dialog_t *dialog = gpx_busy_dialog_new(GTK_WIDGET(appdata->window));
154 harbaum 1
155 harbaum 107 if(!whole_dir)
156     gpx = gpx_parse(dialog, filename);
157     else {
158     /* cur trailing '/' if present */
159     if(strlastchr(filename) == '/')
160     filename[strlen(filename)] = 0;
161    
162     gpx = gpx_parse_dir(dialog, filename);
163     }
164    
165     gpx_busy_dialog_destroy(dialog);
166    
167     /* save path if gpx was successfully loaded */
168     if(gpx) {
169     char *r = strrchr(filename, '/');
170    
171     /* there is a delimiter, use everything left of it as path */
172     if(r && !whole_dir) {
173     *r = 0;
174     if(appdata->path) free(appdata->path);
175     appdata->path = strdup(filename);
176     /* restore path ... just in case ... */
177     *r = '/';
178     }
179    
180     if(whole_dir)
181     appdata->path = strdup(filename);
182     } else
183     errorf(_("Load error"));
184 harbaum 1
185 harbaum 107 g_free (filename);
186     } else {
187     #ifndef USE_MAEMO
188     errorf(_("Error accessing the file."));
189     #else
190     errorf(_("Error accessing the file. This may happen if the file "
191     "resides on a remote file system. Please copy the file onto "
192     "the device (e.g. onto the memory card) and try again."));
193     #endif
194 harbaum 1 }
195     }
196    
197     gtk_widget_destroy (dialog);
198    
199     return gpx;
200     }
201    
202     /******************** begin of cachelist ********************/
203    
204     enum {
205     CACHELIST_COL_TYPE = 0,
206     CACHELIST_COL_ID,
207     CACHELIST_COL_NAME,
208     CACHELIST_COL_SIZE,
209     CACHELIST_COL_RATING,
210     CACHELIST_COL_BEARING,
211     CACHELIST_COL_DISTANCE,
212     CACHELIST_COL_DATA,
213     CACHELIST_COL_AVAIL,
214     CACHELIST_COL_ARCHIVE,
215     CACHELIST_NUM_COLS
216     } ;
217    
218 harbaum 142 void cachelist_goto_cache(appdata_t *appdata, cache_t *cache) {
219     #if !defined(USE_BREAD_CRUMB_TRAIL) && !defined(BCT)
220     cache_dialog(appdata, cache);
221     #else
222     gtk_container_remove(GTK_CONTAINER(appdata->vbox), appdata->cur_view);
223     appdata->cur_view = cache_view(appdata, cache);
224     gtk_box_pack_start_defaults(GTK_BOX(appdata->vbox), appdata->cur_view);
225     gtk_widget_show_all(appdata->vbox);
226    
227     crumb_add(appdata, cache->name, CRUMB_CACHE, cache);
228     #endif
229     }
230    
231     static void cachelist_view_onRowActivated(GtkTreeView *treeview,
232 harbaum 1 GtkTreePath *path,
233     GtkTreeViewColumn *col,
234     gpointer userdata) {
235     appdata_t *appdata = (appdata_t*)userdata;
236     GtkTreeIter iter;
237     GtkTreeModel *model = gtk_tree_view_get_model(treeview);
238    
239 harbaum 45 #ifdef USE_MAEMO
240 harbaum 43 /* check if a cache is already selected and ignore click if yes */
241     /* (was probably a double click) */
242     if(appdata->cur_cache) return;
243 harbaum 45 #endif
244 harbaum 43
245 harbaum 1 if(gtk_tree_model_get_iter(model, &iter, path)) {
246     cache_t *cache;
247     gtk_tree_model_get(model, &iter, CACHELIST_COL_DATA, &cache, -1);
248 harbaum 142 cachelist_goto_cache(appdata, cache);
249 harbaum 1 }
250     }
251    
252     typedef struct {
253     appdata_t *appdata;
254     GtkTreePath *path;
255     gboolean done;
256     } cachelist_expose_t;
257    
258     static gboolean cachelist_expose(GtkWidget *widget, GdkEventExpose *event,
259     gpointer user_data) {
260     cachelist_expose_t *ce = (cachelist_expose_t*)user_data;
261    
262     if(event->type == GDK_EXPOSE) {
263     if(ce->path && !ce->done) {
264     gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget),
265     ce->path, NULL, TRUE, 0.5, 0.5);
266     gtk_tree_path_free(ce->path);
267     ce->done = TRUE;
268     }
269     }
270    
271     return FALSE;
272     }
273    
274     static void cachelist_destroy(GtkWidget *widget, gpointer user_data) {
275     cachelist_expose_t *ce = (cachelist_expose_t*)user_data;
276    
277     printf("cachelist timer removed\n");
278     g_assert(ce->appdata->cachelist_handler_id);
279     gtk_timeout_remove(ce->appdata->cachelist_handler_id);
280     ce->appdata->cachelist_handler_id = 0;
281    
282     free(user_data);
283     }
284    
285     #define CACHELIST_UPDATE_TIMEOUT (30000)
286    
287     static GtkWidget *cachelist_create(appdata_t *appdata, gpx_t *gpx,
288     cache_t *sel_cache);
289    
290     void cachelist_redraw(appdata_t *appdata) {
291 harbaum 11 if(!appdata->cur_view) {
292     printf("cachelist redraw: no active view\n");
293     return;
294     }
295    
296 harbaum 1 g_assert(!appdata->cur_cache);
297     int redraw = 0;
298     if(appdata->search_results)
299     redraw = 1;
300     else {
301     if(appdata->cur_gpx)
302     redraw = 2; // redraw cachelist
303     }
304    
305     if(redraw) {
306 harbaum 11 GtkWidget *container = appdata->vbox;
307    
308     #ifdef USE_STACKABLE_WINDOW
309     HildonWindowStack *stack = hildon_window_stack_get_default();
310     container = hildon_window_stack_peek(stack);
311     #endif
312    
313     gtk_container_remove(GTK_CONTAINER(container), appdata->cur_view);
314 harbaum 1 switch(redraw) {
315     case 1:
316     appdata->cur_view = cachelist_create(appdata,
317     appdata->search_results, NULL);
318     break;
319     case 2:
320     appdata->cur_view = cachelist_create(appdata,
321     appdata->cur_gpx, NULL);
322     break;
323     }
324    
325 harbaum 11 #ifdef USE_STACKABLE_WINDOW
326     if(container != appdata->vbox)
327     gtk_container_add(GTK_CONTAINER(container), appdata->cur_view);
328     else
329     #endif
330     gtk_box_pack_start_defaults(GTK_BOX(container), appdata->cur_view);
331    
332     gtk_widget_show_all(container);
333 harbaum 1 }
334     }
335    
336    
337     static gboolean cachelist_update(gpointer data) {
338    
339     printf("cachelist timer fired!\n");
340    
341     appdata_t *appdata = (appdata_t*)data;
342    
343 harbaum 11 if(appdata->cur_cache)
344     return TRUE;
345    
346 harbaum 129 #ifdef USE_MAEMO
347 harbaum 1 if(appdata->cachelist_disable_screensaver)
348     if (osso_display_blanking_pause(appdata->osso_context) != OSSO_OK)
349     fprintf(stderr, "error with display blank\n");
350 harbaum 129 #endif
351 harbaum 1
352     if(appdata->cachelist_update)
353     cachelist_redraw(appdata);
354 harbaum 122
355 harbaum 1 return TRUE;
356     }
357    
358     static void cachelist_timer_reset(appdata_t *appdata) {
359 harbaum 11 printf("cachelist timer reset\n");
360 harbaum 1 g_assert(appdata->cachelist_handler_id);
361     gtk_timeout_remove(appdata->cachelist_handler_id);
362     appdata->cachelist_handler_id =
363     gtk_timeout_add(CACHELIST_UPDATE_TIMEOUT, cachelist_update, appdata);
364     }
365    
366     static gboolean cachelist_update_reset0(GtkWidget *widget,
367     GdkEventButton *event,
368     gpointer user_data) {
369     cachelist_timer_reset((appdata_t*)user_data);
370     return FALSE;
371     }
372    
373     static void cachelist_update_reset1(GtkAdjustment *adj,
374     gpointer user_data) {
375     cachelist_timer_reset((appdata_t*)user_data);
376     }
377    
378     static GtkWidget *cachelist_create(appdata_t *appdata, gpx_t *gpx,
379     cache_t *sel_cache) {
380     GtkCellRenderer *renderer;
381     GtkWidget *view;
382     GtkListStore *store;
383     GtkTreeIter iter;
384    
385     if(!gpx->notes_loaded) {
386     notes_load_all(appdata, gpx);
387     gpx->notes_loaded = TRUE;
388     }
389    
390     appdata->cur_items = appdata->cachelist_items;
391    
392     /* first sort the caches */
393     pos_t *refpos = get_pos(appdata);
394     gpx_sort(gpx, GPX_SORT_BY_DISTANCE, refpos);
395    
396     view = gtk_tree_view_new();
397    
398     /* --- "Type" column --- */
399     renderer = custom_cell_renderer_type_new();
400     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
401     -1, "Type", renderer, "type", CACHELIST_COL_TYPE, NULL);
402    
403     /* --- "Id" column --- */
404     if(appdata->cachelist_items & CACHELIST_ITEM_ID) {
405     renderer = gtk_cell_renderer_text_new();
406     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
407     -1, "Id", renderer, "text", CACHELIST_COL_ID, NULL);
408     }
409    
410     /* --- "Name" column --- */
411     renderer = gtk_cell_renderer_text_new();
412     g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
413    
414     GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
415     "Name", renderer, "text", CACHELIST_COL_NAME, NULL);
416     gtk_tree_view_column_set_expand(column, TRUE);
417     gtk_tree_view_insert_column(GTK_TREE_VIEW(view), column, -1);
418    
419     g_object_set(renderer, "foreground", "#ff0000", NULL );
420     gtk_tree_view_column_add_attribute(column, renderer, "strikethrough",
421     CACHELIST_COL_AVAIL);
422     gtk_tree_view_column_add_attribute(column, renderer,
423     "foreground-set", CACHELIST_COL_ARCHIVE);
424    
425     /* --- "Size" column --- */
426     if(appdata->cachelist_items & CACHELIST_ITEM_SIZE) {
427     renderer = custom_cell_renderer_size_new();
428     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
429     -1, "Size", renderer, "size", CACHELIST_COL_SIZE, NULL);
430     }
431    
432     /* --- "Rating" column --- */
433     if(appdata->cachelist_items & CACHELIST_ITEM_RATING) {
434     renderer = custom_cell_renderer_rating_new();
435     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
436     -1, "Rating", renderer, "rating", CACHELIST_COL_RATING, NULL);
437     }
438    
439     /* --- "Bearing" column --- */
440     renderer = gtk_cell_renderer_pixbuf_new();
441     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
442     -1, "Bearing", renderer, "pixbuf", CACHELIST_COL_BEARING, NULL);
443    
444     /* --- "Distance" column --- */
445     renderer = gtk_cell_renderer_text_new();
446     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
447     -1, "Distance", renderer, "text", CACHELIST_COL_DISTANCE, NULL);
448    
449     store = gtk_list_store_new(CACHELIST_NUM_COLS, G_TYPE_INT,
450     G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT,
451     G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING,
452     G_TYPE_POINTER, G_TYPE_BOOLEAN,
453     G_TYPE_BOOLEAN);
454    
455     GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
456    
457     GtkTreeIter sel_iter;
458     gboolean sel_iter_valid = FALSE;
459     GtkTreePath *path = NULL;
460     cache_t *cache = gpx->cache;
461     while(cache) {
462     char str[32];
463     gpx_pos_get_distance_str(str, sizeof(str),
464     *refpos, gpx_cache_pos(cache), appdata->imperial);
465    
466     int dint = (int)(cache->difficulty*2-2);
467     if(dint < 0) dint = 0;
468     if(dint > 8) dint = 8;
469    
470     int tint = (int)(cache->terrain*2-2);
471     if(tint < 0) tint = 0;
472     if(tint > 8) tint = 8;
473    
474     /* cache type includes "solved" flag in lowest bit */
475     int type = (cache->type<<8) +
476     (cache->notes?4:0) +
477     ((cache->notes && cache->notes->override)?1:0) +
478     ((cache->notes && cache->notes->found)?2:0);
479    
480     if((!(type & 2)) || !appdata->cachelist_hide_found) {
481    
482     /* Append a row and fill in some data */
483     gtk_list_store_append (store, &iter);
484    
485     gtk_list_store_set(store, &iter,
486     CACHELIST_COL_TYPE, type,
487     CACHELIST_COL_ID, cache->id,
488     CACHELIST_COL_NAME, cache->name,
489     CACHELIST_COL_SIZE, cache->container,
490     CACHELIST_COL_RATING, 100 * dint + tint,
491     CACHELIST_COL_BEARING,
492     icon_bearing(*refpos, gpx_cache_pos(cache)),
493     CACHELIST_COL_DISTANCE, str,
494     CACHELIST_COL_DATA, cache,
495     CACHELIST_COL_AVAIL, !cache->available ||
496     cache->archived,
497     CACHELIST_COL_ARCHIVE, cache->archived,
498     -1);
499    
500     if(cache == sel_cache) {
501     sel_iter = iter;
502     sel_iter_valid = TRUE;
503     }
504     }
505    
506     cache = cache->next;
507     }
508    
509     gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
510     g_object_unref(store);
511    
512     if(sel_iter_valid) {
513     gtk_tree_selection_select_iter(sel, &sel_iter);
514     path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &sel_iter);
515     }
516    
517     /* make list react on clicks */
518     g_signal_connect(view, "row-activated",
519     (GCallback)cachelist_view_onRowActivated, appdata);
520    
521     cachelist_expose_t *ce = malloc(sizeof(cachelist_expose_t));
522     ce->appdata = appdata;
523     ce->path = path;
524     ce->done = FALSE;
525    
526     g_signal_connect(view, "expose-event",
527     (GCallback)cachelist_expose, ce);
528     g_signal_connect(view, "destroy",
529     (GCallback)cachelist_destroy, ce);
530    
531     /* put this inside a scrolled view */
532     #ifndef USE_PANNABLE_AREA
533     GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
534     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
535     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
536     gtk_container_add(GTK_CONTAINER(scrolled_window), view);
537     #else
538     GtkWidget *pannable_area = hildon_pannable_area_new();
539    
540     gtk_container_add(GTK_CONTAINER(pannable_area), view);
541     #endif
542    
543     /* add a timer for automatic update */
544     g_assert(!appdata->cachelist_handler_id);
545     appdata->cachelist_handler_id =
546     gtk_timeout_add(CACHELIST_UPDATE_TIMEOUT, cachelist_update, appdata);
547    
548     /* update timer is being reset if the user scrolls or selects */
549     g_signal_connect(view, "button-press-event",
550     (GCallback)cachelist_update_reset0, appdata);
551    
552     #ifndef USE_PANNABLE_AREA
553     g_signal_connect(gtk_scrolled_window_get_vadjustment(
554     GTK_SCROLLED_WINDOW(scrolled_window)),
555     "value-changed",
556     (GCallback)cachelist_update_reset1, appdata);
557    
558     return scrolled_window;
559     #else
560     g_signal_connect(hildon_pannable_area_get_vadjustment(
561     HILDON_PANNABLE_AREA(pannable_area)),
562     "value-changed",
563     (GCallback)cachelist_update_reset1, appdata);
564    
565    
566     return pannable_area;
567     #endif
568     }
569    
570     #ifndef USE_MAEMO
571     void cachelist_dialog(appdata_t *appdata, gpx_t *gpx) {
572     GtkWidget *dialog =
573     gtk_dialog_new_with_buttons(gpx->name, GTK_WINDOW(appdata->window),
574     GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_MODAL |
575     GTK_DIALOG_DESTROY_WITH_PARENT,
576     GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
577     NULL);
578    
579     gtk_window_set_default_size(GTK_WINDOW(dialog), DIALOG_WIDTH, DIALOG_HEIGHT);
580    
581     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),
582     cachelist_create(appdata, gpx, NULL));
583    
584     gtk_widget_show_all(dialog);
585    
586     gtk_dialog_run(GTK_DIALOG(dialog));
587     gtk_widget_destroy(dialog);
588     }
589     #else
590     #ifdef USE_STACKABLE_WINDOW
591 harbaum 11 static void search_result_free(gpx_t *result);
592    
593     void on_cachelist_destroy(GtkWidget *widget, appdata_t *appdata) {
594     if(appdata->search_results) {
595     search_result_free(appdata->search_results);
596     appdata->search_results = NULL;
597     }
598     appdata->cur_gpx = NULL;
599    
600 harbaum 130 #ifdef ENABLE_OSM_GPS_MAP
601     map_update(appdata);
602     #endif
603    
604 harbaum 11 /* restore cur_view */
605     appdata->cur_view = g_object_get_data(G_OBJECT(widget), "cur_view");
606     }
607    
608 harbaum 1 void cachelist_dialog(appdata_t *appdata, gpx_t *gpx) {
609     GtkWidget *window = hildon_stackable_window_new();
610    
611 harbaum 11 /* store last "cur_view" in window */
612     g_object_set_data(G_OBJECT(window), "cur_view", appdata->cur_view);
613 harbaum 1
614 harbaum 11 appdata->cur_gpx = gpx;
615 harbaum 34 char *title = g_strdup_printf("%s - GPXView", gpx->name);
616 harbaum 11 gtk_window_set_title(GTK_WINDOW(window), title);
617     g_free(title);
618 harbaum 1
619 harbaum 11 appdata->cur_view = cachelist_create(appdata, gpx, NULL);
620     gtk_container_add(GTK_CONTAINER(window), appdata->cur_view);
621    
622    
623 harbaum 3 hildon_window_set_app_menu(HILDON_WINDOW(window),
624     menu_create(appdata, MENU_CACHELIST));
625    
626 harbaum 11 g_signal_connect(G_OBJECT(window), "destroy",
627     G_CALLBACK(on_cachelist_destroy), appdata);
628    
629 harbaum 1 gtk_widget_show_all(window);
630 harbaum 130
631     #ifdef ENABLE_OSM_GPS_MAP
632     map_update(appdata);
633     #endif
634 harbaum 1 }
635     #endif
636     #endif
637    
638     /******************** end of cachelist ********************/
639    
640     /******************** begin of gpxlist ********************/
641    
642     enum {
643     GPXLIST_COL_ICON = 0,
644     GPXLIST_COL_FILENAME,
645     GPXLIST_COL_NAME,
646     GPXLIST_COL_DATE,
647     GPXLIST_COL_CACHES,
648     GPXLIST_COL_OPEN,
649     #ifdef USE_PANNABLE_AREA
650     GPXLIST_COL_DELETE,
651     #endif
652     GPXLIST_COL_DATA,
653     GPXLIST_NUM_COLS
654     } ;
655    
656     static GdkPixbuf *gpx_icon_get(gpx_t *gpx) {
657     if(gpx->filename && g_file_test(gpx->filename, G_FILE_TEST_IS_DIR))
658     return icon_get(ICON_FILE, 1);
659    
660     if(gpx->filename&& !strcasecmp(gpx->filename+strlen(gpx->filename)-4,".zip"))
661     return icon_get(ICON_FILE, 2);
662    
663     return icon_get(ICON_FILE, 0);
664     }
665    
666     static void gpxlist_set(GtkListStore *store, GtkTreeIter *iter, gpx_t *gpx) {
667     char date_str[32], cnum[32];
668    
669     if(gpx->year && gpx->month && gpx->day) {
670     GDate *date = g_date_new_dmy(gpx->day, gpx->month, gpx->year);
671     g_date_strftime(date_str, sizeof(date_str), "%x", date);
672     g_date_free(date);
673     } else
674     strcpy(date_str, "---");
675    
676     char *fname = strrchr(gpx->filename, '/');
677     if(!fname) fname = gpx->filename;
678     else fname++; /* skip '/' */
679    
680     snprintf(cnum, sizeof(cnum), "%d", gpx_total_caches(gpx));
681    
682     /* Append a row and fill in some data */
683     gtk_list_store_set(store, iter,
684     GPXLIST_COL_ICON, gpx_icon_get(gpx),
685     GPXLIST_COL_FILENAME, fname,
686     GPXLIST_COL_NAME, gpx->name,
687     GPXLIST_COL_DATE, gpx->closed?NULL:date_str,
688     GPXLIST_COL_OPEN, !gpx->closed,
689     GPXLIST_COL_CACHES, gpx->closed?NULL:cnum,
690     #ifdef USE_PANNABLE_AREA
691     GPXLIST_COL_DELETE, icon_get(ICON_MISC, 7),
692     #endif
693     GPXLIST_COL_DATA, gpx,
694     -1);
695     }
696    
697     static void gpxlist_remove(appdata_t *appdata,
698     GtkListStore *store, GtkTreeIter *iter,
699     gpx_t *gpx) {
700    
701     printf("removing %s\n", gpx->name);
702    
703     /* de-chain */
704     gpx_t **prev = &appdata->gpx;
705     while(*prev != gpx) prev = &((*prev)->next);
706     *prev = gpx->next;
707    
708     /* remove gconf entry if file was closed */
709     gconf_remove_closed_name(appdata, gpx->filename);
710    
711     /* free gpx itself */
712     gpx_free(gpx);
713    
714     /* and remove from store */
715     gtk_list_store_remove(store, iter);
716     }
717    
718     static void gpxlist_close(appdata_t *appdata,
719     GtkListStore *store, GtkTreeIter *iter,
720     gpx_t *gpx) {
721    
722     printf("closing %s\n", gpx->name);
723    
724     g_assert(!gpx->closed);
725     gpx->closed = TRUE;
726    
727     /* free all associated caches */
728     gpx_free_caches(gpx);
729    
730     /* update entry */
731     gpxlist_set(store, iter, gpx);
732    
733     /* save name in gconf so we know this has been closed */
734     gconf_save_closed_name(appdata, gpx->filename, gpx->name);
735     }
736    
737 harbaum 142 void gpxlist_goto_cachelist(appdata_t *appdata, gpx_t *gpx) {
738     #if !defined(USE_BREAD_CRUMB_TRAIL) && !defined(BCT)
739     #ifdef USE_STACKABLE_WINDOW
740     if(!appdata->cur_gpx)
741     #endif
742     cachelist_dialog(appdata, gpx);
743     #ifdef USE_STACKABLE_WINDOW
744     else
745     printf("selected gpx, but cachelist window already present\n");
746     #endif
747     #else
748     gtk_container_remove(GTK_CONTAINER(appdata->vbox), appdata->cur_view);
749     appdata->cur_view = cachelist_create(appdata, gpx, NULL);
750     gtk_box_pack_start_defaults(GTK_BOX(appdata->vbox), appdata->cur_view);
751     gtk_widget_show_all(appdata->vbox);
752    
753     crumb_add(appdata, gpx->name, CRUMB_CACHELIST, gpx);
754     #endif
755     }
756    
757 harbaum 1 static void gpxlist_view_onRowActivated(GtkTreeView *treeview,
758     GtkTreePath *path,
759     GtkTreeViewColumn *col,
760     gpointer userdata) {
761     appdata_t *appdata = (appdata_t*)userdata;
762     GtkTreeIter iter;
763     GtkTreeModel *model = gtk_tree_view_get_model(treeview);
764    
765 harbaum 45 #ifdef USE_MAEMO
766 harbaum 43 /* check if a cache is already selected and ignore click if yes */
767     /* (was probably a double click) */
768     if(appdata->cur_gpx) return;
769 harbaum 45 #endif
770 harbaum 43
771 harbaum 1 if (gtk_tree_model_get_iter(model, &iter, path)) {
772     gpx_t *gpx;
773     gtk_tree_model_get(model, &iter, GPXLIST_COL_DATA, &gpx, -1);
774    
775     #ifdef USE_PANNABLE_AREA
776     /* get name of column the user clicked on */
777     const char *col_name = NULL;
778     if(col) col_name = gtk_tree_view_column_get_title(col);
779    
780     if(col_name && !strcmp(col_name, "Del")) {
781     printf("clicked delete\n");
782    
783 harbaum 164 #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
784 harbaum 1 /* ask user what he wants */
785     GtkWidget *dialog = gtk_message_dialog_new(
786     GTK_WINDOW(appdata->window),
787     GTK_DIALOG_DESTROY_WITH_PARENT,
788 harbaum 133 GTK_MESSAGE_QUESTION,
789     GTK_BUTTONS_CANCEL,
790 harbaum 1 _("Do you want to close this entry only or do "
791     "you want to remove it completely from the list?"));
792    
793     gtk_dialog_add_buttons(GTK_DIALOG(dialog),
794     _("Remove"), 1,
795     _("Close"), 2,
796     NULL);
797    
798 harbaum 164 gtk_window_set_title(GTK_WINDOW(dialog), _("Close or remove entry?"));
799     #else
800     GtkWidget *dialog =
801     hildon_note_new_confirmation_add_buttons(GTK_WINDOW(appdata->window),
802     _("Do you want to close this entry only or do "
803     "you want to remove it completely from the list?"),
804     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
805     _("Remove"), 1,
806     _("Close"), 2,
807     NULL);
808     #endif
809    
810 harbaum 1 if(gpx->closed)
811     gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), 2, FALSE);
812    
813     /* set the active flag again if the user answered "no" */
814     switch(gtk_dialog_run(GTK_DIALOG(dialog))) {
815    
816     case 1:
817     gpxlist_remove(appdata, GTK_LIST_STORE(model), &iter, gpx);
818     break;
819    
820     case 2:
821     gpxlist_close(appdata, GTK_LIST_STORE(model), &iter, gpx);
822     break;
823    
824     default:
825     break;
826     }
827    
828     gtk_widget_destroy(dialog);
829    
830     } else
831     #endif
832     {
833    
834     /* this gpx file may be closed. Since the user definitely wants */
835     /* to use it, we just open it again */
836     if(gpx->closed) {
837     gpx_dialog_t *dialog =
838     gpx_busy_dialog_new(GTK_WIDGET(appdata->window));
839     gpx_t *new = NULL;
840    
841     if(g_file_test(gpx->filename, G_FILE_TEST_IS_DIR))
842     new = gpx_parse_dir(dialog, gpx->filename);
843     else
844     new = gpx_parse(dialog, gpx->filename);
845    
846     if(new) {
847     gpx_t **prev = &(appdata->gpx);
848     while(*prev && *prev != gpx)
849     prev = &(*prev)->next;
850    
851     /* this entry _must_ be in the list */
852     g_assert(*prev);
853    
854     /* replace gpx entry with the new "open" one */
855     (*prev) = new;
856     new->next = gpx->next;
857     gpx->next = NULL;
858    
859     /* free old closed one */
860     gpx_free(gpx);
861    
862     gpx = new;
863    
864     /* finally update the visible list */
865     gpxlist_set(appdata->gpxstore, &iter, gpx);
866    
867     /* and remove gconf entry */
868     gconf_remove_closed_name(appdata, gpx->filename);
869    
870     #ifndef USE_PANNABLE_AREA
871     gtk_widget_set_sensitive(appdata->menu_close, TRUE);
872     #endif
873     } else {
874     printf("unable to reopen file %s\n", gpx->filename);
875     return;
876     }
877    
878     gpx_busy_dialog_destroy(dialog);
879     }
880 harbaum 142
881     gpxlist_goto_cachelist(appdata, gpx);
882 harbaum 1 }
883     }
884     }
885    
886     #ifndef USE_PANNABLE_AREA
887     static gboolean
888     view_selection_func(GtkTreeSelection *selection, GtkTreeModel *model,
889     GtkTreePath *path, gboolean path_currently_selected,
890     gpointer userdata) {
891     appdata_t *appdata = (appdata_t*)userdata;
892     GtkTreeIter iter;
893    
894     if(gtk_tree_model_get_iter(model, &iter, path)) {
895     gpx_t *gpx;
896     gtk_tree_model_get(model, &iter, GPXLIST_COL_DATA, &gpx, -1);
897    
898     gtk_widget_set_sensitive(appdata->menu_remove, !path_currently_selected);
899    
900     if(!gpx->closed)
901     gtk_widget_set_sensitive(appdata->menu_close, !path_currently_selected);
902     }
903    
904     return TRUE; /* allow selection state to change */
905     }
906     #endif
907    
908     static GtkWidget *gpxlist_create_view_and_model(appdata_t *appdata,
909     gpx_t *sel_gpx) {
910     gpx_t *gpx = appdata->gpx;
911     GtkCellRenderer *renderer;
912    
913     /* saved displayed items */
914     appdata->cur_items = appdata->gpxlist_items;
915    
916     #ifndef USE_PANNABLE_AREA
917     /* nothing selected yet */
918     gtk_widget_set_sensitive(appdata->menu_remove, FALSE);
919     gtk_widget_set_sensitive(appdata->menu_close, FALSE);
920     #endif
921    
922     appdata->gpxview = gtk_tree_view_new ();
923    
924     GtkTreeSelection *selection =
925     gtk_tree_view_get_selection(GTK_TREE_VIEW(appdata->gpxview));
926     #ifndef USE_PANNABLE_AREA
927     gtk_tree_selection_set_select_function(selection, view_selection_func,
928     appdata, NULL);
929     #endif
930    
931     /* --- "Icon" column --- */
932     renderer = gtk_cell_renderer_pixbuf_new();
933     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(appdata->gpxview),
934     -1, "Icon", renderer,
935     "pixbuf", GPXLIST_COL_ICON,
936 harbaum 143 #ifdef USE_PANNABLE_AREA
937     /* at least one entry needs to be sensitive. */
938     /* This is the delete icon if the PANNABLE_AREA is used */
939     "sensitive", GPXLIST_COL_OPEN,
940     #endif
941 harbaum 1 NULL);
942    
943     /* --- "FileName" column --- */
944     if(appdata->gpxlist_items & GPXLIST_ITEM_FILENAME) {
945     renderer = gtk_cell_renderer_text_new();
946     gtk_tree_view_insert_column_with_attributes(
947     GTK_TREE_VIEW(appdata->gpxview),
948     -1, "Filename", renderer,
949     "text", GPXLIST_COL_FILENAME,
950     "sensitive", GPXLIST_COL_OPEN,
951     NULL);
952     }
953    
954     /* --- "Name" column --- */
955     renderer = gtk_cell_renderer_text_new();
956     g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
957    
958     GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
959     "Name", renderer,
960     "text", GPXLIST_COL_NAME,
961     "sensitive", GPXLIST_COL_OPEN,
962     NULL);
963     gtk_tree_view_column_set_expand(column, TRUE);
964     gtk_tree_view_insert_column(GTK_TREE_VIEW(appdata->gpxview), column, -1);
965    
966     /* --- "Date" column --- */
967     if(appdata->gpxlist_items & GPXLIST_ITEM_DATE) {
968     renderer = gtk_cell_renderer_text_new();
969     g_object_set(renderer, "xalign", 1.0, NULL );
970     gtk_tree_view_insert_column_with_attributes(
971     GTK_TREE_VIEW(appdata->gpxview),
972     -1, "Date", renderer,
973     "text", GPXLIST_COL_DATE,
974     "sensitive", GPXLIST_COL_OPEN,
975     NULL);
976     }
977    
978     /* --- "Number of caches" column --- */
979     if(appdata->gpxlist_items & GPXLIST_ITEM_CNUM) {
980     renderer = gtk_cell_renderer_text_new();
981     g_object_set(renderer, "xalign", 1.0, NULL );
982     gtk_tree_view_insert_column_with_attributes(
983     GTK_TREE_VIEW(appdata->gpxview),
984     -1, "#Caches", renderer,
985     "text", GPXLIST_COL_CACHES,
986     "sensitive", GPXLIST_COL_OPEN,
987     NULL);
988     }
989    
990     #ifdef USE_PANNABLE_AREA
991     /* --- "Delete" column --- */
992     renderer = gtk_cell_renderer_pixbuf_new();
993     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(appdata->gpxview),
994     -1, "Del", renderer,
995     "pixbuf", GPXLIST_COL_DELETE,
996 harbaum 143 // "sensitive", GPXLIST_COL_OPEN,
997 harbaum 1 NULL);
998     #endif
999    
1000     /* build and fill the store */
1001     appdata->gpxstore = gtk_list_store_new(GPXLIST_NUM_COLS, GDK_TYPE_PIXBUF,
1002     G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
1003     G_TYPE_STRING, G_TYPE_BOOLEAN,
1004     #ifdef USE_PANNABLE_AREA
1005     GDK_TYPE_PIXBUF,
1006     #endif
1007     G_TYPE_POINTER);
1008    
1009     GtkTreePath *path = NULL;
1010     GtkTreeIter sel_iter;
1011     gboolean sel_iter_valid = FALSE;
1012     while(gpx) {
1013 harbaum 113 GtkTreeIter iter;
1014     gtk_list_store_append(appdata->gpxstore, &iter);
1015     gpxlist_set(appdata->gpxstore, &iter, gpx);
1016    
1017     if(gpx == sel_gpx) {
1018     sel_iter = iter;
1019     sel_iter_valid = TRUE;
1020 harbaum 1 }
1021    
1022     gpx = gpx->next;
1023     }
1024    
1025     gtk_tree_view_set_model(GTK_TREE_VIEW(appdata->gpxview),
1026     GTK_TREE_MODEL(appdata->gpxstore));
1027    
1028     g_object_unref(appdata->gpxstore);
1029    
1030     if(sel_iter_valid) {
1031     gtk_tree_selection_select_iter(selection, &sel_iter);
1032     path = gtk_tree_model_get_path(GTK_TREE_MODEL(appdata->gpxstore),
1033     &sel_iter);
1034     gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(appdata->gpxview),
1035     path, NULL, TRUE, 0.0, 0.0);
1036     gtk_tree_path_free(path);
1037     }
1038    
1039     /* make list react on clicks */
1040     g_signal_connect(appdata->gpxview, "row-activated",
1041     (GCallback)gpxlist_view_onRowActivated, appdata);
1042    
1043     /* put this inside a scrolled view */
1044     #ifndef USE_PANNABLE_AREA
1045     GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1046     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
1047     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1048     gtk_container_add(GTK_CONTAINER(scrolled_window), appdata->gpxview);
1049    
1050     return scrolled_window;
1051     #else
1052     GtkWidget *pannable_area = hildon_pannable_area_new();
1053     gtk_container_add(GTK_CONTAINER(pannable_area), appdata->gpxview);
1054    
1055     return pannable_area;
1056     #endif
1057     }
1058    
1059     /* add last entry in gpx list to visual representation */
1060     static void gpxlist_add(appdata_t *appdata, gpx_t *new) {
1061     GtkTreeIter iter;
1062    
1063     gtk_list_store_append(appdata->gpxstore, &iter);
1064     gpxlist_set(appdata->gpxstore, &iter, new);
1065    
1066     /* and attach entry to end of list */
1067     gpx_t **gpx = &appdata->gpx;
1068     while(*gpx) gpx = &((*gpx)->next);
1069     *gpx = new;
1070     }
1071    
1072     /******************** end of gpxlist ********************/
1073    
1074     /******************** begin of menu *********************/
1075    
1076 harbaum 49 typedef struct {
1077     appdata_t *appdata;
1078     GtkWidget *dialog;
1079     } about_context_t;
1080    
1081     #ifdef ENABLE_BROWSER_INTERFACE
1082     void on_paypal_button_clicked(GtkButton *button, about_context_t *context) {
1083     gtk_dialog_response(GTK_DIALOG(context->dialog), GTK_RESPONSE_ACCEPT);
1084     browser_url(context->appdata,
1085     "https://www.paypal.com/cgi-bin/webscr"
1086     "?cmd=_s-xclick&hosted_button_id=7400558");
1087     }
1088     #endif
1089    
1090 harbaum 1 static void
1091     cb_menu_about(GtkWidget *window, gpointer data) {
1092 harbaum 49 about_context_t context;
1093 harbaum 1
1094 harbaum 49 context.appdata = (appdata_t *)data;
1095 harbaum 1
1096 harbaum 14 #ifdef ENABLE_LIBLOCATION
1097     char *uses = "uses liblocation";
1098     #elif defined(ENABLE_GPSBT)
1099     char *uses = "uses gpsbt and gpsd";
1100     #else
1101     char *uses = "uses gpsd";
1102     #endif
1103    
1104 harbaum 49 const gchar *authors[] = {
1105     "Till Harbaum <till@harbaum.org>",
1106     "John Stowers <john.stowers@gmail.com>",
1107 harbaum 156 "GCVote: Guido Wegener <guido.wegener@gmx.de>",
1108 harbaum 49 NULL };
1109 harbaum 14
1110 harbaum 49 context.dialog = g_object_new(GTK_TYPE_ABOUT_DIALOG,
1111     "name", "GPXView",
1112     "version", VERSION,
1113     "copyright", _("Copyright 2008-2009"),
1114     "authors", authors,
1115     "website", _("http://www.harbaum.org/till/maemo"),
1116     "comments", _(uses),
1117     NULL);
1118 harbaum 14
1119 harbaum 49 #ifdef ENABLE_BROWSER_INTERFACE
1120     /* add a way to donate to the project */
1121     GtkWidget *alignment = gtk_alignment_new(0.5, 0, 0, 0);
1122 harbaum 1
1123 harbaum 49 GtkWidget *hbox = gtk_hbox_new(FALSE, 8);
1124     gtk_box_pack_start(GTK_BOX(hbox),
1125 harbaum 50 gtk_label_new(_("Do you like GPXView?")),
1126 harbaum 49 FALSE, FALSE, 0);
1127 harbaum 1
1128 harbaum 49 GtkWidget *button = gtk_button_new();
1129     gtk_button_set_image(GTK_BUTTON(button),
1130     icon_get_widget(ICON_MISC, 8));
1131     gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
1132     g_signal_connect(button, "clicked",
1133     G_CALLBACK(on_paypal_button_clicked), &context);
1134     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1135    
1136     gtk_container_add(GTK_CONTAINER(alignment), hbox);
1137     gtk_box_pack_start_defaults(GTK_BOX((GTK_DIALOG(context.dialog))->vbox),
1138     alignment);
1139    
1140     gtk_widget_show_all(alignment);
1141     #endif
1142    
1143     gtk_dialog_run(GTK_DIALOG(context.dialog));
1144     gtk_widget_destroy(context.dialog);
1145 harbaum 1 }
1146    
1147     #if defined(USE_MAEMO) && defined(HILDON_HELP)
1148     static void
1149     cb_menu_help(GtkWidget *window, gpointer data) {
1150     appdata_t *appdata = (appdata_t*)data;
1151    
1152     hildon_help_show(appdata->osso_context, HELP_ID_INTRO, 0);
1153     }
1154     #endif
1155    
1156     static void
1157     cb_menu_add(GtkWidget *window, gpointer data) {
1158     appdata_t *appdata = (appdata_t *)data;
1159    
1160     gpx_t *new = choose_file(appdata, FALSE);
1161     if(new) gpxlist_add(appdata, new);
1162     }
1163    
1164     static void
1165     cb_menu_adddir(GtkWidget *window, gpointer data) {
1166     appdata_t *appdata = (appdata_t *)data;
1167    
1168     gpx_t *new = choose_file(appdata, TRUE);
1169     if(new) gpxlist_add(appdata, new);
1170     }
1171    
1172     #ifndef USE_PANNABLE_AREA
1173     static void
1174     cb_menu_close(GtkWidget *window, gpointer data) {
1175     appdata_t *appdata = (appdata_t *)data;
1176     GtkTreeSelection *selection;
1177     GtkTreeModel *model;
1178     GtkTreeIter iter;
1179    
1180     printf("selected close\n");
1181    
1182     /* the entry cannot be closed again */
1183     gtk_widget_set_sensitive(appdata->menu_close, FALSE);
1184    
1185     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(appdata->gpxview));
1186    
1187     printf("gpxlist close\n");
1188    
1189     if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
1190     gpx_t *gpx = NULL;
1191     gtk_tree_model_get(model, &iter, GPXLIST_COL_DATA, &gpx, -1);
1192    
1193     if(gpx) gpxlist_close(appdata, GTK_LIST_STORE(model), &iter, gpx);
1194     } else {
1195     g_print ("no row selected.\n");
1196     }
1197     }
1198    
1199     static void
1200     cb_menu_remove(GtkWidget *window, gpointer data) {
1201     appdata_t *appdata = (appdata_t *)data;
1202    
1203     /* disable menu item */
1204     gtk_widget_set_sensitive(appdata->menu_remove, FALSE);
1205     gtk_widget_set_sensitive(appdata->menu_close, FALSE);
1206    
1207     GtkTreeModel *model;
1208     GtkTreeIter iter;
1209     GtkTreeSelection *selection =
1210     gtk_tree_view_get_selection(GTK_TREE_VIEW(appdata->gpxview));
1211    
1212     printf("gpxlist remove\n");
1213    
1214     if(gtk_tree_selection_get_selected(selection, &model, &iter)) {
1215     gpx_t *gpx = NULL;
1216     gtk_tree_model_get(model, &iter, GPXLIST_COL_DATA, &gpx, -1);
1217    
1218     if(gpx) gpxlist_remove(appdata, GTK_LIST_STORE(model), &iter, gpx);
1219     } else {
1220     g_print ("no row selected.\n");
1221     }
1222     }
1223    
1224     #endif // !USE_PANNABLE_AREA
1225    
1226     static void search_result_free(gpx_t *result) {
1227     printf("freeing search results\n");
1228    
1229     /* free found chain */
1230     cache_t *cache = result->cache;
1231     while(cache) {
1232     cache_t *next = cache->next;
1233     free(cache);
1234     cache = next;
1235     }
1236     free(result->name);
1237     free(result);
1238     }
1239    
1240     #define MAX_HITS 50
1241    
1242     static time_t localize_time(time_t in) {
1243     time_t ret;
1244     char *tz;
1245     struct tm *tm = localtime(&in);
1246    
1247     tz = getenv("TZ");
1248     setenv("TZ", "", 1);
1249     tzset();
1250     ret = mktime(tm);
1251     if (tz)
1252     setenv("TZ", tz, 1);
1253     else
1254     unsetenv("TZ");
1255     tzset();
1256     return ret;
1257     }
1258    
1259     static int days_ago(time_t in) {
1260     int day_in = localize_time(in) / (60*60*24);
1261     int day_now = localize_time(time(NULL)) / (60*60*24);
1262    
1263     return day_now - day_in;
1264     }
1265    
1266     gpx_t *search_do(appdata_t *appdata, gpx_t *gpx, char *phrase,
1267     int what, gboolean local) {
1268     /* walk through all caches */
1269    
1270     int hits = 0;
1271     gpx_t *found = malloc(sizeof(gpx_t));
1272     memset(found, 0, sizeof(gpx_t));
1273     cache_t **cacheP = &(found->cache);
1274    
1275     if(what & SEARCH_FINDS) {
1276     time_t loc_now = localize_time(time(NULL));
1277     printf("now: %ld days since 1/1/1970, days hour is %ld\n",
1278     loc_now/(60*60*24), loc_now%(60*60*24)/(60*60));
1279     }
1280    
1281     while(gpx && hits < MAX_HITS) {
1282    
1283     /* we need all notes ... */
1284     if(what & SEARCH_FINDS) {
1285     notes_load_all(appdata, gpx);
1286     gpx->notes_loaded = TRUE;
1287     }
1288    
1289     cache_t *cache = gpx->cache;
1290    
1291     while(cache && hits < MAX_HITS) {
1292     gboolean hit = FALSE;
1293    
1294     if(what & SEARCH_FINDS) {
1295     if(cache->notes && cache->notes->found ) {
1296     int days = days_ago(cache->notes->ftime);
1297    
1298     if(cache->id)
1299     printf("find of %s is %d days ago\n", cache->id, days);
1300    
1301     if(days <= appdata->search_days)
1302     hit = 1;
1303     }
1304     } else if(cache->id && (what & SEARCH_ID) &&
1305     strcasestr(cache->id, phrase))
1306     hit = 1;
1307     else if(cache->name && (what & SEARCH_NAME) &&
1308     strcasestr(cache->name, phrase))
1309     hit = 1;
1310     else if(cache->short_description && (what & SEARCH_DESC) &&
1311     strcasestr(cache->short_description, phrase))
1312     hit = 1;
1313     else if(cache->long_description && (what & SEARCH_DESC) &&
1314     strcasestr(cache->long_description, phrase))
1315     hit = 1;
1316 harbaum 156 else if(cache->owner && cache->owner->name && (what & SEARCH_OWNER) &&
1317     strcasestr(cache->owner->name, phrase))
1318 harbaum 1 hit = 1;
1319    
1320     if(hit) {
1321     /* chain a copy of this cache structure into the found list */
1322     *cacheP = malloc(sizeof(cache_t));
1323     memcpy(*cacheP, cache, sizeof(cache_t));
1324     (*cacheP)->next = NULL;
1325     cacheP = &((*cacheP)->next);
1326     hits++;
1327     }
1328     cache = cache->next;
1329     }
1330    
1331     if(!local) gpx = gpx->next;
1332     else gpx = NULL; /* local search within one gpx only */
1333     }
1334    
1335     found->name = strdup(_("Search results"));
1336    
1337     return found;
1338     }
1339    
1340     typedef struct {
1341     appdata_t *appdata;
1342     GtkWidget *entry, *spinner;
1343     GtkWidget *in_id, *in_name, *in_desc, *in_owner, *in_finds;
1344     } search_context_t;
1345    
1346     static void callback_finds_toggled(GtkWidget *widget, gpointer data ) {
1347     search_context_t *context = (search_context_t*)data;
1348    
1349     gboolean in_finds = gtk_toggle_button_get_active(
1350     GTK_TOGGLE_BUTTON(context->in_finds));
1351    
1352     gtk_widget_set_sensitive(context->entry, !in_finds);
1353     gtk_widget_set_sensitive(context->in_id, !in_finds);
1354     gtk_widget_set_sensitive(context->in_name, !in_finds);
1355     gtk_widget_set_sensitive(context->in_desc, !in_finds);
1356     gtk_widget_set_sensitive(context->in_owner, !in_finds);
1357     gtk_widget_set_sensitive(context->spinner, in_finds);
1358     }
1359    
1360     static void
1361     cb_menu_search(GtkWidget *window, gpointer data) {
1362     appdata_t *appdata = (appdata_t *)data;
1363    
1364     search_context_t context;
1365     memset(&context, 0, sizeof(search_context_t));
1366     context.appdata = appdata;
1367    
1368     GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Enter search phrase"),
1369     GTK_WINDOW(appdata->window), GTK_DIALOG_MODAL,
1370     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
1371     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
1372     NULL);
1373    
1374     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1375     gtk_label_new(_("Search in:")));
1376    
1377     GtkWidget *table = gtk_table_new(2, 2, TRUE);
1378     gtk_table_set_col_spacing(GTK_TABLE(table), 0, 8);
1379    
1380     context.in_id = gtk_check_button_new_with_label(_("Waypoint IDs"));
1381     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.in_id),
1382     appdata->search & SEARCH_ID);
1383     gtk_table_attach_defaults(GTK_TABLE(table), context.in_id, 0, 1, 0, 1);
1384    
1385     context.in_name = gtk_check_button_new_with_label(_("Names"));
1386     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.in_name),
1387     appdata->search & SEARCH_NAME);
1388     gtk_table_attach_defaults(GTK_TABLE(table), context.in_name, 1, 2, 0, 1);
1389    
1390     context.in_desc = gtk_check_button_new_with_label(_("Descriptions"));
1391     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.in_desc),
1392     appdata->search & SEARCH_DESC);
1393     gtk_table_attach_defaults(GTK_TABLE(table), context.in_desc, 0, 1, 1, 2);
1394    
1395     context.in_owner = gtk_check_button_new_with_label(_("Owner"));
1396     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.in_owner),
1397     appdata->search & SEARCH_OWNER);
1398     gtk_table_attach_defaults(GTK_TABLE(table), context.in_owner, 1, 2, 1, 2);
1399    
1400     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), table);
1401    
1402     /* -------------------------------------------------------------- */
1403    
1404     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1405     gtk_label_new(_("Search for:")));
1406     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1407     context.entry = gtk_entry_new());
1408     if(appdata->search_str)
1409     gtk_entry_set_text(GTK_ENTRY(context.entry), appdata->search_str);
1410    
1411     /* -------------------------------------------------------------- */
1412    
1413     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1414     gtk_hseparator_new());
1415    
1416     GtkWidget *hbox = gtk_hbox_new(FALSE, 5);
1417    
1418     context.in_finds = gtk_check_button_new_with_label(_("Search finds for"));
1419     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.in_finds),
1420     appdata->search & SEARCH_FINDS);
1421     gtk_box_pack_start_defaults(GTK_BOX(hbox), context.in_finds);
1422     g_signal_connect(G_OBJECT(context.in_finds), "toggled",
1423     G_CALLBACK(callback_finds_toggled), &context);
1424    
1425     #ifndef USE_MAEMO
1426     GtkObject *adj = gtk_adjustment_new(appdata->search_days, 0, 99, 1, 10, 10);
1427     context.spinner = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0);
1428     #else
1429     context.spinner = hildon_number_editor_new(0, 99);
1430     hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(context.spinner),
1431     appdata->search_days);
1432     #endif
1433     gtk_box_pack_start_defaults(GTK_BOX(hbox), context.spinner);
1434    
1435     gtk_box_pack_start_defaults(GTK_BOX(hbox), gtk_label_new(_("days")));
1436    
1437     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
1438    
1439     /* -------------------------------------------------------------- */
1440    
1441     gtk_widget_show_all(dialog);
1442     callback_finds_toggled(NULL, &context);
1443    
1444     if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
1445     char *p = strdup(gtk_entry_get_text(GTK_ENTRY(context.entry)));
1446    
1447     /* update saved search string */
1448     if(appdata->search_str) free(appdata->search_str);
1449     if(strlen(p) > 0)
1450     appdata->search_str = strdup(p);
1451    
1452     #ifndef USE_MAEMO
1453     appdata->search_days = gtk_spin_button_get_value_as_int(
1454     GTK_SPIN_BUTTON(context.spinner));
1455     #else
1456     appdata->search_days = hildon_number_editor_get_value(
1457     HILDON_NUMBER_EDITOR(context.spinner));
1458     #endif
1459    
1460     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context.in_finds)))
1461     appdata->search |= SEARCH_FINDS;
1462     else
1463     appdata->search &= ~SEARCH_FINDS;
1464    
1465     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context.in_id)))
1466     appdata->search |= SEARCH_ID;
1467     else
1468     appdata->search &= ~SEARCH_ID;
1469    
1470     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context.in_name)))
1471     appdata->search |= SEARCH_NAME;
1472     else
1473     appdata->search &= ~SEARCH_NAME;
1474    
1475     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context.in_desc)))
1476     appdata->search |= SEARCH_DESC;
1477     else
1478     appdata->search &= ~SEARCH_DESC;
1479    
1480     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context.in_owner)))
1481     appdata->search |= SEARCH_OWNER;
1482     else
1483     appdata->search &= ~SEARCH_OWNER;
1484    
1485     gtk_widget_destroy(dialog);
1486    
1487     /* don't search if we are asked to search for nothing */
1488     if(((appdata->search & (SEARCH_ID|SEARCH_NAME|SEARCH_DESC|SEARCH_OWNER)) &&
1489     strlen(p) > 0) || (appdata->search & SEARCH_FINDS)) {
1490    
1491     printf("Search for %s (flags = %x)...\n", p, appdata->search);
1492    
1493 harbaum 128 #if !defined(USE_BREAD_CRUMB_TRAIL) && !defined(BCT)
1494 harbaum 12 gpx_t *found =
1495 harbaum 11 search_do(appdata, appdata->gpx, p, appdata->search, FALSE);
1496 harbaum 1
1497     /* do search result dialog here ... */
1498 harbaum 12 cachelist_dialog(appdata, found);
1499 harbaum 11 #ifndef USE_STACKABLE_WINDOW
1500 harbaum 12 search_result_free(found);
1501     #else
1502     appdata->search_results = found;
1503 harbaum 11 #endif
1504 harbaum 1 #else
1505 harbaum 11 gpx_t *found = NULL;
1506    
1507 harbaum 1 if(appdata->cur_gpx)
1508     found = search_do(appdata, appdata->cur_gpx, p, appdata->search, TRUE);
1509     else
1510     found = search_do(appdata, appdata->gpx, p, appdata->search, FALSE);
1511    
1512     gtk_container_remove(GTK_CONTAINER(appdata->vbox), appdata->cur_view);
1513     appdata->cur_view = cachelist_create(appdata, found, NULL);
1514     gtk_box_pack_start_defaults(GTK_BOX(appdata->vbox), appdata->cur_view);
1515     gtk_widget_show_all(appdata->vbox);
1516     crumb_add(appdata, found->name,
1517     appdata->cur_gpx?CRUMB_SEARCH_GPX:CRUMB_SEARCH_GLOBAL, found);
1518     #endif
1519     } else
1520     printf("No valid search: \"%s\" with flags %x!\n", p, appdata->search);
1521    
1522     free(p);
1523     } else
1524     gtk_widget_destroy(dialog);
1525     }
1526    
1527 harbaum 40 static void on_window_destroy (GtkWidget *widget, gpointer data);
1528 harbaum 1
1529     #ifndef USE_MAEMO
1530     static void
1531     cb_menu_quit(GtkWidget *window, gpointer data) {
1532     on_window_destroy(window, data);
1533     }
1534     #endif
1535    
1536 harbaum 2 #ifndef NO_COPY_N_PASTE
1537 harbaum 1 static void
1538     cb_menu_cut(GtkWidget *widget, gpointer data) {
1539     appdata_t *appdata = (appdata_t*)data;
1540    
1541     if(appdata->active_buffer) {
1542     if(GTK_WIDGET_TYPE(appdata->active_buffer) == GTK_TYPE_TEXT_BUFFER) {
1543     gtk_text_buffer_cut_clipboard(GTK_TEXT_BUFFER(appdata->active_buffer),
1544     appdata->clipboard, TRUE);
1545     } else
1546     printf("cut: ERROR, not a text buffer\n");
1547     } else
1548     printf("cut: ERROR, no active buffer\n");
1549     }
1550    
1551     static void
1552     cb_menu_copy(GtkWidget *widget, gpointer data) {
1553     appdata_t *appdata = (appdata_t*)data;
1554    
1555     if(appdata->active_buffer) {
1556     if(GTK_WIDGET_TYPE(appdata->active_buffer) == GTK_TYPE_TEXT_BUFFER) {
1557     gtk_text_buffer_copy_clipboard(GTK_TEXT_BUFFER(appdata->active_buffer),
1558     appdata->clipboard);
1559     } else if(GTK_WIDGET_TYPE(appdata->active_buffer) == gtk_html_get_type()) {
1560     printf("copy from html buffer\n");
1561     html_copy_to_clipboard(appdata);
1562     } else
1563     printf("copy: ERROR, not a text nor a html buffer\n");
1564     } else
1565     printf("copy: ERROR, no active buffer\n");
1566     }
1567    
1568     static void
1569     cb_menu_paste(GtkWidget *widget, gpointer data) {
1570     appdata_t *appdata = (appdata_t*)data;
1571    
1572     if(appdata->active_buffer) {
1573     if(GTK_WIDGET_TYPE(appdata->active_buffer) == GTK_TYPE_TEXT_BUFFER) {
1574     gtk_text_buffer_paste_clipboard(GTK_TEXT_BUFFER(appdata->active_buffer),
1575     appdata->clipboard, NULL, TRUE);
1576     } else
1577     printf("paste: ERROR, not a text buffer\n");
1578     } else
1579     printf("paste: ERROR, no active buffer\n");
1580     }
1581 harbaum 2 #endif
1582 harbaum 1
1583 harbaum 6 static void
1584     cb_menu_export_log(GtkWidget *widget, gpointer data) {
1585     appdata_t *appdata = (appdata_t*)data;
1586     notes_log_export(appdata);
1587     }
1588 harbaum 5
1589 harbaum 122 #ifdef ENABLE_MAEMO_MAPPER
1590 harbaum 6 static void
1591     cb_menu_export_mmpoi(GtkWidget *widget, gpointer data) {
1592     appdata_t *appdata = (appdata_t*)data;
1593     mmpoi_export(appdata);
1594     }
1595     #endif
1596 harbaum 5
1597 harbaum 6 static void
1598     cb_menu_export_garmin(GtkWidget *widget, gpointer data) {
1599     appdata_t *appdata = (appdata_t*)data;
1600     garmin_export(appdata);
1601 harbaum 1 }
1602    
1603 harbaum 32 #ifdef ENABLE_OSM_GPS_MAP
1604 harbaum 6 static void
1605 harbaum 32 cb_menu_map(GtkWidget *window, gpointer data) {
1606     map((appdata_t *)data);
1607     }
1608     #endif
1609    
1610     static void
1611 harbaum 6 cb_menu_geomath(GtkWidget *window, gpointer data) {
1612     geomath_dialog((appdata_t *)data);
1613     }
1614 harbaum 5
1615 harbaum 6 static void
1616     cb_menu_geotext(GtkWidget *window, gpointer data) {
1617     geotext_dialog((appdata_t *)data);
1618 harbaum 1 }
1619    
1620 harbaum 6 static void
1621     cb_menu_precpos(GtkWidget *window, gpointer data) {
1622     precise_position((appdata_t *)data);
1623 harbaum 1 }
1624    
1625 harbaum 6 #ifdef USE_STACKABLE_WINDOW
1626 harbaum 30 typedef struct {
1627     char *label, *desc;
1628     GtkSignalFunc activate_cb;
1629     } menu_entry_t;
1630 harbaum 6
1631 harbaum 30 typedef struct {
1632     const char *title;
1633     const menu_entry_t *menu;
1634     int len;
1635     } submenu_t;
1636 harbaum 3
1637 harbaum 30 #define COLUMNS 1
1638 harbaum 4
1639 harbaum 30 void on_submenu_entry_clicked(GtkButton *button, GtkWidget *menu) {
1640 harbaum 5
1641 harbaum 30 /* force closing of submenu dialog */
1642     gtk_dialog_response(GTK_DIALOG(menu), GTK_RESPONSE_NONE);
1643     gtk_widget_hide(menu);
1644    
1645     /* let gtk clean up */
1646     while(gtk_events_pending())
1647     gtk_main_iteration();
1648 harbaum 11 }
1649    
1650 harbaum 30 static GtkWidget *app_submenu_create(appdata_t *appdata,
1651     const submenu_t *submenu) {
1652 harbaum 5
1653 harbaum 30 /* create a oridinary dialog box */
1654     GtkWidget *dialog = gtk_dialog_new();
1655     gtk_window_set_title(GTK_WINDOW(dialog), _(submenu->title));
1656     gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1657     gtk_window_set_transient_for(GTK_WINDOW(dialog),
1658     GTK_WINDOW(appdata->window));
1659     gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
1660 harbaum 5
1661 harbaum 30 GtkWidget *table = gtk_table_new(submenu->len/COLUMNS, COLUMNS, TRUE);
1662     int x = 0, y = 0;
1663 harbaum 11
1664 harbaum 30 const menu_entry_t *menu_entries = submenu->menu;
1665     while(menu_entries->label) {
1666     GtkWidget *button = NULL;
1667 harbaum 21
1668 harbaum 30 button = hildon_button_new_with_text(
1669 harbaum 6 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
1670     HILDON_BUTTON_ARRANGEMENT_VERTICAL,
1671 harbaum 30 _(menu_entries->label), _(menu_entries->desc));
1672 harbaum 5
1673 harbaum 31 /* try to center both texts */
1674     hildon_button_set_title_alignment(HILDON_BUTTON(button), 0.5, 0.5);
1675     hildon_button_set_value_alignment(HILDON_BUTTON(button), 0.5, 0.5);
1676 harbaum 6
1677 harbaum 31 g_signal_connect(button, "clicked",
1678     G_CALLBACK(on_submenu_entry_clicked), dialog);
1679    
1680     g_signal_connect(button, "clicked",
1681     menu_entries->activate_cb, appdata);
1682    
1683 harbaum 30 gtk_table_attach_defaults(GTK_TABLE(table), button, x, x+1, y, y+1);
1684    
1685     x++;
1686     if(x == COLUMNS) { x = 0; y++; }
1687 harbaum 3
1688 harbaum 30 menu_entries++;
1689     }
1690 harbaum 20
1691 harbaum 30 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), table);
1692    
1693     return dialog;
1694 harbaum 3 }
1695    
1696 harbaum 30 /* popup the dialog shaped submenu */
1697     static void submenu_popup(GtkWidget *menu) {
1698     gtk_widget_show_all(menu);
1699     gtk_dialog_run(GTK_DIALOG(menu));
1700     gtk_widget_hide(menu);
1701     }
1702    
1703     static void submenu_cleanup(GtkWidget *menu) {
1704     gtk_widget_destroy(menu);
1705     }
1706    
1707     static const menu_entry_t submenu_export_entries[] = {
1708 harbaum 122 #ifdef ENABLE_MAEMO_MAPPER
1709 harbaum 30 { "Export to Maemo Mapper" , "Save a Maemo Mapper POI file",
1710     G_CALLBACK(cb_menu_export_mmpoi) },
1711 harbaum 122 #endif
1712 harbaum 30 { "Export Field Notes", "Save a Garmin Field Notes file",
1713     G_CALLBACK(cb_menu_export_log) },
1714     { "Export Garmin GPX", "Save modified waypoints in GPX file",
1715     G_CALLBACK(cb_menu_export_garmin) },
1716     { NULL, NULL, NULL }
1717     };
1718    
1719     static const submenu_t submenu_export = {
1720     "Export", submenu_export_entries,
1721     sizeof(submenu_export_entries)/sizeof(menu_entry_t)-1
1722     };
1723    
1724     /* the export submenu */
1725     void on_export_clicked(GtkButton *button, appdata_t *appdata) {
1726     if(!appdata->export_menu)
1727     appdata->export_menu = app_submenu_create(appdata, &submenu_export);
1728    
1729     submenu_popup(appdata->export_menu);
1730     }
1731    
1732     static const menu_entry_t submenu_tools_entries[] = {
1733     { "Geomath", "Geocoordinate calculation",
1734     G_CALLBACK(cb_menu_geomath) },
1735     { "Geotext", "Text analysis",
1736     G_CALLBACK(cb_menu_geotext) },
1737     { "Precise Position", "Calculate a precise GPS position",
1738     G_CALLBACK(cb_menu_precpos) },
1739     { NULL, NULL, NULL }
1740     };
1741    
1742     static const submenu_t submenu_tools = {
1743     "Tools", submenu_tools_entries,
1744     sizeof(submenu_tools_entries)/sizeof(menu_entry_t)-1
1745     };
1746    
1747 harbaum 20 /* the tools submenu */
1748     void on_tools_clicked(GtkButton *button, appdata_t *appdata) {
1749     if(!appdata->tools_menu)
1750 harbaum 30 appdata->tools_menu = app_submenu_create(appdata, &submenu_tools);
1751 harbaum 20
1752 harbaum 30 submenu_popup(appdata->tools_menu);
1753 harbaum 20 }
1754    
1755 harbaum 3 HildonAppMenu *menu_create(appdata_t *appdata, int mode) {
1756     GtkWidget *button;
1757     HildonAppMenu *menu = HILDON_APP_MENU(hildon_app_menu_new());
1758    
1759     /* ------- */
1760 harbaum 7 button = gtk_button_new_with_label(_("About"));
1761     g_signal_connect_after(button, "clicked",
1762     G_CALLBACK(cb_menu_about), appdata);
1763     hildon_app_menu_append(menu, GTK_BUTTON(button));
1764    
1765 harbaum 3 button = gtk_button_new_with_label(_("Settings"));
1766     g_signal_connect_after(button, "clicked", G_CALLBACK(cb_menu_settings),
1767     appdata);
1768     hildon_app_menu_append(menu, GTK_BUTTON(button));
1769    
1770     if(mode == MENU_GPXLIST) {
1771     button = gtk_button_new_with_label(_("Import file"));
1772     g_signal_connect_after(button, "clicked",
1773     G_CALLBACK(cb_menu_add), appdata);
1774     hildon_app_menu_append(menu, GTK_BUTTON(button));
1775    
1776 harbaum 7 button = gtk_button_new_with_label(_("Import directory"));
1777 harbaum 3 g_signal_connect_after(button, "clicked",
1778     G_CALLBACK(cb_menu_adddir), appdata);
1779     hildon_app_menu_append(menu, GTK_BUTTON(button));
1780    
1781 harbaum 4 button = gtk_button_new_with_label(_("Export"));
1782     g_signal_connect_after(button, "clicked",
1783     G_CALLBACK(on_export_clicked), appdata);
1784     hildon_app_menu_append(menu, GTK_BUTTON(button));
1785    
1786     button = gtk_button_new_with_label(_("Search"));
1787     g_signal_connect_after(button, "clicked",
1788     G_CALLBACK(cb_menu_search), appdata);
1789     hildon_app_menu_append(menu, GTK_BUTTON(button));
1790     }
1791    
1792 harbaum 5 button = gtk_button_new_with_label(_("Tools"));
1793     g_signal_connect_after(button, "clicked",
1794     G_CALLBACK(on_tools_clicked), appdata);
1795     hildon_app_menu_append(menu, GTK_BUTTON(button));
1796 harbaum 4
1797 harbaum 44 #ifdef ENABLE_OSM_GPS_MAP
1798     button = gtk_button_new_with_label(_("Map"));
1799     g_signal_connect_after(button, "clicked",
1800     G_CALLBACK(cb_menu_map), appdata);
1801     hildon_app_menu_append(menu, GTK_BUTTON(button));
1802     #endif
1803    
1804 harbaum 15 #ifdef HILDON_HELP
1805     button = gtk_button_new_with_label(_("Help"));
1806     g_signal_connect_after(button, "clicked",
1807     G_CALLBACK(cb_menu_help), appdata);
1808     hildon_app_menu_append(menu, GTK_BUTTON(button));
1809     #endif
1810 harbaum 3
1811 harbaum 15 gtk_widget_show_all(GTK_WIDGET(menu));
1812    
1813 harbaum 3 return menu;
1814     }
1815     #else
1816 harbaum 5
1817 harbaum 1 void menu_create(appdata_t *appdata) {
1818     GtkWidget *menu, *item;
1819     menu = gtk_menu_new();
1820    
1821 harbaum 128 #if defined(USE_BREAD_CRUMB_TRAIL) || defined(BCT)
1822 harbaum 1 appdata->menu_import =
1823     #endif
1824     item = gtk_menu_item_new_with_label(_("Import"));
1825     gtk_menu_append(GTK_MENU_SHELL(menu), item);
1826     GtkWidget *submenu = gtk_menu_new();
1827     gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
1828    
1829 harbaum 7 item = gtk_menu_item_new_with_label( _("File") );
1830 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1831     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_add), appdata);
1832    
1833 harbaum 7 item = gtk_menu_item_new_with_label( _("Directory") );
1834 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1835     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_adddir), appdata);
1836    
1837     #ifndef USE_PANNABLE_AREA
1838     gtk_menu_append(GTK_MENU_SHELL(submenu), gtk_separator_menu_item_new());
1839    
1840     appdata->menu_close =
1841     item = gtk_menu_item_new_with_label( _("Close") );
1842     gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1843     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_close), appdata);
1844    
1845     appdata->menu_remove =
1846     item = gtk_menu_item_new_with_label( _("Remove") );
1847     gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1848     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_remove), appdata);
1849     #endif
1850    
1851 harbaum 128 #if defined(USE_BREAD_CRUMB_TRAIL) || defined(BCT)
1852 harbaum 1 appdata->menu_export =
1853     #endif
1854     item = gtk_menu_item_new_with_label(_("Export"));
1855     gtk_menu_append(GTK_MENU_SHELL(menu), item);
1856     submenu = gtk_menu_new();
1857     gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
1858    
1859 harbaum 122 #ifdef ENABLE_MAEMO_MAPPER
1860 harbaum 7 item = gtk_menu_item_new_with_label( _("Maemo Mapper POI") );
1861 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1862     g_signal_connect(item, "activate",
1863     GTK_SIGNAL_FUNC(cb_menu_export_mmpoi), appdata);
1864     #endif
1865    
1866 harbaum 7 item = gtk_menu_item_new_with_label( _("Garmin Field Notes") );
1867 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1868     g_signal_connect(item, "activate",
1869     GTK_SIGNAL_FUNC(cb_menu_export_log), appdata);
1870    
1871 harbaum 7 item = gtk_menu_item_new_with_label( _("Garmin GPX") );
1872 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1873     g_signal_connect(item, "activate",
1874     GTK_SIGNAL_FUNC(cb_menu_export_garmin), appdata);
1875    
1876 harbaum 128 #if defined(USE_BREAD_CRUMB_TRAIL) || defined(BCT)
1877 harbaum 1 appdata->menu_search =
1878     #endif
1879 harbaum 7 item = gtk_menu_item_new_with_label( _("Search") );
1880 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(menu), item);
1881     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_search), appdata);
1882    
1883     gtk_menu_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1884 harbaum 2
1885 harbaum 133 /* ----------- copy'n paste submenu ----------------- */
1886 harbaum 2 #ifndef NO_COPY_N_PASTE
1887 harbaum 1 item = gtk_menu_item_new_with_label(_("Edit"));
1888     gtk_menu_append(GTK_MENU_SHELL(menu), item);
1889     submenu = gtk_menu_new();
1890     gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
1891    
1892     appdata->menu_cut = item = gtk_menu_item_new_with_label( _("Cut") );
1893     gtk_widget_set_sensitive(item, FALSE);
1894     gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1895     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_cut), appdata);
1896     appdata->menu_copy = item = gtk_menu_item_new_with_label( _("Copy") );
1897     gtk_widget_set_sensitive(item, FALSE);
1898     gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1899     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_copy), appdata);
1900     appdata->menu_paste = item = gtk_menu_item_new_with_label( _("Paste") );
1901     gtk_widget_set_sensitive(item, FALSE);
1902     gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1903     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_paste), appdata);
1904 harbaum 2 #endif
1905 harbaum 1
1906 harbaum 3 item = gtk_menu_item_new_with_label( _("Settings") );
1907 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(menu), item);
1908     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_settings),
1909     appdata);
1910    
1911     gtk_menu_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1912    
1913 harbaum 32 #ifdef ENABLE_OSM_GPS_MAP
1914     item = gtk_menu_item_new_with_label( _("Map") );
1915 harbaum 63 gtk_menu_append(GTK_MENU_SHELL(menu), item);
1916 harbaum 32 g_signal_connect(item, "activate",
1917     GTK_SIGNAL_FUNC(cb_menu_map), appdata);
1918     #endif
1919    
1920 harbaum 63 item = gtk_menu_item_new_with_label(_("Tools"));
1921     gtk_menu_append(GTK_MENU_SHELL(menu), item);
1922     submenu = gtk_menu_new();
1923     gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
1924    
1925 harbaum 7 item = gtk_menu_item_new_with_label( _("Geomath") );
1926 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1927     g_signal_connect(item, "activate",
1928     GTK_SIGNAL_FUNC(cb_menu_geomath), appdata);
1929    
1930 harbaum 7 item = gtk_menu_item_new_with_label( _("Geotext") );
1931 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1932     g_signal_connect(item, "activate",
1933     GTK_SIGNAL_FUNC(cb_menu_geotext), appdata);
1934    
1935 harbaum 7 item = gtk_menu_item_new_with_label( _("Precise Position") );
1936 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(submenu), item);
1937     g_signal_connect(item, "activate",
1938     GTK_SIGNAL_FUNC(cb_menu_precpos), appdata);
1939    
1940     gtk_menu_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1941    
1942     #if defined(USE_MAEMO) && defined(HILDON_HELP)
1943 harbaum 7 item = gtk_menu_item_new_with_label( _("Help") );
1944 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(menu), item);
1945     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_help), appdata);
1946     #endif
1947    
1948 harbaum 7 item = gtk_menu_item_new_with_label( _("About") );
1949 harbaum 1 gtk_menu_append(GTK_MENU_SHELL(menu), item);
1950     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_about), appdata);
1951    
1952     #ifndef USE_MAEMO
1953     item = gtk_menu_item_new_with_label( _("Quit") );
1954     gtk_menu_append(GTK_MENU_SHELL(menu), item);
1955     g_signal_connect(item, "activate", GTK_SIGNAL_FUNC(cb_menu_quit), appdata);
1956     #endif
1957    
1958     #ifdef USE_MAEMO
1959     hildon_window_set_menu(appdata->window, GTK_MENU(menu));
1960     #else
1961     /* attach ordinary gtk menu */
1962     GtkWidget *menu_bar = gtk_menu_bar_new();
1963    
1964     GtkWidget *root_menu = gtk_menu_item_new_with_label (_("Menu"));
1965     gtk_widget_show(root_menu);
1966    
1967     gtk_menu_bar_append(menu_bar, root_menu);
1968     gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
1969    
1970     gtk_widget_show(menu_bar);
1971     gtk_box_pack_start(GTK_BOX(appdata->vbox), menu_bar, 0, 0, 0);
1972     #endif
1973     }
1974 harbaum 3 #endif
1975 harbaum 1
1976     /********************* end of menu **********************/
1977    
1978     void cleanup(appdata_t *appdata) {
1979     gpx_free_all(appdata->gpx);
1980     if(appdata->path) free(appdata->path);
1981     if(appdata->image_path) free(appdata->image_path);
1982     if(appdata->search_str) free(appdata->search_str);
1983    
1984 harbaum 30 #ifdef USE_STACKABLE_WINDOW
1985     if(appdata->export_menu) submenu_cleanup(appdata->export_menu);
1986     if(appdata->tools_menu) submenu_cleanup(appdata->tools_menu);
1987     #endif
1988    
1989 harbaum 1 gnome_vfs_shutdown();
1990     icons_free();
1991     gps_release(appdata);
1992    
1993     #ifdef USE_MAEMO
1994     if(appdata->search_results) {
1995     printf("freeing pending search\n");
1996     search_result_free(appdata->search_results);
1997     }
1998    
1999     if(appdata->osso_context)
2000     osso_deinitialize(appdata->osso_context);
2001    
2002     appdata->program = NULL;
2003     #endif
2004    
2005     /* free chain of locations */
2006     location_t *loc = appdata->location;
2007     while(loc) {
2008     location_t *next = loc->next;
2009     if(loc->name) free(loc->name);
2010     free(loc);
2011     loc = next;
2012     }
2013    
2014     puts("everything is gone");
2015     }
2016    
2017 harbaum 40 static void on_window_destroy (GtkWidget *widget, gpointer data) {
2018 harbaum 1 appdata_t *appdata = (appdata_t*)data;
2019    
2020     gconf_save_state(appdata);
2021     gtk_main_quit();
2022     appdata->window = NULL;
2023     }
2024    
2025     gboolean on_window_key_press(GtkWidget *widget,
2026 harbaum 11 GdkEventKey *event, appdata_t *appdata) {
2027 harbaum 1 int handled = FALSE;
2028    
2029     // printf("key event %d\n", event->keyval);
2030    
2031     switch(event->keyval) {
2032     #ifdef USE_MAEMO
2033    
2034     #ifdef HILDON_HARDKEY_INCREASE
2035     case HILDON_HARDKEY_INCREASE:
2036     html_zoom(appdata, TRUE);
2037     handled = TRUE;
2038     break;
2039     #endif
2040    
2041     #ifdef HILDON_HARDKEY_DECREASE
2042     case HILDON_HARDKEY_DECREASE:
2043     html_zoom(appdata, FALSE);
2044     handled = TRUE;
2045     break;
2046     #endif
2047    
2048     #ifdef HILDON_HARDKEY_FULLSCREEN
2049     case HILDON_HARDKEY_FULLSCREEN:
2050     {
2051     appdata->fullscreen = !appdata->fullscreen;
2052    
2053     if(appdata->fullscreen)
2054     gtk_window_fullscreen(GTK_WINDOW(appdata->window));
2055     else
2056     gtk_window_unfullscreen(GTK_WINDOW(appdata->window));
2057    
2058     handled = TRUE;
2059     }
2060     break;
2061     #endif
2062    
2063     #else
2064     case '+':
2065     printf("zoom+\n");
2066     html_zoom(appdata, TRUE);
2067     handled = TRUE;
2068     break;
2069     case '-':
2070     printf("zoom-\n");
2071     html_zoom(appdata, FALSE);
2072     handled = TRUE;
2073     break;
2074     #endif
2075     }
2076    
2077     return handled;
2078     }
2079    
2080 harbaum 128 #if defined(USE_BREAD_CRUMB_TRAIL) || defined(BCT)
2081 harbaum 1 typedef struct {
2082     int level;
2083     appdata_t *appdata;
2084     gpointer data;
2085     } crumb_t;
2086    
2087     static void
2088     crumb_back(gpointer data) {
2089     crumb_t *crumb = (crumb_t*)data;
2090     printf("crumb_back called with %d\n", crumb->level);
2091    
2092     /* don't do anything if main window has already been destroyed */
2093     if(!crumb->appdata->window) {
2094     printf("Main window gone ...\n");
2095     return;
2096     }
2097    
2098     /* whatever is being displayed: we don't need it anymore */
2099     gtk_container_remove(GTK_CONTAINER(crumb->appdata->vbox),
2100     crumb->appdata->cur_view);
2101    
2102     /* back from cache to cachelist */
2103     if(crumb->level == CRUMB_CACHE) {
2104     gpx_t *gpx = crumb->appdata->search_results;
2105    
2106     if(!gpx) {
2107     gtk_widget_set_sensitive(crumb->appdata->menu_search, TRUE);
2108     gtk_widget_set_sensitive(crumb->appdata->menu_export, TRUE);
2109     printf("no search data found, return to gpx\n");
2110     gpx = crumb->appdata->cur_gpx;
2111     } else
2112     printf("returning to search result\n");
2113    
2114     g_assert(gpx != NULL);
2115    
2116     crumb->appdata->cur_view = cachelist_create(crumb->appdata, gpx,
2117     crumb->appdata->cur_cache);
2118    
2119     /* returning from cache view: invalidate cache reference */
2120     crumb->appdata->cur_cache = NULL;
2121    
2122     gtk_box_pack_start_defaults(GTK_BOX(crumb->appdata->vbox),
2123     crumb->appdata->cur_view);
2124     }
2125    
2126     if(crumb->level == CRUMB_SEARCH_GPX) {
2127     printf("returning from a local search!\n");
2128    
2129     g_assert((gpx_t*)crumb->data == crumb->appdata->search_results);
2130    
2131     search_result_free((gpx_t*)crumb->data);
2132     crumb->appdata->search_results = NULL;
2133    
2134     gtk_widget_set_sensitive(crumb->appdata->menu_search, TRUE);
2135    
2136     crumb->appdata->cur_view = cachelist_create(crumb->appdata,
2137     crumb->appdata->cur_gpx, NULL);
2138     gtk_box_pack_start_defaults(GTK_BOX(crumb->appdata->vbox),
2139     crumb->appdata->cur_view);
2140     }
2141    
2142     /* back from cachelist to gpxlist */
2143     if((crumb->level == CRUMB_CACHELIST) ||
2144     (crumb->level == CRUMB_SEARCH_GLOBAL)) {
2145    
2146     crumb->appdata->cur_view = gpxlist_create_view_and_model(
2147     crumb->appdata, crumb->appdata->cur_gpx);
2148    
2149     /* returning from cachelist/global search view: */
2150     /* invalidate gpx reference */
2151     crumb->appdata->cur_gpx = NULL;
2152    
2153     gtk_box_pack_start_defaults(GTK_BOX(crumb->appdata->vbox),
2154     crumb->appdata->cur_view);
2155    
2156     if((crumb->level == CRUMB_SEARCH_GLOBAL) ||
2157     (crumb->level == CRUMB_SEARCH_GPX)) {
2158     g_assert((gpx_t*)crumb->data == crumb->appdata->search_results);
2159    
2160     search_result_free((gpx_t*)crumb->data);
2161     crumb->appdata->search_results = NULL;
2162     }
2163    
2164     /* enable gpxlist related menu entries */
2165     gtk_widget_set_sensitive(crumb->appdata->menu_import, TRUE);
2166     gtk_widget_set_sensitive(crumb->appdata->menu_search, TRUE);
2167     gtk_widget_set_sensitive(crumb->appdata->menu_export, TRUE);
2168     }
2169    
2170     gtk_widget_show_all(crumb->appdata->vbox);
2171     g_free(data);
2172 harbaum 130
2173     #ifdef ENABLE_OSM_GPS_MAP
2174     map_update(crumb->appdata);
2175     #endif
2176 harbaum 1 }
2177    
2178     static void crumb_add(appdata_t *appdata, char *name, int level,
2179     gpointer user_data) {
2180     crumb_t *crumb = malloc(sizeof(crumb_t));
2181     crumb->level = level;
2182     crumb->appdata = appdata;
2183     crumb->data = user_data;
2184    
2185     printf("crumb_add with level %d\n", level);
2186    
2187     /* save that we are working on search results */
2188     if((level == CRUMB_SEARCH_GLOBAL) ||
2189     (level == CRUMB_SEARCH_GPX)) {
2190     appdata->search_results = (gpx_t*)user_data;
2191    
2192     /* searches cannot be nested */
2193     gtk_widget_set_sensitive(appdata->menu_search, FALSE);
2194     }
2195    
2196     /* save "path" pointers in appdata */
2197     if(crumb->level == CRUMB_CACHELIST)
2198     appdata->cur_gpx = (gpx_t*)user_data;
2199    
2200     if(crumb->level == CRUMB_CACHE) {
2201     appdata->cur_cache = (cache_t*)user_data;
2202     /* the cache view cannot be searched */
2203     gtk_widget_set_sensitive(appdata->menu_search, FALSE);
2204     gtk_widget_set_sensitive(appdata->menu_export, FALSE);
2205     }
2206    
2207     if(level != CRUMB_GPXLIST) {
2208     /* disable gpxlist related menu entries */
2209     gtk_widget_set_sensitive(appdata->menu_import, FALSE);
2210     #ifndef USE_PANNABLE_AREA
2211     gtk_widget_set_sensitive(appdata->menu_remove, FALSE);
2212     gtk_widget_set_sensitive(appdata->menu_close, FALSE);
2213     #endif
2214     }
2215    
2216 harbaum 126 #ifdef USE_BREAD_CRUMB_TRAIL
2217 harbaum 1 hildon_bread_crumb_trail_push_text(HILDON_BREAD_CRUMB_TRAIL(appdata->bct),
2218     name, crumb, (GDestroyNotify)crumb_back);
2219 harbaum 126 #else
2220 harbaum 128 bct_push_text(appdata->bct, name, crumb, (GDestroyNotify)crumb_back);
2221 harbaum 126 #endif
2222 harbaum 130
2223     #ifdef ENABLE_OSM_GPS_MAP
2224     map_update(appdata);
2225     #endif
2226 harbaum 1 }
2227     #endif // USE_BREAD_CRUMB_TRAIL
2228    
2229     void main_after_settings_redraw(appdata_t *appdata, int flags) {
2230 harbaum 11 printf("main after settings redraw\n");
2231    
2232     if(!appdata->cur_view) {
2233     printf("no active view\n");
2234     return;
2235     }
2236    
2237 harbaum 1 /* a cache screen cannot be changed from the settings and thus doesn't */
2238     /* need to be redrawn */
2239     if(appdata->cur_cache) {
2240     printf("No redraw in cache view required\n");
2241     return;
2242     }
2243    
2244     int redraw = 0; // nothing to redraw
2245    
2246     if(appdata->search_results) {
2247     if((appdata->cur_items != appdata->cachelist_items) || flags)
2248     redraw = 1;
2249     } else {
2250     if(!appdata->cur_gpx) {
2251     if(appdata->cur_items != appdata->gpxlist_items)
2252     redraw = 2; // redraw gpxlist
2253     } else {
2254     if((appdata->cur_items != appdata->cachelist_items) || flags)
2255     redraw = 3; // redraw cachelist
2256     }
2257     }
2258    
2259     if(redraw) {
2260 harbaum 11 GtkWidget *container = appdata->vbox;
2261    
2262     #ifdef USE_STACKABLE_WINDOW
2263     HildonWindowStack *stack = hildon_window_stack_get_default();
2264     container = hildon_window_stack_peek(stack);
2265     #endif
2266    
2267     gtk_container_remove(GTK_CONTAINER(container), appdata->cur_view);
2268 harbaum 1 switch(redraw) {
2269     case 1:
2270     appdata->cur_view = cachelist_create(appdata,
2271     appdata->search_results, NULL);
2272     break;
2273     case 2:
2274     appdata->cur_view = gpxlist_create_view_and_model(appdata, NULL);
2275     break;
2276     case 3:
2277     appdata->cur_view = cachelist_create(appdata,
2278     appdata->cur_gpx, NULL);
2279     break;
2280     }
2281    
2282 harbaum 11 #ifdef USE_STACKABLE_WINDOW
2283     if(container != appdata->vbox)
2284     gtk_container_add(GTK_CONTAINER(container), appdata->cur_view);
2285     else
2286     #endif
2287     gtk_box_pack_start_defaults(GTK_BOX(container), appdata->cur_view);
2288    
2289     gtk_widget_show_all(container);
2290 harbaum 1 }
2291     }
2292    
2293     int main(int argc, char *argv[]) {
2294     appdata_t appdata;
2295    
2296     /* init appdata */
2297     memset(&appdata, 0, sizeof(appdata));
2298    
2299     printf("Using locale for %s in %s\n", PACKAGE, LOCALEDIR);
2300    
2301     setlocale(LC_ALL, "");
2302     bindtextdomain(PACKAGE, LOCALEDIR);
2303     bind_textdomain_codeset(PACKAGE, "UTF-8");
2304     textdomain(PACKAGE);
2305    
2306     /* prepare thread system */
2307     g_thread_init(NULL);
2308    
2309     gtk_init (&argc, &argv);
2310    
2311 harbaum 157 curl_global_init(CURL_GLOBAL_ALL);
2312    
2313 harbaum 1 #ifdef USE_MAEMO
2314     printf("Installing osso context for \"org.harbaum." APP "\"\n");
2315     appdata.osso_context = osso_initialize("org.harbaum."APP,
2316     VERSION, TRUE, NULL);
2317     if(appdata.osso_context == NULL) {
2318     fprintf(stderr, "error initiating osso context\n");
2319     }
2320    
2321 harbaum 122 #ifdef ENABLE_MAEMO_MAPPER
2322 harbaum 1 dbus_register(&appdata);
2323     #endif
2324 harbaum 122 #endif
2325 harbaum 1
2326     icons_init();
2327    
2328     if(!gnome_vfs_init()) {
2329     g_error("Gnome VFS init failed\n");
2330     }
2331    
2332     #ifdef USE_MAEMO
2333     /* Create the hildon program and setup the title */
2334     appdata.program = HILDON_PROGRAM(hildon_program_get_instance());
2335     g_set_application_name("GPXView");
2336    
2337     /* Create HildonWindow and set it to HildonProgram */
2338     #ifdef USE_STACKABLE_WINDOW
2339     appdata.window = HILDON_WINDOW(hildon_stackable_window_new());
2340     #else
2341     appdata.window = HILDON_WINDOW(hildon_window_new());
2342     #endif
2343     hildon_program_add_window(appdata.program, appdata.window);
2344     #else
2345     /* Create a Window. */
2346     appdata.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2347     /* Set a decent default size for the window. */
2348 harbaum 129 gtk_window_set_default_size(GTK_WINDOW(appdata.window), 640, 480);
2349 harbaum 1 #endif
2350    
2351 harbaum 12 #if MAEMO_VERSION_MAJOR == 5
2352 harbaum 1 gtk_window_set_title(GTK_WINDOW(appdata.window), "GPXView");
2353 harbaum 12 #endif
2354    
2355 harbaum 1 g_signal_connect(G_OBJECT(appdata.window), "destroy",
2356     G_CALLBACK(on_window_destroy), &appdata);
2357    
2358     g_signal_connect(G_OBJECT(appdata.window), "key_press_event",
2359     G_CALLBACK(on_window_key_press), &appdata);
2360    
2361 harbaum 133 /* prepare clipboard */
2362     appdata.clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
2363     gtk_clipboard_set_can_store(appdata.clipboard, NULL, 0);
2364    
2365 harbaum 1 appdata.vbox = gtk_vbox_new(FALSE, 2);
2366     gtk_container_add(GTK_CONTAINER(appdata.window), appdata.vbox);
2367 harbaum 3 #ifndef USE_STACKABLE_WINDOW
2368 harbaum 1 menu_create(&appdata);
2369 harbaum 3 #else
2370     hildon_window_set_app_menu(HILDON_WINDOW(appdata.window),
2371     menu_create(&appdata, MENU_GPXLIST));
2372     #endif
2373 harbaum 1
2374     #ifdef USE_BREAD_CRUMB_TRAIL
2375     appdata.bct = hildon_bread_crumb_trail_new();
2376    
2377     gtk_box_pack_start(GTK_BOX(appdata.vbox), appdata.bct, FALSE,FALSE,0);
2378    
2379     hildon_bread_crumb_trail_clear(HILDON_BREAD_CRUMB_TRAIL(appdata.bct));
2380 harbaum 126 #else
2381 harbaum 128 #ifdef BCT
2382 harbaum 126 /* on non-hildon machines we use some custom made breadcrumbtrail */
2383     /* replacement */
2384 harbaum 128 appdata.bct = bct_new();
2385 harbaum 126 gtk_box_pack_start(GTK_BOX(appdata.vbox), appdata.bct, FALSE,FALSE,0);
2386 harbaum 1 #endif
2387 harbaum 126 #endif
2388 harbaum 1
2389 harbaum 128 #if defined(USE_BREAD_CRUMB_TRAIL) || defined(BCT)
2390     crumb_add(&appdata, "GPX", CRUMB_GPXLIST, NULL);
2391     #endif
2392    
2393 harbaum 1 /* wait for main gui to appear */
2394     gtk_widget_show_all(GTK_WIDGET(appdata.window));
2395     while(gtk_events_pending())
2396     gtk_main_iteration();
2397    
2398     appdata.gconf_client = gconf_client_get_default();
2399     gconf_load_state(&appdata);
2400     gps_init(&appdata);
2401    
2402     appdata.cur_view = gpxlist_create_view_and_model(&appdata, NULL);
2403     gtk_box_pack_start_defaults(GTK_BOX(appdata.vbox), appdata.cur_view);
2404    
2405     gtk_widget_show_all(GTK_WIDGET(appdata.window));
2406     gtk_main();
2407    
2408     cleanup(&appdata);
2409    
2410     return 0;
2411     }