]> git.itanic.dy.fi Git - maemo-mapper/blob - src/aprs_display.c
Corrected 'Centre Map' bug in station list view
[maemo-mapper] / src / aprs_display.c
1 /*
2  * Created by Rob Williams - 10 Aug 2008
3  * 
4  * This file is part of Maemo Mapper.
5  *
6  * Maemo Mapper 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  * Maemo Mapper 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 Maemo Mapper.  If not, see <http://www.gnu.org/licenses/>.
18  * 
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #    include "config.h"
23 #endif
24
25 #ifdef INCLUDE_APRS
26
27 #include "aprs_display.h"
28 #include "aprs_message.h"
29 #include "types.h"
30 #include "aprs.h"
31
32 #define _GNU_SOURCE
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
37 #include <dbus/dbus-glib.h>
38 #include <bt-dbus.h>
39 #include <gconf/gconf-client.h>
40
41 #ifndef LEGACY
42 #    include <hildon/hildon-help.h>
43 #    include <hildon/hildon-note.h>
44 #    include <hildon/hildon-color-button.h>
45 #    include <hildon/hildon-file-chooser-dialog.h>
46 #    include <hildon/hildon-number-editor.h>
47 #    include <hildon/hildon-banner.h>
48 #else
49 #    include <osso-helplib.h>
50 #    include <hildon-widgets/hildon-note.h>
51 #    include <hildon-widgets/hildon-color-button.h>
52 #    include <hildon-widgets/hildon-file-chooser-dialog.h>
53 #    include <hildon-widgets/hildon-number-editor.h>
54 #    include <hildon-widgets/hildon-banner.h>
55 #    include <hildon-widgets/hildon-input-mode-hint.h>
56 #endif
57
58 #include "types.h"
59 #include "data.h"
60 #include "defines.h"
61
62 #include "gps.h"
63 #include "display.h"
64 #include "gdk-pixbuf-rotate.h"
65 #include "maps.h"
66 #include "marshal.h"
67 #include "poi.h"
68 #include "settings.h"
69 #include "util.h"
70
71 extern AprsDataRow *n_first;
72
73 typedef struct _AprsStationSelectInfo AprsStationSelectInfo;
74 struct _AprsStationSelectInfo
75 {
76     GtkWidget *dialog;
77     GtkWidget *tree_view;
78     gint      column_index;
79     gchar     *call_sign;
80 };
81
82 static AprsStationSelectInfo selected_station;
83
84
85
86 double convert_lat_l2d(long lat);
87 double convert_lon_l2d(long lon);
88 static gboolean panto_station(GtkWidget *widget, AprsStationSelectInfo *aprs_station_sel);
89
90 void convert_temp_f_to_c(gchar * f, gchar ** c)
91 {
92         *c = g_strdup("        ");
93         
94         gdouble df = 0.0;
95         gdouble dc = 0.0;
96         
97         // Convert fahrenheit to fahrenheit (double)
98         df = g_ascii_strtod ( f, (gchar*)(f + strlen(f)));
99         
100         // Convert ff to fc
101         dc = 5*((df - 32.0)/9);
102         
103         // Convert fc to celsius
104         snprintf(*c, 8, "%0.1f°C", dc);
105 }
106
107 void setup_aprs_basic_wx_display_page(GtkWidget *notebook, AprsDataRow *p_station)
108 {
109     GtkWidget *table;
110     GtkWidget *label;
111     
112
113     gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
114         table = gtk_table_new(4/*rows*/, 4/*columns*/, FALSE/*All cells same size*/),
115         label = gtk_label_new(_("WX")));
116
117     /* Last update */    
118     gchar last_update_time[26];
119     
120     gtk_table_attach(GTK_TABLE(table),
121         label = gtk_label_new("Updated:"),
122             0, 1, 0, 1, GTK_FILL, 0, 2, 4);
123     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
124
125     
126     
127     if(p_station->weather_data && p_station->weather_data->wx_sec_time)
128     {
129          strftime(last_update_time, 25, "%x %X", localtime(&p_station->weather_data->wx_sec_time));
130     }
131     else
132     {
133         snprintf(last_update_time, 25, " ");
134     }
135     
136     gtk_table_attach(GTK_TABLE(table),
137                 label = gtk_label_new( last_update_time ),
138             1, 4, 0, 1, GTK_EXPAND |GTK_FILL, 0, 2, 4);
139     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
140         
141     
142     /* Temperature */
143     gchar * temp = NULL;
144     
145     gtk_table_attach(GTK_TABLE(table),
146         label = gtk_label_new("Temp:"),
147             0, 1, 1, 2, GTK_FILL, 0, 2, 4);
148     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
149
150     
151     if(p_station->weather_data && p_station->weather_data->wx_temp)
152     {
153         convert_temp_f_to_c(p_station->weather_data->wx_temp, &temp);
154     }
155     else
156     {
157         temp = g_strdup("");
158     }
159     
160     gtk_table_attach(GTK_TABLE(table),
161                 label = gtk_label_new( temp ),
162             1, 2, 1, 2, GTK_FILL, 0, 2, 4);
163     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
164     
165     g_free(temp);
166     
167     /////////////////
168
169     gtk_table_attach(GTK_TABLE(table),
170         label = gtk_label_new( (p_station->weather_data->wx_storm ? "SEVERE STORM" : "")  ),
171             2, 4, 1, 2, GTK_EXPAND |GTK_FILL, 0, 2, 4);
172     gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
173
174
175     /////
176     gchar course[7];
177     gtk_table_attach(GTK_TABLE(table),
178         label = gtk_label_new( "Wind course:"  ),
179             0, 1, 2, 3, GTK_FILL, 0, 2, 4);
180     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
181     
182     snprintf(course, 6, "%0.f°", 
183                 g_ascii_strtod (p_station->weather_data->wx_course, p_station->weather_data->wx_course + strlen(p_station->weather_data->wx_course))
184                 );
185     gtk_table_attach(GTK_TABLE(table),
186         label = gtk_label_new( course ),
187             1, 2, 2, 3, GTK_FILL, 0, 2, 4);
188     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
189     
190 //    g_free(course);
191     
192     /////
193     gchar speed[15];
194     gtk_table_attach(GTK_TABLE(table),
195         label = gtk_label_new( "Wind speed:"  ),
196             2, 3, 2, 3, GTK_FILL, 0, 2, 4);
197     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
198
199     snprintf(speed, 14, "%0.f->%0.f MPH",
200                 g_ascii_strtod (p_station->weather_data->wx_speed, p_station->weather_data->wx_speed + strlen(p_station->weather_data->wx_speed)),
201                 g_ascii_strtod (p_station->weather_data->wx_gust, p_station->weather_data->wx_gust + strlen(p_station->weather_data->wx_gust))
202                 );
203     gtk_table_attach(GTK_TABLE(table),
204         label = gtk_label_new( speed ),
205             3, 4, 2, 3, GTK_FILL, 0, 2, 4);
206     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
207     
208   
209
210     
211     /////
212     gchar rain_ph[17];
213     gchar rain_total[17];
214     
215     gtk_table_attach(GTK_TABLE(table),
216         label = gtk_label_new( "Rain fall:"  ),
217             0, 1, 3, 4, GTK_FILL, 0, 2, 4);
218     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
219
220     if(p_station->weather_data->wx_rain)
221     {
222             snprintf(rain_ph, 16, "%0.f \"/hr",
223                         g_ascii_strtod (p_station->weather_data->wx_rain, p_station->weather_data->wx_rain + strlen(p_station->weather_data->wx_rain))
224                         );
225     }
226     else
227     {
228         snprintf(rain_ph, 1, " ");
229     }
230     gtk_table_attach(GTK_TABLE(table),
231         label = gtk_label_new( rain_ph ),
232             1, 2, 3, 4, GTK_FILL, 0, 2, 4);
233     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
234
235     
236     gtk_table_attach(GTK_TABLE(table),
237         label = gtk_label_new( "Total:"  ),
238             2, 3, 3, 4, GTK_FILL, 0, 2, 4);
239     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
240
241     if(p_station->weather_data->wx_rain_total)
242     {
243             snprintf(rain_total, 16, "%0.f \"",
244                         g_ascii_strtod (p_station->weather_data->wx_rain_total, p_station->weather_data->wx_rain_total + strlen(p_station->weather_data->wx_rain_total))
245                         );
246     }
247     else
248     {
249         snprintf(rain_total, 1, " ");
250     }
251     gtk_table_attach(GTK_TABLE(table),
252         label = gtk_label_new( rain_total ),
253             3, 4, 3, 4, GTK_FILL, 0, 2, 4);
254     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
255     
256     
257     
258     /*
259
260     char    wx_hurricane_radius[4];  //nautical miles       3
261     char    wx_trop_storm_radius[4]; //nautical miles       3
262     char    wx_whole_gale_radius[4]; // nautical miles      3
263     char    wx_snow[6];         // in inches/24h            3
264     char    wx_prec_24[10];     // in hundredths inch/day   3
265     char    wx_prec_00[10];     // in hundredths inch       3
266     char    wx_hum[5];          // in %                     3
267     char    wx_baro[10];        // in hPa                   6
268     char    wx_fuel_temp[5];    // in °F                    3
269     char    wx_fuel_moisture[5];// in %                     2
270     char    wx_type;
271     char    wx_station[MAX_WXSTATION];
272 */
273
274 }
275
276 void setup_aprs_moving_display_page(GtkWidget *notebook, AprsDataRow *p_station)
277 {
278     GtkWidget *table;
279     GtkWidget *label;
280
281     gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
282         table = gtk_table_new(4/*rows*/, 4/*columns*/, FALSE/*All cells same size*/),
283         label = gtk_label_new(_("Moving")));
284
285
286     ////////////
287     gtk_table_attach(GTK_TABLE(table),
288         label = gtk_label_new("Speed:"),
289             0, 1, 0, 1, GTK_FILL, 0, 2, 4);
290     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
291
292   
293     gchar speed[15];
294     
295 //    snprintf(speed, sizeof(speed), "%.01f %s", atof(p_station->speed) * UNITS_CONVERT[_units], 
296 //              UNITS_ENUM_TEXT[_units]);
297     
298     if(_units == UNITS_NM)
299         snprintf(speed, sizeof(speed), "%.01f nmph", atof(p_station->speed));
300     else if(_units == UNITS_KM)
301         snprintf(speed, sizeof(speed), "%.01f kph", atof(p_station->speed)*1.852);
302     else if(_units == UNITS_MI)
303         snprintf(speed, sizeof(speed), "%.01f mph", atof(p_station->speed)*1.1508);
304
305     
306     gtk_table_attach(GTK_TABLE(table),
307                 label = gtk_label_new( speed ),
308             1, 2, 0, 1, GTK_FILL, 0, 2, 4);
309     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
310     
311     
312
313     ////////////
314     gtk_table_attach(GTK_TABLE(table),
315         label = gtk_label_new("Course:"),
316             0, 1, 1, 2, GTK_FILL, 0, 2, 4);
317     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
318
319     
320     gtk_table_attach(GTK_TABLE(table),
321                 label = gtk_label_new( p_station->course ),
322             1, 2, 1, 2, GTK_FILL, 0, 2, 4);
323     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
324     
325     ////////////
326     gtk_table_attach(GTK_TABLE(table),
327         label = gtk_label_new("Alt (m):"),
328             0, 1, 2, 3, GTK_FILL, 0, 2, 4);
329     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
330
331     
332     gtk_table_attach(GTK_TABLE(table),
333                 label = gtk_label_new( p_station->altitude ),
334             1, 2, 2, 3, GTK_FILL, 0, 2, 4);
335     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
336
337     ////////////
338     gtk_table_attach(GTK_TABLE(table),
339         label = gtk_label_new("Bearing:"),
340             0, 1, 3, 4, GTK_FILL, 0, 2, 4);
341     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
342
343     
344     gtk_table_attach(GTK_TABLE(table),
345                 label = gtk_label_new( p_station->bearing ),
346             1, 2, 3, 4, GTK_FILL, 0, 2, 4);
347     
348     /*   
349     GdkPixmap *pixmap=gdk_pixmap_new(table->window,100,100,16);
350     //gdk_drawable_set_colormap (pixmap,gdk_colormap_get_system ());
351
352
353     GtkWidget *image = NULL;
354  
355     GdkColor color;
356     GdkGC * gc;
357     gc = gdk_gc_new(pixmap);
358     color.red = 0;
359     color.green = 0;
360     color.blue = 0;
361
362     gdk_gc_set_foreground(gc, &color);
363     
364     color.red = 255;
365     color.green = 255;
366     color.blue = 255;
367     gdk_gc_set_background(gc, &color);
368
369     
370     gdk_gc_set_line_attributes(gc, _draw_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
371             
372         gdk_draw_arc (
373                         pixmap, 
374                         gc,
375                         FALSE,
376                         2, 2,
377                         96, 96,
378                         0, 360*64
379                         );
380         
381         gdouble heading = deg2rad(atof(p_station->course));
382         gint y = (gint)(48.0 * cosf(heading) );
383         gint x = (gint)(48.0 * sinf(heading) );
384         
385         gdk_draw_line (
386                         pixmap, 
387                         gc,
388                         50, 50,
389                         50+x, 50-y);
390           
391     gtk_table_attach(GTK_TABLE(table),
392                 image = gtk_image_new_from_pixmap(pixmap, NULL),
393                 2, 3, 0, 4, GTK_FILL, 0, 2, 4);
394                 //2, 3, 0, 4, GTK_SHRINK, GTK_SHRINK, 2, 4);
395     gtk_misc_set_alignment(GTK_MISC(image), 1.0f, 0.5f);
396      
397     
398 //    g_object_unref(image);
399 //    gdk_pixmap_unref(pixmap);
400  
401  * */
402 }
403
404
405 void setup_aprs_station_stats_page(GtkWidget *notebook, AprsDataRow *p_station)
406 {
407     GtkWidget *table;
408     GtkWidget *label;
409     gchar distance[15];
410     gchar lat[15], lon[15];
411     gchar course_deg[9];
412
413     
414     gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
415         table = gtk_table_new(4/*rows*/, 5/*columns*/, FALSE/*All cells same size*/),
416         label = gtk_label_new(_("Location")));
417
418     ////////////
419     
420     course_deg[0] = '\0';
421     distance[0] = '\0';
422     lat[0] = '\0';
423     lon[0] = '\0';
424     
425
426         if(p_station->coord_lat != 0 || p_station->coord_lon != 0)
427         {
428                 gdouble d_lat = convert_lat_l2d(p_station->coord_lat);
429                 gdouble d_lon = convert_lon_l2d(p_station->coord_lon);
430
431                 format_lat_lon(d_lat, d_lon, lat, lon);
432             
433                 gfloat dist = (float)calculate_distance(_gps.lat, _gps.lon, d_lat, d_lon);
434                 
435                 
436                 snprintf(distance, sizeof(distance), "%.01f %s", dist * UNITS_CONVERT[_units], UNITS_ENUM_TEXT[_units]);
437
438                 snprintf(course_deg,  sizeof(course_deg),
439                                 "%.01f°",
440                                 calculate_bearing(_gps.lat, _gps.lon, d_lat, d_lon));
441         }
442
443     /* Last heard */    
444     gchar last_update_time[26];
445     
446     gtk_table_attach(GTK_TABLE(table),
447         label = gtk_label_new("Last Heard:"),
448             0, 1, 4, 5, GTK_FILL, 0, 2, 4);
449     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
450
451     
452     
453     if(p_station->sec_heard)
454     {
455          strftime(last_update_time, 25, "%x %X", localtime(&p_station->sec_heard));
456     }
457     else
458     {
459         snprintf(last_update_time, 25, " ");
460     }
461     
462     gtk_table_attach(GTK_TABLE(table),
463                 label = gtk_label_new( last_update_time ),
464             1, 4, 4, 5, GTK_FILL, 0, 2, 4);
465     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
466         
467
468     
469         ////////////
470         gtk_table_attach(GTK_TABLE(table),
471         label = gtk_label_new("Location:"),
472             0, 1, 1, 2, GTK_FILL, 0, 2, 4);
473     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
474
475     gtk_table_attach(GTK_TABLE(table),
476                 label = gtk_label_new( lat ),
477             1, 3, 1, 2, GTK_EXPAND |GTK_FILL, 0, 2, 4);
478     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
479
480     gtk_table_attach(GTK_TABLE(table),
481                 label = gtk_label_new( lon ),
482             3, 5, 1, 2, GTK_EXPAND |GTK_FILL, 0, 2, 4);
483     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
484
485     ////////////
486     
487     gtk_table_attach(GTK_TABLE(table),
488         label = gtk_label_new(""),
489             0, 5, 2, 3, GTK_FILL, 0, 2, 4);
490     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
491
492     
493     ////////////
494     gtk_table_attach(GTK_TABLE(table),
495         label = gtk_label_new("Distance:"),
496             0, 1, 3, 4, GTK_FILL, 0, 2, 4);
497     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
498
499     gtk_table_attach(GTK_TABLE(table),
500                 label = gtk_label_new( distance ),
501             1, 2, 3, 4, GTK_FILL, 0, 2, 4);
502     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
503
504     //
505     
506     gtk_table_attach(GTK_TABLE(table),
507         label = gtk_label_new("Bearing:"),
508             2, 4, 3, 4, GTK_EXPAND |GTK_FILL, 0, 2, 4);
509     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
510
511     gtk_table_attach(GTK_TABLE(table),
512                 label = gtk_label_new( course_deg ),
513             4, 5, 3, 4, GTK_FILL, 0, 2, 4);
514     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
515  
516
517     ////////////
518     
519 }
520
521
522 void setup_aprs_basic_display_page(GtkWidget *notebook, AprsDataRow *p_station)
523 {
524     GtkWidget *table;
525     GtkWidget *label;
526
527     gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
528         table = gtk_table_new(5/*rows*/, 5/*columns*/, FALSE/*All cells same size*/),
529         label = gtk_label_new(_("Basic")));
530
531     /* Callsign. */
532     // Label
533     
534     gtk_table_attach(GTK_TABLE(table),
535         label = gtk_label_new("Callsign:"),
536             0, 1, 0, 1, GTK_FILL, 0, 2, 4);
537     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
538
539     
540     
541     gtk_table_attach(GTK_TABLE(table),
542                 label = gtk_label_new( p_station->call_sign ),
543             1, 2, 0, 1, GTK_FILL, 0, 2, 4);
544     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
545
546     
547     GdkPixbuf *pixbuf = NULL;
548     
549     gint symbol_column = 0;
550     gint symbol_row    = 0;
551     gint symbol_size = 0;
552
553     extract_aprs_symbol(p_station->aprs_symbol.aprs_symbol, p_station->aprs_symbol.aprs_type, &pixbuf, 
554                 &symbol_size, 
555                 &symbol_column, 
556                 &symbol_row);
557     
558     
559
560     GdkPixmap *pixmap=gdk_pixmap_new(table->window,symbol_size,symbol_size,16);
561     
562         
563     // We found an icon to draw. 
564     gdk_draw_pixbuf(
565         pixmap,
566         _gc[COLORABLE_POI],
567         pixbuf,
568         symbol_size*symbol_column, symbol_size*symbol_row,
569         0,
570         0,
571         symbol_size, symbol_size,
572         GDK_RGB_DITHER_NONE, 0, 0);
573     g_object_unref(pixbuf);
574
575     GtkWidget *image;
576
577     gtk_table_attach(GTK_TABLE(table),
578                 image = gtk_image_new_from_pixmap(pixmap, NULL),
579         2, 3, 0, 1, GTK_FILL, 0, 2, 4);
580     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
581
582     gtk_table_attach(GTK_TABLE(table),
583         label = gtk_label_new("Packets:"),
584             3, 4, 0, 1, GTK_FILL, 0, 2, 4);
585     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
586
587     
588     gchar packets[5];
589     snprintf(packets, 4, "%u", p_station->num_packets);
590     
591     gtk_table_attach(GTK_TABLE(table),
592                 label = gtk_label_new( packets ),
593             4, 5, 0, 1, GTK_FILL, 0, 2, 4);
594     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
595     
596     gtk_table_attach(GTK_TABLE(table),
597                 label  = gtk_label_new("Comment:"),
598             0, 1, 1, 3, GTK_FILL, 0, 2, 4);
599     gtk_misc_set_alignment(GTK_MISC(label ), 1.f, 0.5f);
600     
601     gchar * comment = NULL;
602     
603     
604     if(p_station->comment_data && p_station->comment_data->text_ptr)
605     {
606         comment = g_strdup(p_station->comment_data->text_ptr);
607     }
608     else
609     {
610         comment = g_strdup("");
611     }
612     
613     gtk_table_attach(GTK_TABLE(table),
614                 label  = gtk_label_new(comment),
615             1, 5, 1, 3, GTK_EXPAND |GTK_FILL, 0, 2, 4);
616     gtk_misc_set_alignment(GTK_MISC(label ), 0.f, 0.5f);
617     gtk_label_set_width_chars(label, 30);
618     
619     
620     
621     //// 
622
623     gtk_table_attach(GTK_TABLE(table),
624                 label  = gtk_label_new("Status:"),
625             0, 1, 3, 4, GTK_FILL, 0, 2, 4);
626     gtk_misc_set_alignment(GTK_MISC(label ), 1.f, 0.5f);
627     
628     gchar * status = NULL;
629     
630     
631     if(p_station->status_data && p_station->status_data->text_ptr)
632     {
633         status = g_strdup(p_station->status_data->text_ptr);
634     }
635     else
636     {
637         status = g_strdup("");
638     }
639     
640     gtk_table_attach(GTK_TABLE(table),
641                 label  = gtk_label_new(status),
642             1, 5, 3, 4, GTK_FILL, 0, 2, 4);
643     gtk_misc_set_alignment(GTK_MISC(label ), 0.f, 0.5f);
644     
645     
646     //// 
647
648     gtk_table_attach(GTK_TABLE(table),
649                 label  = gtk_label_new("Path:"),
650             0, 1, 4, 5, GTK_FILL, 0, 2, 4);
651     gtk_misc_set_alignment(GTK_MISC(label ), 1.f, 0.5f);
652     
653     gchar * path = NULL;
654     
655     if(p_station->node_path_ptr)
656     {
657         path = g_strdup(p_station->node_path_ptr);
658     }
659     else
660     {
661         path = g_strdup("");
662     }
663     
664     gtk_table_attach(GTK_TABLE(table),
665                 label  = gtk_label_new(path),
666             1, 5, 4, 5, GTK_FILL, 0, 2, 4);
667     gtk_misc_set_alignment(GTK_MISC(label ), 0.f, 0.5f);
668         
669     
670
671     
672 }
673
674
675
676 void ShowAprsStationPopup(AprsDataRow *p_station)
677 {
678         GtkWidget *dialog = NULL;
679         GtkWidget *notebook = NULL;
680         GtkWidget *btn_panto = NULL;
681
682         dialog = gtk_dialog_new_with_buttons(_("Station Details"),
683                 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
684                 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
685 //                "Send Message...", GTK_RESPONSE_ACCEPT,
686                 NULL);
687         
688     
689     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
690                 btn_panto = gtk_button_new_with_mnemonic(_("C_entre Map...")));
691             
692     
693     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
694             notebook = gtk_notebook_new(), TRUE, TRUE, 0);
695         
696
697     selected_station.dialog = NULL;
698     selected_station.tree_view = NULL;
699     selected_station.column_index = 0;
700     selected_station.call_sign = p_station->call_sign;
701     
702     g_signal_connect(G_OBJECT(btn_panto), "clicked",
703                 G_CALLBACK(panto_station), &selected_station);
704     
705     
706         setup_aprs_basic_display_page(notebook, p_station);
707         
708         
709         if(p_station->weather_data )
710                 setup_aprs_basic_wx_display_page(notebook, p_station);
711
712         
713         
714         if( ( p_station->flag & ST_MOVING) == ST_MOVING){
715                 setup_aprs_moving_display_page(notebook, p_station);
716         }
717         
718         
719         
720         setup_aprs_station_stats_page(notebook, p_station);
721         
722     gtk_widget_show_all(dialog);
723     gtk_dialog_run(GTK_DIALOG(dialog));  
724     gtk_widget_hide(dialog);
725     
726
727 }
728
729
730
731
732
733 void list_stations()
734 {
735     static GtkWidget *dialog = NULL;
736     static GtkWidget *list = NULL;
737     static GtkWidget *sw = NULL;
738     static GtkWidget *btn_panto = NULL;
739     static GtkTreeViewColumn *column = NULL;
740     static GtkCellRenderer *renderer = NULL;
741     GtkListStore *store = NULL;
742     GtkTreeIter iter;
743     gint station_count = 0;
744
745     gint num_cats = 0;
746
747     printf("%s()\n", __PRETTY_FUNCTION__);
748     
749     typedef enum
750     {
751         STATION_CALLSIGN,
752         STATION_DISTANCE,
753         STATION_BEARING,
754         STATION_COMMENT,
755         STATION_DISTANCE_NUM,
756         STATION_NUM_COLUMNS
757     } StationList;
758     
759     /* Initialize store. */
760     store = gtk_list_store_new(STATION_NUM_COLUMNS,
761                 G_TYPE_STRING,
762                 G_TYPE_STRING,
763                 G_TYPE_STRING,
764                 G_TYPE_STRING,
765                 G_TYPE_DOUBLE);/* Category Label */
766  
767     AprsDataRow *p_station = n_first;
768
769     while ( (p_station) != NULL) 
770     {
771         station_count++;
772         
773         gchar * comment = NULL;
774         gchar * callsign = g_strdup(p_station->call_sign);
775         gchar course_deg[8];
776         gchar * formatted_distance = NULL;
777         gdouble distance = 0;
778         
779         course_deg[0] = '\0';
780          
781         
782         if(p_station->coord_lat != 0 && p_station->coord_lon != 0)
783         {
784                 distance = distance_from_my_station(callsign, course_deg, sizeof(course_deg));
785                 
786                 if(_units == UNITS_KM)
787                         formatted_distance = g_strdup_printf("%.01f km", distance);
788                 else if(_units == UNITS_MI)
789                         formatted_distance = g_strdup_printf("%.01f miles", distance);
790                 else if(_units == UNITS_NM)
791                         formatted_distance = g_strdup_printf("%.01f nm", distance); 
792         }
793         else
794         {
795                 formatted_distance = g_strdup_printf("");
796         }
797         
798         if(p_station->comment_data) comment = g_strdup(p_station->comment_data->text_ptr);
799         else comment = g_strdup("");
800         
801   
802         gtk_list_store_append(store, &iter);
803         gtk_list_store_set(store, &iter,
804                         STATION_CALLSIGN, callsign,
805                         STATION_DISTANCE, formatted_distance,
806                         STATION_BEARING, course_deg,
807                         STATION_COMMENT, comment,
808                         STATION_DISTANCE_NUM, distance,
809                 -1);
810         num_cats++;
811         
812         g_free(comment);
813         g_free(callsign);
814         g_free(formatted_distance);
815         
816         (p_station) = (p_station)->n_next;  // Next element in list
817     } // End of while loop
818
819     gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), STATION_DISTANCE_NUM, GTK_SORT_ASCENDING);
820     
821
822
823     if(dialog == NULL)
824     {
825         dialog = gtk_dialog_new_with_buttons(_("Stations"),
826                 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
827                 "Details", GTK_RESPONSE_ACCEPT,
828                 GTK_STOCK_CLOSE, GTK_RESPONSE_REJECT,
829                 NULL);
830
831
832         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
833                         btn_panto = gtk_button_new_with_mnemonic(_("C_entre Map...")));
834                 
835         
836         
837         gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
838
839         sw = gtk_scrolled_window_new (NULL, NULL);
840         
841         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
842                 GTK_SHADOW_ETCHED_IN);
843         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
844                 GTK_POLICY_NEVER,
845                 GTK_POLICY_AUTOMATIC);
846         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
847                 sw, TRUE, TRUE, 0);
848
849         list = gtk_tree_view_new();
850         gtk_container_add(GTK_CONTAINER(sw), list);
851
852         gtk_tree_selection_set_mode(
853                 gtk_tree_view_get_selection(GTK_TREE_VIEW(list)),
854                 GTK_SELECTION_SINGLE);
855         gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
856
857         
858         //////
859         renderer = gtk_cell_renderer_text_new();
860         column = gtk_tree_view_column_new_with_attributes(
861                 _("Callsign"), renderer, "text", STATION_CALLSIGN, NULL);
862         gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
863
864         ///////
865         renderer = gtk_cell_renderer_text_new();
866         column = gtk_tree_view_column_new_with_attributes(
867                 _("Distance"), renderer, "text", STATION_DISTANCE, NULL);
868         gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
869
870         /////////
871         renderer = gtk_cell_renderer_text_new();
872         column = gtk_tree_view_column_new_with_attributes(
873                 _("Bearing"), renderer, "text", STATION_BEARING, NULL);
874         gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
875         
876
877         /////////
878         renderer = gtk_cell_renderer_text_new();
879         column = gtk_tree_view_column_new_with_attributes(
880                 _("Comment"), renderer, "text", STATION_COMMENT, NULL);
881         gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
882         
883
884                 
885     }
886
887     selected_station.dialog = dialog;
888     selected_station.tree_view = list;
889     selected_station.call_sign = NULL;
890     selected_station.column_index = STATION_CALLSIGN;
891     
892     g_signal_connect(G_OBJECT(btn_panto), "clicked",
893                 G_CALLBACK(panto_station), &selected_station);
894             
895     gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));
896     g_object_unref(G_OBJECT(store));
897
898     
899     //
900     gchar *title = g_strdup_printf("Stations (Total: %u)", station_count);
901     gtk_window_set_title(GTK_WINDOW(dialog), title);
902     g_free(title);
903     
904     gtk_widget_show_all(dialog);
905
906     while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
907     {
908
909         if(gtk_tree_selection_get_selected(
910                 gtk_tree_view_get_selection(GTK_TREE_VIEW(list)),
911                 NULL, &iter))
912         {
913                 gchar * callsign = NULL;
914             gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
915                 STATION_CALLSIGN, &(callsign),
916                 -1);
917             
918                 // Find the callsign
919                 p_station = n_first;
920                 while(p_station != NULL)
921                 {
922                     if(strcmp(p_station->call_sign,callsign) == 0)
923                         {
924                                 ShowAprsStationPopup(p_station);
925                                 break;
926                                 
927                         }
928
929                         
930                     p_station = p_station->n_next;
931                 }
932
933         }
934         
935
936         // Setup event again
937         selected_station.dialog = dialog;
938         selected_station.tree_view = list;
939         selected_station.call_sign = NULL;
940         selected_station.column_index = STATION_CALLSIGN;
941         
942         g_signal_connect(G_OBJECT(btn_panto), "clicked",
943                         G_CALLBACK(panto_station), &selected_station);
944
945
946
947     }
948
949     gtk_widget_hide(dialog);
950
951     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
952 }
953
954
955
956
957 static gboolean
958 send_message(GtkWidget *widget)
959 {
960         fprintf(stderr, "Send message...");
961         return FALSE;
962 }
963
964 static gboolean
965 panto_station(GtkWidget *widget, AprsStationSelectInfo *aprs_station_selected)
966 {
967     GtkTreeModel *store;
968     GtkTreeIter iter;
969     GtkTreeSelection *selection;
970         gchar * callsign = NULL;
971     AprsDataRow *p_station = n_first;
972     
973
974     printf("%s()\n", __PRETTY_FUNCTION__);
975
976     
977         if(aprs_station_selected->call_sign != NULL)
978                 callsign = aprs_station_selected->call_sign;
979         else
980         {
981                 store = gtk_tree_view_get_model(GTK_TREE_VIEW(aprs_station_selected->tree_view));
982             selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(aprs_station_selected->tree_view));
983             
984             if(gtk_tree_selection_get_selected(selection, &store, &iter))
985             {
986
987             gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
988                 aprs_station_selected->column_index, &(callsign),
989                 -1);
990
991             }
992         }
993         
994         // Now findout the location of callsign
995         
996         p_station = n_first;
997         while(p_station != NULL)
998         {
999         if(strcmp(p_station->call_sign,callsign) == 0)
1000                 {
1001                 if(p_station->coord_lat == 0 && p_station->coord_lon == 0)
1002                 {
1003                         // Invalid position
1004                 }
1005                 else
1006                 {       
1007                         gdouble d_lat = convert_lat_l2d(p_station->coord_lat);
1008                         gdouble d_lon = convert_lon_l2d(p_station->coord_lon);
1009                         Point unit;
1010         
1011                         
1012                     latlon2unit(d_lat, d_lon, unit.unitx, unit.unity);
1013         
1014                     if(_center_mode > 0)
1015                         gtk_check_menu_item_set_active(
1016                                 GTK_CHECK_MENU_ITEM(_menu_view_ac_none_item), TRUE);
1017         
1018                     map_center_unit(unit);
1019
1020                 }
1021         
1022                 
1023                         break;
1024                         
1025                 }
1026
1027         p_station = p_station->n_next;
1028         }
1029
1030         
1031                 
1032     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1033     return TRUE;
1034 }
1035
1036 void list_messages()
1037 {
1038         static GtkWidget *dialog = NULL;
1039 //      static GtkWidget *btn_send = NULL;
1040     static GtkWidget *list = NULL;
1041     static GtkWidget *sw = NULL;
1042     static GtkTreeViewColumn *column = NULL;
1043     static GtkCellRenderer *renderer = NULL;
1044     GtkListStore *store = NULL;
1045         GtkTreeIter iter;
1046
1047
1048     printf("%s()\n", __PRETTY_FUNCTION__);
1049
1050     typedef enum
1051     {
1052         MSG_FROM,
1053         MSG_TO,
1054         MSG_TEXT,
1055         MSG_TIMESTAMP,
1056         MSG_NUM_COLUMNS
1057     } MessageList;
1058     
1059     /* Initialize store. */
1060     store = gtk_list_store_new(MSG_NUM_COLUMNS,
1061                 G_TYPE_STRING,
1062                 G_TYPE_STRING,
1063                 G_TYPE_STRING,
1064                 G_TYPE_DOUBLE);
1065
1066     
1067     // Loop through each message
1068     
1069     gint  i = 0;
1070     for (i = 0; i < msg_index_end; i++) 
1071     {
1072         gtk_list_store_append(store, &iter);
1073         gtk_list_store_set(store, &iter,
1074                         MSG_FROM, msg_data[msg_index[i]].from_call_sign,
1075                         MSG_TO,   msg_data[msg_index[i]].call_sign,
1076                         MSG_TEXT, msg_data[msg_index[i]].message_line,
1077                         MSG_TIMESTAMP, (gdouble)msg_data[msg_index[i]].sec_heard,
1078                 -1);
1079         
1080     }
1081     
1082     gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), MSG_TIMESTAMP, GTK_SORT_ASCENDING);
1083         
1084     if(dialog == NULL)
1085     {
1086         dialog = gtk_dialog_new_with_buttons(_("Messages"),
1087                 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
1088                 GTK_STOCK_CLOSE, GTK_RESPONSE_REJECT,
1089                 NULL);
1090         
1091         gtk_window_set_default_size(GTK_WINDOW(dialog), 550, 300);
1092
1093 //        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
1094 //                      btn_send = gtk_button_new_with_label(_("Send...")));
1095         
1096 //        g_signal_connect(G_OBJECT(btn_send), "clicked",
1097 //                        G_CALLBACK(send_message), dialog);
1098         
1099                 sw = gtk_scrolled_window_new (NULL, NULL);
1100                 
1101                 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
1102                         GTK_SHADOW_ETCHED_IN);
1103                 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1104                         GTK_POLICY_NEVER,
1105                         GTK_POLICY_AUTOMATIC);
1106                 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1107                         sw, TRUE, TRUE, 0);
1108                 
1109         
1110                 list = gtk_tree_view_new();
1111                 gtk_container_add(GTK_CONTAINER(sw), list);
1112         
1113                 gtk_tree_selection_set_mode(
1114                         gtk_tree_view_get_selection(GTK_TREE_VIEW(list)),
1115                         GTK_SELECTION_SINGLE);
1116                 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
1117
1118         
1119
1120                 renderer = gtk_cell_renderer_text_new();
1121                 column = gtk_tree_view_column_new_with_attributes(
1122                         _("From"), renderer, "text", MSG_FROM, NULL);
1123                 gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
1124
1125                 renderer = gtk_cell_renderer_text_new();
1126                 column = gtk_tree_view_column_new_with_attributes(
1127                         _("To"), renderer, "text", MSG_TO, NULL);
1128                 gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
1129
1130                 renderer = gtk_cell_renderer_text_new();
1131                 column = gtk_tree_view_column_new_with_attributes(
1132                         _("Message"), renderer, "text", MSG_TEXT, NULL);
1133                 gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
1134                 //////
1135             }
1136
1137
1138         gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));
1139             g_object_unref(G_OBJECT(store));
1140         
1141     
1142             gtk_widget_show_all(dialog);
1143
1144             while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
1145             {
1146             }
1147
1148             gtk_widget_hide(dialog);
1149
1150             vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1151         
1152 }
1153
1154 #endif //INCLUDE_APRS