Merge pull request #43 from gergelypolonkai/chart-db
Save charts in a database instead of separate files
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -0,0 +1,3 @@ | ||||
| [submodule "libgd"] | ||||
| 	path = libgd | ||||
| 	url = git://git.gnome.org/libgd.git | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| ACLOCAL_AMFLAGS = -I m4 | ||||
| SUBDIRS = src po data help | ||||
| ACLOCAL_AMFLAGS = -I m4 -I libgd ${ACLOCAL_FLAGS} | ||||
| SUBDIRS = libgd src po data help | ||||
|  | ||||
| EXTRA_DIST = config.rpath ChangeLog | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,8 @@ | ||||
| srcdir=`dirname $0` | ||||
| test -z "$srcdir" && srcdir=. | ||||
|  | ||||
| ACLOCAL_FLAGS="-I libgd $ACLOCAL_FLAGS" | ||||
|  | ||||
| PKG_NAME="astrognome" | ||||
|  | ||||
| (test -f $srcdir/configure.ac \ | ||||
| @@ -18,5 +20,7 @@ which gnome-autogen.sh || { | ||||
|     exit 1 | ||||
| } | ||||
|  | ||||
| git submodule update --init --recursive | ||||
|  | ||||
| REQUIRED_AUTOMAKE_VERSION=1.9 . gnome-autogen.sh | ||||
|  | ||||
|   | ||||
| @@ -35,10 +35,16 @@ PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.8]) | ||||
| PKG_CHECK_MODULES([LIBXML], [libxml-2.0]) | ||||
| PKG_CHECK_MODULES([LIBXSLT], [libexslt]) | ||||
| PKG_CHECK_MODULES([WEBKIT], [webkit2gtk-3.0]) | ||||
| PKG_CHECK_MODULES([GDA], [libgda-5.0 libgda-sqlite-5.0]) | ||||
| PKG_CHECK_MODULES([SWE_GLIB], [swe-glib >= 2.1.0]) | ||||
|  | ||||
| LIBGD_INIT([ | ||||
|     main-view | ||||
| ]) | ||||
|  | ||||
| AC_CONFIG_FILES([ | ||||
|     Makefile | ||||
|     libgd/Makefile | ||||
|     src/Makefile | ||||
|     help/Makefile | ||||
|     po/Makefile.in | ||||
|   | ||||
							
								
								
									
										1
									
								
								libgd
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								libgd
									
									
									
									
									
										Submodule
									
								
							 Submodule libgd added at 62f9b8b925
									
								
							| @@ -18,6 +18,7 @@ astrognome_source_files = \ | ||||
| 						  ag-chart.c       \ | ||||
| 						  ag-settings.c    \ | ||||
| 						  ag-preferences.c \ | ||||
| 						  ag-db.c          \ | ||||
| 						  astrognome.c     \ | ||||
| 						  $(NULL) | ||||
|  | ||||
| @@ -26,11 +27,11 @@ EXTRA_DIST = \ | ||||
| 			 ag.gresource.xml \ | ||||
| 			 $(NULL) | ||||
|  | ||||
| AM_CPPFLAGS = -DG_LOG_DOMAIN=\"Astrognome\" -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" | ||||
| AM_CPPFLAGS = -DG_LOG_DOMAIN=\"Astrognome\" -DLOCALEDIR=\"$(localedir)\" -DPKGDATADIR=\"$(pkgdatadir)\" -I$(top_srcdir)/libgd | ||||
| bin_PROGRAMS = astrognome | ||||
|  | ||||
| astrognome_SOURCES = $(astrognome_source_files) $(BUILT_SOURCES) | ||||
| astrognome_LDADD = $(SWE_GLIB_LIBS) $(GTK_LIBS) $(LIBXML_LIBS) $(LIBXSLT_LIBS) $(WEBKIT_LIBS) | ||||
| astrognome_LDADD = $(SWE_GLIB_LIBS) $(GTK_LIBS) $(LIBXML_LIBS) $(LIBXSLT_LIBS) $(WEBKIT_LIBS) $(GDA_LIBS) $(top_builddir)/libgd/libgd.la | ||||
| astrognome_LDFLAGS = -rdynamic | ||||
| astrognome_CFLAGS = $(SWE_GLIB_CFLAGS) $(CFLAGS) $(GTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBXSLT_CFLAGS) $(WEBKIT_CFLAGS) -Wall | ||||
| astrognome_CFLAGS = $(SWE_GLIB_CFLAGS) $(CFLAGS) $(GTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBXSLT_CFLAGS) $(WEBKIT_CFLAGS) $(GDA_CFLAGS) -Wall | ||||
|  | ||||
|   | ||||
							
								
								
									
										98
									
								
								src/ag-app.c
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								src/ag-app.c
									
									
									
									
									
								
							| @@ -68,7 +68,10 @@ ag_app_create_window(AgApp *app) | ||||
| static void | ||||
| new_window_cb(GSimpleAction *action, GVariant *parameter, gpointer user_data) | ||||
| { | ||||
|     ag_app_create_window(AG_APP(user_data)); | ||||
|     AgWindow *window = AG_WINDOW(ag_app_create_window(AG_APP(user_data))); | ||||
|  | ||||
|     ag_window_load_chart_list(window); | ||||
|     ag_window_change_tab(window, "list"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -130,12 +133,11 @@ quit_cb(GSimpleAction *action, GVariant *parameter, gpointer user_data) | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_app_open_chart(AgApp *app, GFile *file) | ||||
| ag_app_import_chart(AgApp *app, GFile *file) | ||||
| { | ||||
|     GtkWidget *window; | ||||
|     AgChart   *chart; | ||||
|     GError    *err = NULL; | ||||
|     gchar     *uri; | ||||
|  | ||||
|     if ((chart = ag_chart_load_from_file(file, &err)) == NULL) { | ||||
|         g_print("Error: '%s'\n", err->message); | ||||
| @@ -146,14 +148,12 @@ ag_app_open_chart(AgApp *app, GFile *file) | ||||
|     window = ag_app_create_window(app); | ||||
|     ag_window_set_chart(AG_WINDOW(window), chart); | ||||
|     ag_window_update_from_chart(AG_WINDOW(window)); | ||||
|     uri = g_file_get_uri(file); | ||||
|     ag_window_set_uri(AG_WINDOW(window), uri); | ||||
|     g_free(uri); | ||||
|     g_action_group_activate_action(G_ACTION_GROUP(window), "save", NULL); | ||||
|     ag_window_change_tab(AG_WINDOW(window), "chart"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| open_cb(GSimpleAction *action, GVariant *parameter, gpointer user_data) | ||||
| ag_app_import_cb(GSimpleAction *action, GVariant *parameter, gpointer user_data) | ||||
| { | ||||
|     gint      response; | ||||
|     GtkWidget *fs; | ||||
| @@ -163,7 +163,7 @@ open_cb(GSimpleAction *action, GVariant *parameter, gpointer user_data) | ||||
|                                      NULL, | ||||
|                                      GTK_FILE_CHOOSER_ACTION_OPEN, | ||||
|                                      _("_Cancel"), GTK_RESPONSE_CANCEL, | ||||
|                                      _("_Open"), GTK_RESPONSE_ACCEPT, | ||||
|                                      _("_Import"), GTK_RESPONSE_ACCEPT, | ||||
|                                      NULL); | ||||
|     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fs), filter_all); | ||||
|     gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fs), filter_chart); | ||||
| @@ -190,7 +190,7 @@ open_cb(GSimpleAction *action, GVariant *parameter, gpointer user_data) | ||||
|             } | ||||
|  | ||||
|             file = g_file_new_for_commandline_arg(data); | ||||
|             ag_app_open_chart(AG_APP(user_data), file); | ||||
|             ag_app_import_chart(AG_APP(user_data), file); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -245,13 +245,13 @@ help_cb(GSimpleAction *action, GVariant *parameter, gpointer user_data) | ||||
| } | ||||
|  | ||||
| static GActionEntry app_entries[] = { | ||||
|     { "new-window",  new_window_cb,  NULL, NULL, NULL }, | ||||
|     { "preferences", preferences_cb, NULL, NULL, NULL }, | ||||
|     { "about",       about_cb,       NULL, NULL, NULL }, | ||||
|     { "quit",        quit_cb,        NULL, NULL, NULL }, | ||||
|     { "raise",       raise_cb,       NULL, NULL, NULL }, | ||||
|     { "open",        open_cb,        NULL, NULL, NULL }, | ||||
|     { "help",        help_cb,        NULL, NULL, NULL }, | ||||
|     { "new-window",  new_window_cb,    NULL, NULL, NULL }, | ||||
|     { "preferences", preferences_cb,   NULL, NULL, NULL }, | ||||
|     { "about",       about_cb,         NULL, NULL, NULL }, | ||||
|     { "quit",        quit_cb,          NULL, NULL, NULL }, | ||||
|     { "raise",       raise_cb,         NULL, NULL, NULL }, | ||||
|     { "import",      ag_app_import_cb, NULL, NULL, NULL }, | ||||
|     { "help",        help_cb,          NULL, NULL, NULL }, | ||||
| }; | ||||
|  | ||||
| static void | ||||
| @@ -348,12 +348,15 @@ startup(GApplication *gapp) | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_app_open(GApplication *gapp, GFile **files, gint n_files, const gchar *hint) | ||||
| ag_app_import(GApplication *gapp, | ||||
|               GFile **files, | ||||
|               gint n_files, | ||||
|               const gchar *hint) | ||||
| { | ||||
|     gint i; | ||||
|  | ||||
|     for (i = 0; i < n_files; i++) { | ||||
|         ag_app_open_chart(AG_APP(gapp), files[i]); | ||||
|         ag_app_import_chart(AG_APP(gapp), files[i]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -441,7 +444,49 @@ ag_app_class_init(AgAppClass *klass) | ||||
|     GApplicationClass *application_class = G_APPLICATION_CLASS(klass); | ||||
|  | ||||
|     application_class->startup = startup; | ||||
|     application_class->open    = ag_app_open; | ||||
|     application_class->open    = ag_app_import; | ||||
| } | ||||
|  | ||||
| gint | ||||
| ag_app_buttoned_dialog(GtkWidget      *window, | ||||
|                        GtkMessageType message_type, | ||||
|                        const gchar    *message, | ||||
|                        const gchar    *first_button_text, | ||||
|                        ...) | ||||
| { | ||||
|     va_list     ap; | ||||
|     const gchar *button_text; | ||||
|     gint        response_id; | ||||
|     GtkWidget   *dialog; | ||||
|  | ||||
|     dialog = gtk_message_dialog_new( | ||||
|             GTK_WINDOW(window), | ||||
|             GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, | ||||
|             message_type, | ||||
|             GTK_BUTTONS_NONE, | ||||
|             "%s", | ||||
|             message | ||||
|         ); | ||||
|  | ||||
|     if (first_button_text) { | ||||
|         button_text = first_button_text; | ||||
|  | ||||
|         va_start(ap, first_button_text); | ||||
|         response_id = va_arg(ap, gint); | ||||
|         gtk_dialog_add_button(GTK_DIALOG(dialog), button_text, response_id); | ||||
|  | ||||
|         while ((button_text = va_arg(ap, gchar *)) != NULL) { | ||||
|             response_id = va_arg(ap, gint); | ||||
|             gtk_dialog_add_button(GTK_DIALOG(dialog), button_text, response_id); | ||||
|         } | ||||
|  | ||||
|         va_end(ap); | ||||
|     } | ||||
|  | ||||
|     response_id = gtk_dialog_run(GTK_DIALOG(dialog)); | ||||
|     gtk_widget_destroy(dialog); | ||||
|  | ||||
|     return response_id; | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -451,21 +496,18 @@ ag_app_message_dialog(GtkWidget      *window, | ||||
| { | ||||
|     gchar     *msg; | ||||
|     va_list   args; | ||||
|     GtkWidget *dialog; | ||||
|  | ||||
|     va_start(args, fmt); | ||||
|     msg = g_strdup_vprintf(fmt, args); | ||||
|     va_end(args); | ||||
|  | ||||
|     dialog = gtk_message_dialog_new( | ||||
|             GTK_WINDOW(window), | ||||
|             GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, | ||||
|     ag_app_buttoned_dialog( | ||||
|             window, | ||||
|             message_type, | ||||
|             GTK_BUTTONS_OK, | ||||
|             "%s", | ||||
|             msg | ||||
|             msg, | ||||
|             _("Close"), GTK_RESPONSE_CLOSE, | ||||
|             NULL | ||||
|         ); | ||||
|  | ||||
|     g_free(msg); | ||||
|     gtk_dialog_run(GTK_DIALOG(dialog)); | ||||
|     gtk_widget_destroy(dialog); | ||||
| } | ||||
|   | ||||
| @@ -47,6 +47,11 @@ void ag_app_run_action(AgApp                   *app, | ||||
|                        gboolean                is_remote, | ||||
|                        const AstrognomeOptions *options); | ||||
|  | ||||
| gint ag_app_buttoned_dialog(GtkWidget      *window, | ||||
|                             GtkMessageType message_type, | ||||
|                             const gchar    *message, | ||||
|                             const gchar    *first_button_text, ...); | ||||
|  | ||||
| void ag_app_message_dialog(GtkWidget      *window, | ||||
|                            GtkMessageType message_type, | ||||
|                            gchar          *fmt, ...); | ||||
|   | ||||
							
								
								
									
										118
									
								
								src/ag-chart.c
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								src/ag-chart.c
									
									
									
									
									
								
							| @@ -10,6 +10,7 @@ | ||||
| #include <locale.h> | ||||
| #include <math.h> | ||||
|  | ||||
| #include "ag-db.h" | ||||
| #include "ag-chart.h" | ||||
|  | ||||
| typedef struct _AgChartPrivate { | ||||
| @@ -921,6 +922,70 @@ ag_chart_load_from_file(GFile *file, GError **err) | ||||
|     return chart; | ||||
| } | ||||
|  | ||||
| AgChart * | ||||
| ag_chart_new_from_db_save(AgDbSave *save_data, GError **err) | ||||
| { | ||||
|     GsweTimestamp   *timestamp; | ||||
|     gchar           *house_system_enum_name; | ||||
|     GTypeClass      *house_system_class; | ||||
|     GEnumValue      *enum_value; | ||||
|     GsweHouseSystem house_system; | ||||
|     AgChart         *chart; | ||||
|  | ||||
|     if (save_data == NULL) { | ||||
|         g_set_error( | ||||
|                 err, | ||||
|                 AG_CHART_ERROR, AG_CHART_ERROR_EMPTY_RECORD, | ||||
|                 "Invalid chart" | ||||
|             ); | ||||
|  | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     house_system_enum_name = g_utf8_strdown(save_data->house_system, -1); | ||||
|     house_system_class = g_type_class_ref(GSWE_TYPE_HOUSE_SYSTEM); | ||||
|  | ||||
|     if ((enum_value = g_enum_get_value_by_nick( | ||||
|                 G_ENUM_CLASS(house_system_class), | ||||
|                 house_system_enum_name | ||||
|             )) == NULL) { | ||||
|         g_free(house_system_enum_name); | ||||
|         g_set_error( | ||||
|                 err, | ||||
|                 AG_CHART_ERROR, AG_CHART_ERROR_INVALID_HOUSE_SYSTEM, | ||||
|                 "Invalid house system: '%s'", | ||||
|                 save_data->house_system | ||||
|             ); | ||||
|  | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     g_free(house_system_enum_name); | ||||
|  | ||||
|     house_system = enum_value->value; | ||||
|  | ||||
|     timestamp = gswe_timestamp_new_from_gregorian_full( | ||||
|             save_data->year, save_data->month, save_data->day, | ||||
|             save_data->hour, save_data->minute, save_data->second, 0, | ||||
|             save_data->timezone | ||||
|         ); | ||||
|  | ||||
|     chart = ag_chart_new_full( | ||||
|             timestamp, | ||||
|             save_data->longitude, | ||||
|             save_data->latitude, | ||||
|             save_data->altitude, | ||||
|             house_system | ||||
|         ); | ||||
|  | ||||
|     ag_chart_set_name(chart, save_data->name); | ||||
|     ag_chart_set_country(chart, save_data->country); | ||||
|     ag_chart_set_city(chart, save_data->city); | ||||
|     ag_chart_set_note(chart, save_data->note); | ||||
|  | ||||
|     return chart; | ||||
| } | ||||
|  | ||||
| static xmlDocPtr | ||||
| create_save_doc(AgChart *chart) | ||||
| { | ||||
| @@ -1475,3 +1540,56 @@ const gchar *ag_chart_get_note(AgChart *chart) | ||||
|     return priv->note; | ||||
| } | ||||
|  | ||||
| AgDbSave * | ||||
| ag_chart_get_db_save(AgChart *chart, gint db_id) | ||||
| { | ||||
|     GsweCoordinates *coords; | ||||
|     AgChartPrivate  *priv      = ag_chart_get_instance_private(chart); | ||||
|     AgDbSave        *save_data = g_new0(AgDbSave, 1); | ||||
|     GsweTimestamp   *timestamp = gswe_moment_get_timestamp(GSWE_MOMENT(chart)); | ||||
|     GEnumClass      *house_system_class; | ||||
|     GEnumValue      *house_system_enum; | ||||
|  | ||||
|     save_data->db_id = db_id; | ||||
|  | ||||
|     save_data->name         = g_strdup(priv->name); | ||||
|     save_data->country      = g_strdup(priv->country); | ||||
|     save_data->city         = g_strdup(priv->city); | ||||
|     coords                  = gswe_moment_get_coordinates(GSWE_MOMENT(chart)); | ||||
|     save_data->longitude    = coords->longitude; | ||||
|     save_data->latitude     = coords->latitude; | ||||
|     save_data->altitude     = coords->altitude; | ||||
|     g_free(coords); | ||||
|     save_data->year         = gswe_timestamp_get_gregorian_year( | ||||
|             timestamp, | ||||
|             NULL | ||||
|         ); | ||||
|     save_data->month        = gswe_timestamp_get_gregorian_month( | ||||
|             timestamp, | ||||
|             NULL | ||||
|         ); | ||||
|     save_data->day          = gswe_timestamp_get_gregorian_day(timestamp, NULL); | ||||
|     save_data->hour         = gswe_timestamp_get_gregorian_hour( | ||||
|             timestamp, | ||||
|             NULL | ||||
|         ); | ||||
|     save_data->minute       = gswe_timestamp_get_gregorian_minute( | ||||
|             timestamp, | ||||
|             NULL | ||||
|         ); | ||||
|     save_data->second       = gswe_timestamp_get_gregorian_second( | ||||
|             timestamp, | ||||
|             NULL | ||||
|         ); | ||||
|     save_data->timezone     = gswe_timestamp_get_gregorian_timezone(timestamp); | ||||
|     house_system_class      = g_type_class_ref(GSWE_TYPE_HOUSE_SYSTEM); | ||||
|     house_system_enum       = g_enum_get_value( | ||||
|             house_system_class, | ||||
|             gswe_moment_get_house_system(GSWE_MOMENT(chart)) | ||||
|         ); | ||||
|     save_data->house_system = g_strdup(house_system_enum->value_nick); | ||||
|     g_type_class_unref(house_system_class); | ||||
|     save_data->note         = g_strdup(priv->note); | ||||
|  | ||||
|     return save_data; | ||||
| } | ||||
|   | ||||
| @@ -2,13 +2,18 @@ | ||||
| #define __AG_CHART_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <gtk/gtk.h> | ||||
| #include <swe-glib.h> | ||||
|  | ||||
| #include "ag-db.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef enum { | ||||
|     AG_CHART_ERROR_LIBXML, | ||||
|     AG_CHART_ERROR_CORRUPT_FILE, | ||||
|     AG_CHART_ERROR_EMPTY_RECORD, | ||||
|     AG_CHART_ERROR_INVALID_HOUSE_SYSTEM, | ||||
| } AgChartError; | ||||
|  | ||||
| #define AG_TYPE_CHART         (ag_chart_get_type()) | ||||
| @@ -46,6 +51,8 @@ AgChart *ag_chart_new_full(GsweTimestamp   *timestamp, | ||||
| AgChart *ag_chart_load_from_file(GFile  *file, | ||||
|                                  GError **err); | ||||
|  | ||||
| AgChart *ag_chart_new_from_db_save(AgDbSave *save_data, GError **err); | ||||
|  | ||||
| void ag_chart_save_to_file(AgChart *chart, | ||||
|                            GFile   *file, | ||||
|                            GError  **err); | ||||
| @@ -79,6 +86,8 @@ void ag_chart_set_note(AgChart *chart, const gchar *note); | ||||
|  | ||||
| const gchar *ag_chart_get_note(AgChart *chart); | ||||
|  | ||||
| AgDbSave *ag_chart_get_db_save(AgChart *chart, gint db_id); | ||||
|  | ||||
| #define AG_CHART_ERROR (ag_chart_error_quark()) | ||||
| GQuark ag_chart_error_quark(void); | ||||
|  | ||||
|   | ||||
							
								
								
									
										1134
									
								
								src/ag-db.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1134
									
								
								src/ag-db.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										78
									
								
								src/ag-db.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/ag-db.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| #ifndef __AG_DB_H__ | ||||
| #define __AG_DB_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <gtk/gtk.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define AG_TYPE_DB         (ag_db_get_type()) | ||||
| #define AG_DB(o)           (G_TYPE_CHECK_INSTANCE_CAST((o), \ | ||||
|                                                        AG_TYPE_DB, \ | ||||
|                                                        AgDb)) | ||||
| #define AG_DB_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), \ | ||||
|                                                     AG_TYPE_DB, \ | ||||
|                                                     AgDbClass)) | ||||
| #define AG_IS_DB(o)        (G_TYPE_CHECK_INSTANCE_TYPE((o), AG_TYPE_DB)) | ||||
| #define AG_IS_DB_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE((k), AG_TYPE_DB)) | ||||
| #define AG_DB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), \ | ||||
|                                                       AG_TYPE_DB, \ | ||||
|                                                       AgDbClass)) | ||||
|  | ||||
| typedef struct _AgDb      AgDb; | ||||
| typedef struct _AgDbClass AgDbClass; | ||||
|  | ||||
| struct _AgDb { | ||||
|     GObject parent_instance; | ||||
| }; | ||||
|  | ||||
| struct _AgDbClass { | ||||
|     GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| typedef struct _AgDbSave { | ||||
|     gint db_id; | ||||
|     gchar *name; | ||||
|     gchar *country; | ||||
|     gchar *city; | ||||
|     gdouble longitude; | ||||
|     gdouble latitude; | ||||
|     gdouble altitude; | ||||
|     gint year; | ||||
|     guint month; | ||||
|     guint day; | ||||
|     guint hour; | ||||
|     guint minute; | ||||
|     guint second; | ||||
|     gdouble timezone; | ||||
|     gchar *house_system; | ||||
|     gchar *note; | ||||
| } AgDbSave; | ||||
|  | ||||
| typedef enum { | ||||
|     AG_DB_ERROR_NO_CHART, | ||||
|     AG_DB_ERROR_DATABASE_ERROR, | ||||
| } AgDbError; | ||||
|  | ||||
| GType ag_db_get_type(void) G_GNUC_CONST; | ||||
|  | ||||
| AgDb *ag_db_get(void); | ||||
|  | ||||
| void ag_db_save_data_free(AgDbSave *save_data); | ||||
|  | ||||
| gboolean ag_db_save_chart(AgDb      *db, | ||||
|                           AgDbSave  *save_data, | ||||
|                           GError    **err); | ||||
|  | ||||
| GList *ag_db_get_chart_list(AgDb *db, GError **err); | ||||
|  | ||||
| AgDbSave *ag_db_get_chart_data_by_id(AgDb *db, guint row_id, GError **err); | ||||
|  | ||||
| gboolean ag_db_save_identical(const AgDbSave *a, const AgDbSave *b); | ||||
|  | ||||
| #define AG_DB_ERROR (ag_db_error_quark()) | ||||
| GQuark ag_db_error_quark(void); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __AG_DB_H__ */ | ||||
							
								
								
									
										389
									
								
								src/ag-window.c
									
									
									
									
									
								
							
							
						
						
									
										389
									
								
								src/ag-window.c
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ | ||||
| #include <libxml/parser.h> | ||||
| #include <libxml/tree.h> | ||||
| #include <webkit2/webkit2.h> | ||||
| #include <libgd/gd-main-view.h> | ||||
| #include <gtk/gtk.h> | ||||
|  | ||||
| #include <swe-glib.h> | ||||
| @@ -12,9 +13,12 @@ | ||||
| #include "ag-window.h" | ||||
| #include "ag-chart.h" | ||||
| #include "ag-settings.h" | ||||
| #include "ag-db.h" | ||||
|  | ||||
| struct _AgWindowPrivate { | ||||
|     GtkWidget     *header_bar; | ||||
|     GtkWidget     *menubutton_revealer; | ||||
|     GtkWidget     *new_back_stack; | ||||
|     GtkWidget     *stack; | ||||
|     GtkWidget     *name; | ||||
|     GtkWidget     *north_lat; | ||||
| @@ -32,6 +36,7 @@ struct _AgWindowPrivate { | ||||
|     GtkWidget     *timezone; | ||||
|     GtkWidget     *house_system; | ||||
|  | ||||
|     GtkWidget     *tab_list; | ||||
|     GtkWidget     *tab_chart; | ||||
|     GtkWidget     *tab_edit; | ||||
|     GtkWidget     *current_tab; | ||||
| @@ -42,10 +47,11 @@ struct _AgWindowPrivate { | ||||
|  | ||||
|     AgSettings    *settings; | ||||
|     AgChart       *chart; | ||||
|     gchar         *uri; | ||||
|     gboolean      aspect_table_populated; | ||||
|     GtkTextBuffer *note_buffer; | ||||
|     GtkListStore  *house_system_model; | ||||
|     GtkListStore  *db_chart_data; | ||||
|     AgDbSave      *saved_data; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_QUARK(ag_window_error_quark, ag_window_error); | ||||
| @@ -86,19 +92,101 @@ ag_window_view_menu_action(GSimpleAction *action, | ||||
|     g_variant_unref(state); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_close_action(GSimpleAction *action, | ||||
|                        GVariant      *parameter, | ||||
|                        gpointer user_data) | ||||
| gboolean | ||||
| ag_window_can_close(AgWindow *window, gboolean display_dialog) | ||||
| { | ||||
|     AgWindow *window = user_data; | ||||
|     AgWindowPrivate *priv      = ag_window_get_instance_private(window); | ||||
|     gint            db_id      = (priv->saved_data) | ||||
|             ? priv->saved_data->db_id | ||||
|             : -1; | ||||
|     AgDbSave        *save_data = NULL; | ||||
|     AgDb            *db        = ag_db_get(); | ||||
|     GError          *err       = NULL; | ||||
|     gboolean        ret        = TRUE; | ||||
|  | ||||
|     // TODO: Save unsaved changes! | ||||
|     gtk_widget_destroy(GTK_WIDGET(window)); | ||||
|     if (priv->chart) { | ||||
|         save_data = ag_chart_get_db_save(priv->chart, db_id); | ||||
|  | ||||
|         if ( | ||||
|                     !ag_db_save_identical(priv->saved_data, save_data) | ||||
|                     || !(priv->saved_data) | ||||
|                     || (priv->saved_data->db_id == -1) | ||||
|                 ) { | ||||
|             g_debug("Save is needed!"); | ||||
|  | ||||
|             if (display_dialog) { | ||||
|                 gint response; | ||||
|  | ||||
|                 response = ag_app_buttoned_dialog( | ||||
|                         GTK_WIDGET(window), | ||||
|                         GTK_MESSAGE_QUESTION, | ||||
|                         _("Chart is not saved. Do you want to save it?"), | ||||
|                         _("Save and close"), GTK_RESPONSE_YES, | ||||
|                         _("Close without saving"), GTK_RESPONSE_NO, | ||||
|                         _("Return to chart"), GTK_RESPONSE_CANCEL, | ||||
|                         NULL | ||||
|                     ); | ||||
|  | ||||
|                 switch (response) { | ||||
|                     case GTK_RESPONSE_YES: | ||||
|                         if (!ag_db_save_chart(db, save_data, &err)) { | ||||
|                             ag_app_message_dialog( | ||||
|                                     GTK_WIDGET(window), | ||||
|                                     GTK_MESSAGE_ERROR, | ||||
|                                     "Unable to save chart: %s", | ||||
|                                     err->message | ||||
|                                 ); | ||||
|  | ||||
|                             ret = FALSE; | ||||
|                         } else { | ||||
|                             ret = TRUE; | ||||
|                         } | ||||
|  | ||||
|                         break; | ||||
|  | ||||
|                     case GTK_RESPONSE_NO: | ||||
|                         ret = TRUE; | ||||
|  | ||||
|                         break; | ||||
|  | ||||
|                     default: | ||||
|                         ret = FALSE; | ||||
|  | ||||
|                         break; | ||||
|                 } | ||||
|             } else { | ||||
|                 ret = FALSE; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     ag_db_save_data_free(save_data); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| ag_window_delete_event_callback(AgWindow *window, | ||||
|                                 GdkEvent *event, | ||||
|                                 gpointer user_data) | ||||
| { | ||||
|     return (!ag_window_can_close(window, TRUE)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_save_as(AgWindow *window, GError **err) | ||||
| ag_window_close_action(GSimpleAction *action, | ||||
|                        GVariant      *parameter, | ||||
|                        gpointer      user_data) | ||||
| { | ||||
|     AgWindow        *window = AG_WINDOW(user_data); | ||||
|  | ||||
|     if (ag_window_can_close(window, TRUE)) { | ||||
|         gtk_widget_destroy(GTK_WIDGET(window)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_export(AgWindow *window, GError **err) | ||||
| { | ||||
|     gchar           *name; | ||||
|     gchar           *file_name; | ||||
| @@ -146,7 +234,7 @@ ag_window_save_as(AgWindow *window, GError **err) | ||||
|     file_name = g_strdup_printf("%s.agc", name); | ||||
|     g_free(name); | ||||
|  | ||||
|     fs = gtk_file_chooser_dialog_new(_("Save Chart"), | ||||
|     fs = gtk_file_chooser_dialog_new(_("Export Chart"), | ||||
|                                      GTK_WINDOW(window), | ||||
|                                      GTK_FILE_CHOOSER_ACTION_SAVE, | ||||
|                                      _("_Cancel"), GTK_RESPONSE_CANCEL, | ||||
| @@ -175,42 +263,43 @@ ag_window_save_action(GSimpleAction *action, | ||||
|                       GVariant      *parameter, | ||||
|                       gpointer      user_data) | ||||
| { | ||||
|     gchar           *uri; | ||||
|     AgWindow        *window = AG_WINDOW(user_data); | ||||
|     GError          *err    = NULL; | ||||
|     AgWindowPrivate *priv   = ag_window_get_instance_private(window); | ||||
|     AgDb            *db     = ag_db_get(); | ||||
|     GError          *err; | ||||
|     gint            old_id; | ||||
|     AgDbSave        *save_data; | ||||
|  | ||||
|     recalculate_chart(window); | ||||
|     uri = ag_window_get_uri(window); | ||||
|  | ||||
|     if (uri != NULL) { | ||||
|         GFile *file = g_file_new_for_uri(uri); | ||||
|         g_free(uri); | ||||
|     if (!ag_window_can_close(window, FALSE)) { | ||||
|         old_id    = (priv->saved_data) ? priv->saved_data->db_id : -1; | ||||
|         save_data = ag_chart_get_db_save(priv->chart, old_id); | ||||
|  | ||||
|         ag_chart_save_to_file(priv->chart, file, &err); | ||||
|     } else { | ||||
|         ag_window_save_as(window, &err); | ||||
|     } | ||||
|         if (!ag_db_save_chart(db, save_data, &err)) { | ||||
|             ag_app_message_dialog( | ||||
|                     GTK_WIDGET(window), | ||||
|                     GTK_MESSAGE_ERROR, | ||||
|                     _("Unable to save: %s"), | ||||
|                     err->message | ||||
|                 ); | ||||
|         } | ||||
|  | ||||
|     if (err) { | ||||
|         ag_app_message_dialog( | ||||
|                 GTK_WIDGET(window), | ||||
|                 GTK_MESSAGE_ERROR, | ||||
|                 "%s", err->message | ||||
|             ); | ||||
|         ag_db_save_data_free(priv->saved_data); | ||||
|         priv->saved_data = save_data; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_save_as_action(GSimpleAction *action, | ||||
|                          GVariant      *parameter, | ||||
|                          gpointer      user_data) | ||||
| ag_window_export_action(GSimpleAction *action, | ||||
|                         GVariant      *parameter, | ||||
|                         gpointer      user_data) | ||||
| { | ||||
|     AgWindow *window = AG_WINDOW(user_data); | ||||
|     GError   *err    = NULL; | ||||
|  | ||||
|     recalculate_chart(window); | ||||
|     ag_window_save_as(window, &err); | ||||
|     ag_window_export(window, &err); | ||||
|  | ||||
|     if (err) { | ||||
|         ag_app_message_dialog( | ||||
| @@ -874,6 +963,14 @@ ag_window_tab_changed_cb(GtkStack *stack, GParamSpec *pspec, AgWindow *window) | ||||
|         gtk_widget_set_size_request(active_tab, 600, 600); | ||||
|     } | ||||
|  | ||||
|     if (strcmp("list", active_tab_name) == 0) { | ||||
|         gtk_revealer_set_reveal_child(GTK_REVEALER(priv->menubutton_revealer), FALSE); | ||||
|         gtk_stack_set_visible_child_name(GTK_STACK(priv->new_back_stack), "new"); | ||||
|     } else { | ||||
|         gtk_revealer_set_reveal_child(GTK_REVEALER(priv->menubutton_revealer), TRUE); | ||||
|         gtk_stack_set_visible_child_name(GTK_STACK(priv->new_back_stack), "back"); | ||||
|     } | ||||
|  | ||||
|     // If we are coming from the Edit tab, let’s assume the chart data has | ||||
|     // changed. This is a bad idea, though, it should be checked instead! | ||||
|     // (TODO) | ||||
| @@ -900,14 +997,68 @@ ag_window_change_tab_action(GSimpleAction *action, | ||||
|     g_action_change_state(G_ACTION(action), parameter); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_new_chart_action(GSimpleAction *action, | ||||
|                            GVariant      *parameter, | ||||
|                            gpointer      user_data) | ||||
| { | ||||
|     AgWindow        *window = AG_WINDOW(user_data); | ||||
|     AgWindowPrivate *priv   = ag_window_get_instance_private(window); | ||||
|  | ||||
|     if (priv->chart) { | ||||
|         ag_app_message_dialog( | ||||
|                 GTK_WIDGET(window), | ||||
|                 GTK_MESSAGE_ERROR, | ||||
|                 "This window already has a chart. " \ | ||||
|                 "This should not happen, " \ | ||||
|                 "please consider issuing a bug report!" | ||||
|             ); | ||||
|  | ||||
|         gtk_stack_set_visible_child_name(GTK_STACK(priv->stack), "chart"); | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     gtk_stack_set_visible_child_name(GTK_STACK(priv->stack), "edit"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_back_action(GSimpleAction *action, | ||||
|                       GVariant      *parameter, | ||||
|                       gpointer      user_data) | ||||
| { | ||||
|     AgWindow        *window = AG_WINDOW(user_data); | ||||
|     AgWindowPrivate *priv   = ag_window_get_instance_private(window); | ||||
|  | ||||
|     if (ag_window_can_close(window, TRUE)) { | ||||
|         g_clear_object(&(priv->chart)); | ||||
|         ag_db_save_data_free(priv->saved_data); | ||||
|         priv->saved_data = NULL; | ||||
|  | ||||
|         ag_window_load_chart_list(window); | ||||
|         gtk_stack_set_visible_child_name(GTK_STACK(priv->stack), "list"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_refresh_action(GSimpleAction *action, | ||||
|                          GVariant      *parameter, | ||||
|                          gpointer      user_data) | ||||
| { | ||||
|     ag_window_load_chart_list(AG_WINDOW(user_data)); | ||||
| } | ||||
|  | ||||
| static GActionEntry win_entries[] = { | ||||
|     { "close",      ag_window_close_action,      NULL, NULL,      NULL }, | ||||
|     { "save",       ag_window_save_action,       NULL, NULL,      NULL }, | ||||
|     { "save-as",    ag_window_save_as_action,    NULL, NULL,      NULL }, | ||||
|     { "export",     ag_window_export_action,     NULL, NULL,      NULL }, | ||||
|     { "export-svg", ag_window_export_svg_action, NULL, NULL,      NULL }, | ||||
|     { "view-menu",  ag_window_view_menu_action,  NULL, "false",   NULL }, | ||||
|     { "gear-menu",  ag_window_gear_menu_action,  NULL, "false",   NULL }, | ||||
|     { "change-tab", ag_window_change_tab_action, "s",  "'edit'",  NULL }, | ||||
|     { "new-chart",  ag_window_new_chart_action,  NULL, NULL,      NULL }, | ||||
|     { "back",       ag_window_back_action,       NULL, NULL,      NULL }, | ||||
|     { "refresh",    ag_window_refresh_action,    NULL, NULL,      NULL }, | ||||
| }; | ||||
|  | ||||
| static void | ||||
| @@ -972,6 +1123,70 @@ ag_window_set_default_house_system(GtkTreeModel *model, | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_list_item_activated_cb(GdMainView        *view, | ||||
|                                  const gchar       *id, | ||||
|                                  const GtkTreePath *path, | ||||
|                                  AgWindow          *window) | ||||
| { | ||||
|     guint           row_id = atoi(id); | ||||
|     AgWindowPrivate *priv  = ag_window_get_instance_private(window); | ||||
|     AgDb            *db    = ag_db_get(); | ||||
|     GError          *err   = NULL; | ||||
|  | ||||
|     if (priv->saved_data != NULL) { | ||||
|         ag_app_message_dialog( | ||||
|                 GTK_WIDGET(window), | ||||
|                 GTK_MESSAGE_ERROR, | ||||
|                 "Window chart is not saved. " \ | ||||
|                 "This is a bug, it should not happen here. " \ | ||||
|                 "Please consider opening a bug report!" | ||||
|             ); | ||||
|  | ||||
|         ag_window_change_tab(window, "chart"); | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if ((priv->saved_data = ag_db_get_chart_data_by_id( | ||||
|                  db, | ||||
|                  row_id, | ||||
|                  &err)) == NULL) { | ||||
|         ag_app_message_dialog( | ||||
|                 GTK_WIDGET(window), | ||||
|                 GTK_MESSAGE_ERROR, | ||||
|                 "Could not open chart." | ||||
|             ); | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (priv->chart) { | ||||
|         g_object_unref(priv->chart); | ||||
|         priv->chart = NULL; | ||||
|     } | ||||
|  | ||||
|     if ((priv->chart = ag_chart_new_from_db_save( | ||||
|                  priv->saved_data, | ||||
|                  &err | ||||
|             )) == NULL) { | ||||
|         ag_app_message_dialog( | ||||
|                 GTK_WIDGET(window), | ||||
|                 GTK_MESSAGE_ERROR, | ||||
|                 "Error: %s", | ||||
|                 err->message | ||||
|             ); | ||||
|         ag_db_save_data_free(priv->saved_data); | ||||
|         priv->saved_data = NULL; | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     ag_window_update_from_chart(window); | ||||
|  | ||||
|     ag_window_change_tab(window, "chart"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_init(AgWindow *window) | ||||
| { | ||||
| @@ -1021,8 +1236,29 @@ ag_window_init(AgWindow *window) | ||||
|             NULL | ||||
|         ); | ||||
|  | ||||
|     gtk_stack_set_visible_child_name(GTK_STACK(priv->stack), "edit"); | ||||
|     priv->current_tab = priv->tab_edit; | ||||
|     priv->tab_list = GTK_WIDGET(gd_main_view_new(GD_MAIN_VIEW_ICON)); | ||||
|     gtk_stack_add_titled( | ||||
|             GTK_STACK(priv->stack), | ||||
|             priv->tab_list, | ||||
|             "list", | ||||
|             "Chart list" | ||||
|         ); | ||||
|  | ||||
|     gd_main_view_set_selection_mode(GD_MAIN_VIEW(priv->tab_list), FALSE); | ||||
|     gd_main_view_set_model( | ||||
|             GD_MAIN_VIEW(priv->tab_list), | ||||
|             GTK_TREE_MODEL(priv->db_chart_data) | ||||
|         ); | ||||
|     g_signal_connect( | ||||
|             priv->tab_list, | ||||
|             "item-activated", | ||||
|             G_CALLBACK(ag_window_list_item_activated_cb), | ||||
|             window | ||||
|         ); | ||||
|  | ||||
|     gtk_stack_set_visible_child_name(GTK_STACK(priv->stack), "list"); | ||||
|     priv->current_tab = priv->tab_list; | ||||
|  | ||||
|     g_object_set( | ||||
|             priv->year_adjust, | ||||
|             "lower", (gdouble)G_MININT, | ||||
| @@ -1031,7 +1267,6 @@ ag_window_init(AgWindow *window) | ||||
|         ); | ||||
|  | ||||
|     priv->chart    = NULL; | ||||
|     priv->uri      = NULL; | ||||
|  | ||||
|     g_action_map_add_action_entries( | ||||
|             G_ACTION_MAP(window), | ||||
| @@ -1071,6 +1306,21 @@ ag_window_class_init(AgWindowClass *klass) | ||||
|             AgWindow, | ||||
|             header_bar | ||||
|         ); | ||||
|     gtk_widget_class_bind_template_child_private( | ||||
|             widget_class, | ||||
|             AgWindow, | ||||
|             new_back_stack | ||||
|         ); | ||||
|     gtk_widget_class_bind_template_child_private( | ||||
|             widget_class, | ||||
|             AgWindow, | ||||
|             menubutton_revealer | ||||
|         ); | ||||
|     gtk_widget_class_bind_template_child_private( | ||||
|             widget_class, | ||||
|             AgWindow, | ||||
|             db_chart_data | ||||
|         ); | ||||
|     gtk_widget_class_bind_template_child_private(widget_class, AgWindow, name); | ||||
|     gtk_widget_class_bind_template_child_private(widget_class, AgWindow, year); | ||||
|     gtk_widget_class_bind_template_child_private(widget_class, AgWindow, month); | ||||
| @@ -1236,9 +1486,12 @@ ag_window_set_chart(AgWindow *window, AgChart *chart) | ||||
|         g_clear_object(&(priv->chart)); | ||||
|     } | ||||
|  | ||||
|     ag_db_save_data_free(priv->saved_data); | ||||
|  | ||||
|     priv->chart = chart; | ||||
|     g_signal_connect(priv->chart, "changed", G_CALLBACK(chart_changed), window); | ||||
|     g_object_ref(chart); | ||||
|     priv->saved_data = ag_chart_get_db_save(chart, -1); | ||||
| } | ||||
|  | ||||
| AgChart * | ||||
| @@ -1249,26 +1502,6 @@ ag_window_get_chart(AgWindow *window) | ||||
|     return priv->chart; | ||||
| } | ||||
|  | ||||
| void | ||||
| ag_window_set_uri(AgWindow *window, const gchar *uri) | ||||
| { | ||||
|     AgWindowPrivate *priv = ag_window_get_instance_private(window); | ||||
|  | ||||
|     if (priv->uri != NULL) { | ||||
|         g_free(priv->uri); | ||||
|     } | ||||
|  | ||||
|     priv->uri = g_strdup(uri); | ||||
| } | ||||
|  | ||||
| gchar * | ||||
| ag_window_get_uri(AgWindow *window) | ||||
| { | ||||
|     AgWindowPrivate *priv = ag_window_get_instance_private(window); | ||||
|  | ||||
|     return g_strdup(priv->uri); | ||||
| } | ||||
|  | ||||
| void | ||||
| ag_window_settings_restore(GtkWindow *window, GSettings *settings) | ||||
| { | ||||
| @@ -1343,3 +1576,51 @@ 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_add_chart_to_list(AgDbSave *save_data, AgWindow *window) | ||||
| { | ||||
|     GtkTreeIter     iter; | ||||
|     AgWindowPrivate *priv = ag_window_get_instance_private(window); | ||||
|     gchar           *id   = g_strdup_printf("%d", save_data->db_id); | ||||
|  | ||||
|     gtk_list_store_append(priv->db_chart_data, &iter); | ||||
|     gtk_list_store_set( | ||||
|             priv->db_chart_data, &iter, | ||||
|             0, id,              /* ID             */ | ||||
|             1, NULL,            /* URI            */ | ||||
|             2, save_data->name, /* Primary text   */ | ||||
|             3, NULL,            /* Secondary text */ | ||||
|             4, NULL,            /* Icon           */ | ||||
|             5, 0,               /* mtime          */ | ||||
|             6, FALSE,           /* Selected       */ | ||||
|             7, 0,               /* Pulse          */ | ||||
|             -1 | ||||
|         ); | ||||
|     g_free(id); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ag_window_clear_chart_list(AgWindow *window) | ||||
| { | ||||
|     AgWindowPrivate *priv = ag_window_get_instance_private(window); | ||||
|  | ||||
|     gtk_list_store_clear(priv->db_chart_data); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| ag_window_load_chart_list(AgWindow *window) | ||||
| { | ||||
|     AgDb   *db         = ag_db_get(); | ||||
|     GError *err        = NULL; | ||||
|     GList  *chart_list = ag_db_get_chart_list(db, &err); | ||||
|  | ||||
|     ag_window_clear_chart_list(window); | ||||
|     /* With only a few charts, this should be fine. Maybe implementing lazy | ||||
|      * loading would be a better idea. See: | ||||
|      * http://blogs.gnome.org/ebassi/documentation/lazy-loading/ | ||||
|      */ | ||||
|     g_list_foreach(chart_list, (GFunc)ag_window_add_chart_to_list, window); | ||||
|  | ||||
|     return TRUE; | ||||
| } | ||||
|   | ||||
| @@ -50,11 +50,6 @@ AgChart *ag_window_get_chart(AgWindow *window); | ||||
|  | ||||
| void ag_window_update_from_chart(AgWindow *window); | ||||
|  | ||||
| void ag_window_set_uri(AgWindow    *window, | ||||
|                        const gchar *uri); | ||||
|  | ||||
| gchar *ag_window_get_uri(AgWindow *window); | ||||
|  | ||||
| void ag_window_settings_restore(GtkWindow *window, | ||||
|                                 GSettings *settings); | ||||
|  | ||||
| @@ -63,6 +58,8 @@ void ag_window_settings_save(GtkWindow *window, | ||||
|  | ||||
| void ag_window_change_tab(AgWindow *window, const gchar *tab_name); | ||||
|  | ||||
| gboolean ag_window_load_chart_list(AgWindow *window); | ||||
|  | ||||
| #define AG_WINDOW_ERROR (ag_window_error_quark()) | ||||
|  | ||||
| GQuark ag_window_error_quark(void); | ||||
|   | ||||
| @@ -38,9 +38,9 @@ | ||||
|         <attribute name="accel"><Primary>s</attribute> | ||||
|       </item> | ||||
|       <item> | ||||
|         <attribute name="label" translatable="yes">Save as…</attribute> | ||||
|         <attribute name="action">win.save-as</attribute> | ||||
|         <attribute name="accel"><Primary><Shift>s</attribute> | ||||
|         <attribute name="label" translatable="yes">Export…</attribute> | ||||
|         <attribute name="action">win.export</attribute> | ||||
|         <attribute name="accel"><Primary><Shift>e</attribute> | ||||
|       </item> | ||||
|     </section> | ||||
|     <section> | ||||
| @@ -116,11 +116,32 @@ | ||||
|   </object> | ||||
|   <object class="GtkTextBuffer" id="note_buffer"> | ||||
|   </object> | ||||
|   <object class="GtkListStore" id="db_chart_data"> | ||||
|     <columns> | ||||
|       <!-- column-name id --> | ||||
|       <column type="gchararray"/> | ||||
|       <!-- column-name uri --> | ||||
|       <column type="gchararray"/> | ||||
|       <!-- column-name name --> | ||||
|       <column type="gchararray"/> | ||||
|       <!-- column-name secondary-text --> | ||||
|       <column type="gchararray"/> | ||||
|       <!-- column-name icon --> | ||||
|       <column type="GdkPixbuf"/> | ||||
|       <!-- column-name mtime --> | ||||
|       <column type="gint64"/> | ||||
|       <!-- column-name selected --> | ||||
|       <column type="gboolean"/> | ||||
|       <!-- column-name pulse --> | ||||
|       <column type="guint"/> | ||||
|     </columns> | ||||
|   </object> | ||||
|   <template class="AgWindow" parent="GtkApplicationWindow"> | ||||
|     <property name="can_focus">False</property> | ||||
|     <property name="has_focus">False</property> | ||||
|     <property name="is_focus">False</property> | ||||
|     <property name="icon_name">astrognome</property> | ||||
|     <signal name="delete-event" handler="ag_window_delete_event_callback" swapped="no"/> | ||||
|     <child type="titlebar"> | ||||
|       <object class="GtkHeaderBar" id="header_bar"> | ||||
|         <property name="visible">True</property> | ||||
| @@ -128,6 +149,82 @@ | ||||
|         <property name="vexpand">False</property> | ||||
|         <property name="show_close_button">True</property> | ||||
|         <property name="title" translatable="yes">Astrognome</property> | ||||
|         <child> | ||||
|           <object class="GtkStack" id="new_back_stack"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="can_focus">False</property> | ||||
|             <property name="homogeneous">False</property> | ||||
|             <child> | ||||
|               <object class="GtkBox"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="can_focus">False</property> | ||||
|                 <child> | ||||
|                   <object class="GtkButton" id="new_button"> | ||||
|                     <property name="visible">True</property> | ||||
|                     <property name="can_focus">False</property> | ||||
|                     <property name="action_name">win.new-chart</property> | ||||
|                     <style> | ||||
|                       <class name="image-button"/> | ||||
|                     </style> | ||||
|                     <child> | ||||
|                       <object class="GtkImage" id="new_image"> | ||||
|                         <property name="visible">True</property> | ||||
|                         <property name="icon_size">1</property> | ||||
|                         <property name="icon_name">document-new-symbolic</property> | ||||
|                       </object> | ||||
|                     </child> | ||||
|                   </object> | ||||
|                   <packing> | ||||
|                     <property name="position">0</property> | ||||
|                   </packing> | ||||
|                 </child> | ||||
|                 <child> | ||||
|                   <object class="GtkButton" id="refresh_button"> | ||||
|                     <property name="visible">True</property> | ||||
|                     <property name="can_focus">False</property> | ||||
|                     <property name="action_name">win.refresh</property> | ||||
|                     <style> | ||||
|                       <class name="image-button"/> | ||||
|                     </style> | ||||
|                     <child> | ||||
|                       <object class="GtkImage" id="refresh_image"> | ||||
|                         <property name="visible">True</property> | ||||
|                         <property name="icon_size">1</property> | ||||
|                         <property name="icon_name">view-refresh-symbolic</property> | ||||
|                   </object> | ||||
|                 </child> | ||||
|                   </object> | ||||
|                   <packing> | ||||
|                     <property name="position">1</property> | ||||
|                   </packing> | ||||
|                 </child> | ||||
|               </object> | ||||
|               <packing> | ||||
|                 <property name="name">new</property> | ||||
|               </packing> | ||||
|             </child> | ||||
|             <child> | ||||
|               <object class="GtkButton" id="back_button"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="can_focus">False</property> | ||||
|                 <property name="action_name">win.back</property> | ||||
|                 <style> | ||||
|                   <class name="image-button"/> | ||||
|                 </style> | ||||
|                 <child> | ||||
|                   <object class="GtkImage" id="back_image"> | ||||
|                     <property name="visible">True</property> | ||||
|                     <property name="icon_size">1</property> | ||||
|                     <property name="icon_name">go-previous-symbolic</property> | ||||
|                   </object> | ||||
|                 </child> | ||||
|               </object> | ||||
|               <packing> | ||||
|                 <property name="name">back</property> | ||||
|               </packing> | ||||
|             </child> | ||||
|           </object> | ||||
|         </child> | ||||
|         <child> | ||||
|           <object class="GtkBox" id="box"> | ||||
|             <property name="visible">True</property> | ||||
| @@ -139,44 +236,60 @@ | ||||
|           </object> | ||||
|         </child> | ||||
|         <child> | ||||
|           <object class="GtkMenuButton"> | ||||
|           <object class="GtkRevealer" id="menubutton_revealer"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="valign">center</property> | ||||
|             <property name="can_focus">False</property> | ||||
|             <property name="action_name">win.gear-menu</property> | ||||
|             <property name="menu_model">gear_menu</property> | ||||
|             <property name="use_popover">False</property> | ||||
|             <style> | ||||
|               <class name="image-button"/> | ||||
|             </style> | ||||
|             <property name="reveal_child">False</property> | ||||
|             <child> | ||||
|               <object class="GtkImage" id="gear_image"> | ||||
|               <object class="GtkBox" id="menubutton_box"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="icon_size">1</property> | ||||
|                 <property name="icon_name">emblem-system-symbolic</property> | ||||
|               </object> | ||||
|             </child> | ||||
|           </object> | ||||
|           <packing> | ||||
|             <property name="pack_type">end</property> | ||||
|           </packing> | ||||
|         </child> | ||||
|         <child> | ||||
|           <object class="GtkMenuButton"> | ||||
|             <property name="visible">True</property> | ||||
|             <property name="valign">center</property> | ||||
|             <property name="can_focus">False</property> | ||||
|             <property name="action_name">win.view-menu</property> | ||||
|             <property name="menu_model">view_menu</property> | ||||
|             <property name="use_popover">False</property> | ||||
|             <style> | ||||
|               <class name="image-button"/> | ||||
|             </style> | ||||
|             <child> | ||||
|               <object class="GtkImage" id="view_image"> | ||||
|                 <property name="visible">True</property> | ||||
|                 <property name="icon_size">1</property> | ||||
|                 <property name="icon_name">document-properties-symbolic</property> | ||||
|                 <property name="can_focus">False</property> | ||||
|                 <child> | ||||
|                   <object class="GtkMenuButton"> | ||||
|                     <property name="visible">True</property> | ||||
|                     <property name="valign">center</property> | ||||
|                     <property name="can_focus">False</property> | ||||
|                     <property name="action_name">win.view-menu</property> | ||||
|                     <property name="menu_model">view_menu</property> | ||||
|                     <property name="use_popover">False</property> | ||||
|                     <style> | ||||
|                       <class name="image-button"/> | ||||
|                     </style> | ||||
|                     <child> | ||||
|                       <object class="GtkImage" id="view_image"> | ||||
|                         <property name="visible">True</property> | ||||
|                         <property name="icon_size">1</property> | ||||
|                         <property name="icon_name">document-properties-symbolic</property> | ||||
|                       </object> | ||||
|                     </child> | ||||
|                   </object> | ||||
|                   <packing> | ||||
|                     <property name="position">0</property> | ||||
|                   </packing> | ||||
|                 </child> | ||||
|                 <child> | ||||
|                   <object class="GtkMenuButton"> | ||||
|                     <property name="visible">True</property> | ||||
|                     <property name="valign">center</property> | ||||
|                     <property name="can_focus">False</property> | ||||
|                     <property name="action_name">win.gear-menu</property> | ||||
|                     <property name="menu_model">gear_menu</property> | ||||
|                     <property name="use_popover">False</property> | ||||
|                     <style> | ||||
|                       <class name="image-button"/> | ||||
|                     </style> | ||||
|                     <child> | ||||
|                       <object class="GtkImage" id="gear_image"> | ||||
|                         <property name="visible">True</property> | ||||
|                         <property name="icon_size">1</property> | ||||
|                         <property name="icon_name">emblem-system-symbolic</property> | ||||
|                       </object> | ||||
|                     </child> | ||||
|                   </object> | ||||
|                   <packing> | ||||
|                     <property name="position">1</property> | ||||
|                   </packing> | ||||
|                 </child> | ||||
|               </object> | ||||
|             </child> | ||||
|           </object> | ||||
|   | ||||
| @@ -9,8 +9,8 @@ | ||||
|                 <attribute name="accel"><Primary>n</attribute> | ||||
|             </item> | ||||
|             <item> | ||||
|                 <attribute name="label" translatable="yes">Open</attribute> | ||||
|                 <attribute name="action">app.open</attribute> | ||||
|                 <attribute name="label" translatable="yes">Import</attribute> | ||||
|                 <attribute name="action">app.import</attribute> | ||||
|                 <attribute name="accel"><Primary>o</attribute> | ||||
|             </item> | ||||
|         </section> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user