Diff of /trunk/src/project.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 14 by harbaum, Mon Dec 15 19:45:38 2008 UTC revision 159 by harbaum, Fri Apr 10 11:57:28 2009 UTC
# Line 18  Line 18 
18   */   */
19    
20  #include "appdata.h"  #include "appdata.h"
21    #include "banner.h"
22    
23  #include <sys/stat.h>  #include <sys/stat.h>
24    
# Line 191  gboolean project_save(GtkWidget *parent, Line 192  gboolean project_save(GtkWidget *parent,
192    xmlNewChild(root_node, NULL, BAD_CAST "osm", BAD_CAST project->osm);    xmlNewChild(root_node, NULL, BAD_CAST "osm", BAD_CAST project->osm);
193    
194    node = xmlNewChild(root_node, NULL, BAD_CAST "min", NULL);    node = xmlNewChild(root_node, NULL, BAD_CAST "min", NULL);
195    g_ascii_dtostr(str, sizeof(str), project->min.lat);    g_ascii_formatd(str, sizeof(str), LL_FORMAT, project->min.lat);
196    xmlNewProp(node, BAD_CAST "lat", BAD_CAST str);    xmlNewProp(node, BAD_CAST "lat", BAD_CAST str);
197    g_ascii_dtostr(str, sizeof(str), project->min.lon);    g_ascii_formatd(str, sizeof(str), LL_FORMAT, project->min.lon);
198    xmlNewProp(node, BAD_CAST "lon", BAD_CAST str);    xmlNewProp(node, BAD_CAST "lon", BAD_CAST str);
199    
200    node = xmlNewChild(root_node, NULL, BAD_CAST "max", NULL);    node = xmlNewChild(root_node, NULL, BAD_CAST "max", NULL);
201    g_ascii_dtostr(str, sizeof(str), project->max.lat);    g_ascii_formatd(str, sizeof(str), LL_FORMAT, project->max.lat);
202    xmlNewProp(node, BAD_CAST "lat", BAD_CAST str);    xmlNewProp(node, BAD_CAST "lat", BAD_CAST str);
203    g_ascii_dtostr(str, sizeof(str), project->max.lon);    g_ascii_formatd(str, sizeof(str), LL_FORMAT, project->max.lon);
204    xmlNewProp(node, BAD_CAST "lon", BAD_CAST str);    xmlNewProp(node, BAD_CAST "lon", BAD_CAST str);
205    
206    if(project->map_state) {    if(project->map_state) {
207      node = xmlNewChild(root_node, NULL, BAD_CAST "map", BAD_CAST NULL);      node = xmlNewChild(root_node, NULL, BAD_CAST "map", BAD_CAST NULL);
208      g_ascii_dtostr(str, sizeof(str), project->map_state->zoom);      g_ascii_formatd(str, sizeof(str), LL_FORMAT, project->map_state->zoom);
209      xmlNewProp(node, BAD_CAST "zoom", BAD_CAST str);      xmlNewProp(node, BAD_CAST "zoom", BAD_CAST str);
210      snprintf(str, sizeof(str), "%d", project->map_state->scroll_offset.x);      snprintf(str, sizeof(str), "%d", project->map_state->scroll_offset.x);
211      xmlNewProp(node, BAD_CAST "scroll-offset-x", BAD_CAST str);      xmlNewProp(node, BAD_CAST "scroll-offset-x", BAD_CAST str);
# Line 312  static project_t *project_scan(appdata_t Line 313  static project_t *project_scan(appdata_t
313    
314  typedef struct {  typedef struct {
315    project_t *project;    project_t *project;
316    GtkWidget *dialog, *view;    GtkWidget *dialog, *list;
   GtkWidget *but_new, *but_edit, *but_remove;  
317    settings_t *settings;    settings_t *settings;
318  #ifdef USE_HILDON  #ifdef USE_HILDON
319    dbus_mm_pos_t *mmpos;    dbus_mm_pos_t *mmpos;
# Line 323  typedef struct { Line 323  typedef struct {
323    
324  enum {  enum {
325    PROJECT_COL_NAME = 0,    PROJECT_COL_NAME = 0,
326      PROJECT_COL_STATUS,
327    PROJECT_COL_DESCRIPTION,    PROJECT_COL_DESCRIPTION,
328    PROJECT_COL_DATA,    PROJECT_COL_DATA,
329    PROJECT_NUM_COLS    PROJECT_NUM_COLS
330  };  };
331    
332  static void view_selected(select_context_t *context, project_t *project) {  static void view_selected(select_context_t *context, project_t *project) {
333    gtk_widget_set_sensitive(context->but_remove, project != NULL);    list_button_enable(context->list, LIST_BUTTON_REMOVE, project != NULL);
334    gtk_widget_set_sensitive(context->but_edit, project != NULL);    list_button_enable(context->list, LIST_BUTTON_EDIT, project != NULL);
335    
336    /* check if the selected project also has a valid osm file */    /* check if the selected project also has a valid osm file */
337    gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),    gtk_dialog_set_response_sensitive(GTK_DIALOG(context->dialog),
# Line 357  view_selection_func(GtkTreeSelection *se Line 358  view_selection_func(GtkTreeSelection *se
358  }  }
359    
360  /* get the currently selected project in the list, NULL if none */  /* get the currently selected project in the list, NULL if none */
361  static project_t *project_get_selected(GtkWidget *view) {  static project_t *project_get_selected(GtkWidget *list) {
362    project_t *project = NULL;    project_t *project = NULL;
363    GtkTreeModel     *model;    GtkTreeModel     *model;
364    GtkTreeIter       iter;    GtkTreeIter       iter;
365    
366    GtkTreeSelection *selection =    GtkTreeSelection *selection = list_get_selection(list);
     gtk_tree_view_get_selection(GTK_TREE_VIEW(view));  
367    g_assert(gtk_tree_selection_get_selected(selection, &model, &iter));    g_assert(gtk_tree_selection_get_selected(selection, &model, &iter));
368    gtk_tree_model_get(model, &iter, PROJECT_COL_DATA, &project, -1);    gtk_tree_model_get(model, &iter, PROJECT_COL_DATA, &project, -1);
369    
# Line 433  gboolean project_delete(select_context_t Line 433  gboolean project_delete(select_context_t
433    
434    /* remove from view */    /* remove from view */
435    GtkTreeIter iter;    GtkTreeIter iter;
436    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(context->view));    GtkTreeModel *model = list_get_model(context->list);
437    gboolean deleted = FALSE;    gboolean deleted = FALSE;
438    if(gtk_tree_model_get_iter_first(model, &iter)) {    if(gtk_tree_model_get_iter_first(model, &iter)) {
439      do {      do {
# Line 543  project_t *project_new(select_context_t Line 543  project_t *project_new(select_context_t
543    return project;    return project;
544  }  }
545    
546    // predecs
547    void project_get_status_icon_stock_id(project_t *project, gchar **stock_id);
548    
549  static void on_project_new(GtkButton *button, gpointer data) {  static void on_project_new(GtkButton *button, gpointer data) {
550    select_context_t *context = (select_context_t*)data;    select_context_t *context = (select_context_t*)data;
551    project_t **project = &context->project;    project_t **project = &context->project;
552    *project = project_new(context);    *project = project_new(context);
553    if(*project) {    if(*project) {
554    
555      GtkTreeModel *model =      GtkTreeModel *model = list_get_model(context->list);
       gtk_tree_view_get_model(GTK_TREE_VIEW(context->view));  
556    
557      GtkTreeIter iter;      GtkTreeIter iter;
558        gchar *status_stock_id = NULL;
559        project_get_status_icon_stock_id(*project, &status_stock_id);
560      gtk_list_store_append(GTK_LIST_STORE(model), &iter);      gtk_list_store_append(GTK_LIST_STORE(model), &iter);
561      gtk_list_store_set(GTK_LIST_STORE(model), &iter,      gtk_list_store_set(GTK_LIST_STORE(model), &iter,
562                         PROJECT_COL_NAME,        (*project)->name,                         PROJECT_COL_NAME,        (*project)->name,
563                           PROJECT_COL_STATUS,      status_stock_id,
564                         PROJECT_COL_DESCRIPTION, (*project)->desc,                         PROJECT_COL_DESCRIPTION, (*project)->desc,
565                         PROJECT_COL_DATA,        *project,                         PROJECT_COL_DATA,        *project,
566                         -1);                         -1);
567    
568      GtkTreeSelection *selection =      GtkTreeSelection *selection = list_get_selection(context->list);
       gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view));  
569      gtk_tree_selection_select_iter(selection, &iter);      gtk_tree_selection_select_iter(selection, &iter);
570    }    }
571  }  }
572    
573  static void on_project_delete(GtkButton *button, gpointer data) {  static void on_project_delete(GtkButton *button, gpointer data) {
574    select_context_t *context = (select_context_t*)data;    select_context_t *context = (select_context_t*)data;
575    project_t *project = project_get_selected(context->view);    project_t *project = project_get_selected(context->list);
576    
577    char *str = g_strdup_printf(_("Do you really want to delete the "    char *str = g_strdup_printf(_("Do you really want to delete the "
578                                  "project \"%s\"?"), project->name);                                  "project \"%s\"?"), project->name);
# Line 594  static void on_project_delete(GtkButton Line 598  static void on_project_delete(GtkButton
598    
599  static void on_project_edit(GtkButton *button, gpointer data) {  static void on_project_edit(GtkButton *button, gpointer data) {
600    select_context_t *context = (select_context_t*)data;    select_context_t *context = (select_context_t*)data;
601    project_t *project = project_get_selected(context->view);    project_t *project = project_get_selected(context->list);
602    g_assert(project);    g_assert(project);
603  #ifdef USE_HILDON  #ifdef USE_HILDON
604    if(project_edit(context->dialog, project,    if(project_edit(context->dialog, project,
# Line 606  static void on_project_edit(GtkButton *b Line 610  static void on_project_edit(GtkButton *b
610      GtkTreeModel     *model;      GtkTreeModel     *model;
611      GtkTreeIter       iter;      GtkTreeIter       iter;
612    
613      /* description may have changed, so update list */      /* description etc. may have changed, so update list */
614      GtkTreeSelection *selection =      GtkTreeSelection *selection = list_get_selection(context->list);
       gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view));  
615      g_assert(gtk_tree_selection_get_selected(selection, &model, &iter));      g_assert(gtk_tree_selection_get_selected(selection, &model, &iter));
616    
617      //     gtk_tree_model_get(model, &iter, PROJECT_COL_DATA, &project, -1);      //     gtk_tree_model_get(model, &iter, PROJECT_COL_DATA, &project, -1);
618        gchar *status_stock_id = NULL;
619        project_get_status_icon_stock_id(project, &status_stock_id);
620      gtk_list_store_set(GTK_LIST_STORE(model), &iter,      gtk_list_store_set(GTK_LIST_STORE(model), &iter,
621                         PROJECT_COL_NAME, project->name,                         PROJECT_COL_NAME, project->name,
622                           PROJECT_COL_STATUS, status_stock_id,
623                         PROJECT_COL_DESCRIPTION, project->desc,                         PROJECT_COL_DESCRIPTION, project->desc,
624                         -1);                         -1);
625    
# Line 624  static void on_project_edit(GtkButton *b Line 630  static void on_project_edit(GtkButton *b
630    view_selected(context, project);    view_selected(context, project);
631  }  }
632    
633    
634    gboolean project_osm_present(project_t *project) {
635      char *osm_name = g_strdup_printf("%s/%s.osm", project->path, project->name);
636      gboolean is_present = g_file_test(osm_name, G_FILE_TEST_EXISTS);
637      g_free(osm_name);
638      return is_present;
639    }
640    
641    void project_get_status_icon_stock_id(project_t *project, gchar **stock_id) {
642        *stock_id = (! project_osm_present(project)) ? GTK_STOCK_DIALOG_WARNING
643             : diff_present(project) ? GTK_STOCK_PROPERTIES
644             : GTK_STOCK_FILE;
645        // TODO: check for outdatedness too. Which icon to use?
646    }
647    
648  static GtkWidget *project_list_widget(select_context_t *context) {  static GtkWidget *project_list_widget(select_context_t *context) {
649    GtkWidget *vbox = gtk_vbox_new(FALSE,3);    context->list = list_new(LIST_HILDON_WITHOUT_HEADERS);
650    context->view = gtk_tree_view_new();  
651      list_set_selection_function(context->list, view_selection_func, context);
652    
653    gtk_tree_selection_set_select_function(    list_set_columns(context->list,
654           gtk_tree_view_get_selection(GTK_TREE_VIEW(context->view)),                     _("Name"), PROJECT_COL_NAME, 0,
655           view_selection_func,                     _("State"), PROJECT_COL_STATUS, LIST_FLAG_STOCK_ICON,
656           context, NULL);                     _("Description"), PROJECT_COL_DESCRIPTION, LIST_FLAG_ELLIPSIZE,
657                       NULL);
658    /* --- "Name" column --- */  
   GtkCellRenderer *renderer = gtk_cell_renderer_text_new();  
   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(context->view),  
         -1, _("Name"), renderer, "text", PROJECT_COL_NAME, NULL);  
   
   /* --- "Description" column --- */  
   renderer = gtk_cell_renderer_text_new();  
   g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL );  
   GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(  
          _("Description"), renderer, "text", PROJECT_COL_DESCRIPTION, NULL);  
   gtk_tree_view_column_set_expand(column, TRUE);  
   gtk_tree_view_insert_column(GTK_TREE_VIEW(context->view), column, -1);  
659    
660    /* build the store */    /* build the store */
661    GtkListStore *store = gtk_list_store_new(PROJECT_NUM_COLS,    GtkListStore *store = gtk_list_store_new(PROJECT_NUM_COLS,
662        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);        G_TYPE_STRING,    // name
663          G_TYPE_STRING,    // status
664          G_TYPE_STRING,    // desc
665          G_TYPE_POINTER);  // data
666    
667    GtkTreeIter iter;    GtkTreeIter iter;
668    project_t *project = context->project;    project_t *project = context->project;
669    while(project) {    while(project) {
670        gchar *status_stock_id = NULL;
671        project_get_status_icon_stock_id(project, &status_stock_id);
672      /* Append a row and fill in some data */      /* Append a row and fill in some data */
673      gtk_list_store_append(store, &iter);      gtk_list_store_append(store, &iter);
674      gtk_list_store_set(store, &iter,      gtk_list_store_set(store, &iter,
675                 PROJECT_COL_NAME,        project->name,                 PROJECT_COL_NAME,        project->name,
676                   PROJECT_COL_STATUS,      status_stock_id,
677                 PROJECT_COL_DESCRIPTION, project->desc,                 PROJECT_COL_DESCRIPTION, project->desc,
678                 PROJECT_COL_DATA,        project,                 PROJECT_COL_DATA,        project,
679                 -1);                 -1);
680      project = project->next;      project = project->next;
681    }    }
682    
683    gtk_tree_view_set_model(GTK_TREE_VIEW(context->view), GTK_TREE_MODEL(store));    list_set_store(context->list, store);
684    g_object_unref(store);    g_object_unref(store);
685    
686    /* put it into a scrolled window */    list_set_static_buttons(context->list, G_CALLBACK(on_project_new),
687    GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);            G_CALLBACK(on_project_edit), G_CALLBACK(on_project_delete), context);
   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),  
                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);  
   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),  
                                       GTK_SHADOW_ETCHED_IN);  
   gtk_container_add(GTK_CONTAINER(scrolled_window), context->view);  
   gtk_box_pack_start_defaults(GTK_BOX(vbox), scrolled_window);  
   
   /* ------- button box ------------ */  
   
   GtkWidget *hbox = gtk_hbox_new(TRUE,3);  
   context->but_new = gtk_button_new_with_label(_("New..."));  
   gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_new);  
   gtk_signal_connect(GTK_OBJECT(context->but_new), "clicked",  
                      GTK_SIGNAL_FUNC(on_project_new), context);  
   
   context->but_edit = gtk_button_new_with_label(_("Edit..."));  
   gtk_widget_set_sensitive(context->but_edit, FALSE);  
   gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_edit);  
   gtk_signal_connect(GTK_OBJECT(context->but_edit), "clicked",  
              GTK_SIGNAL_FUNC(on_project_edit), context);  
   
   context->but_remove = gtk_button_new_with_label(_("Remove"));  
   gtk_widget_set_sensitive(context->but_remove, FALSE);  
   gtk_box_pack_start_defaults(GTK_BOX(hbox), context->but_remove);  
   gtk_signal_connect(GTK_OBJECT(context->but_remove), "clicked",  
                      GTK_SIGNAL_FUNC(on_project_delete), context);  
   
   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);  
688    
689    return vbox;    return context->list;
690  }  }
691    
692  char *project_select(appdata_t *appdata) {  char *project_select(appdata_t *appdata) {
# Line 734  char *project_select(appdata_t *appdata) Line 722  char *project_select(appdata_t *appdata)
722    
723    gtk_widget_show_all(context->dialog);    gtk_widget_show_all(context->dialog);
724    if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context->dialog)))    if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context->dialog)))
725      name = g_strdup(project_get_selected(context->view)->name);      name = g_strdup(project_get_selected(context->list)->name);
726    
727    gtk_widget_destroy(context->dialog);    gtk_widget_destroy(context->dialog);
728    
# Line 1043  gboolean project_open(appdata_t *appdata Line 1031  gboolean project_open(appdata_t *appdata
1031    /* --------- project structure ok: load its OSM file --------- */    /* --------- project structure ok: load its OSM file --------- */
1032    appdata->project = project;    appdata->project = project;
1033    
1034    printf("project_load: loading osm\n");    printf("project_open: loading osm\n");
1035    appdata->osm = osm_parse(project->osm);    appdata->osm = osm_parse(project->osm);
1036    if(!appdata->osm) return FALSE;    if(!appdata->osm) return FALSE;
1037    
# Line 1061  gboolean project_close(appdata_t *appdat Line 1049  gboolean project_close(appdata_t *appdat
1049    if(appdata->osm)    if(appdata->osm)
1050      diff_save(appdata->project, appdata->osm);      diff_save(appdata->project, appdata->osm);
1051    
1052      /* Save track and turn off the handler callback */
1053      track_save(appdata->project, appdata->track.track);
1054      track_clear(appdata, appdata->track.track);
1055      appdata->track.track = NULL;
1056    
1057    map_clear(appdata, MAP_LAYER_ALL);    map_clear(appdata, MAP_LAYER_ALL);
1058    
1059    if(appdata->osm) {    if(appdata->osm) {
# Line 1074  gboolean project_close(appdata_t *appdat Line 1067  gboolean project_close(appdata_t *appdat
1067    return TRUE;    return TRUE;
1068  }  }
1069    
1070    #define _PROJECT_LOAD_BUF_SIZ 64
1071    
1072  gboolean project_load(appdata_t *appdata, char *name) {  gboolean project_load(appdata_t *appdata, char *name) {
1073    char *proj_name = NULL;    char *proj_name = NULL;
1074    
# Line 1084  gboolean project_load(appdata_t *appdata Line 1079  gboolean project_load(appdata_t *appdata
1079        printf("no project selected\n");        printf("no project selected\n");
1080        return FALSE;        return FALSE;
1081      }      }
1082    } else    }
1083      else {
1084      proj_name = g_strdup(name);      proj_name = g_strdup(name);
1085      }
1086    
1087      char banner_txt[_PROJECT_LOAD_BUF_SIZ];
1088      memset(banner_txt, 0, _PROJECT_LOAD_BUF_SIZ);
1089    
1090      snprintf(banner_txt, _PROJECT_LOAD_BUF_SIZ, _("Loading %s"), proj_name);
1091      banner_busy_start(appdata, TRUE, banner_txt);
1092    
1093    /* close current project */    /* close current project */
1094      banner_busy_tick();
1095    if(appdata->project)    if(appdata->project)
1096      project_close(appdata);      project_close(appdata);
1097    
1098    /* open project itself */    /* open project itself */
1099      banner_busy_tick();
1100    if(!project_open(appdata, proj_name)) {    if(!project_open(appdata, proj_name)) {
1101      printf("error opening requested project\n");      printf("error opening requested project\n");
1102    
1103        if(appdata->project) {
1104          project_free(appdata->project);
1105          appdata->project = NULL;
1106        }
1107    
1108        if(appdata->osm) {
1109          osm_free(&appdata->icon, appdata->osm);
1110          appdata->osm = NULL;
1111        }
1112    
1113        snprintf(banner_txt, _PROJECT_LOAD_BUF_SIZ,
1114                 _("Error opening %s"), proj_name);
1115        banner_busy_stop(appdata);
1116        banner_show_info(appdata, banner_txt);
1117    
1118      g_free(proj_name);      g_free(proj_name);
1119      return FALSE;      return FALSE;
1120    }    }
1121    
   g_free(proj_name);  
   
1122    /* check if OSM data is valid */    /* check if OSM data is valid */
1123      banner_busy_tick();
1124    if(!osm_sanity_check(GTK_WIDGET(appdata->window), appdata->osm)) {    if(!osm_sanity_check(GTK_WIDGET(appdata->window), appdata->osm)) {
1125      printf("project/osm sanity checks failed, unloading project\n");      printf("project/osm sanity checks failed, unloading project\n");
1126      project_free(appdata->project);  
1127        if(appdata->project) {
1128          project_free(appdata->project);
1129          appdata->project = NULL;
1130        }
1131    
1132        if(appdata->osm) {
1133          osm_free(&appdata->icon, appdata->osm);
1134          appdata->osm = NULL;
1135        }
1136    
1137        snprintf(banner_txt, _PROJECT_LOAD_BUF_SIZ,
1138                 _("Error opening %s"), proj_name);
1139        banner_busy_stop(appdata);
1140        banner_show_info(appdata, banner_txt);
1141    
1142        g_free(proj_name);
1143      return FALSE;      return FALSE;
1144    }    }
1145    
1146    /* load diff possibly preset */    /* load diff possibly preset */
1147      banner_busy_tick();
1148    diff_restore(appdata, appdata->project, appdata->osm);    diff_restore(appdata, appdata->project, appdata->osm);
1149    
1150    /* prepare colors etc, draw data and adjust scroll/zoom settings */    /* prepare colors etc, draw data and adjust scroll/zoom settings */
1151      banner_busy_tick();
1152    map_init(appdata);    map_init(appdata);
1153    
1154    /* restore a track */    /* restore a track */
1155      banner_busy_tick();
1156    appdata->track.track = track_restore(appdata, appdata->project);    appdata->track.track = track_restore(appdata, appdata->project);
1157    if(appdata->track.track)    if(appdata->track.track)
1158      map_track_draw(appdata->map, appdata->track.track);      map_track_draw(appdata->map, appdata->track.track);
1159    
1160    /* finally load a background if present */    /* finally load a background if present */
1161      banner_busy_tick();
1162    wms_load(appdata);    wms_load(appdata);
1163    
1164    /* save the name of the project for the perferences */    /* save the name of the project for the perferences */
# Line 1126  gboolean project_load(appdata_t *appdata Line 1166  gboolean project_load(appdata_t *appdata
1166      g_free(appdata->settings->project);      g_free(appdata->settings->project);
1167    appdata->settings->project = g_strdup(appdata->project->name);    appdata->settings->project = g_strdup(appdata->project->name);
1168    
1169      snprintf(banner_txt, _PROJECT_LOAD_BUF_SIZ, _("Loaded %s"), proj_name);
1170      banner_busy_stop(appdata);
1171      banner_show_info(appdata, banner_txt);
1172      statusbar_set(appdata, NULL, 0);
1173    
1174      g_free(proj_name);
1175    return TRUE;    return TRUE;
1176  }  }
1177    // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.14  
changed lines
  Added in v.159