diff --git a/src/sat-cfg.c b/src/sat-cfg.c index 359ad49..ac88cf2 100644 --- a/src/sat-cfg.c +++ b/src/sat-cfg.c @@ -3,8 +3,6 @@ Copyright (C) 2001-2017 Alexandru Csete, OZ9AEC. - Authors: Alexandru Csete - Comments, questions and bugreports should be submitted via http://sourceforge.net/projects/gpredict/ More details can be found at the project home page: @@ -139,8 +137,8 @@ sat_cfg_bool_t sat_cfg_bool[SAT_CFG_BOOL_NUM] = { /** Array containing the integer configuration parameters */ sat_cfg_int_t sat_cfg_int[SAT_CFG_INT_NUM] = { - {"VERSION", "MAJOR", 0}, - {"VERSION", "MINOR", 0}, + {"VERSION", "MAJOR", 1}, + {"VERSION", "MINOR", 3}, {"MODULES", "DATA_TIMEOUT", 300}, {"MODULES", "LAYOUT", 2}, /* FIXME */ {"MODULES", "VIEW_1", GTK_SAT_MOD_VIEW_MAP}, /* FIXME */ @@ -234,6 +232,8 @@ sat_cfg_str_t sat_cfg_str[SAT_CFG_STR_NUM] = { "sarsat.txt;sbas.txt;science.txt;tdrss.txt;tle-new.txt;visual.txt;weather.txt;" "x-comm.txt"}, {"TLE", "PROXY", NULL}, + {"TLE", "URLS", + "http://www.amsat.org/amsat/ftp/keps/current/nasabare.txt"}, {"TLE", "FILE_DIR", NULL}, {"PREDICT", "SAVE_DIR", NULL} }; @@ -294,7 +294,45 @@ guint sat_cfg_load() { sat_cfg_reset_str(SAT_CFG_STR_TLE_FILES); sat_cfg_set_int(SAT_CFG_INT_VERSION_MAJOR, 1); - sat_cfg_set_int(SAT_CFG_INT_VERSION_MINOR, 1); + sat_cfg_set_int(SAT_CFG_INT_VERSION_MINOR, 4); + } + else if (cfg_ver < 0x0104) + { + /* Version 1.4 replaces TLE_SERVER and TLE_FILES with TLE_URLS, + * so import TLE_SERVER and FILES if they exist. + */ + gchar *urls = NULL; + gchar *buff; + gchar *tle_srv = sat_cfg_get_str(SAT_CFG_STR_TLE_SERVER); + gchar *tle_fstr = sat_cfg_get_str(SAT_CFG_STR_TLE_FILES); + gchar **tle_fvec = g_strsplit(tle_fstr, ";", 0); + int i; + + for (i = 0; i < g_strv_length(tle_fvec); i++) + { + if (i > 0) + { + buff = g_strdup_printf("%s;%s/%s", urls, tle_srv, tle_fvec[i]); + g_free(urls); + } + else + { + buff = g_strdup_printf("%s/%s", tle_srv, tle_fvec[i]); + } + urls = g_strdup(buff); + g_free(buff); + } + if (urls) + sat_cfg_set_str(SAT_CFG_STR_TLE_URLS, urls); + //sat_cfg_reset_str(SAT_CFG_STR_TLE_SERVER); + //sat_cfg_reset_str(SAT_CFG_STR_TLE_FILES); + g_free(urls); + g_free(tle_srv); + g_free(tle_fstr); + g_strfreev(tle_fvec); + + sat_cfg_set_int(SAT_CFG_INT_VERSION_MAJOR, 1); + sat_cfg_set_int(SAT_CFG_INT_VERSION_MINOR, 4); } return 0; diff --git a/src/sat-cfg.h b/src/sat-cfg.h index 44b63bc..578a852 100644 --- a/src/sat-cfg.h +++ b/src/sat-cfg.h @@ -3,8 +3,6 @@ Copyright (C) 2001-2017 Alexandru Csete, OZ9AEC. - Authors: Alexandru Csete - Comments, questions and bugreports should be submitted via http://sourceforge.net/projects/gpredict/ More details can be found at the project home page: @@ -147,9 +145,10 @@ typedef enum { SAT_CFG_STR_TRSP_FREQ_FILE, /*!< The file with frequency data on the server (since 1.4) */ SAT_CFG_STR_TRSP_MODE_FILE, /*!< The file with mode descriptions on the server (since 1.4) */ SAT_CFG_STR_TRSP_PROXY, /*!< Proxy server. */ - SAT_CFG_STR_TLE_SERVER, /*!< Server for TLE updates. */ - SAT_CFG_STR_TLE_FILES, /*!< ; separated list of files on server. */ + SAT_CFG_STR_TLE_SERVER, /*!< Server for TLE updates (replaced in 1.4 by TLE_URLS) */ + SAT_CFG_STR_TLE_FILES, /*!< ; separated list of files on server (replaced in 1.4 by TLE_URLS) */ SAT_CFG_STR_TLE_PROXY, /*!< Proxy server. */ + SAT_CFG_STR_TLE_URLS, /*!< ; separated list of TLE file URLs (since 1.4) */ SAT_CFG_STR_TLE_FILE_DIR, /*!< Local directory from which tle were last updated. */ SAT_CFG_STR_PRED_SAVE_DIR, /*!< Last used save directory for pass predictions */ SAT_CFG_STR_NUM /*!< Number of string parameters */ diff --git a/src/sat-pref-tle.c b/src/sat-pref-tle.c index 20ea11a..44918ed 100644 --- a/src/sat-pref-tle.c +++ b/src/sat-pref-tle.c @@ -1,9 +1,7 @@ /* Gpredict: Real-time satellite tracking and orbit prediction program - Copyright (C) 2001-2009 Alexandru Csete, OZ9AEC. - - Authors: Alexandru Csete + Copyright (C) 2001-2017 Alexandru Csete, OZ9AEC. Comments, questions and bugreports should be submitted via http://sourceforge.net/projects/gpredict/ @@ -31,10 +29,13 @@ #include #include "sat-cfg.h" +#include "sat-log.h" #include "sat-pref-tle.h" #include "tle-update.h" +extern GtkWidget *window; /* dialog window defined in sat-pref.c */ + /* Update frequency widget */ static GtkWidget *freq; @@ -42,7 +43,7 @@ static GtkWidget *freq; static GtkWidget *warn, *autom; /* internet updates */ -static GtkWidget *server, *proxy, *files; +static GtkWidget *proxy, *tle_url_view, *add_tle, *del_tle; /* add new sats */ static GtkWidget *addnew; @@ -60,10 +61,6 @@ static void create_reset_button(GtkBox * vbox); static void reset_cb(GtkWidget * button, gpointer data); static void value_changed_cb(GtkWidget * widget, gpointer data); -#if 0 -static void create_local(GtkWidget * vbox); -#endif - /** Create and initialise widgets for the locations TLE update tab. */ GtkWidget *sat_pref_tle_create() @@ -81,26 +78,20 @@ GtkWidget *sat_pref_tle_create() gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, TRUE, 0); create_misc(vbox); -#if 0 - create_local(vbox); -#endif - /* create RESET button */ create_reset_button(GTK_BOX(vbox)); return vbox; } -/** \brief User pressed cancel. Any changes to config must be cancelled. - */ +/** User pressed cancel. Any changes to config must be cancelled. */ void sat_pref_tle_cancel() { dirty = FALSE; reset = FALSE; } -/** \brief User pressed OK. Any changes should be stored in config. - */ +/** User pressed OK. Any changes should be stored in config. */ void sat_pref_tle_ok() { if (dirty) @@ -119,22 +110,47 @@ void sat_pref_tle_ok() sat_cfg_set_int(SAT_CFG_INT_TLE_AUTO_UPD_ACTION, TLE_AUTO_UPDATE_NOTIFY); - /* server */ - sat_cfg_set_str(SAT_CFG_STR_TLE_SERVER, - gtk_entry_get_text(GTK_ENTRY(server))); - /* proxy */ sat_cfg_set_str(SAT_CFG_STR_TLE_PROXY, gtk_entry_get_text(GTK_ENTRY(proxy))); - /* files */ - sat_cfg_set_str(SAT_CFG_STR_TLE_FILES, - gtk_entry_get_text(GTK_ENTRY(files))); + /* URLS */ + gsize num; + guint i; + gchar *url, *buff, *all_urls = NULL; + GtkTreeModel *model; + GtkTreeIter iter; - /* add new sats */ - sat_cfg_set_bool(SAT_CFG_BOOL_TLE_ADD_NEW, - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON - (addnew))); + model = gtk_tree_view_get_model(GTK_TREE_VIEW(tle_url_view)); + num = gtk_tree_model_iter_n_children(model, NULL); + for (i = 0; i < num; i++) + { + if (gtk_tree_model_iter_nth_child(model, &iter, NULL, i)) + { + gtk_tree_model_get(model, &iter, 0, &url, -1); + if (i > 0) + { + buff = g_strdup_printf("%s;%s", all_urls, url); + g_free(all_urls); + } + else + { + buff = g_strdup_printf("%s", url); + } + all_urls = g_strdup(buff); + g_free(buff); + g_free(url); + } + else + { + sat_log_log(SAT_LOG_LEVEL_ERROR, + _("%s:%s: Error fetching entry %d in URL list"), + __FILE__, __func__, i); + } + + } + sat_cfg_set_str(SAT_CFG_STR_TLE_URLS, all_urls); + g_free(all_urls); dirty = FALSE; } @@ -143,9 +159,8 @@ void sat_pref_tle_ok() /* use sat_cfg_reset */ sat_cfg_reset_int(SAT_CFG_INT_TLE_AUTO_UPD_FREQ); sat_cfg_reset_int(SAT_CFG_INT_TLE_AUTO_UPD_ACTION); - sat_cfg_reset_str(SAT_CFG_STR_TLE_SERVER); sat_cfg_reset_str(SAT_CFG_STR_TLE_PROXY); - sat_cfg_reset_str(SAT_CFG_STR_TLE_FILES); + sat_cfg_reset_str(SAT_CFG_STR_TLE_URLS); sat_cfg_reset_bool(SAT_CFG_BOOL_TLE_ADD_NEW); reset = FALSE; @@ -206,11 +221,140 @@ static void create_auto_update(GtkWidget * vbox) g_signal_connect(autom, "toggled", G_CALLBACK(value_changed_cb), NULL); } +/* Calback function called when an URL entry in the list has been edited */ +static void url_edited_cb(GtkCellRendererText * renderer, gchar * path, + gchar * new_text, GtkListStore * tle_store) +{ + GtkTreeIter iter; + + gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(tle_store), &iter, + path); + gtk_list_store_set(tle_store, &iter, 0, new_text, -1); + dirty = TRUE; +} + +/* Add TLE button clicked */ +static void add_tle_cb(GtkWidget * button, GtkListStore * tle_store) +{ + GtkTreeView *tv = GTK_TREE_VIEW(tle_url_view); + GtkTreePath *path; + GtkTreeIter iter; + GtkTreeSelection *selection; + + gtk_list_store_append(tle_store, &iter); + gtk_list_store_set(tle_store, &iter, 0, "http://server.com/file.txt", -1); + + /* activate the newly added row */ + path = gtk_tree_model_get_path(GTK_TREE_MODEL(tle_store), &iter); + selection = gtk_tree_view_get_selection(tv); + gtk_tree_selection_select_path(selection, path); + gtk_tree_view_scroll_to_cell(tv, path, NULL, FALSE, 0.0, 0.0); + + /* TODO: Enable editing on row */ + + dirty = TRUE; +} + +/* Delete TLE button clicked */ +static void del_tle_cb(GtkWidget * button, gpointer data) +{ + (void)button; + (void)data; + + GtkTreeView *tv = GTK_TREE_VIEW(tle_url_view); + GtkTreeModel *model = gtk_tree_view_get_model(tv); + GtkTreeModel *selmod; + GtkTreeSelection *selection; + GtkTreeIter iter; + + /* if this is the only entry, tell user that it is not possible to delete */ + if (gtk_tree_model_iter_n_children(model, NULL) < 2) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new(GTK_WINDOW(window), + GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Can not delete TLE source!\n\n" + "You should have at least one TLE source configured, " + "otherwise Gpredict may not work correctly.\n\n" + "If you want to modify the TLE source, click twice " + "on the row to edit it.")); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + } + else + { + /* get selected row + FIXME: do we really need to work with two models? + */ + selection = gtk_tree_view_get_selection(tv); + if (gtk_tree_selection_get_selected(selection, &selmod, &iter)) + gtk_list_store_remove(GTK_LIST_STORE(selmod), &iter); + + dirty = TRUE; + } +} + +static GtkWidget *create_tle_buttons(GtkListStore * tle_store) +{ + GtkWidget *box; + + add_tle = gtk_button_new_with_label(_("Add TLE source")); + gtk_widget_set_tooltip_text(add_tle, + _("Add a new TLE source to the list")); + g_signal_connect(add_tle, "clicked", (GCallback) add_tle_cb, tle_store); + + del_tle = gtk_button_new_with_label(_("Delete TLE source")); + gtk_widget_set_tooltip_text(del_tle, _("Delete the selected TLE source")); + g_signal_connect(del_tle, "clicked", (GCallback) del_tle_cb, NULL); + + box = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(box), GTK_BUTTONBOX_START); + gtk_container_add(GTK_CONTAINER(box), add_tle); + gtk_container_add(GTK_CONTAINER(box), del_tle); + + return box; +} + +/* Update TLE URL view with URLs from tle_url_str */ +static void set_tle_urls(const gchar * tle_url_str) +{ + if (!tle_url_str) + return; + + gchar **tle_url_strv = g_strsplit(tle_url_str, ";", -1); + + if (g_strv_length(tle_url_strv) > 0) + { + GtkTreeIter iter; + GtkListStore *tle_store; + int i; + + tle_store = + GTK_LIST_STORE(gtk_tree_view_get_model + (GTK_TREE_VIEW(tle_url_view))); + gtk_list_store_clear(tle_store); + for (i = 0; i < g_strv_length(tle_url_strv); i++) + { + gtk_list_store_append(tle_store, &iter); + gtk_list_store_set(tle_store, &iter, 0, tle_url_strv[i], -1); + } + } + g_strfreev(tle_url_strv); +} + /** Create widgets for network update configuration */ static void create_network(GtkWidget * vbox) { + GtkWidget *swin; GtkWidget *label; - GtkWidget *table; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkListStore *tle_store; + /* auto update */ label = gtk_label_new(NULL); @@ -220,36 +364,14 @@ static void create_network(GtkWidget * vbox) gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0); /* create table */ - table = gtk_table_new(3, 3, FALSE); + GtkWidget *table; + + table = gtk_table_new(2, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); - /* server */ - label = gtk_label_new(_("Remote server:")); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, - 0, 0); - - server = gtk_entry_new(); - if (sat_cfg_get_str(SAT_CFG_STR_TLE_SERVER)) - gtk_entry_set_text(GTK_ENTRY(server), - sat_cfg_get_str(SAT_CFG_STR_TLE_SERVER)); - - gtk_widget_set_tooltip_text(server, - _ - ("Enter URL for remote server including directory, i.e.\n" - "protocol://servername/directory\n" - "Protocol can be both http and ftp.")); - - g_signal_connect(server, "changed", G_CALLBACK(value_changed_cb), NULL); - gtk_table_attach(GTK_TABLE(table), server, 1, 2, 0, 1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - - /* proxy */ label = gtk_label_new(_("Proxy server:")); gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, - 0, 0); proxy = gtk_entry_new(); if (sat_cfg_get_str(SAT_CFG_STR_TLE_PROXY)) @@ -259,29 +381,53 @@ static void create_network(GtkWidget * vbox) _("Enter URL for local proxy server. e.g.\n" "http://my.proxy.com")); g_signal_connect(proxy, "changed", G_CALLBACK(value_changed_cb), NULL); - gtk_table_attach(GTK_TABLE(table), proxy, 1, 2, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, + GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), proxy, 1, 2, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); - /* Files */ - label = gtk_label_new(_("Files to fetch:")); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, - 0, 0); + /* URLs */ + label = gtk_label_new(_("TLE sources:")); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.0); - files = gtk_entry_new(); - if (sat_cfg_get_str(SAT_CFG_STR_TLE_FILES)) - gtk_entry_set_text(GTK_ENTRY(files), - sat_cfg_get_str(SAT_CFG_STR_TLE_FILES)); - gtk_widget_set_tooltip_text(files, + tle_store = gtk_list_store_new(1, G_TYPE_STRING); + tle_url_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(tle_store)); + g_object_unref(tle_store); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tle_url_view), FALSE); + gtk_widget_set_tooltip_text(tle_url_view, _ - ("Enter list of files to fetch from remote server.\n" - "The files should be separated with ; (semicolon)")); - g_signal_connect(files, "changed", G_CALLBACK(value_changed_cb), NULL); - gtk_table_attach(GTK_TABLE(table), files, 1, 2, 2, 3, + ("List of files with TLE data to retrieve from " + "the Internet\nClick twice on a row to edit")); + + renderer = gtk_cell_renderer_text_new(); + g_object_set(renderer, "editable", TRUE, NULL); + g_signal_connect(renderer, "edited", G_CALLBACK(url_edited_cb), tle_store); + column = gtk_tree_view_column_new_with_attributes("Invisible title :)", + renderer, "text", 0, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tle_url_view), column); + + /* set URL data */ + gchar *tle_url_str = sat_cfg_get_str(SAT_CFG_STR_TLE_URLS); + + set_tle_urls(tle_url_str); + g_free(tle_url_str); + + /* scrolled window to contain the URL list */ + swin = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(swin), tle_url_view); + + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, + GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), swin, 1, 2, 1, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); - /* put table into vbox */ - gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, TRUE, 0); + gtk_table_attach(GTK_TABLE(table), create_tle_buttons(tle_store), + 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + + gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0); } /** Create widgets for network update configuration */ @@ -292,32 +438,15 @@ static void create_misc(GtkWidget * vbox) ("Add new satellites to local database")); gtk_widget_set_tooltip_text(addnew, _ - ("Note that new satellites will be added to a group called Other")); + ("New satellites will be added to a group called Other")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(addnew), sat_cfg_get_bool(SAT_CFG_BOOL_TLE_ADD_NEW)); g_signal_connect(addnew, "toggled", G_CALLBACK(value_changed_cb), NULL); gtk_box_pack_start(GTK_BOX(vbox), addnew, FALSE, TRUE, 0); - } -#if 0 -/** Create widgets for local update configuration */ -static void create_local(GtkWidget * vbox) -{ - GtkWidget *label; - - /* auto update */ - label = gtk_label_new(NULL); - gtk_label_set_markup(GTK_LABEL(label), - _("Update from Local Files:")); - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0); - -} -#endif - /** * Create RESET button. * @param cfg Config data or NULL in global mode. @@ -375,17 +504,15 @@ static void reset_cb(GtkWidget * button, gpointer data) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(warn), TRUE); } - /* server */ - gtk_entry_set_text(GTK_ENTRY(server), - sat_cfg_get_str_def(SAT_CFG_STR_TLE_SERVER)); /* proxy */ gtk_entry_set_text(GTK_ENTRY(proxy), ""); - /* files */ - gtk_entry_set_text(GTK_ENTRY(files), - sat_cfg_get_str_def(SAT_CFG_STR_TLE_FILES)); + /* URLS */ + gchar *tle_url_str = sat_cfg_get_str_def(SAT_CFG_STR_TLE_URLS); + set_tle_urls(tle_url_str); + g_free(tle_url_str); /* add new sats */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(addnew), diff --git a/src/sat-pref-tle.h b/src/sat-pref-tle.h index 72874ba..f72dfea 100644 --- a/src/sat-pref-tle.h +++ b/src/sat-pref-tle.h @@ -3,8 +3,6 @@ Copyright (C) 2001-2009 Alexandru Csete, OZ9AEC. - Authors: Alexandru Csete - Comments, questions and bugreports should be submitted via http://sourceforge.net/projects/gpredict/ More details can be found at the project home page: