From 4a52e037afaaea37ba9d249e2a3798ff6dffd252 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sat, 16 Aug 2014 23:47:48 +0200 Subject: [PATCH 01/15] Add PPLC (capitals) to cities.txt, and thus to geodata.xml --- data/geonames/geonames_process.awk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/geonames/geonames_process.awk b/data/geonames/geonames_process.awk index 57f0cd6..c503559 100644 --- a/data/geonames/geonames_process.awk +++ b/data/geonames/geonames_process.awk @@ -2,6 +2,6 @@ BEGIN { FS="\t" } { - if ($7 != "P" || $8 != "PPL" || $15 < 1000) next + if ($7 != "P" || ($8 != "PPL" && $8 != "PPLC") || $15 < 1000) next print $9 FS $2 FS $5 FS $6 FS $16 FS $18 } From 15737de254d83620724a104da0924c88d8c6fdbd Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sat, 16 Aug 2014 23:48:04 +0200 Subject: [PATCH 02/15] Redesign geodata.xml so it also stores country names --- data/geonames/geonames_process.pl | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/data/geonames/geonames_process.pl b/data/geonames/geonames_process.pl index 5311276..e8bddeb 100644 --- a/data/geonames/geonames_process.pl +++ b/data/geonames/geonames_process.pl @@ -16,25 +16,34 @@ while () { } close(TIMEZONES); +my $xml_file = IO::File->new('>geodata.xml'); +my $writer = XML::Writer->new(OUTPUT => $xml_file, NEWLINES => 0); + +$writer->xmlDecl('utf-8'); +$writer->startTag('geodata'); +$writer->startTag('countries'); + open(COUNTRIES, 'countryInfo.txt') or die("Cannot open countryInfo.txt: $!\n"); while () { my ($country_code, $iso3, $iso_numeric, $fips, $name, $capital, $area, $population, $continent, $tld, $currency_code, $currency_name, $phone, $postal_code_format, $postal_code_regex, $languages, $geonameid, $neighbours, $equivalent_fips_code) = split(/\t/, $_); next if ($country_code !~ /^[A-Z]{2}$/); + $writer->emptyTag('c', + 'n' => $name, + 'c' => $country_code, + ); + if ($country_code =~ /^[A-Z]{2}$/) { $countries{$country_code} = $name; } } close(COUNTRIES); +$writer->endTag('countries'); +$writer->startTag('places'); + open(GEONAMES, "cities.txt") or die("Cannot open cities.txt: $!\n"); -my $xml_file = IO::File->new('>geodata.xml'); -my $writer = XML::Writer->new(OUTPUT => $xml_file, NEWLINES => 0); - -$writer->xmlDecl('utf-8'); -$writer->startTag('geodata'); - while () { chomp($_); my ($country_code, $name, $latitude, $longitude, $elevation, $timezone) = split(/\t/, $_); @@ -62,6 +71,7 @@ while () { print $., "\n" if ($. % 19083 == 0); } +$writer->endTag('places'); $writer->endTag('geodata'); $writer->end(); $xml_file->close(); From cb99af5a0de90b98ab849555bbbbe2cbc44cd90e Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sun, 17 Aug 2014 00:53:48 +0200 Subject: [PATCH 03/15] Add GtkListStore for city and country list --- src/astrognome.c | 19 +++++++++++++++++++ src/astrognome.h | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/astrognome.c b/src/astrognome.c index 03f487e..04f1bf9 100644 --- a/src/astrognome.c +++ b/src/astrognome.c @@ -19,6 +19,8 @@ GtkBuilder *builder; GtkFileFilter *filter_all = NULL; GtkFileFilter *filter_chart = NULL; GtkFileFilter *filter_hor = NULL; +GtkTreeModel *country_list = NULL; +GtkTreeModel *city_list = NULL; GHashTable *xinclude_positions; const char *moonStateName[] = { @@ -279,6 +281,23 @@ main(int argc, char *argv[]) return EXIT_SUCCESS; } + country_list = GTK_TREE_MODEL(gtk_list_store_new( + AG_COUNTRY_COLCOUNT, + G_TYPE_STRING, + G_TYPE_STRING + )); + + city_list = GTK_TREE_MODEL(gtk_list_store_new( + AG_CITY_COLCOUNT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE + )); + status = g_application_run(G_APPLICATION(app), argc, argv); g_hash_table_destroy(xinclude_positions); diff --git a/src/astrognome.h b/src/astrognome.h index 6ad04e8..80a1eeb 100644 --- a/src/astrognome.h +++ b/src/astrognome.h @@ -12,6 +12,25 @@ typedef struct { extern GtkFileFilter *filter_all; extern GtkFileFilter *filter_chart; extern GtkFileFilter *filter_hor; +extern GtkTreeModel *country_list; +extern GtkTreeModel *city_list; + +enum { + AG_COUNTRY_CODE, + AG_COUNTRY_NAME, + AG_COUNTRY_COLCOUNT +}; + +enum { + AG_CITY_COUNTRY, + AG_CITY_NAME, + AG_CITY_LAT, + AG_CITY_LONG, + AG_CITY_ALT, + AG_CITY_TZO, + AG_CITY_TZD, + AG_CITY_COLCOUNT +}; const gchar *ag_house_system_id_to_nick(GsweHouseSystem house_system); GsweHouseSystem ag_house_system_nick_to_id(const gchar *nick); From cdb856d8ed21bed4b0d1eafff5218e691685691d Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sun, 17 Aug 2014 09:36:30 +0200 Subject: [PATCH 04/15] Create a DEFAULT_ALTITUDE macro It is set to 280.0, which is roughly the average altitude of dry land --- configure.ac | 1 + src/ag-chart.c | 3 ++- src/ag-db.c | 3 +-- src/ag-window.c | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 7a9ce88..aef683b 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,7 @@ AC_PATH_PROGS(UNZIP, [unzip]) have_geonames_perl_modules=no AX_PROG_PERL_MODULES([XML::Writer IO::File], [have_geonames_perl_modules=yes], AC_MSG_WARN([XML::Writer and IO::File perl modules are required if you want to regenerate geodata.xml!])) AC_SUBST([have_geonames_perl_modules]) +AC_DEFINE([DEFAULT_ALTITUDE], [280.0], [Set this to the default altitude value, which is used if there is no value in geodata.xml]) IT_PROG_INTLTOOL([0.35.0]) GETTEXT_PACKAGE=astrognome AC_SUBST(GETTEXT_PACKAGE) diff --git a/src/ag-chart.c b/src/ag-chart.c index cad1283..f9279e4 100644 --- a/src/ag-chart.c +++ b/src/ag-chart.c @@ -11,6 +11,7 @@ #include #include +#include "config.h" #include "ag-db.h" #include "ag-chart.h" #include "placidus.h" @@ -1262,7 +1263,7 @@ AgChart *ag_chart_load_from_placidus_file(GFile *file, chart = ag_chart_new_full( timestamp, - real_long, real_lat, 280.0, + real_long, real_lat, DEFAULT_ALTITUDE, GSWE_HOUSE_SYSTEM_PLACIDUS ); diff --git a/src/ag-db.c b/src/ag-db.c index 2e28d93..afa4ac3 100644 --- a/src/ag-db.c +++ b/src/ag-db.c @@ -955,8 +955,7 @@ ag_db_get_chart_data_by_id(AgDb *db, guint row_id, GError **err) attributes = gda_data_model_get_attributes_at(result, COLUMN_ALTITUDE, 0); if (attributes | GDA_VALUE_ATTR_IS_NULL) { - /* TODO: this value should be macroified */ - save_data->altitude = 280.0; + save_data->altitude = DEFAULT_ALTITUDE; } else { save_data->altitude = g_value_get_double(value); } diff --git a/src/ag-window.c b/src/ag-window.c index a2fa189..2f8f90a 100644 --- a/src/ag-window.c +++ b/src/ag-window.c @@ -10,6 +10,7 @@ #include +#include "config.h" #include "ag-app.h" #include "ag-window.h" #include "ag-chart.h" @@ -574,7 +575,7 @@ ag_window_recalculate_chart(AgWindow *window, gboolean set_everything) } // TODO: So as this… - edit_data->altitude = 280.0; + edit_data->altitude = DEFAULT_ALTITUDE; edit_data->year = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(priv->year) ); From 1c2c2d0342f1b4fd335886c9508b055da6ff3190 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Mon, 18 Aug 2014 22:17:50 +0200 Subject: [PATCH 05/15] Bind signal callbacks with gtk_widget_class_bind_template_callback() --- src/ag-window.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/ag-window.c b/src/ag-window.c index 2f8f90a..bfdb6d0 100644 --- a/src/ag-window.c +++ b/src/ag-window.c @@ -984,7 +984,7 @@ ag_window_close_action(GSimpleAction *action, } } -gboolean +static gboolean ag_window_delete_event_callback(AgWindow *window, GdkEvent *event, gpointer user_data) @@ -992,7 +992,7 @@ ag_window_delete_event_callback(AgWindow *window, return (!ag_window_can_close(window, TRUE)); } -void +static void ag_window_tab_changed_cb(GtkStack *stack, GParamSpec *pspec, AgWindow *window) { GtkWidget *active_tab; @@ -1495,6 +1495,17 @@ ag_window_dispose(GObject *gobject) G_OBJECT_CLASS(ag_window_parent_class)->dispose(gobject); } +static void +ag_window_name_changed_cb(GtkEntry *name_entry, AgWindow *window) +{ + const gchar *name; + AgWindowPrivate *priv = ag_window_get_instance_private(window); + + name = gtk_entry_get_text(name_entry); + + gtk_header_bar_set_subtitle(GTK_HEADER_BAR(priv->header_bar), name); +} + static void ag_window_class_init(AgWindowClass *klass) { @@ -1618,6 +1629,19 @@ ag_window_class_init(AgWindowClass *klass) AgWindow, selection_toolbar ); + + gtk_widget_class_bind_template_callback( + widget_class, + ag_window_delete_event_callback + ); + gtk_widget_class_bind_template_callback( + widget_class, + ag_window_tab_changed_cb + ); + gtk_widget_class_bind_template_callback( + widget_class, + ag_window_name_changed_cb + ); } gboolean @@ -1787,17 +1811,6 @@ ag_window_change_tab(AgWindow *window, const gchar *tab_name) ); } -void -ag_window_name_changed_cb(GtkEntry *name_entry, AgWindow *window) -{ - const gchar *name; - AgWindowPrivate *priv = ag_window_get_instance_private(window); - - name = gtk_entry_get_text(name_entry); - - gtk_header_bar_set_subtitle(GTK_HEADER_BAR(priv->header_bar), name); -} - static void ag_window_add_chart_to_list(AgDbSave *save_data, AgWindow *window) { From 8d82c48f5f8177ab9e12d09dc4e2b76d4f0234f6 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Tue, 19 Aug 2014 00:29:21 +0200 Subject: [PATCH 06/15] Fix ag_db_get_chart_data_by_id() to recognise NULL values --- src/ag-db.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/ag-db.c b/src/ag-db.c index afa4ac3..3656dac 100644 --- a/src/ag-db.c +++ b/src/ag-db.c @@ -857,7 +857,6 @@ ag_db_get_chart_data_by_id(AgDb *db, guint row_id, GError **err) { AgDbSave *save_data; const GValue *value; - GdaValueAttribute attributes; gchar *query, *columns; guint i; @@ -918,18 +917,16 @@ ag_db_get_chart_data_by_id(AgDb *db, guint row_id, GError **err) /* country */ value = gda_data_model_get_value_at(result, COLUMN_COUNTRY, 0, NULL); - attributes = gda_data_model_get_attributes_at(result, COLUMN_COUNTRY, 0); - if (attributes | GDA_VALUE_ATTR_IS_NULL) { + if (GDA_VALUE_HOLDS_NULL(value)) { save_data->country = NULL; } else { save_data->country = g_strdup(g_value_get_string(value)); } value = gda_data_model_get_value_at(result, COLUMN_CITY, 0, NULL); - attributes = gda_data_model_get_attributes_at(result, COLUMN_CITY, 0); - if (attributes | GDA_VALUE_ATTR_IS_NULL) { + if (GDA_VALUE_HOLDS_NULL(value)) { save_data->city = NULL; } else { save_data->city = g_strdup(g_value_get_string(value)); @@ -952,9 +949,8 @@ ag_db_get_chart_data_by_id(AgDb *db, guint row_id, GError **err) save_data->latitude = g_value_get_double(value); value = gda_data_model_get_value_at(result, COLUMN_ALTITUDE, 0, NULL); - attributes = gda_data_model_get_attributes_at(result, COLUMN_ALTITUDE, 0); - if (attributes | GDA_VALUE_ATTR_IS_NULL) { + if (GDA_VALUE_HOLDS_NULL(value)) { save_data->altitude = DEFAULT_ALTITUDE; } else { save_data->altitude = g_value_get_double(value); @@ -1010,9 +1006,8 @@ ag_db_get_chart_data_by_id(AgDb *db, guint row_id, GError **err) save_data->house_system = g_strdup(g_value_get_string(value)); value = gda_data_model_get_value_at(result, COLUMN_NOTE, 0, NULL); - attributes = gda_data_model_get_attributes_at(result, 15, 0); - if (attributes | GDA_VALUE_ATTR_IS_NULL) { + if (GDA_VALUE_HOLDS_NULL(value)) { save_data->note = NULL; } else { save_data->note = g_strdup(g_value_get_string(value)); From 4e93781bb9cc457ea15cac43cc1e7a05a58e4860 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sun, 17 Aug 2014 09:42:22 +0200 Subject: [PATCH 07/15] Read country/city list from geodata.xml into GtkListStores --- src/astrognome.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 2 deletions(-) diff --git a/src/astrognome.c b/src/astrognome.c index 04f1bf9..b7bb512 100644 --- a/src/astrognome.c +++ b/src/astrognome.c @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -15,6 +16,10 @@ #include "ag-app.h" #include "ag-window.h" +#ifndef LIBXML_READER_ENABLED +#error "You need to have libxml2 with XmlReader enabled" +#endif + GtkBuilder *builder; GtkFileFilter *filter_all = NULL; GtkFileFilter *filter_chart = NULL; @@ -188,9 +193,9 @@ main(int argc, char *argv[]) { gint status; AgApp *app; - GError *err = NULL; + xmlTextReaderPtr reader; AstrognomeOptions options; - + GError *err = NULL; GOptionEntry option_entries[] = { { "new-window", 'n', @@ -298,6 +303,128 @@ main(int argc, char *argv[]) G_TYPE_DOUBLE )); + reader = xmlReaderForFile(PKGDATADIR "/geodata.xml", NULL, 0); + + if (reader != NULL) { + int ret; + + while ((ret = xmlTextReaderRead(reader)) == 1) { + gchar *name; + GtkTreeIter iter; + + name = (gchar *)xmlTextReaderConstName(reader); + + if (strcmp(name, "p") == 0) { + gchar *aname, + *acode, + *alat, + *alon, + *aalt, + *atzo, + *atzd, + *endptr; + gdouble lat, + lon, + alt, + tzo, + tzd; + + aname = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "n" + ); + acode = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "c" + ); + alat = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "lat" + ); + alon = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "lon" + ); + aalt = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "alt" + ); + atzo = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "tzo" + ); + atzd = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "tzd" + ); + + lat = g_ascii_strtod(alat, &endptr); + lon = g_ascii_strtod(alon, &endptr); + + if (*aalt == '\0') { + alt = DEFAULT_ALTITUDE; + } else { + alt = g_ascii_strtod(aalt, &endptr); + } + + tzo = g_ascii_strtod(atzo, &endptr); + tzd = g_ascii_strtod(atzd, &endptr); + + gtk_list_store_append(GTK_LIST_STORE(city_list), &iter); + gtk_list_store_set( + GTK_LIST_STORE(city_list), &iter, + AG_CITY_COUNTRY, acode, + AG_CITY_NAME, aname, + AG_CITY_LAT, lat, + AG_CITY_LONG, lon, + AG_CITY_ALT, alt, + AG_CITY_TZO, tzo, + AG_CITY_TZD, tzd, + -1 + ); + + g_free(aname); + g_free(acode); + g_free(alat); + g_free(alon); + g_free(aalt); + g_free(atzo); + g_free(atzd); + } else if (strcmp(name, "c") == 0) { + gchar *aname, + *acode; + + aname = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "n" + ); + acode = (gchar *)xmlTextReaderGetAttribute( + reader, + BAD_CAST "c" + ); + + gtk_list_store_append(GTK_LIST_STORE(country_list), &iter); + gtk_list_store_set( + GTK_LIST_STORE(country_list), &iter, + AG_COUNTRY_CODE, acode, + AG_COUNTRY_NAME, aname, + -1 + ); + + g_free(aname); + g_free(acode); + } + } + + xmlFreeTextReader(reader); + + if (ret != 0) { + g_error("Parse error in geodata.xml!"); + } + } else { + g_error("Unable to open geodata.xml!"); + } + status = g_application_run(G_APPLICATION(app), argc, argv); g_hash_table_destroy(xinclude_positions); From 86414b37dfae0c4f86452484f3a8bfa7476b3c10 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sun, 17 Aug 2014 11:45:34 +0200 Subject: [PATCH 08/15] Update UI to use country/city chooser --- src/ag-window.c | 60 +++++++++++++++++++++++++++++++++++ src/resources/ui/ag-window.ui | 11 +++++-- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/ag-window.c b/src/ag-window.c index bfdb6d0..dc98a2a 100644 --- a/src/ag-window.c +++ b/src/ag-window.c @@ -24,6 +24,8 @@ struct _AgWindowPrivate { GtkWidget *selection_toolbar; GtkWidget *stack; GtkWidget *name; + GtkWidget *country; + GtkWidget *city; GtkWidget *north_lat; GtkWidget *south_lat; GtkWidget *latitude; @@ -55,6 +57,8 @@ struct _AgWindowPrivate { GtkListStore *house_system_model; GtkListStore *db_chart_data; AgDbSave *saved_data; + GtkEntryCompletion *country_comp; + GtkEntryCompletion *city_comp; }; G_DEFINE_QUARK(ag_window_error_quark, ag_window_error); @@ -1387,6 +1391,15 @@ ag_window_list_selection_changed_cb(GdMainView *view, AgWindow *window) // Here it is possible to set button sensitivity later } +gboolean +ag_window_country_selected_callback(GtkEntryCompletion *country_comp, + GtkTreeModel *list, + GtkTreeIter *iter, + AgWindow *window) +{ + return FALSE; +} + static void ag_window_init(AgWindow *window) { @@ -1414,6 +1427,15 @@ ag_window_init(AgWindow *window) window ); + gtk_entry_completion_set_model(priv->country_comp, country_list); + gtk_entry_completion_set_text_column(priv->country_comp, AG_COUNTRY_NAME); + gtk_entry_set_completion(GTK_ENTRY(priv->country), priv->country_comp); + + gtk_entry_completion_set_model(priv->city_comp, city_list); + gtk_entry_completion_set_text_column(priv->city_comp, AG_CITY_NAME); + gtk_entry_completion_set_minimum_key_length(priv->city_comp, 3); + gtk_entry_set_completion(GTK_ENTRY(priv->city), priv->city_comp); + house_system_list = gswe_all_house_systems(); g_list_foreach(house_system_list, (GFunc)ag_window_add_house_system, priv); g_list_free(house_system_list); @@ -1506,6 +1528,16 @@ ag_window_name_changed_cb(GtkEntry *name_entry, AgWindow *window) gtk_header_bar_set_subtitle(GTK_HEADER_BAR(priv->header_bar), name); } +static void +ag_window_country_changed_callback(GtkSearchEntry *country, AgWindow *window) +{ +} + +static void +ag_window_city_changed_callback(GtkSearchEntry *city, AgWindow *window) +{ +} + static void ag_window_class_init(AgWindowClass *klass) { @@ -1544,6 +1576,22 @@ ag_window_class_init(AgWindowClass *klass) tab_edit ); gtk_widget_class_bind_template_child_private(widget_class, AgWindow, name); + gtk_widget_class_bind_template_child_private( + widget_class, + AgWindow, + country + ); + gtk_widget_class_bind_template_child_private( + widget_class, + AgWindow, + country_comp + ); + gtk_widget_class_bind_template_child_private(widget_class, AgWindow, city); + gtk_widget_class_bind_template_child_private( + widget_class, + AgWindow, + city_comp + ); gtk_widget_class_bind_template_child_private(widget_class, AgWindow, year); gtk_widget_class_bind_template_child_private(widget_class, AgWindow, month); gtk_widget_class_bind_template_child_private(widget_class, AgWindow, day); @@ -1642,6 +1690,18 @@ ag_window_class_init(AgWindowClass *klass) widget_class, ag_window_name_changed_cb ); + gtk_widget_class_bind_template_callback( + widget_class, + ag_window_country_selected_callback + ); + gtk_widget_class_bind_template_callback( + widget_class, + ag_window_country_changed_callback + ); + gtk_widget_class_bind_template_callback( + widget_class, + ag_window_city_changed_callback + ); } gboolean diff --git a/src/resources/ui/ag-window.ui b/src/resources/ui/ag-window.ui index ee4e41f..4aec62e 100644 --- a/src/resources/ui/ag-window.ui +++ b/src/resources/ui/ag-window.ui @@ -136,6 +136,11 @@ + + + + +