Contents of /trunk/src/project.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 45 - (hide annotations)
Mon Jan 26 23:47:27 2009 UTC (15 years, 4 months ago) by achadwick
File MIME type: text/plain
File size: 38676 byte(s)
Show projects' statuses in Open... dialog
1 harbaum 1 /*
2     * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of OSM2Go.
5     *
6     * OSM2Go is free software: you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * OSM2Go 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 OSM2Go. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include "appdata.h"
21 achadwick 28 #include "banner.h"
22 harbaum 1
23     #include <sys/stat.h>
24    
25     #include <libxml/parser.h>
26     #include <libxml/tree.h>
27    
28     #if !defined(LIBXML_TREE_ENABLED) || !defined(LIBXML_OUTPUT_ENABLED)
29     #error "libxml doesn't support required tree or output"
30     #endif
31    
32     typedef struct {
33     // appdata_t *appdata;
34     project_t *project;
35     GtkWidget *dialog, *fsize, *diff_stat, *diff_remove;
36     GtkWidget *desc, *server;
37     GtkWidget *minlat, *minlon, *maxlat, *maxlon;
38     area_edit_t area_edit;
39     } project_context_t;
40    
41     /* ------------ project file io ------------- */
42    
43     static gboolean project_read(appdata_t *appdata,
44     char *project_file, project_t *project) {
45    
46     LIBXML_TEST_VERSION;
47    
48     xmlDoc *doc = NULL;
49     xmlNode *root_element = NULL;
50    
51     /* parse the file and get the DOM */
52     if((doc = xmlReadFile(project_file, NULL, 0)) == NULL) {
53     printf("error: could not parse file %s\n", project_file);
54     return FALSE;
55     }
56    
57     /* Get the root element node */
58     root_element = xmlDocGetRootElement(doc);
59    
60     xmlNode *cur_node = NULL;
61     for (cur_node = root_element; cur_node; cur_node = cur_node->next) {
62     if (cur_node->type == XML_ELEMENT_NODE) {
63     if(strcasecmp((char*)cur_node->name, "proj") == 0) {
64     char *str;
65    
66     if((str = (char*)xmlGetProp(cur_node, BAD_CAST "dirty"))) {
67     project->data_dirty = (strcasecmp(str, "true") == 0);
68     xmlFree(str);
69     } else
70     project->data_dirty = FALSE;
71    
72     xmlNode *node = cur_node->children;
73    
74     while(node != NULL) {
75     if(node->type == XML_ELEMENT_NODE) {
76    
77     if(strcasecmp((char*)node->name, "desc") == 0) {
78     str = (char*)xmlNodeListGetString(doc, node->children, 1);
79     project->desc = g_strdup(str);
80     printf("desc = %s\n", project->desc);
81     xmlFree(str);
82    
83     } else if(strcasecmp((char*)node->name, "server") == 0) {
84     str = (char*)xmlNodeListGetString(doc, node->children, 1);
85     project->server = g_strdup(str);
86     printf("server = %s\n", project->server);
87     xmlFree(str);
88    
89     } else if(project->map_state &&
90     strcasecmp((char*)node->name, "map") == 0) {
91     if((str = (char*)xmlGetProp(node, BAD_CAST "zoom"))) {
92     project->map_state->zoom = g_ascii_strtod(str, NULL);
93     xmlFree(str);
94     }
95     if((str = (char*)xmlGetProp(node, BAD_CAST "scroll-offset-x"))) {
96     project->map_state->scroll_offset.x = strtoul(str, NULL, 10);
97     xmlFree(str);
98     }
99     if((str = (char*)xmlGetProp(node, BAD_CAST "scroll-offset-y"))) {
100     project->map_state->scroll_offset.y = strtoul(str, NULL, 10);
101     xmlFree(str);
102     }
103    
104     } else if(strcasecmp((char*)node->name, "wms") == 0) {
105    
106     if((str = (char*)xmlGetProp(node, BAD_CAST "server"))) {
107     project->wms_server = g_strdup(str);
108     xmlFree(str);
109     }
110     if((str = (char*)xmlGetProp(node, BAD_CAST "path"))) {
111     project->wms_path = g_strdup(str);
112     xmlFree(str);
113     }
114     if((str = (char*)xmlGetProp(node, BAD_CAST "x-offset"))) {
115     project->wms_offset.x = strtoul(str, NULL, 10);
116     xmlFree(str);
117     }
118     if((str = (char*)xmlGetProp(node, BAD_CAST "y-offset"))) {
119     project->wms_offset.y = strtoul(str, NULL, 10);
120     xmlFree(str);
121     }
122    
123     } else if(strcasecmp((char*)node->name, "osm") == 0) {
124     str = (char*)xmlNodeListGetString(doc, node->children, 1);
125     project->osm = g_strdup(str);
126     printf("osm = %s\n", project->osm);
127     xmlFree(str);
128     } else if(strcasecmp((char*)node->name, "min") == 0) {
129     if((str = (char*)xmlGetProp(node, BAD_CAST "lat"))) {
130     project->min.lat = g_ascii_strtod(str, NULL);
131     xmlFree(str);
132     }
133     if((str = (char*)xmlGetProp(node, BAD_CAST "lon"))) {
134     project->min.lon = g_ascii_strtod(str, NULL);
135     xmlFree(str);
136     }
137    
138     } else if(strcasecmp((char*)node->name, "max") == 0) {
139     if((str = (char*)xmlGetProp(node, BAD_CAST "lat"))) {
140     project->max.lat = g_ascii_strtod(str, NULL);
141     xmlFree(str);
142     }
143     if((str = (char*)xmlGetProp(node, BAD_CAST "lon"))) {
144     project->max.lon = g_ascii_strtod(str, NULL);
145     xmlFree(str);
146     }
147     }
148     }
149     node = node->next;
150     }
151     }
152     }
153     }
154    
155     xmlFreeDoc(doc);
156     xmlCleanupParser();
157    
158     return TRUE;
159     }
160    
161     gboolean project_save(GtkWidget *parent, project_t *project) {
162     char str[32];
163     char *project_file = g_strdup_printf("%s%s.proj",
164     project->path, project->name);
165    
166     printf("saving project to %s\n", project_file);
167    
168     /* check if project path exists */
169     if(!g_file_test(project->path, G_FILE_TEST_IS_DIR)) {
170     /* make sure project base path exists */
171     if(g_mkdir_with_parents(project->path, S_IRWXU) != 0) {
172     errorf(GTK_WIDGET(parent),
173     _("Unable to create project path %s"), project->path);
174     return FALSE;
175     }
176     }
177    
178     LIBXML_TEST_VERSION;
179    
180     xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
181     xmlNodePtr node, root_node = xmlNewNode(NULL, BAD_CAST "proj");
182     xmlNewProp(root_node, BAD_CAST "name", BAD_CAST project->name);
183     if(project->data_dirty)
184     xmlNewProp(root_node, BAD_CAST "dirty", BAD_CAST "true");
185    
186     xmlDocSetRootElement(doc, root_node);
187    
188     node = xmlNewChild(root_node, NULL, BAD_CAST "server",
189     BAD_CAST project->server);
190    
191     xmlNewChild(root_node, NULL, BAD_CAST "desc", BAD_CAST project->desc);
192     xmlNewChild(root_node, NULL, BAD_CAST "osm", BAD_CAST project->osm);
193    
194     node = xmlNewChild(root_node, NULL, BAD_CAST "min", NULL);
195     g_ascii_dtostr(str, sizeof(str), project->min.lat);
196     xmlNewProp(node, BAD_CAST "lat", BAD_CAST str);
197     g_ascii_dtostr(str, sizeof(str), project->min.lon);
198     xmlNewProp(node, BAD_CAST "lon", BAD_CAST str);
199    
200     node = xmlNewChild(root_node, NULL, BAD_CAST "max", NULL);
201     g_ascii_dtostr(str, sizeof(str), project->max.lat);
202     xmlNewProp(node, BAD_CAST "lat", BAD_CAST str);
203     g_ascii_dtostr(str, sizeof(str), project->max.lon);
204     xmlNewProp(node, BAD_CAST "lon", BAD_CAST str);
205    
206     if(project->map_state) {
207     node = xmlNewChild(root_node, NULL, BAD_CAST "map", BAD_CAST NULL);
208     g_ascii_dtostr(str, sizeof(str), project->map_state->zoom);
209     xmlNewProp(node, BAD_CAST "zoom", BAD_CAST str);
210     snprintf(str, sizeof(str), "%d", project->map_state->scroll_offset.x);
211     xmlNewProp(node, BAD_CAST "scroll-offset-x", BAD_CAST str);
212     snprintf(str, sizeof(str), "%d", project->map_state->scroll_offset.y);
213     xmlNewProp(node, BAD_CAST "scroll-offset-y", BAD_CAST str);
214     }
215    
216     node = xmlNewChild(root_node, NULL, BAD_CAST "wms", NULL);
217 harbaum 14 if(project->wms_server)
218     xmlNewProp(node, BAD_CAST "server", BAD_CAST project->wms_server);
219     if(project->wms_path)
220     xmlNewProp(node, BAD_CAST "path", BAD_CAST project->wms_path);
221 harbaum 1 snprintf(str, sizeof(str), "%d", project->wms_offset.x);
222     xmlNewProp(node, BAD_CAST "x-offset", BAD_CAST str);
223     snprintf(str, sizeof(str), "%d", project->wms_offset.y);
224     xmlNewProp(node, BAD_CAST "y-offset", BAD_CAST str);
225    
226     xmlSaveFormatFileEnc(project_file, doc, "UTF-8", 1);
227     xmlFreeDoc(doc);
228     xmlCleanupParser();
229    
230     g_free(project_file);
231    
232     return TRUE;
233     }
234    
235     /* ------------ freeing projects --------------------- */
236    
237     void project_free(project_t *project) {
238     if(!project) return;
239    
240     if(project->name) g_free(project->name);
241     if(project->desc) g_free(project->desc);
242     if(project->server) g_free(project->server);
243    
244     if(project->wms_server) g_free(project->wms_server);
245     if(project->wms_path) g_free(project->wms_path);
246    
247     if(project->path) g_free(project->path);
248     if(project->osm) g_free(project->osm);
249    
250     map_state_free(project->map_state);
251    
252     g_free(project);
253     }
254    
255     /* ------------ project selection dialog ------------- */
256    
257     static char *project_fullname(settings_t *settings, const char *name) {
258     return g_strdup_printf("%s%s/%s.proj", settings->base_path, name, name);
259     }
260    
261     static gboolean project_exists(settings_t *settings, const char *name) {
262     gboolean ok = FALSE;
263     char *fulldir = g_strdup_printf("%s%s", settings->base_path, name);
264    
265     if(g_file_test(fulldir, G_FILE_TEST_IS_DIR)) {
266    
267     /* check for project file */
268     char *fullname = project_fullname(settings, name);
269    
270     if(g_file_test(fullname, G_FILE_TEST_IS_REGULAR))
271     ok = TRUE;
272    
273     g_free(fullname);
274     }
275     g_free(fulldir);
276    
277     return ok;
278     }
279    
280     static project_t *project_scan(appdata_t *appdata) {
281     project_t *projects = NULL, **current = &projects;
282    
283     /* scan for projects */
284     GDir *dir = g_dir_open(appdata->settings->base_path, 0, NULL);
285     const char *name = NULL;
286     do {
287     if((name = g_dir_read_name(dir))) {
288     if(project_exists(appdata->settings, name)) {
289     printf("found project %s\n", name);
290    
291     /* try to read project and append it to chain */
292     *current = g_new0(project_t, 1);
293     (*current)->name = g_strdup(name);
294     (*current)->path = g_strdup_printf("%s%s/",
295     appdata->settings->base_path, name);
296    
297     char *fullname = project_fullname(appdata->settings, name);
298     if(project_read(appdata, fullname, *current))
299     current = &((*current)->next);
300     else {
301     g_free(*current);
302     *current = NULL;
303     }
304     g_free(fullname);
305     }
306     }
307     } while(name);
308    
309     g_dir_close(dir);
310    
311     return projects;
312     }
313    
314     typedef struct {
315     project_t *project;
316     GtkWidget *dialog, *view;
317     GtkWidget *but_new, *but_edit, *but_remove;
318     settings_t *settings;
319     #ifdef USE_HILDON
320     dbus_mm_pos_t *mmpos;
321     osso_context_t *osso_context;
322     #endif
323     } select_context_t;
324    
325     enum {
326     PROJECT_COL_NAME = 0,
327 achadwick 45 PROJECT_COL_STATUS,
328 harbaum 1 PROJECT_COL_DESCRIPTION,
329     PROJECT_COL_DATA,
330     PROJECT_NUM_COLS
331     };
332    
333     static void view_selected(select_context_t *context, project_t *project) {
334     gtk_widget_set_sensitive(context->but_remove, project != NULL);
335     gtk_widget_set_sensitive(context->but_edit, project != NULL);
336    
337     /* check if the selected project also has a valid osm file */
338     gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),
339     GTK_RESPONSE_ACCEPT,
340     project && g_file_test(project->osm, G_FILE_TEST_IS_REGULAR));
341     }
342    
343     static gboolean
344     view_selection_func(GtkTreeSelection *selection, GtkTreeModel *model,
345     GtkTreePath *path, gboolean path_currently_selected,
346     gpointer userdata) {
347     select_context_t *context = (select_context_t*)userdata;
348     GtkTreeIter iter;
349    
350     if(gtk_tree_model_get_iter(model, &iter, path)) {
351     project_t *project = NULL;
352     gtk_tree_model_get(model, &iter, PROJECT_COL_DATA, &project, -1);
353     g_assert(gtk_tree_path_get_depth(path) == 1);
354    
355     view_selected(context, project);
356     }
357    
358     return TRUE; /* allow selection state to change */
359     }
360    
361     /* get the currently selected project in the list, NULL if none */
362     static project_t *project_get_selected(GtkWidget *view) {
363     project_t *project = NULL;
364     GtkTreeModel *model;
365     GtkTreeIter iter;
366    
367     GtkTreeSelection *selection =
368     gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
369     g_assert(gtk_tree_selection_get_selected(selection, &model, &iter));
370     gtk_tree_model_get(model, &iter, PROJECT_COL_DATA, &project, -1);
371    
372     return project;
373     }
374    
375     /* ------------------------- create a new project ---------------------- */
376    
377     /* returns true of str contains one of the characters in chars */
378     static gboolean strchrs(char *str, char *chars) {
379     while(*chars) {
380     char *p = str;
381     while(*p) {
382     if(*p == *chars)
383     return TRUE;
384    
385     p++;
386     }
387     chars++;
388     }
389     return FALSE;
390     }
391    
392     typedef struct {
393     GtkWidget *dialog;
394     settings_t *settings;
395     } name_callback_context_t;
396    
397     static void callback_modified_name(GtkWidget *widget, gpointer data) {
398     name_callback_context_t *context = (name_callback_context_t*)data;
399    
400     char *name = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
401    
402     /* name must not contain some special chars */
403     gboolean ok = FALSE;
404    
405     /* check if there's a name */
406     if(name && strlen(name) > 0) {
407     /* check if it consists of valid characters */
408     if(!strchrs(name, "\\*?()\n\t\r")) {
409     /* check if such a project already exists */
410     if(!project_exists(context->settings, name))
411     ok = TRUE;
412     }
413     }
414    
415     gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),
416     GTK_RESPONSE_ACCEPT, ok);
417     }
418    
419    
420     gboolean project_delete(select_context_t *context, project_t *project) {
421    
422     /* remove entire directory from disk */
423     GDir *dir = g_dir_open(project->path, 0, NULL);
424     const char *name = NULL;
425     do {
426     if((name = g_dir_read_name(dir))) {
427     char *fullname = g_strdup_printf("%s/%s", project->path, name);
428     g_remove(fullname);
429     g_free(fullname);
430     }
431     } while(name);
432    
433     /* remove the projects directory */
434     g_remove(project->path);
435    
436     /* remove from view */
437     GtkTreeIter iter;
438     GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(context->view));
439     gboolean deleted = FALSE;
440     if(gtk_tree_model_get_iter_first(model, &iter)) {
441     do {
442     project_t *prj = NULL;
443     gtk_tree_model_get(model, &iter, PROJECT_COL_DATA, &prj, -1);
444     if(prj && (prj == project)) {
445     printf("found %s to remove\n", prj->name);
446     /* and remove from store */
447     gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
448     deleted = TRUE;
449     }
450     } while(!deleted && gtk_tree_model_iter_next(model, &iter));
451     }
452    
453     /* de-chain entry from project list */
454     project_t **project_list = &context->project;
455     while(*project_list) {
456     if(*project_list == project)
457     *project_list = (*project_list)->next;
458     else
459     project_list = &((*project_list)->next);
460     }
461    
462     /* free project structure */
463     project_free(project);
464    
465     /* disable edit/remove buttons */
466     view_selected(context, NULL);
467    
468     return TRUE;
469     }
470    
471     project_t *project_new(select_context_t *context) {
472     printf("creating project with default values\n");
473    
474     /* -------------- first choose a name for the project --------------- */
475     GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Project name"),
476     GTK_WINDOW(context->dialog), GTK_DIALOG_MODAL,
477     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
478     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
479     NULL);
480    
481     GtkWidget *hbox = gtk_hbox_new(FALSE, 8);
482     gtk_box_pack_start_defaults(GTK_BOX(hbox), gtk_label_new(_("Name:")));
483    
484     name_callback_context_t name_context = { dialog, context->settings };
485     GtkWidget *entry = gtk_entry_new();
486     // gtk_entry_set_text(GTK_ENTRY(entry), "<enter name>");
487     gtk_box_pack_start_defaults(GTK_BOX(hbox), entry);
488     g_signal_connect(G_OBJECT(entry), "changed",
489     G_CALLBACK(callback_modified_name), &name_context);
490    
491     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
492    
493     /* don't all user to click ok until something useful has been entered */
494     gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
495     GTK_RESPONSE_ACCEPT, FALSE);
496    
497     gtk_widget_show_all(dialog);
498     if(GTK_RESPONSE_ACCEPT != gtk_dialog_run(GTK_DIALOG(dialog))) {
499     gtk_widget_destroy(dialog);
500     return NULL;
501     }
502    
503     project_t *project = g_new0(project_t, 1);
504     project->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
505     gtk_widget_destroy(dialog);
506    
507    
508     project->path = g_strdup_printf("%s%s/",
509     context->settings->base_path, project->name);
510     project->desc = g_strdup(_("<project description>"));
511    
512     /* no data downloaded yet */
513     project->data_dirty = TRUE;
514    
515     /* use global server/access settings */
516     project->server = g_strdup(context->settings->server);
517    
518     /* build project osm file name */
519     project->osm = g_strdup_printf("%s%s.osm", project->path, project->name);
520    
521     /* around the castle in karlsruhe, germany ... */
522     project->min.lat = 49.005; project->min.lon = 8.3911;
523     project->max.lat = 49.023; project->max.lon = 8.4185;
524    
525     /* create project file on disk */
526     project_save(context->dialog, project);
527    
528     #ifdef USE_HILDON
529     if(!project_edit(context->dialog, project, context->mmpos,
530     context->osso_context))
531     #else
532     if(!project_edit(context->dialog, project))
533     #endif
534     {
535     printf("edit cancelled!!\n");
536    
537     project_delete(context, project);
538    
539     project = NULL;
540     }
541    
542 harbaum 14 /* enable/disable edit/remove buttons */
543     view_selected(context, project);
544    
545 harbaum 1 return project;
546     }
547    
548 achadwick 45 // predecs
549     void project_get_status_icon_stock_id(project_t *project, gchar **stock_id);
550    
551 harbaum 1 static void on_project_new(GtkButton *button, gpointer data) {
552     select_context_t *context = (select_context_t*)data;
553     project_t **project = &context->project;
554     *project = project_new(context);
555     if(*project) {
556    
557     GtkTreeModel *model =
558     gtk_tree_view_get_model(GTK_TREE_VIEW(context->view));
559    
560     GtkTreeIter iter;
561 achadwick 45 gchar *status_stock_id = NULL;
562     project_get_status_icon_stock_id(*project, &status_stock_id);
563 harbaum 1 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
564     gtk_list_store_set(GTK_LIST_STORE(model), &iter,
565     PROJECT_COL_NAME, (*project)->name,
566 achadwick 45 PROJECT_COL_STATUS, status_stock_id,
567 harbaum 1 PROJECT_COL_DESCRIPTION, (*project)->desc,
568     PROJECT_COL_DATA, *project,
569     -1);
570    
571     GtkTreeSelection *selection =
572     gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view));
573     gtk_tree_selection_select_iter(selection, &iter);
574     }
575     }
576    
577     static void on_project_delete(GtkButton *button, gpointer data) {
578     select_context_t *context = (select_context_t*)data;
579     project_t *project = project_get_selected(context->view);
580    
581     char *str = g_strdup_printf(_("Do you really want to delete the "
582     "project \"%s\"?"), project->name);
583     GtkWidget *dialog = gtk_message_dialog_new(
584     GTK_WINDOW(context->dialog),
585     GTK_DIALOG_DESTROY_WITH_PARENT,
586     GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, str);
587     g_free(str);
588    
589     gtk_window_set_title(GTK_WINDOW(dialog), _("Delete project?"));
590    
591     /* set the active flag again if the user answered "no" */
592     if(GTK_RESPONSE_NO == gtk_dialog_run(GTK_DIALOG(dialog))) {
593     gtk_widget_destroy(dialog);
594     return;
595     }
596    
597     gtk_widget_destroy(dialog);
598    
599     if(!project_delete(context, project))
600     printf("unable to delete project\n");
601     }
602    
603     static void on_project_edit(GtkButton *button, gpointer data) {
604     select_context_t *context = (select_context_t*)data;
605     project_t *project = project_get_selected(context->view);
606     g_assert(project);
607     #ifdef USE_HILDON
608     if(project_edit(context->dialog, project,
609     context->mmpos, context->osso_context))
610     #else
611     if(project_edit(context->dialog, project))
612     #endif
613     {
614     GtkTreeModel *model;
615     GtkTreeIter iter;
616    
617 achadwick 45 /* description etc. may have changed, so update list */
618 harbaum 1 GtkTreeSelection *selection =
619     gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view));
620     g_assert(gtk_tree_selection_get_selected(selection, &model, &iter));
621    
622     // gtk_tree_model_get(model, &iter, PROJECT_COL_DATA, &project, -1);
623 achadwick 45 gchar *status_stock_id = NULL;
624     project_get_status_icon_stock_id(project, &status_stock_id);
625 harbaum 1 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
626     PROJECT_COL_NAME, project->name,
627 achadwick 45 PROJECT_COL_STATUS, status_stock_id,
628 harbaum 1 PROJECT_COL_DESCRIPTION, project->desc,
629     -1);
630    
631    
632     }
633 harbaum 14
634     /* enable/disable edit/remove buttons */
635     view_selected(context, project);
636 harbaum 1 }
637    
638 achadwick 45
639     gboolean project_osm_present(project_t *project) {
640     char *osm_name = g_strdup_printf("%s/%s.osm", project->path, project->name);
641     gboolean is_present = g_file_test(osm_name, G_FILE_TEST_EXISTS);
642     g_free(osm_name);
643     return is_present;
644     }
645    
646     void project_get_status_icon_stock_id(project_t *project, gchar **stock_id) {
647     *stock_id = (! project_osm_present(project)) ? GTK_STOCK_DIALOG_WARNING
648     : diff_present(project) ? GTK_STOCK_PROPERTIES
649     : GTK_STOCK_FILE;
650     // TODO: check for outdatedness too. Which icon to use?
651     }
652    
653 harbaum 1 static GtkWidget *project_list_widget(select_context_t *context) {
654     GtkWidget *vbox = gtk_vbox_new(FALSE,3);
655     context->view = gtk_tree_view_new();
656    
657     gtk_tree_selection_set_select_function(
658     gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)),
659     view_selection_func,
660     context, NULL);
661    
662     /* --- "Name" column --- */
663     GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
664     gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view),
665     -1, _("Name"), renderer, "text", PROJECT_COL_NAME, NULL);
666    
667 achadwick 45 /* --- State flags column --- */
668     GtkCellRenderer *pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
669     GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(_("State"),
670     pixbuf_renderer, "stock_id", PROJECT_COL_STATUS,
671     NULL);
672     //gtk_tree_view_column_pack_start(column, renderer2, FALSE);
673     //gtk_tree_view_column_add_attribute(column, renderer2, "stock_id", PROJECT_COL_FLAG_DIFF_PRESENT);
674     gtk_tree_view_column_set_expand(column, FALSE);
675     gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1);
676    
677 harbaum 1 /* --- "Description" column --- */
678     renderer = gtk_cell_renderer_text_new();
679     g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
680 achadwick 45 column = gtk_tree_view_column_new_with_attributes(
681 harbaum 1 _("Description"), renderer, "text", PROJECT_COL_DESCRIPTION, NULL);
682     gtk_tree_view_column_set_expand(column, TRUE);
683     gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1);
684    
685     /* build the store */
686     GtkListStore *store = gtk_list_store_new(PROJECT_NUM_COLS,
687 achadwick 45 G_TYPE_STRING, // name
688     G_TYPE_STRING, // status
689     G_TYPE_STRING, // desc
690     G_TYPE_POINTER); // data
691 harbaum 1
692     GtkTreeIter iter;
693     project_t *project = context->project;
694     while(project) {
695 achadwick 45 gchar *status_stock_id = NULL;
696     project_get_status_icon_stock_id(project, &status_stock_id);
697 harbaum 1 /* Append a row and fill in some data */
698     gtk_list_store_append(store, &iter);
699     gtk_list_store_set(store, &iter,
700     PROJECT_COL_NAME, project->name,
701 achadwick 45 PROJECT_COL_STATUS, status_stock_id,
702 harbaum 1 PROJECT_COL_DESCRIPTION, project->desc,
703     PROJECT_COL_DATA, project,
704     -1);
705     project = project->next;
706     }
707    
708     gtk_tree_view_set_model(GTK_TREE_VIEW(context->view), GTK_TREE_MODEL(store));
709     g_object_unref(store);
710    
711     /* put it into a scrolled window */
712     GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
713     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
714     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
715     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
716     GTK_SHADOW_ETCHED_IN);
717     gtk_container_add(GTK_CONTAINER(scrolled_window), context->view);
718     gtk_box_pack_start_defaults(GTK_BOX(vbox), scrolled_window);
719    
720     /* ------- button box ------------ */
721    
722     GtkWidget *hbox = gtk_hbox_new(TRUE,3);
723     context->but_new = gtk_button_new_with_label(_("New..."));
724     gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_new);
725     gtk_signal_connect(GTK_OBJECT(context->but_new), "clicked",
726     GTK_SIGNAL_FUNC(on_project_new), context);
727    
728     context->but_edit = gtk_button_new_with_label(_("Edit..."));
729     gtk_widget_set_sensitive(context->but_edit, FALSE);
730     gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_edit);
731     gtk_signal_connect(GTK_OBJECT(context->but_edit), "clicked",
732     GTK_SIGNAL_FUNC(on_project_edit), context);
733    
734     context->but_remove = gtk_button_new_with_label(_("Remove"));
735     gtk_widget_set_sensitive(context->but_remove, FALSE);
736     gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_remove);
737     gtk_signal_connect(GTK_OBJECT(context->but_remove), "clicked",
738     GTK_SIGNAL_FUNC(on_project_delete), context);
739    
740     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
741    
742     return vbox;
743     }
744    
745     char *project_select(appdata_t *appdata) {
746     char *name = NULL;
747    
748     select_context_t *context = g_new0(select_context_t, 1);
749     #ifdef USE_HILDON
750     context->mmpos = &appdata->mmpos;
751     context->osso_context = appdata->osso_context;
752     #endif
753     context->settings = appdata->settings;
754     context->project = project_scan(appdata);
755    
756     /* create project selection dialog */
757     context->dialog = gtk_dialog_new_with_buttons(_("Project selection"),
758     GTK_WINDOW(appdata->window), GTK_DIALOG_MODAL,
759     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
760     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
761     NULL);
762    
763     #ifdef USE_HILDON
764     gtk_window_set_default_size(GTK_WINDOW(context->dialog), 500, 300);
765     #else
766     gtk_window_set_default_size(GTK_WINDOW(context->dialog), 400, 200);
767     #endif
768    
769     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox),
770     project_list_widget(context));
771    
772     /* don't all user to click ok until something is selected */
773     gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),
774     GTK_RESPONSE_ACCEPT, FALSE);
775    
776     gtk_widget_show_all(context->dialog);
777     if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context->dialog)))
778     name = g_strdup(project_get_selected(context->view)->name);
779    
780     gtk_widget_destroy(context->dialog);
781    
782     /* free all entries */
783     project_t *project = context->project;
784     while(project) {
785     project_t *next = project->next;
786     project_free(project);
787     project = next;
788     }
789    
790     g_free(context);
791    
792     return name;
793     }
794    
795     /* ---------------------------------------------------- */
796    
797     /* return file length or -1 on error */
798     static gsize file_length(char *name) {
799     GMappedFile *gmap = g_mapped_file_new(name, FALSE, NULL);
800     if(!gmap) return -1;
801     gsize size = g_mapped_file_get_length(gmap);
802     g_mapped_file_free(gmap);
803     return size;
804     }
805    
806     void project_filesize(project_context_t *context) {
807     char *str = NULL;
808    
809     printf("Checking size of %s\n", context->project->osm);
810    
811     if(!g_file_test(context->project->osm, G_FILE_TEST_IS_REGULAR)) {
812     GdkColor color;
813     gdk_color_parse("red", &color);
814     gtk_widget_modify_fg(context->fsize, GTK_STATE_NORMAL, &color);
815    
816     str = g_strdup(_("Not downloaded!"));
817     gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),
818     GTK_RESPONSE_ACCEPT, 0);
819     } else {
820     gtk_widget_modify_fg(context->fsize, GTK_STATE_NORMAL, NULL);
821    
822     if(!context->project->data_dirty)
823     str = g_strdup_printf(_("%d bytes present"),
824     file_length(context->project->osm));
825     else
826     str = g_strdup_printf(_("Outdated, please download!"));
827    
828     /* project also must not be dirty to proceed */
829     gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),
830     GTK_RESPONSE_ACCEPT, !context->project->data_dirty);
831     }
832    
833     if(str) {
834     gtk_label_set_text(GTK_LABEL(context->fsize), str);
835     g_free(str);
836     }
837     }
838    
839     void project_diffstat(project_context_t *context) {
840     char *str = NULL;
841    
842     if(diff_present(context->project))
843     str = g_strdup(_("present"));
844     else
845     str = g_strdup(_("not present"));
846    
847     gtk_label_set_text(GTK_LABEL(context->diff_stat), str);
848     g_free(str);
849     }
850    
851     static void project_update(project_context_t *context) {
852    
853     /* fetch values from dialog */
854     if(context->project->desc) g_free(context->project->desc);
855     context->project->desc = g_strdup(gtk_entry_get_text(
856     GTK_ENTRY(context->desc)));
857    
858     if(context->project->server) g_free(context->project->server);
859     context->project->server = g_strdup(gtk_entry_get_text(
860     GTK_ENTRY(context->server)));
861     }
862    
863     static void on_edit_clicked(GtkButton *button, gpointer data) {
864     project_context_t *context = (project_context_t*)data;
865    
866     if(area_edit(&context->area_edit)) {
867     printf("coordinates changed!!\n");
868    
869     pos_lon_label_set(context->minlat, context->project->min.lat);
870     pos_lon_label_set(context->minlon, context->project->min.lon);
871     pos_lon_label_set(context->maxlat, context->project->max.lat);
872     pos_lon_label_set(context->maxlon, context->project->max.lon);
873     }
874     }
875    
876     static void on_download_clicked(GtkButton *button, gpointer data) {
877     project_context_t *context = (project_context_t*)data;
878    
879     project_update(context);
880    
881     printf("download %s\n", context->project->osm);
882    
883     if(osm_download(context->dialog, context->project)) {
884     context->project->data_dirty = FALSE;
885     project_filesize(context);
886     } else
887     printf("download failed\n");
888     }
889    
890     static void on_diff_remove_clicked(GtkButton *button, gpointer data) {
891     project_context_t *context = (project_context_t*)data;
892    
893     printf("clicked diff remove\n");
894    
895     GtkWidget *dialog = gtk_message_dialog_new(
896     GTK_WINDOW(context->dialog),
897     GTK_DIALOG_DESTROY_WITH_PARENT,
898     GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
899     _("Do you really want to remove the diff file? This "
900     "will delete all changes you've made so far and which "
901     "you didn't upload yet."));
902    
903     gtk_window_set_title(GTK_WINDOW(dialog), _("Remove diff?"));
904    
905     /* set the active flag again if the user answered "no" */
906     if(GTK_RESPONSE_YES == gtk_dialog_run(GTK_DIALOG(dialog))) {
907     diff_remove(context->project);
908     project_diffstat(context);
909     gtk_widget_set_sensitive(context->diff_remove, FALSE);
910     }
911    
912     gtk_widget_destroy(dialog);
913     }
914    
915     gboolean project_edit(GtkWidget *parent, project_t *project POS_PARM) {
916     gboolean ok = FALSE;
917    
918     /* ------------ project edit dialog ------------- */
919    
920     project_context_t *context = g_new0(project_context_t, 1);
921     context->project = project;
922    
923     context->area_edit.min = &project->min;
924     context->area_edit.max = &project->max;
925     #ifdef USE_HILDON
926     context->area_edit.mmpos = mmpos;
927     context->area_edit.osso_context = osso_context;
928     #endif
929    
930     char *str = g_strdup_printf(_("Project - %s"), project->name);
931     context->area_edit.parent =
932     context->dialog = gtk_dialog_new_with_buttons(str,
933     GTK_WINDOW(parent), GTK_DIALOG_MODAL,
934     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
935     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
936     NULL);
937     g_free(str);
938    
939     #ifdef USE_HILDON
940     /* making the dialog a little wider makes it less "crowded" */
941     gtk_window_set_default_size(GTK_WINDOW(context->dialog), 640, 100);
942     #else
943     gtk_window_set_default_size(GTK_WINDOW(context->dialog), 400, 100);
944     #endif
945    
946     GtkWidget *download, *label;
947     GtkWidget *table = gtk_table_new(4, 6, FALSE); // x, y
948    
949     label = gtk_label_new(_("Description:"));
950     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
951     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
952     context->desc = gtk_entry_new();
953     gtk_entry_set_text(GTK_ENTRY(context->desc), project->desc);
954     gtk_table_attach_defaults(GTK_TABLE(table), context->desc, 1, 4, 0, 1);
955    
956     gtk_table_set_row_spacing(GTK_TABLE(table), 0, 4);
957    
958     label = gtk_label_new(_("Latitude"));
959     gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 1, 2);
960     label = gtk_label_new(_("Longitude"));
961     gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 1, 2);
962    
963     label = gtk_label_new(_("Min:"));
964     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
965     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
966     context->minlat = pos_lat_label_new(project->min.lat);
967     gtk_table_attach_defaults(GTK_TABLE(table), context->minlat, 1, 2, 2, 3);
968     context->minlon = pos_lon_label_new(project->min.lon);
969     gtk_table_attach_defaults(GTK_TABLE(table), context->minlon, 2, 3, 2, 3);
970    
971     label = gtk_label_new(_("Max:"));
972     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
973     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
974     context->maxlat = pos_lat_label_new(project->max.lat);
975     gtk_table_attach_defaults(GTK_TABLE(table), context->maxlat, 1, 2, 3, 4);
976     context->maxlon = pos_lon_label_new(project->max.lon);
977     gtk_table_attach_defaults(GTK_TABLE(table), context->maxlon, 2, 3, 3, 4);
978    
979     GtkWidget *edit = gtk_button_new_with_label(_("Edit..."));
980     gtk_signal_connect(GTK_OBJECT(edit), "clicked",
981     (GtkSignalFunc)on_edit_clicked, context);
982     gtk_table_attach(GTK_TABLE(table), edit, 3, 4, 2, 4,
983     GTK_EXPAND | GTK_FILL,0,0,0);
984    
985     gtk_table_set_col_spacing(GTK_TABLE(table), 0, 4);
986     gtk_table_set_row_spacing(GTK_TABLE(table), 3, 4);
987    
988     label = gtk_label_new(_("Server:"));
989     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
990     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 4, 5);
991     context->server = gtk_entry_new();
992     HILDON_ENTRY_NO_AUTOCAP(context->server);
993     gtk_entry_set_text(GTK_ENTRY(context->server), project->server);
994     gtk_table_attach_defaults(GTK_TABLE(table), context->server, 1, 4, 4, 5);
995    
996     label = gtk_label_new(_("OSM file:"));
997     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
998     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 5, 6);
999     GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
1000     context->fsize = gtk_label_new(_(""));
1001     gtk_misc_set_alignment(GTK_MISC(context->fsize), 0.f, 0.5f);
1002     project_filesize(context);
1003     gtk_box_pack_start_defaults(GTK_BOX(hbox), context->fsize);
1004     download = gtk_button_new_with_label(_("Download..."));
1005     gtk_signal_connect(GTK_OBJECT(download), "clicked",
1006     (GtkSignalFunc)on_download_clicked, context);
1007     gtk_box_pack_start(GTK_BOX(hbox), download, FALSE, FALSE, 0);
1008     gtk_table_attach_defaults(GTK_TABLE(table), hbox, 1, 4, 5, 6);
1009    
1010     label = gtk_label_new(_("Diff file:"));
1011     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1012     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 6, 7);
1013     hbox = gtk_hbox_new(FALSE, 0);
1014     context->diff_stat = gtk_label_new(_(""));
1015     gtk_misc_set_alignment(GTK_MISC(context->diff_stat), 0.f, 0.5f);
1016     project_diffstat(context);
1017     gtk_box_pack_start_defaults(GTK_BOX(hbox), context->diff_stat);
1018     context->diff_remove = gtk_button_new_with_label(_("Remove..."));
1019     if(!diff_present(project))
1020     gtk_widget_set_sensitive(context->diff_remove, FALSE);
1021     gtk_signal_connect(GTK_OBJECT(context->diff_remove), "clicked",
1022     (GtkSignalFunc)on_diff_remove_clicked, context);
1023     gtk_box_pack_start(GTK_BOX(hbox), context->diff_remove, FALSE, FALSE, 0);
1024     gtk_table_attach_defaults(GTK_TABLE(table), hbox, 1, 4, 6, 7);
1025    
1026    
1027     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox),
1028     table);
1029     gtk_widget_show_all(context->dialog);
1030    
1031     if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context->dialog))) {
1032     ok = TRUE;
1033    
1034     /* transfer values from edit dialog into project structure */
1035     project_update(context);
1036    
1037     /* save project */
1038     project_save(context->dialog, project);
1039     }
1040    
1041     gtk_widget_destroy(context->dialog);
1042     g_free(context);
1043    
1044     return ok;
1045     }
1046    
1047     gboolean project_open(appdata_t *appdata, char *name) {
1048     project_t *project = g_new0(project_t, 1);
1049    
1050     /* link to map state if a map already exists */
1051     if(appdata->map) {
1052     printf("Project: Using map state\n");
1053     project->map_state = appdata->map->state;
1054     } else {
1055     printf("Project: Creating new map_state\n");
1056     project->map_state = g_new0(map_state_t,1);
1057     }
1058     project->map_state->refcount++;
1059    
1060     /* build project path */
1061     project->path = g_strdup_printf("%s%s/",
1062     appdata->settings->base_path, name);
1063     project->name = g_strdup(name);
1064    
1065     char *project_file = g_strdup_printf("%s%s.proj", project->path, name);
1066    
1067     printf("project file = %s\n", project_file);
1068     if(!g_file_test(project_file, G_FILE_TEST_IS_REGULAR)) {
1069     printf("requested project file doesn't exist\n");
1070     project_free(project);
1071     g_free(project_file);
1072     return FALSE;
1073     }
1074    
1075     if(!project_read(appdata, project_file, project)) {
1076     printf("error reading project file\n");
1077     project_free(project);
1078     g_free(project_file);
1079     return FALSE;
1080     }
1081    
1082     g_free(project_file);
1083    
1084     /* --------- project structure ok: load its OSM file --------- */
1085     appdata->project = project;
1086    
1087 achadwick 28 printf("project_open: loading osm\n");
1088 harbaum 1 appdata->osm = osm_parse(project->osm);
1089 harbaum 4 if(!appdata->osm) return FALSE;
1090 harbaum 1
1091     printf("parsing ok\n");
1092    
1093     return TRUE;
1094     }
1095    
1096     gboolean project_close(appdata_t *appdata) {
1097     if(!appdata->project) return FALSE;
1098    
1099     printf("closing current project\n");
1100    
1101     /* redraw the entire map by destroying all map items and redrawing them */
1102     if(appdata->osm)
1103     diff_save(appdata->project, appdata->osm);
1104    
1105 achadwick 26 /* Save track and turn off the handler callback */
1106     track_save(appdata->project, appdata->track.track);
1107     track_do(appdata, TRACK_NONE, NULL);
1108    
1109 harbaum 1 map_clear(appdata, MAP_LAYER_ALL);
1110    
1111     if(appdata->osm) {
1112     osm_free(&appdata->icon, appdata->osm);
1113     appdata->osm = NULL;
1114     }
1115    
1116     project_free(appdata->project);
1117     appdata->project = NULL;
1118    
1119     return TRUE;
1120     }
1121    
1122 achadwick 28 #define _PROJECT_LOAD_BUF_SIZ 64
1123    
1124 harbaum 1 gboolean project_load(appdata_t *appdata, char *name) {
1125     char *proj_name = NULL;
1126    
1127     if(!name) {
1128     /* make user select a project */
1129     proj_name = project_select(appdata);
1130     if(!proj_name) {
1131     printf("no project selected\n");
1132     return FALSE;
1133     }
1134 achadwick 28 }
1135     else {
1136 harbaum 1 proj_name = g_strdup(name);
1137 achadwick 28 }
1138 harbaum 1
1139 achadwick 28 char banner_txt[_PROJECT_LOAD_BUF_SIZ];
1140     memset(banner_txt, 0, _PROJECT_LOAD_BUF_SIZ);
1141    
1142 harbaum 29 snprintf(banner_txt, _PROJECT_LOAD_BUF_SIZ, _("Loading %s"), proj_name);
1143 achadwick 28 banner_busy_start(appdata, TRUE, banner_txt);
1144    
1145 harbaum 1 /* close current project */
1146 achadwick 28 banner_busy_tick();
1147 harbaum 1 if(appdata->project)
1148     project_close(appdata);
1149    
1150     /* open project itself */
1151 achadwick 28 banner_busy_tick();
1152 harbaum 1 if(!project_open(appdata, proj_name)) {
1153     printf("error opening requested project\n");
1154 harbaum 29 snprintf(banner_txt, _PROJECT_LOAD_BUF_SIZ, _("Error opening %s"), proj_name);
1155 achadwick 28 banner_busy_stop(appdata);
1156     banner_show_info(appdata, banner_txt);
1157 harbaum 1 g_free(proj_name);
1158     return FALSE;
1159     }
1160    
1161     /* check if OSM data is valid */
1162 achadwick 28 banner_busy_tick();
1163 harbaum 1 if(!osm_sanity_check(GTK_WIDGET(appdata->window), appdata->osm)) {
1164     printf("project/osm sanity checks failed, unloading project\n");
1165     project_free(appdata->project);
1166 harbaum 29 snprintf(banner_txt, _PROJECT_LOAD_BUF_SIZ, _("Error opening %s"), proj_name);
1167 achadwick 28 banner_busy_stop(appdata);
1168     banner_show_info(appdata, banner_txt);
1169     g_free(proj_name);
1170 harbaum 1 return FALSE;
1171     }
1172    
1173     /* load diff possibly preset */
1174 achadwick 28 banner_busy_tick();
1175 harbaum 1 diff_restore(appdata, appdata->project, appdata->osm);
1176    
1177     /* prepare colors etc, draw data and adjust scroll/zoom settings */
1178 achadwick 28 banner_busy_tick();
1179 harbaum 1 map_init(appdata);
1180    
1181     /* restore a track */
1182 achadwick 28 banner_busy_tick();
1183 harbaum 1 appdata->track.track = track_restore(appdata, appdata->project);
1184     if(appdata->track.track)
1185     map_track_draw(appdata->map, appdata->track.track);
1186    
1187     /* finally load a background if present */
1188 achadwick 28 banner_busy_tick();
1189 harbaum 1 wms_load(appdata);
1190    
1191     /* save the name of the project for the perferences */
1192     if(appdata->settings->project)
1193     g_free(appdata->settings->project);
1194     appdata->settings->project = g_strdup(appdata->project->name);
1195    
1196 harbaum 29 snprintf(banner_txt, _PROJECT_LOAD_BUF_SIZ, _("Loaded %s"), proj_name);
1197 achadwick 28 banner_busy_stop(appdata);
1198     banner_show_info(appdata, banner_txt);
1199     statusbar_set(appdata, NULL, 0);
1200    
1201     g_free(proj_name);
1202 harbaum 1 return TRUE;
1203     }
1204 achadwick 28 // vim:et:ts=8:sw=2:sts=2:ai