Diff of /trunk/src/geotoad.c

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

revision 194 by harbaum, Wed Nov 18 11:40:31 2009 UTC revision 208 by harbaum, Tue Nov 24 15:21:22 2009 UTC
# Line 19  Line 19 
19    
20  #include "gpxview.h"  #include "gpxview.h"
21    
22    #define __USE_GNU
23    #include <string.h>
24    
25  #include <fcntl.h>  #include <fcntl.h>
26  #include <sys/types.h>  #include <sys/types.h>
27  #include <sys/wait.h>  #include <sys/wait.h>
28  #include <errno.h>  #include <errno.h>
29    #include <math.h>
30    
31    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
32    #include <hildon/hildon-entry.h>
33    #endif
34    
35  #define COLOR_ERR  "red"  #define GEOTOAD "/usr/bin/geotoad"
 #define COLOR_OK   "darkgreen"  
36    
37  #define BUFFER_SIZE  1500  #define COLOR_ERR     "red"
38    #define COLOR_OK      "darkgreen"
39    #define COLOR_SYSTEM  "darkblue"
40    
41    #define BUFFER_SIZE  256
42    
43    typedef enum {
44      GT_STATE_ILLEGAL = 0,
45      GT_STATE_STARTED,
46      GT_STATE_PREMATURE_END,
47      GT_STATE_SAVE_FOUND,
48    } gt_state_t;
49    
50  typedef struct {  typedef struct {
51    appdata_t *appdata;    appdata_t *appdata;
52    
53      GPtrArray *argv;
54      gchar *info, *color;
55      GMutex *update_mutex;
56      GCond *update_cond;
57    
58    char buf[BUFFER_SIZE];    gt_state_t state;
   int bused;  
59    
60    /** gdk input tag for async IO */    GtkWidget *dialog;
61    gint stdout_tag, stderr_tag;  
62    gint stdin_fd, stdout_fd, stderr_fd;    long pid;
63    
64    struct log_s {    struct log_s {
65      GtkTextBuffer *buffer;      GtkTextBuffer *buffer;
66      GtkWidget *view;      GtkWidget *view;
67    } log;    } log;
68    
69      GtkWidget *username, *password, *filename;
70      GtkWidget *lat, *lon, *dst;
71    
72      int use_cnt;
73    
74  } gt_context_t;  } gt_context_t;
75    
76    static void arg_free(gpointer data, gpointer user_data) {
77      if(data) g_free(data);
78    }
79    
80    static void context_free(gt_context_t *context) {
81      context->use_cnt--;
82    
83      if(context->use_cnt > 0)
84        printf("still in use by %d, keeping context\n", context->use_cnt);
85      else {
86        printf("freeing context\n");
87    
88        if(context->info) g_free(context->info);
89    
90        g_ptr_array_foreach(context->argv, arg_free, NULL);
91        g_ptr_array_free (context->argv, TRUE);
92    
93        g_free(context);
94      }
95    }
96    
97  static void appendf(struct log_s *log, char *colname,  static void appendf(struct log_s *log, char *colname,
98                      const char *fmt, ...) {                      const char *fmt, ...) {
99    va_list args;    va_list args;
# Line 53  static void appendf(struct log_s *log, c Line 101  static void appendf(struct log_s *log, c
101    char *buf = g_strdup_vprintf(fmt, args);    char *buf = g_strdup_vprintf(fmt, args);
102    va_end( args );    va_end( args );
103    
104      //  printf("append: %s", buf);
105    
106    GtkTextTag *tag = NULL;    GtkTextTag *tag = NULL;
107    if(colname)    if(colname)
108      tag = gtk_text_buffer_create_tag(log->buffer, NULL,      tag = gtk_text_buffer_create_tag(log->buffer, NULL,
# Line 69  static void appendf(struct log_s *log, c Line 119  static void appendf(struct log_s *log, c
119    g_free(buf);    g_free(buf);
120    
121    gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(log->view),    gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(log->view),
122                                 &end, 0.0, FALSE, 0, 0);                                 &end, 0.0, TRUE, 0, 1.0);
123  }  }
124    
125  /* watch child process and receive events */  // This function receives a requst from a worker thread asking to
126  static void child_state_cb(GPid pid, gint status, gpointer data) {  // update the gui with the required info.
127    gboolean cb_update_job(gt_context_t *context) {
128    puts("child state");    if (context->info) {
129    
130    if(WIFEXITED(status)) {      /* check if client reports "saved to ..." */
131      printf("child exited with return code %d\n", WEXITSTATUS(status));      if(strstr(context->info, "Saved to "))
132    } else        context->state = GT_STATE_SAVE_FOUND;
     printf("child failed\n");  
   
   puts("gt exited");  
133    
134    /* Reap child if needed. */      appendf(&context->log, context->color, context->info);
135    waitpid (pid, NULL, WNOHANG);  
136        g_free(context->info);
137        context->info = NULL;
138      }
139    
140      // Indicate that the update is done
141      g_mutex_lock(context->update_mutex);
142      g_cond_signal(context->update_cond);
143      g_mutex_unlock(context->update_mutex);
144    
145      return FALSE;
146  }  }
147    
148  static void child_input_cb(gpointer data, int fd, GdkInputCondition cond) {  // A helper function run in the job thread receiving the string that
149    gt_context_t *context = (gt_context_t*)data;  // should be displayed in the textview.
150    void append_parentf(gt_context_t *context, char *colname,
151                 const char *fmt, ...) {
152      va_list args;
153      va_start( args, fmt );
154      context->info = g_strdup_vprintf(fmt, args);
155      va_end( args );
156    
157    ssize_t bytes;    if(colname)
158    int errnosave=0;      context->color = colname;
159      else
160        context->color = NULL;
161    
162    if(cond != GDK_INPUT_READ) {    // Lock mutex to make sure that we will receive the condition signal
163      puts("fixme");    g_mutex_lock(context->update_mutex);
     return;  
   }  
164    
165    /* append to current buffer content */    g_idle_add((GSourceFunc)cb_update_job, context);
166    while( (bytes = read(fd, context->buf+context->bused,  
167                   sizeof(context->buf) - context->bused - 1)) > 0) {    // Wait for cb_update_job to tell me that the update is done
168      context->bused += bytes;    g_cond_wait(context->update_cond, context->update_mutex);
169      context->buf[context->bused]='\0';    g_mutex_unlock(context->update_mutex);
170    }
171    
172      /* consume line by line */  /* custom version of popen to get access to the pid and to be able */
173      gchar *ptr = context->buf;  /* to slaughter the child process */
174    static FILE *gt_popen(gt_context_t *context, char **args,
175                          const char *type, long *tid) {
176      int   p[2];
177      FILE *fp;
178    
179      if (*type != 'r' && *type != 'w')
180        return NULL;
181    
182      if (pipe(p) < 0)
183        return NULL;
184    
185      if ((*tid = fork()) > 0) { /* then we are the parent */
186        if (*type == 'r') {
187          close(p[1]);
188          fp = fdopen(p[0], type);
189        } else {
190          close(p[0]);
191          fp = fdopen(p[1], type);
192        }
193    
194      /* parse as long as the buffer contains a newline */      return fp;
195      while( strchr(ptr, '\n') != NULL) {    } else if (*tid == 0) {  /* we're the child */
       char *p = strchr(ptr, '\n');  
       *p = '\0';  
196    
197        appendf(&context->log, NULL, "%s\n", ptr);      /* make our thread id the process group leader */
198        setpgid(0, 0);
199        ptr = p+1;  
200        if (*type == 'r') {
201          fflush(stdout);
202          fflush(stderr);
203          close(1);
204          if (dup(p[1]) < 0)
205            perror("dup of write side of pipe failed");
206          close(2);
207          if (dup(p[1]) < 0)
208            perror("dup of write side of pipe failed");
209        } else {
210          close(0);
211          if (dup(p[0]) < 0)
212            perror("dup of read side of pipe failed");
213      }      }
214    
215        close(p[0]); /* close since we dup()'ed what we needed */
216        close(p[1]);
217    
218        execve(args[0], args, NULL);
219    
220        /* this printf will actually be redirected through the pipe */
221        printf("Error: Failed to execute!\n");
222        context_free(context);
223        exit(0);
224      } else {         /* we're having major problems... */
225        close(p[0]);
226        close(p[1]);
227    
228      /* move remaining bytes down the buffer */      /* this printf will actually be redirected through the pipe??? No! */
229      memmove(context->buf, ptr, sizeof(context->buf)-(ptr-context->buf));      printf("Error: Failed to fork!\n");
     context->bused -= ptr - context->buf;  
   
     /* check if buffer is full but doesn't contain any newline */  
     if(context->bused >= sizeof(context->buf)-1) {  
       printf("ERROR: reply buffer overflow\n");  
       context->bused = 0;  
     }  
230    }    }
231    
232      return NULL;
233    }
234    
235    /* save errno from read */  // The thread entry point. It will do the job, send the data to the
236    errnosave=errno;  // GUI and self destruct when it is done.
237    static gpointer thread_worker(gt_context_t *context)
238    {
239      FILE *fh;
240      GIOStatus status;
241      GError *error = NULL;
242      gsize length;
243      gsize terminator_pos;
244      gchar *str_return;
245    
246      fh = gt_popen(context, (char**)(context->argv->pdata),"r", &context->pid);
247      if(!fh) {
248        printf("fail free\n");
249        context_free(context);
250        //    g_thread_exit(NULL);
251        return NULL;
252      }
253    
254    if(errnosave != EAGAIN && errnosave != 0) {    /* the client is running */
255      /* we probably hit EOF */    printf("client inc use_cnt\n");
256      puts("removing io");    context->use_cnt++;
257    
258      /* switch to line buffered mode */
259      if(setvbuf(fh, NULL, _IOLBF, 0))
260        perror("setvbuf(_IOLBF)");
261    
262      GIOChannel *gh = g_io_channel_unix_new(fileno(fh));
263    
264      // TODO: fixme, make sure process is dead! kill it otherwise, but dont    while( (status = g_io_channel_read_line(gh,
265      // issue an disconnect(NULL) !!!!                                            &str_return,
266                                              &length,
267                                              &terminator_pos,
268                                              &error)) == G_IO_STATUS_NORMAL) {
269        char *color = NULL;
270        if(strstr(str_return, "Saved to "))  color = COLOR_OK;
271        if(strcasestr(str_return, "error"))  color = COLOR_ERR;
272    
273      gdk_input_remove(context->stdout_tag);      append_parentf(context, color, str_return);
274      gdk_input_remove(context->stderr_tag);      g_free(str_return);
275      }
276    
277      g_io_channel_unref(gh);
278      pclose(fh);
279      append_parentf(context, COLOR_SYSTEM, "Job done!");
280    
281      /* TODO: this happens on the copy!!!! */;
282      printf("client context free = %d\n", context->use_cnt);
283      context_free(context);
284    
285      //  g_thread_exit(NULL);
286      return NULL;
287    }
288    
     appendf(&context->log, COLOR_OK, "GeoToad finished\n");  
289    
290      appendf(&context->log, COLOR_ERR, "TODO: free context!!!\n");  static void arg_dsp(gpointer data, gpointer user_data) {
291      //    printf("freeing context\n");    gt_context_t *context = (gt_context_t*)user_data;
292      //    g_free(context);  
293    }    if(data)
294        appendf(&context->log, COLOR_SYSTEM, "%s\n", data);
295  }  }
296    
297  static void run(gt_context_t *context) {  static void run(gt_context_t *context) {
298    /* setup context */    GError *error = NULL;
299    context->bused = 0;    char str[8];
   context->stdout_tag = -1;  
   context->stderr_tag = -1;  
   context->stdin_fd  = -1;  
   context->stderr_fd = -1;  
   context->stderr_fd = -1;  
300    
301    /* build list of arguments to call geotoad */    /* build list of arguments to call geotoad */
302    GPtrArray *gt_argv = g_ptr_array_new();    context->argv = g_ptr_array_new();
303    g_ptr_array_add (gt_argv, "/usr/bin/geotoad");    g_ptr_array_add (context->argv, g_strdup_printf(GEOTOAD "a"));
304    g_ptr_array_add (gt_argv, "--distanceMax=1.5");    g_ascii_dtostr(str, sizeof(str), context->appdata->gt.distance);
305    g_ptr_array_add (gt_argv, "--output=gtoad.gpx");    g_ptr_array_add (context->argv, g_strdup_printf("--distanceMax=%s", str));
306    g_ptr_array_add (gt_argv, "--password=winterblume");    g_ptr_array_add (context->argv, g_strdup_printf("--output=%s", context->appdata->gt.filename));
307    g_ptr_array_add (gt_argv, "--queryType=coord");    g_ptr_array_add (context->argv, g_strdup_printf("--password=%s", context->appdata->gt.password));
308    g_ptr_array_add (gt_argv, "--user=Tantil");    g_ptr_array_add (context->argv, g_strdup_printf("--queryType=coord"));
309      g_ptr_array_add (context->argv, g_strdup_printf("--user=%s", context->appdata->username));
310    
311    /* check if we need to add proxy config */    /* check if we need to add proxy config */
312    char *proxy = NULL;    char *proxy = NULL;
# Line 175  static void run(gt_context_t *context) { Line 315  static void run(gt_context_t *context) {
315         context->appdata->proxy->authentication_user &&         context->appdata->proxy->authentication_user &&
316         context->appdata->proxy->authentication_password)         context->appdata->proxy->authentication_password)
317        proxy = g_strdup_printf("--proxy=http://%s:%s@%s:%d",        proxy = g_strdup_printf("--proxy=http://%s:%s@%s:%d",
318                                context->appdata->proxy->authentication_user,                                context->appdata->proxy->authentication_user,
319                                context->appdata->proxy->authentication_password,                                context->appdata->proxy->authentication_password,
320                                context->appdata->proxy->host,                                context->appdata->proxy->host,
321                                context->appdata->proxy->port);                                context->appdata->proxy->port);
322      else      else
323        proxy = g_strdup_printf("--proxy=http://%s:%d",        proxy = g_strdup_printf("--proxy=http://%s:%d",
324                                context->appdata->proxy->host,                                context->appdata->proxy->host,
325                                context->appdata->proxy->port);                                context->appdata->proxy->port);
326    
327      appendf(&context->log, COLOR_OK, "Using proxy: %s\n", proxy);      g_ptr_array_add (context->argv, proxy);
     g_ptr_array_add (gt_argv, proxy);  
328    }    }
329    
330      /* convert coordinates into simple ascii format */
331    g_ptr_array_add (gt_argv, "N49 00.000 E008 23.000");    char n = (context->appdata->gt.lat >= 0)?'N':'S';
332    g_ptr_array_add (gt_argv, NULL);    char e = (context->appdata->gt.lon >= 0)?'E':'W';
333      float lat = fabs(context->appdata->gt.lat);
334    GError *error=NULL;    float lon = fabs(context->appdata->gt.lon);
335    GPid pid;    float lat_mint, lat_int, lat_frac = modff(lat, &lat_int);
336    GSource *gt_watch;    float lon_mint, lon_int, lon_frac = modff(lon, &lon_int);
337      lat_frac = modff(lat_frac*60.0, &lat_mint);
338    if (!g_spawn_async_with_pipes (NULL, /* CWD */    lon_frac = modff(lon_frac*60.0, &lon_mint);
339                                   (char **) gt_argv->pdata, /* argv */  
340                                   NULL, /* envp */    g_ptr_array_add (context->argv,
341                                   G_SPAWN_DO_NOT_REAP_CHILD, /* flags */             g_strdup_printf("%c%02u %02u.%03u %c%03u %02u.%03u",
342                                   NULL, /* child setup */             n, (int)lat_int, (int)lat_mint, (int)(lat_frac*1000.0+0.5),
343                                   NULL, /* user data */             e, (int)lon_int, (int)lon_mint, (int)(lon_frac*1000.0+0.5)));
344                                   &pid,  
345                                   &context->stdin_fd,    //  g_ptr_array_add (context->argv, g_strdup_printf("2>&1"));
346                                   &context->stdout_fd,    g_ptr_array_add (context->argv, NULL);
347                                   &context->stderr_fd,  
348                                   &error)) {    /* show all entries */
349      g_ptr_array_free(gt_argv, TRUE);    g_ptr_array_foreach(context->argv, arg_dsp, context);
350      if(proxy) g_free(proxy);  
351      appendf(&context->log, COLOR_ERR,    g_thread_create((GThreadFunc)thread_worker, context, FALSE, &error);
352              _("GeoToad failed to start: '%s'"), error->message);    if (error) {
353        appendf(&context->log, COLOR_ERR, "Error: %s\n", error->message);
354      g_error_free(error);      g_error_free(error);
     return;  
355    }    }
   g_ptr_array_free (gt_argv, TRUE);  
     if(proxy) g_free(proxy);  
   
   gt_watch = g_child_watch_source_new(pid);  
   g_source_set_callback(gt_watch, (GSourceFunc) child_state_cb, NULL, NULL);  
   
   g_source_attach(gt_watch, NULL);  
   g_source_unref(gt_watch);  
   
   /* make nonblocking */  
   if(fcntl(context->stdout_fd, F_SETFL, O_NONBLOCK) == -1)  
     perror("fcntl failed");  
   
   if(fcntl(context->stderr_fd, F_SETFL, O_NONBLOCK) == -1)  
     perror("fcntl failed");  
   
   /* use gdk to monitor read end of stdout */  
   context->stdout_tag = gdk_input_add(context->stdout_fd,  
                   GDK_INPUT_READ, child_input_cb, context);  
   context->stderr_tag = gdk_input_add(context->stderr_fd,  
                   GDK_INPUT_READ, child_input_cb, context);  
356  }  }
357    
358  void geotoad(appdata_t *appdata) {  /* show text window and display output of running geotoad */
359    gt_context_t *context = g_new0(gt_context_t, 1);  static void gui_run(gt_context_t *context) {
360    context->appdata = appdata;    GtkWidget *dialog = gtk_dialog_new_with_buttons(_("GeoToad - Run"),
361                              GTK_WINDOW(context->appdata->window),
   printf("geoToad\n");  
   
   GtkWidget *dialog = gtk_dialog_new_with_buttons(_("GeoToad"),  
                           GTK_WINDOW(appdata->window),  
362                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
363                            GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,                            GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
364                            NULL);                            NULL);
# Line 286  void geotoad(appdata_t *appdata) { Line 400  void geotoad(appdata_t *appdata) {
400    
401    gtk_widget_show_all(dialog);    gtk_widget_show_all(dialog);
402    
403    appendf(&context->log, COLOR_OK, "Running GeoToad\n");    appendf(&context->log, COLOR_SYSTEM, "Running GeoToad\n");
404    run(context);    run(context);
405    
406    gtk_dialog_run(GTK_DIALOG(dialog));    gtk_dialog_run(GTK_DIALOG(dialog));
407    
408    gtk_widget_destroy(dialog);    gtk_widget_destroy(dialog);
409    
410      errorf("Fertig!\n");
411    
412  }  }
413    
414    static void on_browse(GtkWidget *widget, gpointer data) {
415      gt_context_t *context = (gt_context_t*)data;
416    
417      printf("Browse %p\n", context->dialog);
418    
419    #ifdef USE_MAEMO
420      GtkWidget *dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(context->dialog),
421                                              GTK_FILE_CHOOSER_ACTION_SAVE);
422    #else
423      GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Save GPX file"),
424                                           GTK_WINDOW(context->dialog),
425                                           GTK_FILE_CHOOSER_ACTION_SAVE,
426                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
427                                           GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
428                                           NULL);
429    #endif
430    
431      printf("set filename <%s>\n", context->appdata->gt.filename);
432    
433      if(!g_file_test(context->appdata->gt.filename, G_FILE_TEST_EXISTS)) {
434        char *last_sep = strrchr(context->appdata->gt.filename, '/');
435        if(last_sep) {
436          *last_sep = 0;  // seperate path from file
437    
438          /* the user just created a new document */
439          gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
440                                              context->appdata->gt.filename);
441          gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), last_sep+1);
442    
443          /* restore full filename */
444          *last_sep = '/';
445        }
446      } else
447        gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
448                                      context->appdata->gt.filename);
449    
450      if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) {
451        gchar *name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
452        gtk_label_set_text(GTK_LABEL(context->filename), name);
453      }
454    
455      gtk_widget_destroy (dialog);
456    }
457    
458    static gboolean gui_setup(gt_context_t *context) {
459      appdata_t *appdata = context->appdata;
460      gboolean ok = FALSE;
461    
462      /* if no filename has been setup yet, create one */
463      if(!appdata->gt.filename && appdata->path) {
464        printf("creating path\n");
465        appdata->gt.filename =
466          g_strdup_printf("%s/gtoad.gpx", appdata->path);
467      }
468    
469      context->dialog = gtk_dialog_new_with_buttons(_("GeoToad - Setup"),
470                            GTK_WINDOW(appdata->window),
471                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
472                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
473                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
474                            NULL);
475    
476      /* ------------------- Coordinates ------------------------- */
477      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
478    
479      GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
480      gtk_box_pack_start_defaults(GTK_BOX(vbox), left_label_new(_("Position:")));
481      gtk_box_pack_start_defaults(GTK_BOX(vbox), left_label_new(_("Distance:")));
482      gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
483    
484      /* setup default positions */
485      pos_t *refpos = get_pos(appdata);
486      if((isnan(appdata->gt.lat) || isnan(appdata->gt.lat)) && refpos) {
487        appdata->gt.lat = refpos->lat;
488        appdata->gt.lon = refpos->lon;
489      }
490    
491      vbox = gtk_vbox_new(FALSE, 0);
492      GtkWidget *ihbox = gtk_hbox_new(FALSE, 0);
493      context->lat = lat_entry_new(appdata->gt.lat);
494      gtk_box_pack_start_defaults(GTK_BOX(ihbox), context->lat);
495      context->lon = lon_entry_new(appdata->gt.lon);
496      gtk_box_pack_start_defaults(GTK_BOX(ihbox), context->lon);
497      gtk_box_pack_start_defaults(GTK_BOX(vbox), ihbox);
498      float dst = appdata->gt.distance;  // distance is given in kilometers
499      if(appdata->imperial) dst /= 1.609344;
500      context->dst = dist_entry_new(dst, appdata->imperial);
501      gtk_box_pack_start_defaults(GTK_BOX(vbox), context->dst);
502      gtk_box_pack_start_defaults(GTK_BOX(hbox), vbox);
503    
504      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), hbox);
505    
506      /* ------------------- file name ------------------------- */
507      hbox = gtk_hbox_new(FALSE, 0);
508    
509      context->filename = gtk_label_new(appdata->gt.filename);
510      gtk_misc_set_alignment(GTK_MISC(context->filename), 0.f, 0.5f);
511      gtk_label_set_ellipsize(GTK_LABEL(context->filename), PANGO_ELLIPSIZE_MIDDLE);
512      gtk_box_pack_start_defaults(GTK_BOX(hbox), context->filename);
513    
514      GtkWidget *button = gtk_button_new_with_label(_("Browse"));
515    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
516      hildon_gtk_widget_set_theme_size(button,
517               (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
518    #endif
519      gtk_signal_connect(GTK_OBJECT(button), "clicked",
520                         GTK_SIGNAL_FUNC(on_browse), context);
521      gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
522    
523      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), hbox);
524    
525    
526      /* ------------------- Username/Password ------------------------- */
527      hbox = gtk_hbox_new(FALSE, 0);
528      vbox = gtk_vbox_new(FALSE, 0);
529      gtk_box_pack_start_defaults(GTK_BOX(vbox), left_label_new(_("Username:")));
530      gtk_box_pack_start_defaults(GTK_BOX(vbox), left_label_new(_("Password:")));
531      gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
532    
533      vbox = gtk_vbox_new(FALSE, 0);
534    #ifndef FREMANTLE
535      context->username = gtk_entry_new();
536      context->password = gtk_entry_new();
537    #else
538      context->username = hildon_entry_new(HILDON_SIZE_AUTO);
539      hildon_gtk_entry_set_input_mode(GTK_ENTRY(context->username),
540                                      HILDON_GTK_INPUT_MODE_FULL);
541      context->password = hildon_entry_new(HILDON_SIZE_AUTO);
542      hildon_gtk_entry_set_input_mode(GTK_ENTRY(context->password),
543                                      HILDON_GTK_INPUT_MODE_FULL);
544    #endif
545      gtk_entry_set_visibility(GTK_ENTRY(context->password), FALSE);
546    
547      /* set saved defaults */
548      if(appdata->username)
549        gtk_entry_set_text(GTK_ENTRY(context->username),
550                           appdata->username);
551    
552      if(appdata->gt.password)
553        gtk_entry_set_text(GTK_ENTRY(context->password),
554                           appdata->gt.password);
555    
556      gtk_box_pack_start_defaults(GTK_BOX(vbox), context->username);
557      gtk_box_pack_start_defaults(GTK_BOX(vbox), context->password);
558      gtk_box_pack_start_defaults(GTK_BOX(hbox), vbox);
559    
560      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), hbox);
561    
562      gtk_dialog_set_default_response(GTK_DIALOG(context->dialog), GTK_RESPONSE_OK);
563    
564      gtk_widget_show_all(context->dialog);
565    
566      if(gtk_dialog_run(GTK_DIALOG(context->dialog)) == GTK_RESPONSE_OK) {
567    
568        /* parse coordinates */
569        appdata->gt.lat = lat_get(context->lat);
570        appdata->gt.lon = lon_get(context->lon);
571    
572        /* save values */
573        if(appdata->username) g_free(appdata->username);
574        appdata->username =
575          g_strdup(gtk_entry_get_text(GTK_ENTRY(context->username)));
576    
577        if(appdata->gt.password) g_free(appdata->gt.password);
578        appdata->gt.password =
579          g_strdup(gtk_entry_get_text(GTK_ENTRY(context->password)));
580    
581        if(appdata->gt.filename) g_free(appdata->gt.filename);
582        appdata->gt.filename =
583          g_strdup(gtk_label_get_text(GTK_LABEL(context->filename)));
584    
585        /* get distance in kilometers */
586        appdata->gt.distance = dist_get(context->dst, FALSE);
587    
588    
589        /* check for valid entries */
590        if(isnan(appdata->gt.lat) || isnan(appdata->gt.lon) ||
591           isnan(appdata->gt.distance) || !appdata->gt.filename ||
592           !appdata->username || !appdata->gt.password)
593          errorf(_("GeoToad setup not complete"));
594        else
595          ok = TRUE;
596      }
597    
598      gtk_widget_destroy(context->dialog);
599    
600      return ok;
601    }
602    
603    void geotoad(appdata_t *appdata) {
604      if(!geotoad_available()) {
605        errorf(_("GeoToad is not installed on this device.\n"
606                 "You need to install it in order to be able to use it."));
607        return;
608      }
609    
610      gt_context_t *context = g_new0(gt_context_t, 1);
611      context->appdata = appdata;
612      context->use_cnt++;          // parent still uses this
613    
614      context->update_mutex = g_mutex_new();
615      context->update_cond = g_cond_new();
616      //  context->mutex_to_run = mutex_to_run;
617    
618      printf("geoToad\n");
619    
620      if(gui_setup(context))
621        gui_run(context);
622    
623      printf("main context free\n");
624      context_free(context);
625    }
626    
627    gboolean geotoad_available(void) {
628      /* before doing anything make sure geotoad is installed */
629      return g_file_test(GEOTOAD, G_FILE_TEST_IS_EXECUTABLE);
630    }
631    
632    

Legend:
Removed from v.194  
changed lines
  Added in v.208