From: Alexandru C. <cs...@us...> - 2006-02-05 14:20:41
|
Update of /cvsroot/groundstation/gpredict2/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28000 Modified Files: sat-pref-qth.c Log Message: Added list of QTH including reading data from .qth files. Still need edit capabilities. Index: sat-pref-qth.c =================================================================== RCS file: /cvsroot/groundstation/gpredict2/src/sat-pref-qth.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** sat-pref-qth.c 9 Nov 2005 17:12:01 -0000 1.4 --- sat-pref-qth.c 5 Feb 2006 14:20:32 -0000 1.5 *************** *** 33,38 **** --- 33,45 ---- #include "gpredict-utils.h" #include "sat-cfg.h" + #include "sat-log.h" + #include "gtk-sat-data.h" #include "sat-pref-qth.h" + #if WANT_HAMLIB + # include <hamlib/rig.h> + # include <hamlib/rotator.h> + #endif + /** \brief Coumn definitions for QTH list. */ *************** *** 47,50 **** --- 54,59 ---- QTH_LIST_COL_QRA, /*!< QRA locator. */ QTH_LIST_COL_WX, /*!< 4 letter weather station. */ + QTH_LIST_COL_DEF, /*!< Is this QTH the default one? */ + QTH_LIST_COL_CHGD, /*!< Flag indicating whether data has changed or not. */ QTH_LIST_COL_NUM /*!< The number of fields. */ } qth_list_col_t; *************** *** 54,62 **** static GtkWidget *editbutton; static GtkWidget *delbutton; /* private function prototypes */ ! static GtkWidget *create_qth_list (void); ! static GtkWidget *create_buttons (void); --- 63,84 ---- static GtkWidget *editbutton; static GtkWidget *delbutton; + static GtkWidget *qthlist; /* private function prototypes */ ! static GtkWidget *create_qth_list (void); ! static GtkTreeModel *create_and_fill_model (void); ! static guint read_qth_file (GtkListStore *liststore, gchar *filename); ! static GtkWidget *create_buttons (void); ! static void default_toggled (GtkCellRendererToggle *cell, ! gchar *path_str, ! gpointer data); ! ! static void float_cell_data_function (GtkTreeViewColumn *col, ! GtkCellRenderer *renderer, ! GtkTreeModel *model, ! GtkTreeIter *iter, ! gpointer column); ! *************** *** 112,120 **** create_qth_list () { ! return gtk_label_new ("LIST"); } /** \brief Create buttons. * --- 134,437 ---- create_qth_list () { + GtkTreeModel *model; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; ! ! ! qthlist = gtk_tree_view_new (); ! ! model = create_and_fill_model (); ! gtk_tree_view_set_model (GTK_TREE_VIEW (qthlist), model); ! g_object_unref (model); ! ! /* name column */ ! renderer = gtk_cell_renderer_text_new (); ! column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, ! "text", QTH_LIST_COL_NAME, ! NULL); ! gtk_tree_view_insert_column (GTK_TREE_VIEW (qthlist), column, -1); ! ! /* lat column */ ! renderer = gtk_cell_renderer_text_new (); ! column = gtk_tree_view_column_new_with_attributes (_("Lat"), renderer, ! "text", QTH_LIST_COL_LAT, ! NULL); ! gtk_tree_view_column_set_alignment (column, 0.5); ! gtk_tree_view_column_set_cell_data_func (column, ! renderer, ! float_cell_data_function, ! GUINT_TO_POINTER (QTH_LIST_COL_LAT), ! NULL); ! gtk_tree_view_insert_column (GTK_TREE_VIEW (qthlist), column, -1); ! ! /* lon column */ ! renderer = gtk_cell_renderer_text_new (); ! column = gtk_tree_view_column_new_with_attributes (_("Lon"), renderer, ! "text", QTH_LIST_COL_LON, ! NULL); ! gtk_tree_view_column_set_alignment (column, 0.5); ! gtk_tree_view_column_set_cell_data_func (column, ! renderer, ! float_cell_data_function, ! GUINT_TO_POINTER (QTH_LIST_COL_LON), ! NULL); ! gtk_tree_view_insert_column (GTK_TREE_VIEW (qthlist), column, -1); ! ! /* alt column */ ! renderer = gtk_cell_renderer_text_new (); ! if (sat_cfg_get_bool (SAT_CFG_BOOL_USE_IMPERIAL)) { ! column = gtk_tree_view_column_new_with_attributes (_("Alt (ft)"), renderer, ! "text", QTH_LIST_COL_ALT, ! NULL); ! } ! else { ! column = gtk_tree_view_column_new_with_attributes (_("Alt (m)"), renderer, ! "text", QTH_LIST_COL_ALT, ! NULL); ! } ! gtk_tree_view_insert_column (GTK_TREE_VIEW (qthlist), column, -1); ! gtk_tree_view_column_set_alignment (column, 0.5); ! ! /* locator */ ! #if WANT_HAMLIB ! renderer = gtk_cell_renderer_text_new (); ! column = gtk_tree_view_column_new_with_attributes (_("QRA"), renderer, ! "text", QTH_LIST_COL_QRA, ! NULL); ! gtk_tree_view_insert_column (GTK_TREE_VIEW (qthlist), column, -1); ! gtk_tree_view_column_set_alignment (column, 0.5); ! #endif ! ! /* weather station */ ! renderer = gtk_cell_renderer_text_new (); ! column = gtk_tree_view_column_new_with_attributes (_("WX"), renderer, ! "text", QTH_LIST_COL_WX, ! NULL); ! gtk_tree_view_insert_column (GTK_TREE_VIEW (qthlist), column, -1); ! gtk_tree_view_column_set_alignment (column, 0.5); ! ! /* default */ ! renderer = gtk_cell_renderer_toggle_new (); ! g_signal_connect (renderer, "toggled", ! G_CALLBACK (default_toggled), model); ! ! column = gtk_tree_view_column_new_with_attributes (_("Default"), renderer, ! "active", QTH_LIST_COL_DEF, ! NULL); ! gtk_tree_view_append_column (GTK_TREE_VIEW (qthlist), column); ! gtk_tree_view_column_set_alignment (column, 0.5); ! ! ! return qthlist; } + /** \brief Create data storage for QTH list. + * + * This function creates the data storage necessary for the + * list view. The newly created tree model is populated with + * data from the .qth files in the users config diretory. + * The individual .qth files are read by the read_qth_file + * function. + */ + static GtkTreeModel * + create_and_fill_model () + { + GtkListStore *liststore; /* the list store data structure */ + GDir *dir = NULL; /* directory handle */ + GError *error = NULL; /* error flag and info */ + gchar *dirname; /* directory name */ + gchar *filename; /* file name */ + gchar *msg; /* debug message */ + gchar *buff; + + /* create a new list store */ + liststore = gtk_list_store_new (QTH_LIST_COL_NUM, + G_TYPE_STRING, // File name + G_TYPE_STRING, // QTH name + G_TYPE_STRING, // Location + G_TYPE_STRING, // Description + G_TYPE_FLOAT, // Latitude + G_TYPE_FLOAT, // Longitude + G_TYPE_INT, // Altitude + G_TYPE_STRING, // QRA locator + G_TYPE_STRING, // Weather station + G_TYPE_BOOLEAN, // Default + G_TYPE_BOOLEAN // Changed + ); + + /* scan for .qth files in the user config directory and + add the contents of each .qth file to the list store + */ + dirname = g_strconcat (g_get_home_dir (), G_DIR_SEPARATOR_S, + ".gpredict2", NULL); + dir = g_dir_open (dirname, 0, &error); + + + if (dir) { + /**** FIXME: There is a compile warning here */ + while ((filename = g_dir_read_name (dir))) { + + if (g_strrstr (filename, ".qth")) { + + buff = g_strconcat (dirname, G_DIR_SEPARATOR_S, + filename, NULL); + + /* read qth file */ + if (read_qth_file (liststore, buff)) { + /* send debug message */ + msg = g_strdup_printf (_("%s:%d: Read QTH data from %s."), + __FILE__, __LINE__, + filename); + sat_log_log (SAT_LOG_LEVEL_DEBUG, msg); + g_free (msg); + } + else { + /* error reading the file */ + msg = g_strdup_printf (_("%s:%d: Error reading %s (see prev msg)"), + __FILE__, __LINE__, filename); + sat_log_log (SAT_LOG_LEVEL_ERROR, msg); + g_free (msg); + } + + g_free (buff); + } + } + } + else { + msg = g_strdup_printf (_("%s:%d: Failed to open user cfg dir (%s)"), + __FILE__, __LINE__, error->message); + sat_log_log (SAT_LOG_LEVEL_ERROR, msg); + g_free (msg); + g_clear_error (&error); + + } + + g_free (dirname); + g_dir_close (dir); + + return GTK_TREE_MODEL (liststore); + } + + + /** \brief Read QTH file and add data to list store. + * \param liststore The GtkListStore where the data should be stored. + * \param filename The full name of the qth file. + * \return 1 if read is successful, 0 if an error occurs. + * + * The function uses the gtk-sat-data infrastructure to read the qth + * data from the specified file. + * + * There is a little challenge here. First, we want to read the data from + * the .qth files and store them in the list store. To do this we use a + * qth_t structure, which can be populated using gtk_sat_data_read_qth. + * Then, when the configuration is finished and the user presses "OK", we + * want to write all the data back to the .qth files. To do that, we create + * an up-to-date qth_t data structure and pass it to the gtk_sat_data_write_qth + * function, which will take care of updating the GKeyFile data structure and + * writing the contents to the .qth file. + */ + static guint + read_qth_file (GtkListStore *liststore, gchar *filename) + { + GtkTreeIter item; /* new item added to the list store */ + qth_t *qth=NULL; /* qth data structure */ + gchar *defqth; + gboolean is_default = FALSE; + gchar *msg; + + + qth = g_try_new (qth_t, 1); + + if (qth == NULL) { + msg = g_strdup_printf (_("%s:%d: Failed to allocate memory!\n"), + __FILE__,__LINE__); + sat_log_log (SAT_LOG_LEVEL_ERROR, msg); + g_free (msg); + + return FALSE; + } + + /* read data from file */ + if (!gtk_sat_data_read_qth (filename, qth)) { + return FALSE; + } + + /* calculate QRA locator */ + #if WANT_HAMLIB + gint retcode; + + qth->qra = g_malloc (7); + retcode = longlat2locator (qth->lon, qth->lat, qth->qra, 3); + + if (retcode != RIG_OK) { + msg = g_strdup_printf (_("%s:%d: Could not convert (%.2f,%.2f) to QRA (%s)"), + __FILE__, __LINE__, + qth->lat, qth->lon, + rigerror (retcode)); + sat_log_log (SAT_LOG_LEVEL_ERROR, msg); + g_free (msg); + qth->qra[0] = '\0'; + } + else { + qth->qra[6] = '\0'; + msg = g_strdup_printf (_("%s:%d: QRA locator is %s"), + __FILE__, __LINE__, qth->qra); + sat_log_log (SAT_LOG_LEVEL_DEBUG, msg); + g_free (msg); + + } + #endif + + /* is this the default qth? */ + defqth = sat_cfg_get_str (SAT_CFG_STR_DEF_QTH); + + if (g_str_has_suffix (filename, defqth)) { + is_default = TRUE; + + msg = g_strdup_printf (_("%s:%d: This appears to be the default QTH."), + __FILE__, __LINE__); + sat_log_log (SAT_LOG_LEVEL_MSG, msg); + g_free (msg); + } + + g_free (defqth); + + /* check wehter we are using imperial or metric system; + in case of imperial we have to convert altitude from + meters to feet. + */ + if (sat_cfg_get_bool (SAT_CFG_BOOL_USE_IMPERIAL)) { + qth->alt = (guint) ((gfloat) qth->alt * 3.2808399); + } + + /* we now have all necessary data in the qth_t structure; + add the data to the list store */ + gtk_list_store_append (liststore, &item); + gtk_list_store_set (liststore, &item, + QTH_LIST_COL_FILE, filename, + QTH_LIST_COL_NAME, qth->name, + QTH_LIST_COL_LOC, qth->loc, + QTH_LIST_COL_DESC, qth->desc, + QTH_LIST_COL_LAT, qth->lat, + QTH_LIST_COL_LON, qth->lon, + QTH_LIST_COL_ALT, qth->alt, + QTH_LIST_COL_QRA, qth->qra, + QTH_LIST_COL_WX, qth->wx, + QTH_LIST_COL_DEF, is_default, + QTH_LIST_COL_CHGD, FALSE, + -1); + + + /* we are finished with this qth, free it */ + /*** FIXME Segmentation fault, but we should free some memory! */ + // gtk_sat_data_free_qth (qth); + + return TRUE; + } + + + /** \brief Create buttons. * *************** *** 138,142 **** _("Edit the currently selected location")); ! /* delete button */ delbutton = gpredict_hstock_button (GTK_STOCK_DELETE, _("Delete"), --- 455,459 ---- _("Edit the currently selected location")); ! /* delete button; don't forget to delete file.... */ delbutton = gpredict_hstock_button (GTK_STOCK_DELETE, _("Delete"), *************** *** 156,157 **** --- 473,576 ---- + /** \brief Handle toggle events on "Default" check box + * \param cell The item that received the signal. + * \param path_str Path string. + * \param data Pointer to user data (list store). + * + * This function is called when the user clicks on "Default" check box + * indicating that a new default location has been selected. If the + * clicked check box has been un-checked the action is ignored, because + * we need a default location. If the clicked check box has been checked, + * the default flag of the checked QTH is set to TRUE, while the flag is + * cleared for all the other QTH's. + */ + static void + default_toggled (GtkCellRendererToggle *cell, + gchar *path_str, + gpointer data) + { + GtkTreeModel *model = (GtkTreeModel *)data; + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string (path_str); + gboolean fixed; + + g_print ("check clicked\n"); + + /* get toggled iter */ + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, QTH_LIST_COL_DEF, &fixed, -1); + + /* do something with the value */ + fixed ^= 1; + + /* set new value */ + gtk_list_store_set (GTK_LIST_STORE (model), &iter, QTH_LIST_COL_DEF, fixed, -1); + + /* clean up */ + gtk_tree_path_free (path); + } + + + /* render column containg float + 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 + float_cell_data_function (GtkTreeViewColumn *col, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer column) + { + gfloat number; + 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 == QTH_LIST_COL_LAT) { + if (number < 0.0) { + number *= -1.0; + hmf = 'S'; + } + else { + hmf = 'N'; + } + } + else if (coli == QTH_LIST_COL_LON) { + if (number < 0.0) { + number *= -1.0; + hmf = 'W'; + } + else { + hmf = 'E'; + } + } + else { + buff = g_strdup_printf (_("%s:%d: Invalid column: %d"), + __FILE__, __LINE__, + coli); + sat_log_log (SAT_LOG_LEVEL_BUG, buff); + g_free (buff); + hmf = '?'; + } + } + + /* format the number */ + buff = g_strdup_printf ("%.2f\302\260%c", number, hmf); + g_object_set (renderer, "text", buff, NULL); + g_free (buff); + } + + |