[gnome-builder] editor: add save-as action using GtkSourceFileSaver.
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] editor: add save-as action using GtkSourceFileSaver.
- Date: Mon, 8 Sep 2014 22:54:27 +0000 (UTC)
commit ff72abbbb416a2264abdedddf20657d87f88786c
Author: Christian Hergert <christian hergert me>
Date: Mon Sep 8 15:54:12 2014 -0700
editor: add save-as action using GtkSourceFileSaver.
src/editor/gb-editor-tab.c | 195 +++++++++++++++++++++++++++++----
src/editor/gb-editor-tab.h | 1 +
src/editor/gb-editor-workspace.c | 24 ++++-
src/resources/keybindings/default.ini | 1 +
4 files changed, 195 insertions(+), 26 deletions(-)
---
diff --git a/src/editor/gb-editor-tab.c b/src/editor/gb-editor-tab.c
index f6633ce..a4b0ed3 100644
--- a/src/editor/gb-editor-tab.c
+++ b/src/editor/gb-editor-tab.c
@@ -105,6 +105,11 @@ struct _GbEditorTabPrivate
* track our unsaved file number.
*/
guint unsaved_number;
+
+ /*
+ * Animation for save progress.
+ */
+ GbAnimation *save_animation;
};
enum {
@@ -154,24 +159,6 @@ gb_editor_tab_get_file (GbEditorTab *tab)
return tab->priv->file;
}
-static void
-gb_editor_tab_set_file (GbEditorTab *tab,
- GtkSourceFile *file)
-{
- GbEditorTabPrivate *priv;
-
- g_return_if_fail (GB_IS_EDITOR_TAB (tab));
- g_return_if_fail (!file || GTK_SOURCE_IS_FILE (file));
- g_return_if_fail (!tab->priv->file);
-
- priv = tab->priv;
-
- priv->file = file ? g_object_ref (file) : NULL;
-
- g_object_notify_by_pspec (G_OBJECT (tab), gParamSpecs [PROP_FILE]);
-}
-
-
/**
* gb_editor_tab_go_to_start:
* @tab: A #GbEditorTab.
@@ -707,6 +694,168 @@ gb_editor_tab_set_font_desc (GbEditorTab *tab,
}
static void
+file_progress_cb (goffset current_num_bytes,
+ goffset total_num_bytes,
+ GbEditorTab *tab)
+{
+ GbEditorTabPrivate *priv;
+ gdouble fraction;
+
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ priv = tab->priv;
+
+ if (priv->save_animation)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (priv->save_animation),
+ (gpointer *)&priv->save_animation);
+ gb_animation_stop (priv->save_animation);
+ priv->save_animation = NULL;
+ }
+
+ fraction = total_num_bytes
+ ? ((gdouble)current_num_bytes / (gdouble)total_num_bytes)
+ : 1.0;
+
+ priv->save_animation = gb_object_animate (priv->progress_bar,
+ GB_ANIMATION_LINEAR,
+ 250,
+ NULL,
+ "fraction", fraction,
+ NULL);
+ g_object_add_weak_pointer (G_OBJECT (priv->save_animation),
+ (gpointer *)&priv->save_animation);
+}
+
+static gboolean
+hide_progress_bar_cb (gpointer data)
+{
+ GbEditorTab *tab = data;
+
+ g_assert (GB_IS_EDITOR_TAB (tab));
+
+ gb_object_animate_full (tab->priv->progress_bar,
+ GB_ANIMATION_EASE_OUT_CUBIC,
+ 250,
+ NULL,
+ (GDestroyNotify)gtk_widget_hide,
+ tab->priv->progress_bar,
+ "opacity", 0.0,
+ NULL);
+
+ g_object_unref (tab);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+on_save_cb (GtkSourceFileSaver *saver,
+ GAsyncResult *result,
+ GbEditorTab *tab)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver));
+ g_return_if_fail (G_IS_ASYNC_RESULT (result));
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ /*
+ * Hide the progress bar after a timeout period.
+ */
+ g_timeout_add (350, hide_progress_bar_cb, g_object_ref (tab));
+
+ if (!gtk_source_file_saver_save_finish (saver, result, &error))
+ {
+ /*
+ * TODO: Propagate error to tab.
+ */
+ g_warning ("%s", error->message);
+ g_clear_error (&error);
+ }
+
+ g_object_unref (tab);
+}
+
+static void
+gb_editor_tab_do_save (GbEditorTab *tab)
+{
+ GbEditorTabPrivate *priv;
+ GtkSourceFileSaver *saver;
+
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+ g_return_if_fail (tab->priv->file);
+
+ priv = tab->priv;
+
+ /*
+ * TODO: Tab needs a state machine for what are valid operations.
+ */
+
+ gtk_progress_bar_set_fraction (priv->progress_bar, 0.0);
+ gtk_widget_set_opacity (GTK_WIDGET (priv->progress_bar), 1.0);
+ gtk_widget_show (GTK_WIDGET (priv->progress_bar));
+
+ saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (priv->document),
+ priv->file);
+
+ gtk_source_file_saver_save_async (saver,
+ G_PRIORITY_DEFAULT,
+ NULL, /* TODO: Cancellable */
+ (GFileProgressCallback)file_progress_cb,
+ tab,
+ NULL,
+ (GAsyncReadyCallback)on_save_cb,
+ g_object_ref (tab));
+}
+
+void
+gb_editor_tab_save_as (GbEditorTab *tab)
+{
+ GtkFileChooserDialog *dialog;
+ GtkWidget *toplevel;
+ GtkWidget *suggested;
+ GtkResponseType response;
+
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab));
+
+ dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
+ "action", GTK_FILE_CHOOSER_ACTION_SAVE,
+ "do-overwrite-confirmation", TRUE,
+ "local-only", FALSE,
+ "select-multiple", FALSE,
+ "show-hidden", FALSE,
+ "transient-for", toplevel,
+ "title", _("Save As"),
+ NULL);
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ _("Cancel"), GTK_RESPONSE_CANCEL,
+ _("Save"), GTK_RESPONSE_OK,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ suggested = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK);
+ gtk_style_context_add_class (gtk_widget_get_style_context (suggested),
+ GTK_STYLE_CLASS_SUGGESTED_ACTION);
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (response == GTK_RESPONSE_OK)
+ {
+ GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ gtk_source_file_set_location (tab->priv->file, file);
+ gb_editor_tab_do_save (tab);
+ g_clear_object (&file);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
gb_editor_tab_freeze_drag (GbTab *tab)
{
GbEditorTab *editor = (GbEditorTab *) tab;
@@ -1281,10 +1430,6 @@ gb_editor_tab_set_property (GObject *object,
gb_editor_tab_set_document (tab, g_value_get_object (value));
break;
- case PROP_FILE:
- gb_editor_tab_set_file (tab, g_value_get_object (value));
- break;
-
case PROP_FONT_DESC:
gb_editor_tab_set_font_desc (tab, g_value_get_boxed (value));
break;
@@ -1332,8 +1477,7 @@ gb_editor_tab_class_init (GbEditorTabClass *klass)
_("File"),
_("The file for the tab."),
GTK_SOURCE_TYPE_FILE,
- (G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
+ (G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_FILE,
gParamSpecs [PROP_FILE]);
@@ -1391,5 +1535,8 @@ static void
gb_editor_tab_init (GbEditorTab *tab)
{
tab->priv = gb_editor_tab_get_instance_private (tab);
+
gtk_widget_init_template (GTK_WIDGET (tab));
+
+ tab->priv->file = gtk_source_file_new ();
}
diff --git a/src/editor/gb-editor-tab.h b/src/editor/gb-editor-tab.h
index e684cac..0d27520 100644
--- a/src/editor/gb-editor-tab.h
+++ b/src/editor/gb-editor-tab.h
@@ -63,6 +63,7 @@ void gb_editor_tab_set_show_find (GbEditorTab *tab,
void gb_editor_tab_reformat (GbEditorTab *tab);
void gb_editor_tab_go_to_end (GbEditorTab *tab);
void gb_editor_tab_go_to_start (GbEditorTab *tab);
+void gb_editor_tab_save_as (GbEditorTab *tab);
G_END_DECLS
diff --git a/src/editor/gb-editor-workspace.c b/src/editor/gb-editor-workspace.c
index 9b7fcf2..5931b48 100644
--- a/src/editor/gb-editor-workspace.c
+++ b/src/editor/gb-editor-workspace.c
@@ -104,6 +104,25 @@ on_reformat_activate (GSimpleAction *action,
}
static void
+on_save_as_activate (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GbEditorWorkspace *workspace = user_data;
+ GbTab *tab;
+
+ g_return_if_fail (GB_IS_EDITOR_WORKSPACE (workspace));
+
+ tab = gb_multi_notebook_get_active_tab (workspace->priv->multi_notebook);
+
+ if (tab)
+ {
+ g_assert (GB_IS_EDITOR_TAB (tab));
+ gb_editor_tab_save_as (GB_EDITOR_TAB (tab));
+ }
+}
+
+static void
on_go_to_start_activate (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
@@ -185,9 +204,10 @@ static void
gb_editor_workspace_init (GbEditorWorkspace *workspace)
{
static const GActionEntry action_entries[] = {
- { "reformat", on_reformat_activate },
- { "go-to-start", on_go_to_start_activate },
{ "go-to-end", on_go_to_end_activate },
+ { "go-to-start", on_go_to_start_activate },
+ { "reformat", on_reformat_activate },
+ { "save-as", on_save_as_activate },
};
GbEditorWorkspacePrivate *priv;
GbNotebook *notebook;
diff --git a/src/resources/keybindings/default.ini b/src/resources/keybindings/default.ini
index 9b68607..6714a8f 100644
--- a/src/resources/keybindings/default.ini
+++ b/src/resources/keybindings/default.ini
@@ -6,3 +6,4 @@ find = <Control>F
reformat = <Control><Shift>R
go-to-end = <Control>Page_Down
go-to-start = <Control>Page_Up
+save-as = <Control><Shift>S
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]