[gnome-builder/editor-layout] start on save and save as for tabs
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/editor-layout] start on save and save as for tabs
- Date: Sun, 30 Nov 2014 10:04:42 +0000 (UTC)
commit 3e36864a202fc5c95ec38eda957dfd3e31b99efb
Author: Christian Hergert <christian hergert me>
Date: Sun Nov 30 02:02:13 2014 -0800
start on save and save as for tabs
src/editor/gb-editor-document.c | 78 ++++++++++++
src/editor/gb-editor-document.h | 20 +++-
src/editor/gb-editor-tab.c | 251 +++++++++++++++++++++++++++++++------
src/editor/gb-editor-tab.h | 4 +
src/editor/gb-editor-workspace.c | 28 ++++
src/resources/ui/gb-editor-tab.ui | 33 ++++--
6 files changed, 363 insertions(+), 51 deletions(-)
---
diff --git a/src/editor/gb-editor-document.c b/src/editor/gb-editor-document.c
index 531d89f..7debd2f 100644
--- a/src/editor/gb-editor-document.c
+++ b/src/editor/gb-editor-document.c
@@ -332,6 +332,84 @@ gb_editor_document_code_assistant_changed (GbEditorDocument *document,
}
static void
+gb_editor_document_save_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtkSourceFileSaver *saver = (GtkSourceFileSaver *)object;
+ GError *error = NULL;
+ GTask *task = user_data;
+
+ ENTRY;
+
+ g_return_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver));
+ g_return_if_fail (G_IS_ASYNC_RESULT (result));
+ g_return_if_fail (G_IS_TASK (task));
+
+ if (!gtk_source_file_saver_save_finish (saver, result, &error))
+ {
+ g_task_return_error (task, error);
+ GOTO (cleanup);
+ }
+
+ g_task_return_boolean (task, TRUE);
+
+cleanup:
+ g_object_unref (task);
+
+ EXIT;
+}
+
+void
+gb_editor_document_save_async (GbEditorDocument *document,
+ GCancellable *cancellable,
+ GFileProgressCallback progress_callback,
+ gpointer progress_data,
+ GDestroyNotify progress_data_notify,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GtkSourceFileSaver *saver;
+ GTask *task;
+
+ ENTRY;
+
+ g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (document, cancellable, callback, user_data);
+
+ saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (document),
+ document->priv->file);
+
+ gtk_source_file_saver_save_async (saver,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ progress_callback,
+ progress_data,
+ progress_data_notify,
+ gb_editor_document_save_cb,
+ task);
+
+ g_object_unref (saver);
+
+ EXIT;
+}
+
+gboolean
+gb_editor_document_save_finish (GbEditorDocument *document,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = (GTask *)result;
+
+ g_return_val_if_fail (GB_IS_EDITOR_DOCUMENT (document), FALSE);
+ g_return_val_if_fail (G_IS_TASK (task), FALSE);
+
+ return g_task_propagate_boolean (task, error);
+}
+
+static void
gb_editor_document_finalize (GObject *object)
{
GbEditorDocumentPrivate *priv = GB_EDITOR_DOCUMENT (object)->priv;
diff --git a/src/editor/gb-editor-document.h b/src/editor/gb-editor-document.h
index 2c6f902..a2d51e5 100644
--- a/src/editor/gb-editor-document.h
+++ b/src/editor/gb-editor-document.h
@@ -55,11 +55,21 @@ struct _GbEditorDocumentClass
GbEditorDocument *gb_editor_document_new (void);
GType gb_editor_document_get_type (void) G_GNUC_CONST;
-GtkSourceFile *gb_editor_document_get_file (GbEditorDocument *document);
-void gb_editor_document_set_file (GbEditorDocument *document,
- GtkSourceFile *file);
-GbSourceChangeMonitor *gb_editor_document_get_change_monitor (GbEditorDocument *document);
-GbSourceCodeAssistant *gb_editor_document_get_code_assistant (GbEditorDocument *document);
+GtkSourceFile *gb_editor_document_get_file (GbEditorDocument *document);
+void gb_editor_document_set_file (GbEditorDocument *document,
+ GtkSourceFile *file);
+GbSourceChangeMonitor *gb_editor_document_get_change_monitor (GbEditorDocument *document);
+GbSourceCodeAssistant *gb_editor_document_get_code_assistant (GbEditorDocument *document);
+void gb_editor_document_save_async (GbEditorDocument *document,
+ GCancellable *cancellable,
+ GFileProgressCallback progress_callback,
+ gpointer progress_data,
+ GDestroyNotify progress_data_notify,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gb_editor_document_save_finish (GbEditorDocument *document,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/editor/gb-editor-tab.c b/src/editor/gb-editor-tab.c
index f9fabf4..df8d7fa 100644
--- a/src/editor/gb-editor-tab.c
+++ b/src/editor/gb-editor-tab.c
@@ -16,35 +16,202 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define G_LOG_DOMAIN "editor-tab"
+
#include <glib/gi18n.h>
+#include <gtksourceview/gtksource.h>
+#include "gb-animation.h"
#include "gb-editor-document.h"
#include "gb-editor-frame.h"
#include "gb-editor-tab.h"
+#include "gb-log.h"
+#include "gb-widget.h"
struct _GbEditorTabPrivate
{
/* Widgets owned by GtkBuilder */
GbEditorFrame *frame;
GtkPaned *paned;
+ GtkProgressBar *progress_bar;
GtkToggleButton *split_button;
/* Weak references */
GbEditorFrame *last_frame;
+ GbAnimation *progress_animation;
/* Objects owned by GbEditorTab */
GbEditorDocument *document;
};
-enum
+G_DEFINE_TYPE_WITH_PRIVATE (GbEditorTab, gb_editor_tab, GB_TYPE_TAB)
+
+static void
+gb_editor_tab_progress_cb (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer user_data)
{
- PROP_0,
- LAST_PROP
-};
+ GbEditorTabPrivate *priv;
+ GbEditorTab *tab = user_data;
+ gdouble fraction;
-G_DEFINE_TYPE_WITH_PRIVATE (GbEditorTab, gb_editor_tab, GB_TYPE_TAB)
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ priv = tab->priv;
+
+ if (priv->progress_animation)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (priv->progress_animation),
+ (gpointer *)&priv->progress_animation);
+ gb_animation_stop (priv->progress_animation);
+ priv->progress_animation = NULL;
+ }
+
+ fraction = total_num_bytes
+ ? ((gdouble)current_num_bytes / (gdouble)total_num_bytes)
+ : 1.0;
+
+ priv->progress_animation =
+ gb_object_animate (priv->progress_bar,
+ GB_ANIMATION_LINEAR,
+ 250,
+ NULL,
+ "fraction", fraction,
+ NULL);
+ g_object_add_weak_pointer (G_OBJECT (priv->progress_animation),
+ (gpointer *)&priv->progress_animation);
+}
+
+static void
+gb_editor_tab_save_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbEditorTab *tab = user_data;
+ GbEditorDocument *document = (GbEditorDocument *)source_object;
+ GError *error = NULL;
+
+ ENTRY;
+
+ g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+ g_return_if_fail (G_IS_ASYNC_RESULT (result));
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ if (!gb_editor_document_save_finish (document, result, &error))
+ {
+ g_print ("%s", error->message);
+ //gb_editor_tab_set_error (tab, error);
+ g_clear_error (&error);
+ }
-static GParamSpec *gParamSpecs [LAST_PROP];
+ gb_widget_fade_hide (GTK_WIDGET (tab->priv->progress_bar));
+
+ g_object_unref (tab);
+
+ EXIT;
+}
+
+static void
+gb_editor_tab_do_save (GbEditorTab *tab)
+{
+ ENTRY;
+
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ gtk_progress_bar_set_fraction (tab->priv->progress_bar, 0.0);
+ gtk_widget_show (GTK_WIDGET (tab->priv->progress_bar));
+
+ gb_editor_document_save_async (tab->priv->document,
+ NULL, /* cancellable */
+ gb_editor_tab_progress_cb,
+ tab,
+ NULL,
+ gb_editor_tab_save_cb,
+ g_object_ref (tab));
+
+ EXIT;
+}
+
+void
+gb_editor_tab_save_as (GbEditorTab *tab)
+{
+ GtkWidget *toplevel;
+ GtkDialog *dialog;
+ GtkWidget *suggested;
+ GFile *chosen_file;
+ guint response;
+
+ ENTRY;
+
+ 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 Document 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));
+ gtk_widget_hide (GTK_WIDGET (dialog));
+
+ if (response == GTK_RESPONSE_OK)
+ {
+ GtkSourceFile *sfile;
+
+ sfile = gb_editor_document_get_file (tab->priv->document);
+ chosen_file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ gtk_source_file_set_location (sfile, chosen_file);
+ gb_editor_tab_do_save (tab);
+ g_clear_object (&chosen_file);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ EXIT;
+}
+
+void
+gb_editor_tab_save (GbEditorTab *tab)
+{
+ GtkSourceFile *file;
+ gboolean has_location;
+
+ ENTRY;
+
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ file = gb_editor_document_get_file (tab->priv->document);
+ has_location = !!gtk_source_file_get_location (file);
+
+ if (has_location)
+ gb_editor_tab_do_save (tab);
+ else
+ gb_editor_tab_save_as (tab);
+
+ EXIT;
+}
+
+void
+gb_editor_tab_open (GbEditorTab *tab)
+{
+}
static void
gb_editor_tab_on_frame_focused (GbEditorTab *tab,
@@ -133,10 +300,28 @@ gb_editor_tab_grab_focus (GtkWidget *widget)
}
static void
+gb_editor_tab_on_notify_location (GbEditorTab *tab,
+ GParamSpec *pspec,
+ GtkSourceFile *file)
+{
+ gchar *title;
+ GFile *location;
+
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+ g_return_if_fail (GTK_SOURCE_IS_FILE (file));
+
+ location = gtk_source_file_get_location (file);
+ title = g_file_get_basename (location);
+ gb_tab_set_title (GB_TAB (tab), title);
+ g_free (title);
+}
+
+static void
gb_editor_tab_constructed (GObject *object)
{
GbEditorTabPrivate *priv;
GbEditorTab *tab = (GbEditorTab *)object;
+ GtkSourceFile *file;
g_return_if_fail (GB_IS_EDITOR_TAB (tab));
@@ -148,6 +333,13 @@ gb_editor_tab_constructed (GObject *object)
NULL);
gb_editor_frame_set_document (priv->frame, priv->document);
+ file = gb_editor_document_get_file (priv->document);
+ g_signal_connect_object (file,
+ "notify::location",
+ G_CALLBACK (gb_editor_tab_on_notify_location),
+ tab,
+ G_CONNECT_SWAPPED);
+
g_signal_connect_object (priv->frame,
"focused",
G_CALLBACK (gb_editor_tab_on_frame_focused),
@@ -168,43 +360,27 @@ gb_editor_tab_dispose (GObject *object)
g_clear_object (&priv->document);
- G_OBJECT_CLASS (gb_editor_tab_parent_class)->dispose (object);
-}
-
-static void
-gb_editor_tab_finalize (GObject *object)
-{
- G_OBJECT_CLASS (gb_editor_tab_parent_class)->finalize (object);
-}
-
-static void
-gb_editor_tab_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GbEditorTab *self = GB_EDITOR_TAB (object);
+ if (priv->last_frame)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (priv->last_frame),
+ (gpointer *)&priv->last_frame);
+ priv->last_frame = NULL;
+ }
- switch (prop_id)
+ if (priv->progress_animation)
{
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ g_object_remove_weak_pointer (G_OBJECT (priv->progress_animation),
+ (gpointer *)&priv->progress_animation);
+ priv->progress_animation = NULL;
}
+
+ G_OBJECT_CLASS (gb_editor_tab_parent_class)->dispose (object);
}
static void
-gb_editor_tab_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+gb_editor_tab_finalize (GObject *object)
{
- GbEditorTab *self = GB_EDITOR_TAB (object);
-
- switch (prop_id)
- {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
+ G_OBJECT_CLASS (gb_editor_tab_parent_class)->finalize (object);
}
static void
@@ -216,8 +392,6 @@ gb_editor_tab_class_init (GbEditorTabClass *klass)
object_class->constructed = gb_editor_tab_constructed;
object_class->dispose = gb_editor_tab_dispose;
object_class->finalize = gb_editor_tab_finalize;
- object_class->get_property = gb_editor_tab_get_property;
- object_class->set_property = gb_editor_tab_set_property;
widget_class->grab_focus = gb_editor_tab_grab_focus;
@@ -225,6 +399,7 @@ gb_editor_tab_class_init (GbEditorTabClass *klass)
"/org/gnome/builder/ui/gb-editor-tab.ui");
gtk_widget_class_bind_template_child_private (widget_class, GbEditorTab, frame);
gtk_widget_class_bind_template_child_private (widget_class, GbEditorTab, paned);
+ gtk_widget_class_bind_template_child_private (widget_class, GbEditorTab, progress_bar);
gtk_widget_class_bind_template_child_private (widget_class, GbEditorTab, split_button);
g_type_ensure (GB_TYPE_EDITOR_FRAME);
diff --git a/src/editor/gb-editor-tab.h b/src/editor/gb-editor-tab.h
index cc01f1c..31d9f65 100644
--- a/src/editor/gb-editor-tab.h
+++ b/src/editor/gb-editor-tab.h
@@ -19,6 +19,7 @@
#ifndef GB_EDITOR_TAB_H
#define GB_EDITOR_TAB_H
+#include <gio/gio.h>
#include <gtk/gtk.h>
#include "gb-tab.h"
@@ -51,6 +52,9 @@ struct _GbEditorTabClass
};
GType gb_editor_tab_get_type (void) G_GNUC_CONST;
+void gb_editor_tab_save (GbEditorTab *tab);
+void gb_editor_tab_save_as (GbEditorTab *tab);
+void gb_editor_tab_open (GbEditorTab *tab);
G_END_DECLS
diff --git a/src/editor/gb-editor-workspace.c b/src/editor/gb-editor-workspace.c
index 604bd5e..46cd3c3 100644
--- a/src/editor/gb-editor-workspace.c
+++ b/src/editor/gb-editor-workspace.c
@@ -52,6 +52,32 @@ gb_editor_workspace_open (GbEditorWorkspace *workspace,
}
static void
+save_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GbEditorWorkspace *workspace = user_data;
+ GbTab *tab;
+
+ tab = gb_tab_grid_get_active (workspace->priv->tab_grid);
+ if (GB_IS_EDITOR_TAB (tab))
+ gb_editor_tab_save (GB_EDITOR_TAB (tab));
+}
+
+static void
+save_as_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GbEditorWorkspace *workspace = user_data;
+ GbTab *tab;
+
+ tab = gb_tab_grid_get_active (workspace->priv->tab_grid);
+ if (GB_IS_EDITOR_TAB (tab))
+ gb_editor_tab_save_as (GB_EDITOR_TAB (tab));
+}
+
+static void
new_tab (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
@@ -122,6 +148,8 @@ gb_editor_workspace_init (GbEditorWorkspace *workspace)
{
const GActionEntry entries[] = {
{ "new-tab", new_tab },
+ { "save", save_tab },
+ { "save-as", save_as_tab },
};
workspace->priv = gb_editor_workspace_get_instance_private (workspace);
diff --git a/src/resources/ui/gb-editor-tab.ui b/src/resources/ui/gb-editor-tab.ui
index 5ede5b1..3f9476c 100644
--- a/src/resources/ui/gb-editor-tab.ui
+++ b/src/resources/ui/gb-editor-tab.ui
@@ -42,19 +42,36 @@
<child internal-child="content">
<object class="GtkBox" id="content">
<child>
- <object class="GtkPaned" id="paned">
+ <object class="GtkOverlay">
<property name="visible">true</property>
- <property name="orientation">vertical</property>
- <property name="vexpand">true</property>
+ <child type="overlay">
+ <object class="GtkProgressBar" id="progress_bar">
+ <property name="visible">false</property>
+ <property name="fraction">0.0</property>
+ <property name="valign">start</property>
+ <property name="halign">fill</property>
+ <property name="vexpand">false</property>
+ <style>
+ <class name="osd"/>
+ </style>
+ </object>
+ </child>
<child>
- <object class="GbEditorFrame" id="frame">
+ <object class="GtkPaned" id="paned">
<property name="visible">true</property>
+ <property name="orientation">vertical</property>
<property name="vexpand">true</property>
+ <child>
+ <object class="GbEditorFrame" id="frame">
+ <property name="visible">true</property>
+ <property name="vexpand">true</property>
+ </object>
+ <packing>
+ <property name="resize">true</property>
+ <property name="shrink">false</property>
+ </packing>
+ </child>
</object>
- <packing>
- <property name="resize">true</property>
- <property name="shrink">false</property>
- </packing>
</child>
</object>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]