[Gpredict-svn] SF.net SVN: gpredict:[529] trunk
Real time satellite tracking and orbit prediction
Status: Beta
Brought to you by:
csete
From: <cs...@us...> - 2009-11-29 16:07:52
|
Revision: 529 http://gpredict.svn.sourceforge.net/gpredict/?rev=529&view=rev Author: csete Date: 2009-11-29 16:07:38 +0000 (Sun, 29 Nov 2009) Log Message: ----------- Added new files with GtkEventList view (not finished). Modified Paths: -------------- trunk/ChangeLog trunk/src/gtk-sat-module.h Added Paths: ----------- trunk/src/gtk-event-list.c trunk/src/gtk-event-list.h Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-11-29 12:36:54 UTC (rev 528) +++ trunk/ChangeLog 2009-11-29 16:07:38 UTC (rev 529) @@ -1,3 +1,12 @@ +2009-11-29 Alexandru Csete <oz9aec at gmail.com> + + * src/gtk-event-list.[ch]: + Added files containing new view listing upcoming events. + + * src/gtk-sat-module.[ch]: + Use new GtkEventList view. + + 2009-11-22 Alexandru Csete <oz9aec at gmail.com> * src/sat-cfg.c: Added: trunk/src/gtk-event-list.c =================================================================== --- trunk/src/gtk-event-list.c (rev 0) +++ trunk/src/gtk-event-list.c 2009-11-29 16:07:38 UTC (rev 529) @@ -0,0 +1,1063 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + Gpredict: Real-time satellite tracking and orbit prediction program + + Copyright (C) 2001-2009 Alexandru Csete, OZ9AEC. + + Authors: Alexandru Csete <oz...@gm...> + + Comments, questions and bugreports should be submitted via + http://sourceforge.net/projects/gpredict/ + More details can be found at the project home page: + + http://gpredict.oz9aec.net/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, visit http://www.fsf.org/ +*/ +/** \brief Satellite List Widget. + * + * More info... + */ +#include <gtk/gtk.h> +#include <glib/gi18n.h> +#include "sgpsdp/sgp4sdp4.h" +#include "gtk-event-list.h" +#include "sat-log.h" +#include "config-keys.h" +#include "sat-cfg.h" +#include "mod-cfg-get-param.h" +#include "gtk-sat-data.h" +#include "gpredict-utils.h" +#include "locator.h" +#include "sat-vis.h" +#ifdef HAVE_CONFIG_H +# include <build-config.h> +#endif + + + +/** \brief Column titles indexed with column symb. refs. */ +const gchar *EVENT_LIST_COL_TITLE[EVENT_LIST_COL_NUMBER] = { + N_("Sat"), + N_("Catnum"), + N_("A/L"), + N_("Time") +}; + + +/** \brief Column title hints indexed with column symb. refs. */ +const gchar *EVENT_LIST_COL_HINT[EVENT_LIST_COL_NUMBER] = { + N_("Satellite Name"), + N_("Catalogue Number"), + N_("Next event type (A: AOS, L: LOS)"), + N_("Countdown until next event") +}; + +const gfloat EVENT_LIST_COL_XALIGN[EVENT_LIST_COL_NUMBER] = { + 0.0, // name + 0.5, // catnum + 0.5, // event type + 0.5, // time +}; + +static void gtk_event_list_class_init (GtkEventListClass *class); +static void gtk_event_list_init (GtkEventList *list); +static void gtk_event_list_destroy (GtkObject *object); +static GtkTreeModel *create_and_fill_model (GHashTable *sats); +static void event_list_add_satellites (gpointer key, + gpointer value, + gpointer user_data); +static gboolean event_list_update_sats (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data); + +/* cell rendering related functions */ +static void check_and_set_cell_renderer (GtkTreeViewColumn *column, + GtkCellRenderer *renderer, + gint i); + +static void evtype_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column); + +static void time_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column); + +static gint event_cell_compare_function (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data); + + +static gboolean popup_menu_cb (GtkWidget *treeview, + gpointer list); + +static gboolean button_press_cb (GtkWidget *treeview, + GdkEventButton *event, + gpointer list); + +static void view_popup_menu (GtkWidget *treeview, + GdkEventButton *event, + gpointer list); + + +static GtkVBoxClass *parent_class = NULL; + + +GType gtk_event_list_get_type () +{ + static GType gtk_event_list_type = 0; + + if (!gtk_event_list_type) + { + static const GTypeInfo gtk_event_list_info = + { + sizeof (GtkEventListClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_event_list_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkEventList), + 5, /* n_preallocs */ + (GInstanceInitFunc) gtk_event_list_init, + }; + + gtk_event_list_type = g_type_register_static (GTK_TYPE_VBOX, + "GtkEventList", + >k_event_list_info, + 0); + } + + return gtk_event_list_type; +} + + +static void gtk_event_list_class_init (GtkEventListClass *class) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + gobject_class = G_OBJECT_CLASS (class); + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + container_class = (GtkContainerClass*) class; + + parent_class = g_type_class_peek_parent (class); + + object_class->destroy = gtk_event_list_destroy; + +} + + +static void gtk_event_list_init (GtkEventList *list) +{ + +} + + +static void gtk_event_list_destroy (GtkObject *object) +{ + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +/** \brief Create a new GtkEventList widget. + * \param cfgdata Pointer to the module configuration data. + * \param sats Hash table containing the satellites tracked by the parent module. + * \param qth Pointer to the QTH used by this module. + * \param columns Visible columns (currently not in use). + * + */ +GtkWidget *gtk_event_list_new (GKeyFile *cfgdata, GHashTable *sats, qth_t *qth, guint32 columns) +{ + GtkWidget *widget; + GtkEventList *evlist; + GtkTreeModel *model; + guint i; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + + widget = g_object_new (GTK_TYPE_EVENT_LIST, NULL); + evlist = GTK_EVENT_LIST (widget); + + evlist->update = gtk_event_list_update; + + /* Read configuration data. */ + /* ... */ + + evlist->satellites = sats; + evlist->qth = qth; + + + /* initialise column flags */ + evlist->flags = 0; +/* if (columns > 0) + evlist->flags = columns; + else + evlist->flags = mod_cfg_get_int (cfgdata, + MOD_CFG_EVLIST_SECTION, + MOD_CFG_EVLIST_COLUMNS, + SAT_CFG_INT_EVLIST_COLUMNS); + */ + + /* get refresh rate and cycle counter */ +/* evlist->refresh = mod_cfg_get_int (cfgdata, + MOD_CFG_EVLIST_SECTION, + MOD_CFG_EVLIST_REFRESH, + SAT_CFG_INT_EVLIST_REFRESH); + */ + evlist->refresh = 1000; + + evlist->counter = 1; + + /* create the tree view and add columns */ + evlist->treeview = gtk_tree_view_new (); + + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (evlist->treeview), FALSE); + + /* create treeview columns */ + for (i = 0; i < EVENT_LIST_COL_NUMBER; i++) { + + renderer = gtk_cell_renderer_text_new (); + g_object_set (G_OBJECT (renderer), "xalign", EVENT_LIST_COL_XALIGN[i], NULL); + + column = gtk_tree_view_column_new_with_attributes (_(EVENT_LIST_COL_TITLE[i]), + renderer, + "text", i, + NULL); + gtk_tree_view_insert_column (GTK_TREE_VIEW (evlist->treeview), + column, -1); + + /* only aligns the headers */ + gtk_tree_view_column_set_alignment (column, 0.5); + + /* set sort id */ + gtk_tree_view_column_set_sort_column_id (column, i); + + /* set cell data function; allows to format data before rendering */ + check_and_set_cell_renderer (column, renderer, i); + + /* hide columns that have not been specified */ + /*if (!(evlist->flags & (1 << i))) { + gtk_tree_view_column_set_visible (column, FALSE); + }*/ + + } + + /* create model and finalise treeview */ + model = create_and_fill_model (evlist->satellites); + gtk_tree_view_set_model (GTK_TREE_VIEW (evlist->treeview), model); + + /* The time sort function needs to be special */ + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model), + EVENT_LIST_COL_TIME, + event_cell_compare_function, + NULL, NULL); + + /* initial sorting criteria */ + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), + EVENT_LIST_COL_TIME, + GTK_SORT_ASCENDING), + + g_object_unref (model); + +/* g_signal_connect (evlist->treeview, "button-press-event", + G_CALLBACK (button_press_cb), widget); + g_signal_connect (evlist->treeview, "popup-menu", + G_CALLBACK (popup_menu_cb), widget);*/ + + evlist->swin = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (evlist->swin), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_container_add (GTK_CONTAINER (evlist->swin), evlist->treeview); + + gtk_container_add (GTK_CONTAINER (widget), evlist->swin); + gtk_widget_show_all (widget); + + return widget; +} + + +/** \brief Create and file the tree model for the even list. */ +static GtkTreeModel *create_and_fill_model (GHashTable *sats) +{ + GtkListStore *liststore; + + + liststore = gtk_list_store_new (SAT_LIST_COL_NUMBER, + G_TYPE_STRING, // name + G_TYPE_INT, // catnum + G_TYPE_BOOLEAN, // TRUE if AOS, FALSE if LOS + G_TYPE_DOUBLE); // time + + /* add each satellite from hash table */ + g_hash_table_foreach (sats, event_list_add_satellites, liststore); + + + return GTK_TREE_MODEL (liststore); +} + + +/** \brief Add satellites. This function is a g_hash_table_foreach() callback. + * \param key The key of the satellite in the hash table. + * \param value Pointer to the satellite (sat_t structure) that should be added. + * \param user_data Pointer to the GtkListStore where the satellite should be added + * + * This function is called by by the create_and_fill_models() function for adding + * the satellites to the internal liststore. + */ +static void event_list_add_satellites (gpointer key, gpointer value, gpointer user_data) +{ + GtkListStore *store = GTK_LIST_STORE (user_data); + GtkTreeIter item; + sat_t *sat = SAT (value); + + + gtk_list_store_append (store, &item); + gtk_list_store_set (store, &item, + EVENT_LIST_COL_NAME, sat->nickname, + EVENT_LIST_COL_CATNUM, sat->tle.catnr, + EVENT_LIST_COL_EVT, (sat->el >= 0) ? TRUE : FALSE, + EVENT_LIST_COL_TIME, 0.0, + -1); +} + + + +/** \brief Update satellites */ +void gtk_event_list_update (GtkWidget *widget) +{ + GtkTreeModel *model; + GtkEventList *evlist = GTK_EVENT_LIST (widget); + + + /* first, do some sanity checks */ + if ((evlist == NULL) || !IS_GTK_EVENT_LIST (satlist)) { + sat_log_log (SAT_LOG_LEVEL_BUG, + _("%s: Invalid GtkEventList!"), + __FUNCTION__); + } + + + /* check refresh rate */ + if (evlist->counter < evlist->refresh) { + evlist->counter++; + } + else { + evlist->counter = 1; + + /* get and tranverse the model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (evlist->treeview)); + + /* update */ + gtk_tree_model_foreach (model, event_list_update_sats, satlist); + } +} + + +/** \brief Update data in each column in a given row */ +static gboolean event_list_update_sats (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + GtkEventList *satlist = GTK_EVENT_LIST (data); + guint *catnum; + sat_t *sat; + gchar *buff; + gint retcode; + + + /* get the catalogue number for this row + then look it up in the hash table + */ + catnum = g_new0 (guint, 1); + gtk_tree_model_get (model, iter, EVENT_LIST_COL_CATNUM, catnum, -1); + sat = SAT (g_hash_table_lookup (satlist->satellites, catnum)); + + if (sat == NULL) { + /* satellite not tracked anymore => remove */ + sat_log_log (SAT_LOG_LEVEL_MSG, + _("%s: Failed to get data for #%d."), + __FUNCTION__, *catnum); + + gtk_list_store_remove (GTK_LIST_STORE (model), iter); + + sat_log_log (SAT_LOG_LEVEL_BUG, + _("%s: Satellite #%d removed from list."), + __FUNCTION__, *catnum); + } + else { + + /**** UPDATED UNTIL HERE *****/ + /* store new data */ + gtk_list_store_set (GTK_LIST_STORE (model), iter, + SAT_LIST_COL_AZ, sat->az, + SAT_LIST_COL_EL, sat->el, + SAT_LIST_COL_RANGE, sat->range, + SAT_LIST_COL_RANGE_RATE, sat->range_rate, + SAT_LIST_COL_LAT, sat->ssplat, + SAT_LIST_COL_LON, sat->ssplon, + SAT_LIST_COL_FOOTPRINT, sat->footprint, + SAT_LIST_COL_ALT, sat->alt, + SAT_LIST_COL_VEL, sat->velo, + SAT_LIST_COL_MA, sat->ma, + SAT_LIST_COL_PHASE, sat->phase, + SAT_LIST_COL_ORBIT, sat->orbit, + -1); + + if (satlist->flags & SAT_LIST_FLAG_NEXT_EVENT) { + gdouble number; + gchar buff[TIME_FORMAT_MAX_LENGTH]; + gchar *tfstr; + gchar *fmtstr; + gchar *alstr; + time_t t; + guint size; + + + if (sat->aos > sat->los) { + /* next event is LOS */ + number = sat->los; + alstr = g_strdup ("LOS: "); + } + else { + /* next event is AOS */ + number = sat->aos; + alstr = g_strdup ("AOS: "); + } + + if (number == 0.0) { + gtk_list_store_set (GTK_LIST_STORE (model), iter, + SAT_LIST_COL_NEXT_EVENT, "--- N/A ---", + -1); + } + else { + + /* convert julian date to struct tm */ + t = (number - 2440587.5)*86400.; + + /* format the number */ + tfstr = sat_cfg_get_str (SAT_CFG_STR_TIME_FORMAT); + fmtstr = g_strconcat (alstr, tfstr, NULL); + g_free (tfstr); + + /* format either local time or UTC depending on check box */ + if (sat_cfg_get_bool (SAT_CFG_BOOL_USE_LOCAL_TIME)) + size = strftime (buff, TIME_FORMAT_MAX_LENGTH, + fmtstr, localtime (&t)); + else + size = strftime (buff, TIME_FORMAT_MAX_LENGTH, + fmtstr, gmtime (&t)); + + if (size == 0) + /* size > MAX_LENGTH */ + buff[TIME_FORMAT_MAX_LENGTH-1] = '\0'; + + gtk_list_store_set (GTK_LIST_STORE (model), iter, + SAT_LIST_COL_NEXT_EVENT, buff, + -1); + + + g_free (fmtstr); + } + + g_free (alstr); + + } + + } + + g_free (catnum); + + /* Return value not documented what to return, but it seems that + FALSE continues to next row while TRUE breaks + */ + return FALSE; +} + + + +/** \brief Set cell renderer function. */ +static void check_and_set_cell_renderer (GtkTreeViewColumn *column, + GtkCellRenderer *renderer, + gint i) +{ + + switch (i) { + + /* general float with 2 dec. precision + no extra format besides a degree char + */ + case SAT_LIST_COL_AZ: + case SAT_LIST_COL_EL: + case SAT_LIST_COL_RA: + case SAT_LIST_COL_DEC: + case SAT_LIST_COL_MA: + case SAT_LIST_COL_PHASE: + gtk_tree_view_column_set_cell_data_func (column, + renderer, + degree_cell_data_function, + GUINT_TO_POINTER (i), + NULL); + break; + + /* LAT/LON format */ + case SAT_LIST_COL_LAT: + case SAT_LIST_COL_LON: + gtk_tree_view_column_set_cell_data_func (column, + renderer, + latlon_cell_data_function, + GUINT_TO_POINTER (i), + NULL); + break; + + /* distances and velocities */ + case SAT_LIST_COL_RANGE: + case SAT_LIST_COL_ALT: + case SAT_LIST_COL_FOOTPRINT: + gtk_tree_view_column_set_cell_data_func (column, + renderer, + distance_cell_data_function, + GUINT_TO_POINTER (i), + NULL); + break; + + case SAT_LIST_COL_VEL: + case SAT_LIST_COL_RANGE_RATE: + gtk_tree_view_column_set_cell_data_func (column, + renderer, + range_rate_cell_data_function, + GUINT_TO_POINTER (i), + NULL); + break; + + case SAT_LIST_COL_DOPPLER: + gtk_tree_view_column_set_cell_data_func (column, + renderer, + float_to_int_cell_data_function, + GUINT_TO_POINTER (i), + NULL); + break; + + case SAT_LIST_COL_DELAY: + case SAT_LIST_COL_LOSS: + gtk_tree_view_column_set_cell_data_func (column, + renderer, + two_dec_cell_data_function, + GUINT_TO_POINTER (i), + NULL); + break; + + case SAT_LIST_COL_AOS: + case SAT_LIST_COL_LOS: + gtk_tree_view_column_set_cell_data_func (column, + renderer, + event_cell_data_function, + GUINT_TO_POINTER (i), + NULL); + break; + + default: + break; + + } + +} + + +/* render column containg lat/lon + by using this instead of the default data function, we can + control the number of decimals and display the coordinates in a + fancy way, including degree sign and NWSE suffixes. + + Please note that this function only affects how the numbers are + displayed (rendered), the tree_store will still contain the + original flaoting point numbers. Very cool! +*/ +static void +latlon_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column) +{ + gdouble number = 0.0; + gchar *buff; + guint coli = GPOINTER_TO_UINT (column); + gchar hmf = ' '; + + gtk_tree_model_get (model, iter, coli, &number, -1); + + /* check whether configuration requests the use + of N, S, E and W instead of signs + */ + if (sat_cfg_get_bool (SAT_CFG_BOOL_USE_NSEW)) { + + if (coli == SAT_LIST_COL_LAT) { + if (number < 0.00) { + number = -number; + hmf = 'S'; + } + else { + hmf = 'N'; + } + } + else if (coli == SAT_LIST_COL_LON) { + if (number < 0.00) { + number = -number; + hmf = 'W'; + } + else { + hmf = 'E'; + } + } + else { + sat_log_log (SAT_LOG_LEVEL_BUG, + _("%s:%d: Invalid column: %d"), + __FILE__, __LINE__, + coli); + hmf = '?'; + } + } + + /* format the number */ + buff = g_strdup_printf ("%.2f\302\260%c", number, hmf); + g_object_set (renderer, + "text", buff, + NULL); + g_free (buff); +} + + +/* general floats with 2 digits + degree char */ +static void +degree_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column) +{ + gdouble number; + gchar *buff; + guint coli = GPOINTER_TO_UINT (column); + + gtk_tree_model_get (model, iter, coli, &number, -1); + + /* format the number */ + buff = g_strdup_printf ("%.2f\302\260", number); + g_object_set (renderer, + "text", buff, + NULL); + g_free (buff); +} + + +/* distance and velocity, 0 decimal digits */ +static void +distance_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column) +{ + gdouble number; + gchar *buff; + guint coli = GPOINTER_TO_UINT (column); + + gtk_tree_model_get (model, iter, coli, &number, -1); + + /* convert distance to miles? */ + if (sat_cfg_get_bool (SAT_CFG_BOOL_USE_IMPERIAL)) { + number = KM_TO_MI(number); + } + + /* format the number */ + buff = g_strdup_printf ("%.0f", number); + g_object_set (renderer, + "text", buff, + NULL); + g_free (buff); +} + +/* range rate is special, because we may need to convert to miles + and want 2-3 decimal digits. +*/ +static void +range_rate_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column) +{ + gdouble number; + gchar *buff; + guint coli = GPOINTER_TO_UINT (column); + + gtk_tree_model_get (model, iter, coli, &number, -1); + + /* convert distance to miles? */ + if (sat_cfg_get_bool (SAT_CFG_BOOL_USE_IMPERIAL)) { + number = KM_TO_MI(number); + } + + /* format the number */ + buff = g_strdup_printf ("%.3f", number); + g_object_set (renderer, + "text", buff, + NULL); + g_free (buff); +} + +/* 0 decimal digits */ +static void +float_to_int_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column) +{ + gdouble number; + gchar *buff; + guint coli = GPOINTER_TO_UINT (column); + + gtk_tree_model_get (model, iter, coli, &number, -1); + + /* format the number */ + buff = g_strdup_printf ("%.0f", number); + g_object_set (renderer, + "text", buff, + NULL); + g_free (buff); +} + +/* 2 decimal digits */ +static void +two_dec_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column) +{ + gdouble number; + gchar *buff; + guint coli = GPOINTER_TO_UINT (column); + + gtk_tree_model_get (model, iter, coli, &number, -1); + + /* format the number */ + buff = g_strdup_printf ("%.2f", number); + g_object_set (renderer, + "text", buff, + NULL); + g_free (buff); +} + + +/* AOS/LOS; convert julian date to string */ +static void +event_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column) +{ + gdouble number; + gchar buff[TIME_FORMAT_MAX_LENGTH]; + gchar *fmtstr; + guint coli = GPOINTER_TO_UINT (column); + time_t t; + guint size; + + + gtk_tree_model_get (model, iter, coli, &number, -1); + + if (number == 0.0) { + g_object_set (renderer, + "text", "--- N/A ---", + NULL); + } + else { + + /* convert julian date to struct tm */ + t = (number - 2440587.5)*86400.; + + /* format the number */ + fmtstr = sat_cfg_get_str (SAT_CFG_STR_TIME_FORMAT); + + /* format either local time or UTC depending on check box */ + if (sat_cfg_get_bool (SAT_CFG_BOOL_USE_LOCAL_TIME)) + size = strftime (buff, TIME_FORMAT_MAX_LENGTH, fmtstr, localtime (&t)); + else + size = strftime (buff, TIME_FORMAT_MAX_LENGTH, fmtstr, gmtime (&t)); + + if (size == 0) + /* size > TIME_FORMAT_MAX_LENGTH */ + buff[TIME_FORMAT_MAX_LENGTH-1] = '\0'; + + g_object_set (renderer, + "text", buff, + NULL); + + g_free (fmtstr); + } + +} + + +/** \brief Function to compare to Event cells. + * \param model Pointer to the GtkTreeModel. + * \param a Pointer to the first element. + * \param b Pointer to the second element. + * \param user_data Always NULL (TBC). + * \return See detailed description. + * + * This function is used by the SatList sort function to determine whether + * AOS/LOS cell a is greater than b or not. The cells a and b contain the + * time of the event in Julian days, thus the result can be computed by a + * simple comparison between the two numbers contained in the cells. + * + * The function returns -1 if a < b; +1 if a > b; 0 otherwise. + */ +static gint event_cell_compare_function (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + gint result; + gdouble ta,tb; + gint sort_col; + GtkSortType sort_type; + + + /* Since this function is used for both AOS and LOS columns, + we need to get the sort column */ + gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), + &sort_col, + &sort_type); + + /* get a and b */ + gtk_tree_model_get (model, a, sort_col, &ta, -1); + gtk_tree_model_get (model, b, sort_col, &tb, -1); + + if (ta < tb) { + result = -1; + } + else if (ta > tb) { + result = 1; + } + else { + result = 0; + } + + return result; +} + + +/** \brief Reload configuration */ +void +gtk_sat_list_reconf (GtkWidget *widget, GKeyFile *cfgdat) +{ + sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: FIXME I am not implemented")); +} + + + +/** \brief Manage "popup-menu" events. + * \param treeview The tree view in the GtkSatList widget + * \param list Pointer to the GtkSatList widget. + * + * This function is called when the "popup-menu" signal is emitted. This + * usually happens if the user presses SHJIFT-F10? It is used as a wrapper + * for the function that actually creates the popup menu. + */ +static gboolean +popup_menu_cb (GtkWidget *treeview, gpointer list) +{ + + /* if there is no selection, select the first row */ + + + view_popup_menu (treeview, NULL, list); + + return TRUE; /* we handled this */ +} + + +/** \brief Manage button press events. + * \param treeview The tree view in the GtkSatList widget. + * \param event The event received. + * \param list Pointer to the GtkSatList widget. + * + */ +static gboolean +button_press_cb (GtkWidget *treeview, GdkEventButton *event, gpointer list) +{ + + /* single click with the right mouse button? */ + if (event->type == GDK_BUTTON_PRESS && event->button == 3) { + + /* optional: select row if no row is selected or only + * one other row is selected (will only do something + * if you set a tree selection mode as described later + * in the tutorial) */ + if (1) { + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + + /* Note: gtk_tree_selection_count_selected_rows() does not + * exist in gtk+-2.0, only in gtk+ >= v2.2 ! */ + if (gtk_tree_selection_count_selected_rows (selection) <= 1) { + GtkTreePath *path; + + /* Get tree path for row that was clicked */ + if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview), + (gint) event->x, + (gint) event->y, + &path, NULL, NULL, NULL)) { + gtk_tree_selection_unselect_all (selection); + gtk_tree_selection_select_path (selection, path); + gtk_tree_path_free (path); + } + } + } /* end of optional bit */ + + view_popup_menu (treeview, event, list); + + return TRUE; /* we handled this */ + } + + return FALSE; /* we did not handle this */ +} + + +static void +view_popup_menu (GtkWidget *treeview, GdkEventButton *event, gpointer list) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + guint *catnum; + sat_t *sat; + + catnum = g_new0 (guint, 1); + + /* get selected satellite */ + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + + + gtk_tree_model_get (model, &iter, + SAT_LIST_COL_CATNUM, catnum, + -1); + + sat = SAT (g_hash_table_lookup (GTK_SAT_LIST (list)->satellites, catnum)); + + if (sat == NULL) { + sat_log_log (SAT_LOG_LEVEL_MSG, + _("%s:%d Failed to get data for %d."), + __FILE__, __LINE__, catnum); + + } + else { + gtk_sat_list_popup_exec (sat, GTK_SAT_LIST (list)->qth, event, + GTK_SAT_LIST (list)); + } + + + } + else { + sat_log_log (SAT_LOG_LEVEL_BUG, + _("%s:%d: There is no selection; skip popup."), + __FILE__, __LINE__); + } + + g_free (catnum); +} + + +/*** FIXME: formalise with other copies, only need az,el and jul_utc */ +static void +Calculate_RADec (sat_t *sat, qth_t *qth, obs_astro_t *obs_set) +{ + /* Reference: Methods of Orbit Determination by */ + /* Pedro Ramon Escobal, pp. 401-402 */ + + double phi,theta,sin_theta,cos_theta,sin_phi,cos_phi, + az,el,Lxh,Lyh,Lzh,Sx,Ex,Zx,Sy,Ey,Zy,Sz,Ez,Zz, + Lx,Ly,Lz,cos_delta,sin_alpha,cos_alpha; + geodetic_t geodetic; + + + geodetic.lon = qth->lon * de2ra; + geodetic.lat = qth->lat * de2ra; + geodetic.alt = qth->alt / 1000.0; + geodetic.theta = 0; + + + + az = sat->az * de2ra; + el = sat->el * de2ra; + phi = geodetic.lat; + theta = FMod2p(ThetaG_JD(sat->jul_utc) + geodetic.lon); + sin_theta = sin(theta); + cos_theta = cos(theta); + sin_phi = sin(phi); + cos_phi = cos(phi); + Lxh = -cos(az) * cos(el); + Lyh = sin(az) * cos(el); + Lzh = sin(el); + Sx = sin_phi * cos_theta; + Ex = -sin_theta; + Zx = cos_theta * cos_phi; + Sy = sin_phi * sin_theta; + Ey = cos_theta; + Zy = sin_theta*cos_phi; + Sz = -cos_phi; + Ez = 0; + Zz = sin_phi; + Lx = Sx*Lxh + Ex * Lyh + Zx*Lzh; + Ly = Sy*Lxh + Ey * Lyh + Zy*Lzh; + Lz = Sz*Lxh + Ez * Lyh + Zz*Lzh; + obs_set->dec = ArcSin(Lz); /* Declination (radians)*/ + cos_delta = sqrt(1 - Sqr(Lz)); + sin_alpha = Ly / cos_delta; + cos_alpha = Lx / cos_delta; + obs_set->ra = AcTan(sin_alpha,cos_alpha); /* Right Ascension (radians)*/ + obs_set->ra = FMod2p(obs_set->ra); + +} + + + + +/** \brief Reload reference to satellites (e.g. after TLE update). */ +void +gtk_sat_list_reload_sats (GtkWidget *satlist, GHashTable *sats) +{ + GTK_SAT_LIST (satlist)->satellites = sats; +} Added: trunk/src/gtk-event-list.h =================================================================== --- trunk/src/gtk-event-list.h (rev 0) +++ trunk/src/gtk-event-list.h 2009-11-29 16:07:38 UTC (rev 529) @@ -0,0 +1,119 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + Gpredict: Real-time satellite tracking and orbit prediction program + + Copyright (C) 2001-2009 Alexandru Csete, OZ9AEC. + + Authors: Alexandru Csete <oz...@gm...> + + Comments, questions and bugreports should be submitted via + http://sourceforge.net/projects/gpredict/ + More details can be found at the project home page: + + http://gpredict.oz9aec.net/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, visit http://www.fsf.org/ +*/ +#ifndef __GTK_EVENT_LIST_H__ +#define __GTK_EVENT_LIST_H__ 1 + +#include <glib.h> +#include <glib/gi18n.h> +#include <gdk/gdk.h> +#include <gtk/gtkvbox.h> +#include "gtk-sat-data.h" + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GTK_TYPE_EVENT_LIST (gtk_EVENT_list_get_type ()) +#define GTK_EVENT_LIST(obj) GTK_CHECK_CAST (obj,\ + gtk_event_list_get_type (),\ + GtkEventList) + +#define GTK_EVENT_LIST_CLASS(klass) GTK_CHECK_CLASS_CAST (klass,\ + gtk_event_list_get_type (),\ + GtkEventListClass) + +#define IS_GTK_EVENT_LIST(obj) GTK_CHECK_TYPE (obj, gtk_event_list_get_type ()) + + +typedef struct _gtk_event_list GtkEventList; +typedef struct _GtkEventListClass GtkEventListClass; + + +struct _gtk_event_list +{ + GtkVBox vbox; + + GtkWidget *treeview; /*!< the tree view itself */ + GtkWidget *swin; /*!< scrolled window */ + + GHashTable *satellites; /*!< Satellites. */ + qth_t *qth; /*!< Pointer to current location. */ + + guint32 flags; /*!< Flags indicating which columns are visible */ + guint refresh; /*!< Refresh rate, ie. how many cycles should pass between updates */ + guint counter; /*!< cycle counter */ + + gdouble tstamp; /*!< time stamp of calculations; set by GtkSatModule */ + + void (* update) (GtkWidget *widget); /*!< update function */ +}; + +struct _GtkEventListClass +{ + GtkVBoxClass parent_class; +}; + + +/** \brief Symbolic references to columns */ +typedef enum { + EVENT_LIST_COL_NAME = 0, /*!< Satellite name. */ + EVENT_LIST_COL_CATNUM, /*!< Catalogue number. */ + EVENT_LIST_COL_EVT, /*!< Next event (AOS or LOS). */ + EVENT_LIST_COL_TIME, /*!< Time countdown. */ + EVENT_LIST_COL_NUMBER +} event_list_col_t; + + + +/** \brief Column Flags */ +typedef enum { + EVENT_LIST_FLAG_NAME = 1 << EVENT_LIST_COL_NAME, /*!< Satellite name. */ + EVENT_LIST_FLAG_CATNUM = 1 << EVENT_LIST_COL_CATNUM, + EVENT_LIST_FLAG_EVT = 1 << EVENT_LIST_COL_EVT, /*!< Next event (AOS or LOS) */ + EVENT_LIST_FLAG_TIME = 1 << EVENT_LIST_COL_TIME, /*!< Time countdown */ +} event_list_flag_t; + + +GtkType gtk_event_list_get_type (void); +GtkWidget* gtk_event_list_new (GKeyFile *cfgdata, + GHashTable *sats, + qth_t *qth, + guint32 columns); +void gtk_event_list_update (GtkWidget *widget); +void gtk_event_list_reconf (GtkWidget *widget, GKeyFile *cfgdat); + +void gtk_event_list_reload_sats (GtkWidget *satlist, GHashTable *sats); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GTK_SAT_MODULE_H__ */ Modified: trunk/src/gtk-sat-module.h =================================================================== --- trunk/src/gtk-sat-module.h 2009-11-29 12:36:54 UTC (rev 528) +++ trunk/src/gtk-sat-module.h 2009-11-29 16:07:38 UTC (rev 529) @@ -49,20 +49,22 @@ /** \brief Module layout */ -typedef enum { - GTK_SAT_MOD_LAYOUT_1 = 0, /*!< one view */ - GTK_SAT_MOD_LAYOUT_2, /*!< Two views, one above the other */ - GTK_SAT_MOD_LAYOUT_3, /*!< Three views, big one on top, two small one at bottom */ - GTK_SAT_MOD_LAYOUT_4 /*!< Three views, big one on bottom, small ones on top */ -} gtk_sat_mod_layout_t; +//typedef enum { +// GTK_SAT_MOD_LAYOUT_1 = 0, /*!< one view */ +// GTK_SAT_MOD_LAYOUT_2, /*!< Two views, one above the other */ +// GTK_SAT_MOD_LAYOUT_3, /*!< Three views, big one on top, two small one at bottom */ +// GTK_SAT_MOD_LAYOUT_4 /*!< Three views, big one on bottom, small ones on top */ +//} gtk_sat_mod_layout_t; + /** \brief View types */ typedef enum { GTK_SAT_MOD_VIEW_LIST = 0, /*!< GtkSatList */ GTK_SAT_MOD_VIEW_MAP, /*!< GtkSatMap */ GTK_SAT_MOD_VIEW_POLAR, /*!< GtkPolarView */ GTK_SAT_MOD_VIEW_SINGLE, /*!< GtkSingleSat */ + GTK_SAT_MOD_VIEW_EVENT, /*!< GtkEventList */ GTK_SAT_MOD_VIEW_NUM, /*!< Number of modules */ } gtk_sat_mod_view_t; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |