diff --git a/src/ag-chart.h b/src/ag-chart.h
index 12e97ec..03bb0d6 100644
--- a/src/ag-chart.h
+++ b/src/ag-chart.h
@@ -43,6 +43,8 @@ struct _AgChartClass {
GsweMomentClass parent_class;
};
+typedef void (*AgChartSaveImageFunc)(AgChart *, GFile *, GError **);
+
GType ag_chart_get_type(void) G_GNUC_CONST;
AgChart *ag_chart_new_full(GsweTimestamp *timestamp,
diff --git a/src/ag-window.c b/src/ag-window.c
index 7fe567e..91f6dc9 100644
--- a/src/ag-window.c
+++ b/src/ag-window.c
@@ -808,12 +808,12 @@ ag_window_recalculate_chart(AgWindow *window, gboolean set_everything)
}
static void
-ag_window_export_svg(AgWindow *window, GError **err)
+ag_window_export_image(AgWindow *window, GError **err)
{
const gchar *name;
- gchar *file_name;
GtkWidget *fs;
gint response;
+ GError *local_err = NULL;
AgWindowPrivate *priv = ag_window_get_instance_private(window);
ag_window_recalculate_chart(window, TRUE);
@@ -851,41 +851,196 @@ ag_window_export_svg(AgWindow *window, GError **err)
return;
}
- file_name = g_strdup_printf("%s.svg", name);
-
fs = gtk_file_chooser_dialog_new(_("Export Chart as SVG"),
GTK_WINDOW(window),
GTK_FILE_CHOOSER_ACTION_SAVE,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Save"), GTK_RESPONSE_ACCEPT,
NULL);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fs), filter_svg);
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fs), filter_svg);
gtk_dialog_set_default_response(GTK_DIALOG(fs), GTK_RESPONSE_ACCEPT);
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(fs), FALSE);
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fs), TRUE);
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fs), file_name);
- g_free(file_name);
+ // Due to file name modifying later (depending on the file type selection),
+ // we must do this manually
+ gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fs), FALSE);
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fs), name);
- response = gtk_dialog_run(GTK_DIALOG(fs));
- gtk_widget_hide(fs);
+ while (TRUE) {
+ response = gtk_dialog_run(GTK_DIALOG(fs));
+ gtk_widget_hide(fs);
- if (response == GTK_RESPONSE_ACCEPT) {
- GFile *file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(fs));
+ if (response == GTK_RESPONSE_ACCEPT) {
+ GFile *file = gtk_file_chooser_get_file(
+ GTK_FILE_CHOOSER(fs)
+ );
+ GtkFileFilter *filter = gtk_file_chooser_get_filter(
+ GTK_FILE_CHOOSER(fs)
+ );
+ gchar *filename = g_file_get_uri(file),
+ *extension,
+ *current_extension;
+ AgChartSaveImageFunc save_func = NULL;
+ gboolean can_save = FALSE;
- ag_chart_export_svg_to_file(priv->chart, file, err);
+ if (filter == filter_svg) {
+ extension = ".svg";
+ save_func = &ag_chart_export_svg_to_file;
+ } else {
+ g_warning("Unknown file type");
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fs), filter_svg);
+ }
+
+ current_extension = g_utf8_strrchr(filename, -1, '.');
+
+ if (current_extension == NULL) {
+ gchar *tmp;
+
+ tmp = filename;
+ filename = g_strdup_printf("%s%s", tmp, extension);
+ g_free(tmp);
+ } else {
+ GFileInfo *fileinfo;
+ GFile *tmp_file;
+ gboolean valid;
+ GtkFileFilterInfo filter_info;
+
+ tmp_file = g_file_new_for_uri(filename);
+ fileinfo = g_file_query_info(
+ tmp_file,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL
+ );
+ g_object_unref(tmp_file);
+
+ filter_info.contains =
+ GTK_FILE_FILTER_URI
+ | GTK_FILE_FILTER_DISPLAY_NAME;
+ filter_info.uri = filename;
+ filter_info.display_name = g_file_info_get_display_name(
+ fileinfo
+ );
+
+ valid = gtk_file_filter_filter(filter, &filter_info);
+ g_object_unref(fileinfo);
+
+ if (!valid) {
+ GtkResponseType response;
+ gchar *message,
+ *new_filename;
+
+ new_filename = g_strdup_printf("%s%s", filename, extension);
+
+ message = g_strdup_printf(
+ "File extension doesn’t match the chosen format. " \
+ "Do you want Astrognome to append the correct " \
+ "extension (the new filename will be %s) or " \
+ "choose a new name?",
+ new_filename
+ );
+
+ response = ag_app_buttoned_dialog(
+ GTK_WINDOW(window),
+ GTK_MESSAGE_QUESTION,
+ message,
+ "Cancel", GTK_RESPONSE_CANCEL,
+ "Append extension", GTK_RESPONSE_APPLY,
+ "Choose new file", GTK_RESPONSE_NO,
+ NULL
+ );
+
+ if (response == GTK_RESPONSE_APPLY) {
+ g_free(filename);
+ filename = new_filename;
+ } else {
+ g_free(filename);
+ g_clear_object(&file);
+
+ if (response == GTK_RESPONSE_NO) {
+ continue;
+ }
+
+ break;
+ }
+ }
+ }
+
+ g_clear_object(&file);
+ file = g_file_new_for_uri(filename);
+ g_free(filename);
+
+ // Now check if a file under the modified name exists
+ if (g_file_query_exists(file, NULL)) {
+ GtkResponseType sub_response;
+ gchar *message;
+ GFileInfo *fileinfo;
+
+ fileinfo = g_file_query_info(
+ file,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL
+ );
+ message = g_strdup_printf(
+ "File %s already exists. Do you want to overwrite it?",
+ g_file_info_get_display_name(fileinfo)
+ );
+ g_object_unref(fileinfo);
+
+ sub_response = ag_app_buttoned_dialog(
+ GTK_WINDOW(window), GTK_MESSAGE_QUESTION,
+ message,
+ _("No"), GTK_RESPONSE_NO,
+ _("Yes"), GTK_RESPONSE_YES,
+ NULL
+ );
+
+ g_free(message);
+
+ can_save = (sub_response == GTK_RESPONSE_YES);
+ } else {
+ can_save = TRUE;
+ }
+
+ if (can_save) {
+ g_clear_error(&local_err);
+ save_func(priv->chart, file, &local_err);
+
+ if (local_err) {
+ ag_app_message_dialog(
+ GTK_WINDOW(window),
+ GTK_MESSAGE_ERROR,
+ "%s",
+ local_err->message
+ );
+ }
+
+ g_clear_object(&file);
+
+ break;
+ }
+
+ g_clear_object(&file);
+ } else {
+ break;
+ }
}
gtk_widget_destroy(fs);
}
static void
-ag_window_export_svg_action(GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
+ag_window_export_image_action(GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
AgWindow *window = AG_WINDOW(user_data);
- GError *err = NULL;
+ GError *err = NULL;
- ag_window_export_svg(window, &err);
+ ag_window_export_image(window, &err);
if (err) {
ag_app_message_dialog(
@@ -1612,19 +1767,19 @@ ag_window_connection_action(GSimpleAction *action,
}
static GActionEntry win_entries[] = {
- { "close", ag_window_close_action, NULL, NULL, NULL },
- { "save", ag_window_save_action, NULL, NULL, NULL },
- { "export-agc", ag_window_export_agc_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 },
- { "selection", ag_window_selection_mode_action, NULL, "false", NULL },
- { "delete", ag_window_delete_action, NULL, NULL, NULL },
- { "connection", ag_window_connection_action, "s", "'aspects'", NULL },
+ { "close", ag_window_close_action, NULL, NULL, NULL },
+ { "save", ag_window_save_action, NULL, NULL, NULL },
+ { "export-agc", ag_window_export_agc_action, NULL, NULL, NULL },
+ { "export-image", ag_window_export_image_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 },
+ { "selection", ag_window_selection_mode_action, NULL, "false", NULL },
+ { "delete", ag_window_delete_action, NULL, NULL, NULL },
+ { "connection", ag_window_connection_action, "s", "'aspects'", NULL },
};
static void
diff --git a/src/astrognome.c b/src/astrognome.c
index 85e71db..9f3c87c 100644
--- a/src/astrognome.c
+++ b/src/astrognome.c
@@ -24,6 +24,7 @@ GtkBuilder *builder;
GtkFileFilter *filter_all = NULL;
GtkFileFilter *filter_chart = NULL;
GtkFileFilter *filter_hor = NULL;
+GtkFileFilter *filter_svg = NULL;
GtkTreeModel *country_list = NULL;
GtkTreeModel *city_list = NULL;
GHashTable *xinclude_positions;
@@ -84,6 +85,11 @@ init_filters(void)
gtk_file_filter_set_name(filter_hor, _("Placidus charts"));
gtk_file_filter_add_pattern(filter_hor, "*.hor");
g_object_ref_sink(filter_hor);
+
+ filter_svg = gtk_file_filter_new();
+ gtk_file_filter_set_name(filter_svg, _("SVG image"));
+ gtk_file_filter_add_pattern(filter_svg, "*.svg");
+ g_object_ref_sink(filter_svg);
}
static int
diff --git a/src/astrognome.h b/src/astrognome.h
index 9697c32..0288e9b 100644
--- a/src/astrognome.h
+++ b/src/astrognome.h
@@ -13,6 +13,7 @@ typedef struct {
extern GtkFileFilter *filter_all;
extern GtkFileFilter *filter_chart;
extern GtkFileFilter *filter_hor;
+extern GtkFileFilter *filter_svg;
extern GtkTreeModel *country_list;
extern GtkTreeModel *city_list;
extern const GswePlanet used_planets[];
diff --git a/src/resources/ui/ag-window.ui b/src/resources/ui/ag-window.ui
index 3c2a80f..9f0701f 100644
--- a/src/resources/ui/ag-window.ui
+++ b/src/resources/ui/ag-window.ui
@@ -45,8 +45,8 @@
-
- Export as SVG
- win.export-svg
+ Export as image…
+ win.export-image