* Road plan (HACKING)
authorAndy Spencer <andy753421@gmail.com>
Sat, 16 May 2009 01:34:34 +0000 (01:34 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sat, 16 May 2009 01:34:34 +0000 (01:34 +0000)
* Removing curl
* Refresh button
* Better caching
* More accurate RIDGE overlays
* Misc cleanup

14 files changed:
HACKING [new file with mode: 0644]
Makefile.am
configure.ac
docs/api/Makefile.am
gen.sh [new file with mode: 0755]
src/Makefile.am
src/aweather-gui.c
src/aweather-view.c
src/aweather-view.h
src/data.c
src/data.h
src/main.c
src/plugin-radar.c
src/plugin-ridge.c

diff --git a/HACKING b/HACKING
new file mode 100644 (file)
index 0000000..25a2add
--- /dev/null
+++ b/HACKING
@@ -0,0 +1,29 @@
+Road plan
+---------
+0.1 - Working
+  * Fix all memory leaks
+  * Asynchronous IO and data loading
+  * Pre-load textures and polys in OpenGL
+  * GObject integration (plugin object/interface)
+  * `Refresh button' (pull new level 2 data)
+
+0.x - Volume scans
+  * Display iso surfaces of volume scans
+
+0.x - GIS
+  * Replace RIDGE overlays with GIS images
+  * Set up LLH coordinate system
+  * Generic Time/Location selection
+    (not dependent on level 2 listings)
+
+0.x - More data
+  * Derived from Level 2:
+    * Composite reflectivity
+    * Storm relative motion
+    * Echo tops
+  * Warning/watch boxes
+  * Fronts
+  * Air pressure
+
+0.x - Animation
+  * Loop though times
index 0940733..c404399 100644 (file)
@@ -1,9 +1,9 @@
 SUBDIRS = src data docs
 
+MAINTAINERCLEANFILES = aclocal.m4 compile config.guess config.h.in gtk-doc.make \
+                       configure depcomp install-sh Makefile.in missing
+
 test: all
        LD_LIBRARY_PATH=/usr/local/trmm/GVBOX/lib/ \
        ./src/aweather
 
-maintainer-clean-local:
-       rm -f aclocal.m4 compile config.guess config.h.in gtk-doc.make \
-             configure depcomp install-sh Makefile.in missing
index 8d5d34b..49ca761 100644 (file)
@@ -10,7 +10,6 @@ GTK_DOC_CHECK(1.9)
 
 # Check for required packages
 PKG_CHECK_MODULES(GTK,  gtk+-2.0 gtkglext-1.0 gmodule-export-2.0 gobject-2.0)
-PKG_CHECK_MODULES(CURL, libcurl)
 
 # Define odd RSL install location
 #AC_SUBST(RSL_CFLAGS, "-I/usr/local/trmm/GVBOX/include/")
index 755262f..68213ac 100644 (file)
@@ -11,7 +11,6 @@ DOC_MODULE=aweather
 DOC_SOURCE_DIR=../../src/
 DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
 MKDB_OPTIONS=--sgml-mode --output-format=xml
+MAINTAINERCLEANFILES= \
+       Makefile.in aweather-docs.sgml aweather-overrides.txt aweather.types 
 include $(top_srcdir)/gtk-doc.make
-maintainer-clean-local:
-       rm -f Makefile.in aweather-docs.sgml aweather-overrides.txt aweather.types
-       rm -rf html/ tmpl/ 
diff --git a/gen.sh b/gen.sh
new file mode 100755 (executable)
index 0000000..e2723ee
--- /dev/null
+++ b/gen.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+dir=$(dirname $(readlink -f $0))
+echo CFLAGS="-g" ./autogen.sh "--datadir=$dir/data" --enable-gtk-doc
+CFLAGS="-g" ./autogen.sh "--datadir=$dir/data" --enable-gtk-doc
index 8611e50..18b7fba 100644 (file)
@@ -1,6 +1,5 @@
-AM_CPPFLAGS  = -DDATADIR="\"$(datadir)\"" $(RSL_CFLAGS) $(GTK_CFLAGS) $(CURL_CFLAGS) 
+AM_LDFLAGS   = $(RSL_LIBS) $(GTK_LIBS)
 AM_CFLAGS    = -Wall -Werror -Wno-unused --std=gnu99 
-AM_LDFLAGS   = -Wl,--export-dynamic
 bin_PROGRAMS = aweather wsr88ddec
 
 aweather_SOURCES  = main.c \
@@ -12,7 +11,7 @@ aweather_SOURCES  = main.c \
        plugin-radar-colormap.c           \
        plugin-ridge.c   plugin-ridge.h   \
        plugin-example.c plugin-example.h
-aweather_LDADD    = $(RSL_LIBS) $(GTK_LIBS) $(CURL_LIBS)
+aweather_CPPFLAGS = $(RSL_CFLAGS) $(GTK_CFLAGS) -DDATADIR="\"$(datadir)\"" 
 
 wsr88ddec         = wsr88ddec.c
 wsr88ddec_LDADD   = -lbz2
index 2c7b5c1..555a9c2 100644 (file)
@@ -37,6 +37,24 @@ gboolean on_window_key_press_event(GtkWidget *widget, GdkEventKey *event, gpoint
        return TRUE;
 }
 
+void on_refresh(GtkToolButton *button, AWeatherGui *gui)
+{
+       AWeatherView *view = aweather_gui_get_view(gui);
+       aweather_view_refresh(view);
+}
+
+void on_zoomin(GtkToolButton *button, AWeatherGui *gui)
+{
+       AWeatherView *view = aweather_gui_get_view(gui);
+       aweather_view_zoomin(view);
+}
+
+void on_zoomout(GtkToolButton *button, AWeatherGui *gui)
+{
+       AWeatherView *view = aweather_gui_get_view(gui);
+       aweather_view_zoomout(view);
+}
+
 void on_site_changed(GtkComboBox *combo, AWeatherGui *gui)
 {
        gchar *site;
@@ -62,7 +80,7 @@ void on_time_changed(GtkTreeView *view, GtkTreePath *path,
        g_free(time);
 }
 
-static gboolean map(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui)
+static gboolean on_map(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui)
 {
        //g_message("map:map");
        AWeatherView *view = aweather_gui_get_view(gui);
@@ -88,7 +106,7 @@ static gboolean map(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui)
        return FALSE;
 }
 
-static gboolean configure(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui)
+static gboolean on_configure(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui)
 {
        aweather_gui_gl_begin(gui);
 
@@ -116,12 +134,12 @@ static gboolean configure(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *
        return FALSE;
 }
 
-static gboolean expose_begin(GtkWidget *da, GdkEventExpose *event, AWeatherGui *gui)
+static gboolean on_expose_begin(GtkWidget *da, GdkEventExpose *event, AWeatherGui *gui)
 {
        aweather_gui_gl_begin(gui);
        return FALSE;
 }
-static gboolean expose_end(GtkWidget *da, GdkEventExpose *event, AWeatherGui *gui)
+static gboolean on_expose_end(GtkWidget *da, GdkEventExpose *event, AWeatherGui *gui)
 {
        g_message("aweather:espose_end\n");
        aweather_gui_gl_end(gui);
@@ -238,7 +256,7 @@ static void time_setup(AWeatherGui *gui)
        g_signal_connect(aview, "time-changed", G_CALLBACK(update_time_widget), gui);
 }
 
-gboolean opengl_setup(AWeatherGui *gui)
+static void opengl_setup(AWeatherGui *gui)
 {
        GtkDrawingArea *drawing = GTK_DRAWING_AREA(aweather_gui_get_widget(gui, "drawing"));
 
@@ -252,11 +270,20 @@ gboolean opengl_setup(AWeatherGui *gui)
                g_error("GL lacks required capabilities");
 
        /* Set up OpenGL Stuff */
-       g_signal_connect      (drawing, "map-event",       G_CALLBACK(map),          gui);
-       g_signal_connect      (drawing, "configure-event", G_CALLBACK(configure),    gui);
-       g_signal_connect      (drawing, "expose-event",    G_CALLBACK(expose_begin), gui);
-       g_signal_connect_after(drawing, "expose-event",    G_CALLBACK(expose_end),   gui);
-       return TRUE;
+       g_signal_connect      (drawing, "map-event",       G_CALLBACK(on_map),          gui);
+       g_signal_connect      (drawing, "configure-event", G_CALLBACK(on_configure),    gui);
+       g_signal_connect      (drawing, "expose-event",    G_CALLBACK(on_expose_begin), gui);
+       g_signal_connect_after(drawing, "expose-event",    G_CALLBACK(on_expose_end),   gui);
+}
+
+static void toolbar_setup(AWeatherGui *gui)
+{
+       GtkWidget *refresh = aweather_gui_get_widget(gui, "refresh_button");
+       GtkWidget *zoomin  = aweather_gui_get_widget(gui, "zoomin_button");
+       GtkWidget *zoomout = aweather_gui_get_widget(gui, "zoomout_button");
+       g_signal_connect(refresh, "clicked", G_CALLBACK(on_refresh), gui);
+       g_signal_connect(zoomin,  "clicked", G_CALLBACK(on_zoomin ), gui);
+       g_signal_connect(zoomout, "clicked", G_CALLBACK(on_zoomout), gui);
 }
 
 
@@ -324,6 +351,7 @@ AWeatherGui *aweather_gui_new()
        gtk_builder_connect_signals(gui->builder, NULL);
 
        /* Load components */
+       toolbar_setup(gui);
        site_setup(gui);
        time_setup(gui);
        opengl_setup(gui);
index 5cf3534..2f240a7 100644 (file)
@@ -30,6 +30,7 @@ enum {
 enum {
        SIG_TIME_CHANGED,
        SIG_LOCATION_CHANGED,
+       SIG_REFRESH,
        NUM_SIGNALS,
 };
 
@@ -134,6 +135,16 @@ static void aweather_view_class_init(AWeatherViewClass *klass)
                        G_TYPE_NONE,
                        1,
                        G_TYPE_STRING);
+       signals[SIG_REFRESH] = g_signal_new(
+                       "refresh",
+                       G_TYPE_FROM_CLASS(gobject_class),
+                       G_SIGNAL_RUN_LAST,
+                       0,
+                       NULL,
+                       NULL,
+                       g_cclosure_marshal_VOID__VOID,
+                       G_TYPE_NONE,
+                       0);
 
 }
 
@@ -175,3 +186,19 @@ gchar *aweather_view_get_location(AWeatherView *view)
        //g_message("aweather_view_get_location");
        return view->location;
 }
+
+void aweather_view_refresh(AWeatherView *view)
+{
+       g_message("aweather_view_refresh: ..");
+       g_signal_emit(view, signals[SIG_REFRESH], 0);
+}
+
+void aweather_view_zoomin(AWeatherView *view)
+{
+       g_message("aweather_view_zoomin: ..");
+}
+
+void aweather_view_zoomout(AWeatherView *view)
+{
+       g_message("aweather_view_zoomout: ..");
+}
index 9d3ee8d..eed4bad 100644 (file)
@@ -55,4 +55,8 @@ gchar *aweather_view_get_time(AWeatherView *view);
 void aweather_view_set_location(AWeatherView *view, const gchar *location);
 gchar *aweather_view_get_location(AWeatherView *view);
 
+void aweather_view_refresh(AWeatherView *view);
+void aweather_view_zoomin(AWeatherView *view);
+void aweather_view_zoomout(AWeatherView *view);
+
 #endif
index e4f2a8c..007c423 100644 (file)
 
 typedef struct {
        AWeatherCacheDoneCallback callback;
-       gchar *url;
-       gchar *local;
        GFile *src;
        GFile *dst;
        gchar *user_data;
 } cache_file_end_t;
 
-static void cache_file_cb(GObject *source_object, GAsyncResult *res, gpointer _info)
-{
-       cache_file_end_t *info = _info;
-       GError *error = NULL;
-       g_file_copy_finish(G_FILE(source_object), res, &error);
-       if (error) {
-               g_message("error copying file ([%s]->[%s]): %s",
-                       info->url, info->local, error->message);
-               g_error_free(error);
-       } else {
-               info->callback(info->local, info->user_data);
-       }
-       g_object_unref(info->src);
-       g_object_unref(info->dst);
-       g_free(info->url);
-       g_free(info->local);
-       g_free(info);
-}
-
 static goffset g_file_get_size(GFile *file)
 {
        GError *error = NULL;
@@ -64,40 +43,41 @@ static goffset g_file_get_size(GFile *file)
        return size;
 }
 
-/**
- * Cache a image from Ridge to the local disk
- * \param  path  Path to the Ridge file, starting after /ridge/
- * \return The local path to the cached image
- */
-void cache_file(char *base, char *path, AWeatherCacheDoneCallback callback, gpointer user_data)
+static void cache_file_cb(GObject *source_object, GAsyncResult *res, gpointer _info)
 {
-       gchar *url   = g_strconcat(base, path, NULL);
-       gchar *local = g_build_filename(g_get_user_cache_dir(), PACKAGE, path, NULL);
-       GFile *src   = g_file_new_for_uri(url);
-       GFile *dst   = g_file_new_for_path(local);
-
-       if (!g_file_test(local, G_FILE_TEST_EXISTS))
-               g_message("Caching file: local does not exist - %s", local);
-       else if (g_file_get_size(src) != g_file_get_size(dst))
-               g_message("Caching file: sizes mismatch - %lld != %lld",
-                               g_file_get_size(src), g_file_get_size(dst));
-       else {
-               callback(local, user_data);
-               g_object_unref(src);
-               g_object_unref(dst);
-               g_free(local);
-               g_free(url);
-               return;
+       cache_file_end_t *info = _info;
+       char   *url   = g_file_get_path(info->src);
+       char   *local = g_file_get_path(info->dst);
+       GError *error = NULL;
+       g_file_copy_finish(G_FILE(source_object), res, &error);
+       if (error) {
+               g_message("error copying file ([%s]->[%s]): %s",
+                       url, local, error->message);
+               g_error_free(error);
+       } else {
+               info->callback(local, TRUE, info->user_data);
        }
+       g_object_unref(info->src);
+       g_object_unref(info->dst);
+       g_free(info);
+       g_free(url);
+       g_free(local);
+}
+
+static void do_cache(GFile *src, GFile *dst, char *reason,
+               AWeatherCacheDoneCallback callback, gpointer user_data)
+{
+       char *name = g_file_get_basename(dst);
+       g_message("Caching file %s: %s", name, reason);
+       g_free(name);
+
+       GFile *parent = g_file_get_parent(dst);
+       if (!g_file_query_exists(parent, NULL))
+               g_file_make_directory_with_parents(parent, NULL, NULL);
+       g_object_unref(parent);
 
-       char *dir = g_path_get_dirname(local);
-       if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
-               g_mkdir_with_parents(dir, 0755);
-       g_free(dir);
        cache_file_end_t *info = g_malloc0(sizeof(cache_file_end_t));
        info->callback  = callback;
-       info->url       = url;
-       info->local     = local;
        info->src       = src;
        info->dst       = dst;
        info->user_data = user_data;
@@ -109,4 +89,36 @@ void cache_file(char *base, char *path, AWeatherCacheDoneCallback callback, gpoi
                NULL,                  // gpointer progress_callback_data,
                cache_file_cb,         // GAsyncReadyCallback callback,
                info);                 // gpointer user_data
+       return;
+}
+
+/**
+ * Cache a image from Ridge to the local disk
+ * \param  path  Path to the Ridge file, starting after /ridge/
+ * \return The local path to the cached image
+ */
+void cache_file(char *base, char *path, AWeatherPolicyType update,
+               AWeatherCacheDoneCallback callback, gpointer user_data)
+{
+       gchar *url   = g_strconcat(base, path, NULL);
+       gchar *local = g_build_filename(g_get_user_cache_dir(), PACKAGE, path, NULL);
+       GFile *src   = g_file_new_for_uri(url);
+       GFile *dst   = g_file_new_for_path(local);
+
+       if (update == AWEATHER_ALWAYS)
+               return do_cache(src, dst, "cache forced", callback, user_data);
+
+       if (!g_file_test(local, G_FILE_TEST_EXISTS))
+               return do_cache(src, dst, "local does not exist", callback, user_data);
+
+       if (update == AWEATHER_AUTOMATIC && g_file_get_size(src) != g_file_get_size(dst))
+               return do_cache(src, dst, "size mismatch", callback, user_data);
+
+       /* No nead to cache, run the callback now and clean up */
+       callback(local, FALSE, user_data);
+       g_object_unref(src);
+       g_object_unref(dst);
+       g_free(local);
+       g_free(url);
+       return;
 }
index 994384b..b0ecf61 100644 (file)
 #ifndef __DATA_H__
 #define __DATA_H__
 
-typedef void (*AWeatherCacheDoneCallback)(gchar *file, gpointer user_data);
+typedef enum {
+       AWEATHER_ALWAYS,
+       AWEATHER_AUTOMATIC,
+       AWEATHER_NEVER,
+} AWeatherPolicyType;
 
-void cache_file(char *base, char *path, AWeatherCacheDoneCallback callback, gpointer user_data);
+typedef void (*AWeatherCacheDoneCallback)(gchar *file, gboolean updated,
+               gpointer user_data);
+
+void cache_file(char *base, char *path, AWeatherPolicyType update,
+               AWeatherCacheDoneCallback callback, gpointer user_data);
 
 #endif
index 9bd7332..cf13c87 100644 (file)
@@ -38,8 +38,8 @@ int main(int argc, char *argv[])
 
        /* Load plugins */
        //example_init(gui);
-        ridge_init  (gui);
-       radar_init  (gui);
+        ridge_init(gui);
+       radar_init(gui);
 
        gtk_widget_show_all(aweather_gui_get_widget(gui, "window"));
        gtk_main();
index 4e4376d..4d75c73 100644 (file)
@@ -191,12 +191,13 @@ static void load_radar_rsl(GPid pid, gint status, gpointer _path)
 }
 
 /* decompress a radar file, then chain to the actuall loading function */
-static void load_radar(char *path, gpointer user_data)
+static void load_radar(char *path, gboolean updated, gpointer user_data)
 {
        char *raw  = g_strconcat(path, ".raw", NULL);
-       if (g_file_test(raw, G_FILE_TEST_EXISTS)) {
+       if (!updated) {
                load_radar_rsl(0, 0, raw);
        } else {
+               g_message("File updated, decompressing..");
                char *argv[] = {"wsr88ddec", path, raw, NULL};
                GPid pid;
                GError *error = NULL;
@@ -220,10 +221,50 @@ static void load_radar(char *path, gpointer user_data)
        }
 }
 
+static void update_times(char *site, char **last_time)
+{
+       char *list_uri = g_strdup_printf(
+                       "http://mesonet.agron.iastate.edu/data/nexrd2/raw/K%s/dir.list",
+                       site);
+       GFile *list    = g_file_new_for_uri(list_uri);
+       g_free(list_uri);
+
+       gchar *data;
+       gsize length;
+       GError *error = NULL;
+       g_file_load_contents(list, NULL, &data, &length, NULL, &error);
+       g_object_unref(list);
+       if (error) {
+               g_warning("Error loading list for %s: %s", site, error->message);
+               g_error_free(error);
+               return;
+       }
+       gchar **lines = g_strsplit(data, "\n", -1);
+       GtkTreeView  *tview  = GTK_TREE_VIEW(aweather_gui_get_widget(gui, "time"));
+       GtkListStore *lstore = GTK_LIST_STORE(gtk_tree_view_get_model(tview));
+       gtk_list_store_clear(lstore);
+       GtkTreeIter iter;
+       for (int i = 0; lines[i] && lines[i][0]; i++) {
+               // format: `841907 KABR_20090510_0159'
+               //g_message("\tadding %p [%s]", lines[i], lines[i]);
+               char **parts = g_strsplit(lines[i], " ", 2);
+               char *time = parts[1]+5;
+               gtk_list_store_insert(lstore, &iter, 0);
+               gtk_list_store_set(lstore, &iter, 0, time, -1);
+               g_strfreev(parts);
+       }
+
+       if (last_time)
+               gtk_tree_model_get(GTK_TREE_MODEL(lstore), &iter, 0, last_time, -1);
+
+       g_free(data);
+       g_strfreev(lines);
+}
+
 /*************
  * Callbacks *
  *************/
-static gboolean expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data)
+static gboolean on_expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data)
 {
        g_message("radar:expose");
        if (cur_sweep == NULL)
@@ -239,16 +280,20 @@ static gboolean expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data)
        glDisable(GL_ALPHA_TEST);
        glColor4f(1,1,1,1);
        glBegin(GL_QUAD_STRIP);
-       for (int ri = 0; ri <= sweep->h.nrays+1; ri++) {
-               /* Do the first sweep twice to complete the last Quad */
-               Ray *ray = sweep->ray[ri % sweep->h.nrays];
-
-               /* right and left looking out from radar */
-               double left  = ((ray->h.azimuth - ((double)ray->h.beam_width/2.))*M_PI)/180.0; 
-               //double right = ((ray->h.azimuth + ((double)ray->h.beam_width/2.))*M_PI)/180.0; 
+       for (int ri = 0; ri <= sweep->h.nrays; ri++) {
+               Ray  *ray = NULL;
+               double angle = 0;
+               if (ri < sweep->h.nrays) {
+                       ray = sweep->ray[ri];
+                       angle = ((ray->h.azimuth - ((double)ray->h.beam_width/2.))*M_PI)/180.0; 
+               } else {
+                       /* Do the right side of the last sweep */
+                       ray = sweep->ray[ri-1];
+                       angle = ((ray->h.azimuth + ((double)ray->h.beam_width/2.))*M_PI)/180.0; 
+               }
 
-               double lx = sin(left);
-               double ly = cos(left);
+               double lx = sin(angle);
+               double ly = cos(angle);
 
                double near_dist = ray->h.range_bin1;
                double far_dist  = ray->h.nbins*ray->h.gate_size + ray->h.range_bin1;
@@ -299,63 +344,39 @@ static gboolean expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data)
        return FALSE;
 }
 
-static void set_time(AWeatherView *view, char *time, gpointer user_data)
+static void on_time_changed(AWeatherView *view, char *time, gpointer user_data)
 {
        g_message("radar:setting time");
        // format: http://mesonet.agron.iastate.edu/data/nexrd2/raw/KABR/KABR_20090510_0323
        char *site = aweather_view_get_location(view);
        char *base = "http://mesonet.agron.iastate.edu/data/";
        char *path = g_strdup_printf("nexrd2/raw/K%s/K%s_%s", site, site, time);
-       //g_message("caching %s/%s", base, path);
+
+       radar = NULL;
        cur_sweep = NULL; // Clear radar
        gtk_widget_queue_draw(aweather_gui_get_widget(gui, "drawing"));
-       cache_file(base, path, load_radar, NULL);
+
+       cache_file(base, path, AWEATHER_AUTOMATIC, load_radar, NULL);
        g_free(path);
 }
 
-static void set_site(AWeatherView *view, char *site, gpointer user_data)
+static void on_location_changed(AWeatherView *view, char *site, gpointer user_data)
 {
        g_message("Loading wsr88d list for %s", site);
-       cur_sweep = NULL; // Clear radar
+       char *time = NULL;
+       update_times(site, &time);
+       aweather_view_set_time(view, time);
 
-       char *list_uri = g_strdup_printf(
-                       "http://mesonet.agron.iastate.edu/data/nexrd2/raw/K%s/dir.list",
-                       site);
-       GFile *list    = g_file_new_for_uri(list_uri);
-       g_free(list_uri);
+       g_free(time);
+}
 
-       gchar *data;
-       gsize length;
-       GError *error = NULL;
-       gtk_widget_queue_draw(aweather_gui_get_widget(gui, "drawing"));
-       g_file_load_contents(list, NULL, &data, &length, NULL, &error);
-       g_object_unref(list);
-       if (error) {
-               g_warning("Error loading list for %s: %s", site, error->message);
-               g_error_free(error);
-               return;
-       }
-       gchar **lines = g_strsplit(data, "\n", -1);
-       GtkTreeView  *tview  = GTK_TREE_VIEW(aweather_gui_get_widget(gui, "time"));
-       GtkListStore *lstore = GTK_LIST_STORE(gtk_tree_view_get_model(tview));
-       gtk_list_store_clear(lstore);
-       radar = NULL;
-       GtkTreeIter iter;
-       for (int i = 0; lines[i] && lines[i][0]; i++) {
-               // format: `841907 KABR_20090510_0159'
-               //g_message("\tadding %p [%s]", lines[i], lines[i]);
-               char **parts = g_strsplit(lines[i], " ", 2);
-               char *time = parts[1]+5;
-               gtk_list_store_insert(lstore, &iter, 0);
-               gtk_list_store_set(lstore, &iter, 0, time, -1);
-               g_strfreev(parts);
-       }
+static void on_refresh(AWeatherView *view, gpointer user_data)
+{
+       char *site = aweather_view_get_location(view);
        char *time = NULL;
-       gtk_tree_model_get(GTK_TREE_MODEL(lstore), &iter, 0, &time, -1);
+       update_times(site, &time);
        aweather_view_set_time(view, time);
        g_free(time);
-       g_free(data);
-       g_strfreev(lines);
 }
 
 /* Init */
@@ -376,9 +397,10 @@ gboolean radar_init(AWeatherGui *_gui)
                        config_body, gtk_label_new("Radar"));
 
        /* Set up OpenGL Stuff */
-       g_signal_connect(drawing, "expose-event",     G_CALLBACK(expose),   NULL);
-       g_signal_connect(view,    "location-changed", G_CALLBACK(set_site), NULL);
-       g_signal_connect(view,    "time-changed",     G_CALLBACK(set_time), NULL);
+       g_signal_connect(drawing, "expose-event",     G_CALLBACK(on_expose),           NULL);
+       g_signal_connect(view,    "location-changed", G_CALLBACK(on_location_changed), NULL);
+       g_signal_connect(view,    "time-changed",     G_CALLBACK(on_time_changed),     NULL);
+       g_signal_connect(view,    "refresh",          G_CALLBACK(on_refresh),          NULL);
 
        return TRUE;
 }
index 77bffe9..11d716c 100644 (file)
@@ -46,7 +46,7 @@ static layer_t layers[] = {
        [LAYER_TOPO]     = {"Topo",     "Overlays/Topo/Short/%s_Topo_Short.jpg",         TRUE,  1, 0},
        [LAYER_COUNTY]   = {"Counties", "Overlays/County/Short/%s_County_Short.gif",     TRUE,  3, 0},
        [LAYER_RIVERS]   = {"Rivers",   "Overlays/Rivers/Short/%s_Rivers_Short.gif",     FALSE, 4, 0},
-       [LAYER_HIGHWAYS] = {"Highways", "Overlays/Highways/Short/%s_Highways_Short.gif", TRUE,  5, 0},
+       [LAYER_HIGHWAYS] = {"Highways", "Overlays/Highways/Short/%s_Highways_Short.gif", FALSE, 5, 0},
        [LAYER_CITY]     = {"Cities",   "Overlays/Cities/Short/%s_City_Short.gif",       TRUE,  6, 0},
 };
 
@@ -57,7 +57,7 @@ static AWeatherGui *gui = NULL;
  * \param  filename  Path to the image file
  * \return The OpenGL identifier for the texture
  */
-void load_texture(gchar *filename, gpointer _layer)
+void load_texture(gchar *filename, gboolean updated, gpointer _layer)
 {
        layer_t *layer = _layer;
        aweather_gui_gl_begin(gui);
@@ -102,7 +102,7 @@ static void set_site(AWeatherView *view, gchar *site, gpointer user_data)
        for (int i = 0; i < LAYER_COUNT; i++) {
                gchar *base = "http://radar.weather.gov/ridge/";
                gchar *path  = g_strdup_printf(layers[i].fmt, site);
-               cache_file(base, path, load_texture, &layers[i]);
+               cache_file(base, path, AWEATHER_NEVER, load_texture, &layers[i]);
                g_free(path);
        }
 }
@@ -119,10 +119,10 @@ static gboolean expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data)
                        continue;
                glBindTexture(GL_TEXTURE_2D, layers[i].tex);
                glBegin(GL_POLYGON);
-               glTexCoord2f(0.0, 0.0); glVertex3f(250*1000*-1.0, 250*1000* 1.0, layers[i].z);
-               glTexCoord2f(0.0, 1.0); glVertex3f(250*1000*-1.0, 250*1000*-1.0, layers[i].z);
-               glTexCoord2f(1.0, 1.0); glVertex3f(250*1000* 1.0, 250*1000*-1.0, layers[i].z);
-               glTexCoord2f(1.0, 0.0); glVertex3f(250*1000* 1.0, 250*1000* 1.0, layers[i].z);
+               glTexCoord2f(0.0, 0.0); glVertex3f(240*1000*-1.0, 282*1000* 1.0, layers[i].z);
+               glTexCoord2f(0.0, 1.0); glVertex3f(240*1000*-1.0, 282*1000*-1.0, layers[i].z);
+               glTexCoord2f(1.0, 1.0); glVertex3f(240*1000* 1.0, 282*1000*-1.0, layers[i].z);
+               glTexCoord2f(1.0, 0.0); glVertex3f(240*1000* 1.0, 282*1000* 1.0, layers[i].z);
                glEnd();
        }