[almanah] Add text file and database export support



commit 446ac9684147a484309ff99ec59d8bb798f01f5f
Author: Philip Withnall <philip tecnocode co uk>
Date:   Wed Apr 21 21:44:11 2010 +0100

    Add text file and database export support

 data/almanah.ui            |    8 ++
 src/import-export-dialog.c |  164 +++++++++++++++++++++++++++++++++++++++-----
 src/main-window.c          |   11 +++
 src/main.c                 |    2 +
 src/main.h                 |    1 +
 src/storage-manager.c      |    6 ++
 src/storage-manager.h      |    2 +
 7 files changed, 177 insertions(+), 17 deletions(-)
---
diff --git a/data/almanah.ui b/data/almanah.ui
index f7a106b..f053073 100644
--- a/data/almanah.ui
+++ b/data/almanah.ui
@@ -17,6 +17,13 @@
 					</object>
 				</child>
 				<child>
+					<object class="GtkAction" id="almanah_ui_export">
+						<property name="name">file-export</property>
+						<property name="label" translatable="yes">_Exportâ?¦</property>
+						<signal name="activate" handler="mw_export_activate_cb"/>
+					</object>
+				</child>
+				<child>
 					<object class="GtkAction" id="almanah_ui_page_setup">
 						<property name="stock-id">gtk-page-setup</property>
 						<property name="name">file-page-setup</property>
@@ -221,6 +228,7 @@
 			<menubar name="almanah_mw_menu_bar">
 				<menu action="almanah_ui_file">
 					<menuitem action="almanah_ui_import"/>
+					<menuitem action="almanah_ui_export"/>
 					<separator/>
 					<menuitem action="almanah_ui_page_setup"/>
 					<menuitem action="almanah_ui_print_preview"/>
diff --git a/src/import-export-dialog.c b/src/import-export-dialog.c
index ad252ee..e35e680 100644
--- a/src/import-export-dialog.c
+++ b/src/import-export-dialog.c
@@ -28,27 +28,38 @@
 #include "main-window.h"
 
 typedef gboolean (*ImportFunc) (AlmanahImportExportDialog *self, AlmanahImportResultsDialog *results_dialog, GError **error);
+typedef gboolean (*ExportFunc) (AlmanahImportExportDialog *self, GError **error);
 
 typedef struct {
 	const gchar *name; /* translatable */
 	const gchar *import_description; /* translatable */
-	GtkFileChooserAction import_action;
+	const gchar *export_description; /* translatable */
+	GtkFileChooserAction action;
 	ImportFunc import_func;
+	ExportFunc export_func;
 } ImportExportModeDetails;
 
 static gboolean import_text_files (AlmanahImportExportDialog *self, AlmanahImportResultsDialog *results_dialog, GError **error);
+static gboolean export_text_files (AlmanahImportExportDialog *self, GError **error);
+
 static gboolean import_database (AlmanahImportExportDialog *self, AlmanahImportResultsDialog *results_dialog, GError **error);
+static gboolean export_database (AlmanahImportExportDialog *self, GError **error);
 
 static const ImportExportModeDetails import_export_modes[] = {
 	{ N_("Text Files"),
 	  N_("Select a folder containing text files, one per entry, with names in the format 'yyyy-mm-dd', and no extension. "
 	     "Any and all such files will be imported."),
+	  N_("Select a folder to export the entries to as text files, one per entry, with names in the format 'yyyy-mm-dd', and no extension. "
+	     "All entries will be exported, unencrypted in plain text format."),
 	  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
-	  import_text_files },
+	  import_text_files,
+	  export_text_files },
 	{ N_("Database"),
 	  N_("Select a database file created by Almanah Diary to import."),
+	  N_("Select a filename for a complete copy of the unencrypted Almanah Diary database to be given."),
 	  GTK_FILE_CHOOSER_ACTION_OPEN,
-	  import_database }
+	  import_database,
+	  export_database }
 };
 
 static void response_cb (GtkDialog *dialog, gint response_id, AlmanahImportExportDialog *self);
@@ -59,6 +70,7 @@ void ied_file_chooser_selection_changed_cb (GtkFileChooser *file_chooser, Almana
 void ied_file_chooser_file_activated_cb (GtkFileChooser *file_chooser, AlmanahImportExportDialog *self);
 
 struct _AlmanahImportExportDialogPrivate {
+	gboolean import; /* TRUE if we're in import mode, FALSE otherwise */
 	GtkComboBox *mode_combo_box;
 	GtkListStore *mode_store;
 	guint current_mode; /* index into import_export_modes */
@@ -153,6 +165,7 @@ almanah_import_export_dialog_new (gboolean import)
 	}
 
 	priv = import_export_dialog->priv;
+	priv->import = import;
 
 	/* Grab our child widgets */
 	priv->mode_combo_box = GTK_COMBO_BOX (gtk_builder_get_object (builder, "almanah_ied_mode_combo_box"));
@@ -351,7 +364,7 @@ import_text_files (AlmanahImportExportDialog *self, AlmanahImportResultsDialog *
 		g_assert (file != NULL);
 
 		/* Load the content */
-		if (g_file_load_contents (file, NULL, &contents, &length, NULL, error) == FALSE) {
+		if (g_file_load_contents (file, NULL, &contents, &length, NULL, &child_error) == FALSE) {
 			g_object_unref (file);
 			g_object_unref (file_info);
 			break; /* let the error get handled by the code just after the loop */
@@ -393,6 +406,80 @@ finish:
 }
 
 static gboolean
+export_text_files (AlmanahImportExportDialog *self, GError **error)
+{
+	AlmanahImportExportDialogPrivate *priv = self->priv;
+	GFile *folder;
+	GSList *entries;
+	GtkTextBuffer *buffer;
+	gboolean success = FALSE;
+	GError *child_error = NULL;
+
+	/* Get the output folder */
+	folder = gtk_file_chooser_get_file (priv->file_chooser);
+	g_assert (folder != NULL);
+
+	/* Build a text buffer to use when getting all the entries */
+	buffer = gtk_text_buffer_new (NULL);
+
+	/* Get the list of entries */
+	entries = almanah_storage_manager_get_entries (almanah->storage_manager);
+
+	for (; entries != NULL; entries = g_slist_delete_link (entries, entries)) {
+		AlmanahEntry *entry = ALMANAH_ENTRY (entries->data);
+		GDate date;
+		gchar *filename, *content;
+		GFile *file;
+		GtkTextIter start_iter, end_iter;
+
+		/* Get the filename */
+		almanah_entry_get_date (entry, &date);
+		filename = g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (&date), g_date_get_month (&date), g_date_get_day (&date));
+		file = g_file_get_child (folder, filename);
+		g_free (filename);
+
+		/* Get the entry contents */
+		if (almanah_entry_get_content (entry, buffer, TRUE, &child_error) == FALSE) {
+			/* Error */
+			g_object_unref (file);
+			g_object_unref (entry);
+			break;
+		}
+
+		g_object_unref (entry);
+
+		gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
+		content = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
+
+		/* Create the file */
+		if (g_file_replace_contents (file, content, strlen (content), NULL, FALSE,
+		                             G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, NULL, NULL, &child_error) == FALSE) {
+			/* Error */
+			g_object_unref (file);
+			g_free (content);
+			break;
+		}
+
+		g_object_unref (file);
+		g_free (content);
+	}
+
+	/* Check if the loop was broken due to an error */
+	if (child_error != NULL) {
+		g_propagate_error (error, child_error);
+		goto finish;
+	}
+
+	success = TRUE;
+
+finish:
+	g_object_unref (folder);
+	g_object_unref (buffer);
+
+	return success;
+}
+
+static gboolean
 import_database (AlmanahImportExportDialog *self, AlmanahImportResultsDialog *results_dialog, GError **error)
 {
 	GFile *file;
@@ -457,12 +544,35 @@ import_database (AlmanahImportExportDialog *self, AlmanahImportResultsDialog *re
 	return TRUE;
 }
 
+static gboolean
+export_database (AlmanahImportExportDialog *self, GError **error)
+{
+	AlmanahImportExportDialogPrivate *priv = self->priv;
+	GFile *source, *destination;
+	gboolean success;
+
+	/* Get the output file */
+	destination = gtk_file_chooser_get_file (priv->file_chooser);
+	g_assert (destination != NULL);
+
+	/* Get the input file (current unencrypted database) */
+	source = g_file_new_for_path (almanah_storage_manager_get_filename (almanah->storage_manager, TRUE));
+
+	/* Copy the current database to that location */
+	success = g_file_copy (source, destination, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, error);
+
+	g_object_unref (source);
+	g_object_unref (destination);
+
+	return success;
+}
+
 static void
 response_cb (GtkDialog *dialog, gint response_id, AlmanahImportExportDialog *self)
 {
 	GError *error = NULL;
 	AlmanahImportExportDialogPrivate *priv = self->priv;
-	AlmanahImportResultsDialog *results_dialog;
+	AlmanahImportResultsDialog *results_dialog = NULL; /* shut up, gcc */
 
 	/* Just return if the user pressed Cancel */
 	if (response_id != GTK_RESPONSE_OK) {
@@ -470,16 +580,21 @@ response_cb (GtkDialog *dialog, gint response_id, AlmanahImportExportDialog *sel
 		return;
 	}
 
-	/* Import the entries according to the selected method. It's OK if we block here, since the dialogue should
-	 * be running in its own main loop. */
-	results_dialog = almanah_import_results_dialog_new ();
-	import_export_modes[priv->current_mode].import_func (self, results_dialog, &error);
+	if (priv->import == TRUE) {
+		/* Import the entries according to the selected method.
+		 * It's OK if we block, since the dialogue should be running in its own main loop. */
+		results_dialog = almanah_import_results_dialog_new ();
+		import_export_modes[priv->current_mode].import_func (self, results_dialog, &error);
+	} else {
+		/* Export the entries according to the selected method. */
+		import_export_modes[priv->current_mode].export_func (self, &error);
+	}
 
 	/* Check for errors (e.g. errors opening databases or files; not errors importing individual entries once we have the content to import) */
 	if (error != NULL) {
 		/* Show an error */
 		GtkWidget *error_dialog = gtk_message_dialog_new (GTK_WINDOW (self), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
-		                                                  GTK_BUTTONS_OK, _("Import failed"));
+		                                                  GTK_BUTTONS_OK, (priv->import == TRUE) ? _("Import failed") : _("Export failed"));
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog), "%s", error->message);
 		gtk_dialog_run (GTK_DIALOG (error_dialog));
 		gtk_widget_destroy (error_dialog);
@@ -488,13 +603,26 @@ response_cb (GtkDialog *dialog, gint response_id, AlmanahImportExportDialog *sel
 
 		gtk_widget_hide (GTK_WIDGET (self));
 	} else {
-		/* Show the results dialogue */
-		gtk_widget_hide (GTK_WIDGET (self));
-		gtk_widget_show_all (GTK_WIDGET (results_dialog));
-		gtk_dialog_run (GTK_DIALOG (results_dialog));
+		if (priv->import == TRUE) {
+			/* Show the results dialogue */
+			gtk_widget_hide (GTK_WIDGET (self));
+			gtk_widget_show_all (GTK_WIDGET (results_dialog));
+			gtk_dialog_run (GTK_DIALOG (results_dialog));
+		} else {
+			/* Show a success message */
+			GtkWidget *message_dialog;
+
+			gtk_widget_hide (GTK_WIDGET (self));
+			message_dialog = gtk_message_dialog_new (GTK_WINDOW (self), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
+			                                         GTK_BUTTONS_OK, _("Export successful"));
+			gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog), _("The diary was successfully exported."));
+			gtk_dialog_run (GTK_DIALOG (message_dialog));
+			gtk_widget_destroy (message_dialog);
+		}
 	}
 
-	gtk_widget_destroy (GTK_WIDGET (results_dialog));
+	if (priv->import == TRUE)
+		gtk_widget_destroy (GTK_WIDGET (results_dialog));
 }
 
 void
@@ -510,8 +638,10 @@ ied_mode_combo_box_changed_cb (GtkComboBox *combo_box, AlmanahImportExportDialog
 	priv->current_mode = new_mode;
 
 	/* Change the dialogue */
-	gtk_file_chooser_set_action (priv->file_chooser, import_export_modes[priv->current_mode].import_action);
-	gtk_label_set_text (priv->description_label, _(import_export_modes[priv->current_mode].import_description));
+	gtk_file_chooser_set_action (priv->file_chooser, import_export_modes[priv->current_mode].action);
+	gtk_label_set_text (priv->description_label,
+	                    (priv->import == TRUE) ? _(import_export_modes[priv->current_mode].import_description)
+	                                           : _(import_export_modes[priv->current_mode].export_description));
 }
 
 void
diff --git a/src/main-window.c b/src/main-window.c
index 1dd00fc..98595e5 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -63,6 +63,7 @@ static void mw_definition_removed_cb (AlmanahStorageManager *storage_manager, co
 /* GtkBuilder callbacks */
 void mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_window);
 void mw_import_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
+void mw_export_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
 void mw_page_setup_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
 void mw_print_preview_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
 void mw_print_activate_cb (GtkAction *action, AlmanahMainWindow *main_window);
@@ -697,6 +698,16 @@ mw_import_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 }
 
 void
+mw_export_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
+{
+	if (almanah->export_dialog == NULL)
+		almanah->export_dialog = GTK_WIDGET (almanah_import_export_dialog_new (FALSE));
+
+	gtk_widget_show_all (almanah->export_dialog);
+	gtk_dialog_run (GTK_DIALOG (almanah->export_dialog));
+}
+
+void
 mw_page_setup_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
 	almanah_print_page_setup ();
diff --git a/src/main.c b/src/main.c
index 5c5e0de..b208397 100644
--- a/src/main.c
+++ b/src/main.c
@@ -75,6 +75,8 @@ almanah_quit (void)
 		gtk_widget_destroy (almanah->date_entry_dialog);
 	if (almanah->import_dialog != NULL)
 		gtk_widget_destroy (almanah->import_dialog);
+	if (almanah->export_dialog != NULL)
+		gtk_widget_destroy (almanah->export_dialog);
 #ifdef ENABLE_ENCRYPTION
 	if (almanah->preferences_dialog != NULL)
 		gtk_widget_destroy (almanah->preferences_dialog);
diff --git a/src/main.h b/src/main.h
index 8010a97..085c3df 100644
--- a/src/main.h
+++ b/src/main.h
@@ -47,6 +47,7 @@ typedef struct {
 	GtkWidget *date_entry_dialog;
 	GtkWidget *definition_manager_window;
 	GtkWidget *import_dialog;
+	GtkWidget *export_dialog;
 #ifdef ENABLE_ENCRYPTION
 	GtkWidget *preferences_dialog;
 #endif /* ENABLE_ENCRYPTION */
diff --git a/src/storage-manager.c b/src/storage-manager.c
index f012394..845f544 100644
--- a/src/storage-manager.c
+++ b/src/storage-manager.c
@@ -1160,3 +1160,9 @@ almanah_storage_manager_remove_definition (AlmanahStorageManager *self, const gc
 
 	return FALSE;
 }
+
+const gchar *
+almanah_storage_manager_get_filename (AlmanahStorageManager *self, gboolean plain)
+{
+	return (plain == TRUE) ? self->priv->plain_filename : self->priv->filename;
+}
diff --git a/src/storage-manager.h b/src/storage-manager.h
index 46a770d..ad09d08 100644
--- a/src/storage-manager.h
+++ b/src/storage-manager.h
@@ -93,6 +93,8 @@ AlmanahDefinition *almanah_storage_manager_get_definition (AlmanahStorageManager
 gboolean almanah_storage_manager_add_definition (AlmanahStorageManager *self, AlmanahDefinition *definition);
 gboolean almanah_storage_manager_remove_definition (AlmanahStorageManager *self, const gchar *definition_text);
 
+const gchar *almanah_storage_manager_get_filename (AlmanahStorageManager *self, gboolean plain);
+
 G_END_DECLS
 
 #endif /* !ALMANAH_STORAGE_MANAGER_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]