[gedit/wip/libgedit-file-loading-saving-ui] New GeditFileLoader class
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit/wip/libgedit-file-loading-saving-ui] New GeditFileLoader class
- Date: Thu, 2 Apr 2015 14:37:21 +0000 (UTC)
commit cdf7fbbd56fd18bf1f6fce7d344374a71dd26d07
Author: Sébastien Wilmet <swilmet gnome org>
Date: Thu Apr 2 14:35:36 2015 +0200
New GeditFileLoader class
The goal is to make the file loading UI code re-usable, so it can be
used in other text editors.
gedit/Makefile.am | 2 +
gedit/gedit-file-loader.c | 325 +++++++++++++++++++++++++++++++++++++++++++++
gedit/gedit-file-loader.h | 59 ++++++++
3 files changed, 386 insertions(+), 0 deletions(-)
---
diff --git a/gedit/Makefile.am b/gedit/Makefile.am
index c720e39..c531dd8 100644
--- a/gedit/Makefile.am
+++ b/gedit/Makefile.am
@@ -110,6 +110,7 @@ gedit_NOINST_H_FILES = \
gedit/gedit-open-document-selector-store.h \
gedit/gedit-file-chooser-dialog.h \
gedit/gedit-file-chooser-dialog-gtk.h \
+ gedit/gedit-file-loader.h \
gedit/gedit-highlight-mode-dialog.h \
gedit/gedit-highlight-mode-selector.h \
gedit/gedit-history-entry.h \
@@ -186,6 +187,7 @@ gedit_libgedit_c_files = \
gedit/gedit-open-document-selector-store.c \
gedit/gedit-file-chooser-dialog.c \
gedit/gedit-file-chooser-dialog-gtk.c \
+ gedit/gedit-file-loader.c \
gedit/gedit-highlight-mode-dialog.c \
gedit/gedit-highlight-mode-selector.c \
gedit/gedit-history-entry.c \
diff --git a/gedit/gedit-file-loader.c b/gedit/gedit-file-loader.c
new file mode 100644
index 0000000..3a8dc49
--- /dev/null
+++ b/gedit/gedit-file-loader.c
@@ -0,0 +1,325 @@
+/*
+ * gedit-file-loader.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-file-loader.h"
+#include "gedit-progress-info-bar.h"
+#include "gedit-utils.h"
+
+/* TODO do not depend on GeditTab. */
+#include "gedit-tab.h"
+
+/* TODO do not depend on GeditDocument. */
+#include "gedit-document.h"
+
+/* When you modify this class, keep in mind that it must remain re-usable for
+ * other text editors.
+ * This class wraps GtkSourceFileLoader to add an info bar that shows the
+ * progress of the file loading, and handles errors by asking some questions to
+ * stop or relaunch the file loading with different options.
+ */
+
+struct _GeditFileLoaderPrivate
+{
+ /* GtkInfoBars can be added/removed shown/hidden in @info_bar. */
+ GtkGrid *info_bar;
+ GeditProgressInfoBar *progress_info_bar;
+ GtkInfoBar *error_info_bar;
+
+ /* FIXME is the state useful? If yes, create a new enum to not depend on
+ * GeditTab.
+ */
+ GeditTabState state;
+};
+
+typedef struct _TaskData TaskData;
+struct _TaskData
+{
+ GTimer *timer;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GeditFileLoader, _gedit_file_loader, G_TYPE_OBJECT)
+
+GeditDocument *
+get_document (GeditFileLoader *loader)
+{
+ return GEDIT_DOCUMENT (gtk_source_file_loader_get_buffer (GTK_SOURCE_FILE_LOADER (loader)));
+}
+
+static TaskData *
+task_data_new (void)
+{
+ return g_slice_new0 (TaskData);
+}
+
+static void
+task_data_free (TaskData *data)
+{
+ if (data != NULL)
+ {
+ if (data->timer != NULL)
+ {
+ g_timer_destroy (data->timer);
+ }
+
+ g_slice_free (TaskData, data);
+ }
+}
+
+static void
+_gedit_file_loader_dispose (GObject *object)
+{
+ GeditFileLoader *loader = GEDIT_FILE_LOADER (object);
+
+ if (loader->priv->progress_info_bar != NULL)
+ {
+ gtk_widget_destroy (GTK_WIDGET (loader->priv->progress_info_bar));
+ loader->priv->progress_info_bar = NULL;
+ }
+
+ if (loader->priv->error_info_bar != NULL)
+ {
+ gtk_widget_destroy (GTK_WIDGET (loader->priv->error_info_bar));
+ loader->priv->error_info_bar = NULL;
+ }
+
+ G_OBJECT_CLASS (_gedit_file_loader_parent_class)->dispose (object);
+}
+
+static void
+_gedit_file_loader_class_init (GeditFileLoaderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = _gedit_file_loader_dispose;
+}
+
+static void
+_gedit_file_loader_init (GeditFileLoader *loader)
+{
+ loader->priv = _gedit_file_loader_get_instance_private (loader);
+
+ loader->priv->info_bar = GTK_GRID (gtk_grid_new ());
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (loader->priv->info_bar),
+ GTK_ORIENTATION_VERTICAL);
+ gtk_widget_show (GTK_WIDGET (loader->priv->info_bar);
+}
+
+GeditFileLoader *
+_gedit_file_loader_new (void)
+{
+ return GEDIT_FILE_LOADER (g_object_new (GEDIT_TYPE_FILE_LOADER, NULL));
+}
+
+GtkWidget *
+_gedit_file_loader_get_info_bar (GeditFileLoader *loader)
+{
+ g_return_val_if_fail (GEDIT_IS_FILE_LOADER (loader), NULL);
+
+ return GTK_WIDGET (loader->priv->info_bar);
+}
+
+#define MAX_MSG_LENGTH 100
+
+static void
+show_progress_info_bar (GTask *task)
+{
+ GeditFileLoader *loader = g_task_get_source_object (task);
+ GtkWidget *info_bar;
+ GeditDocument *doc;
+ gchar *name;
+ gchar *dirname = NULL;
+ gchar *msg = NULL;
+ gchar *name_markup;
+ gchar *dirname_markup;
+ gint len;
+
+ if (loader->priv->progress_info_bar != NULL)
+ {
+ return;
+ }
+
+ doc = get_document (loader);
+
+ name = gedit_document_get_short_name_for_display (doc);
+ len = g_utf8_strlen (name, -1);
+
+ /* If the name is awfully long, truncate it and be done with it,
+ * otherwise also show the directory (ellipsized if needed).
+ */
+ if (len > MAX_MSG_LENGTH)
+ {
+ gchar *str;
+
+ str = gedit_utils_str_middle_truncate (name, MAX_MSG_LENGTH);
+ g_free (name);
+ name = str;
+ }
+ else
+ {
+ GFile *location = gtk_source_file_loader_get_location (GTK_SOURCE_FILE_LOADER (loader));
+
+ if (location != NULL)
+ {
+ gchar *str = gedit_utils_location_get_dirname_for_display (location);
+
+ /* Use the remaining space for the dir, but use a min of 20 chars
+ * so that we do not end up with a dirname like "(a...b)".
+ * This means that in the worst case when the filename is long 99
+ * we have a title long 99 + 20, but I think it's a rare enough
+ * case to be acceptable. It's justa darn title afterall :)
+ */
+ dirname = gedit_utils_str_middle_truncate (str,
+ MAX (20, MAX_MSG_LENGTH - len));
+ g_free (str);
+ }
+ }
+
+ name_markup = g_markup_printf_escaped ("<b>%s</b>", name);
+
+ if (loader->priv->state == GEDIT_TAB_STATE_REVERTING)
+ {
+ if (dirname != NULL)
+ {
+ dirname_markup = g_markup_printf_escaped ("<b>%s</b>", dirname);
+
+ /* Translators: the first %s is a file name (e.g. test.txt) the second one
+ * is a directory (e.g. ssh://master.gnome.org/home/users/paolo).
+ */
+ msg = g_strdup_printf (_("Reverting %s from %s"),
+ name_markup,
+ dirname_markup);
+ g_free (dirname_markup);
+ }
+ else
+ {
+ msg = g_strdup_printf (_("Reverting %s"), name_markup);
+ }
+
+ info_bar = gedit_progress_info_bar_new ("document-revert", msg, TRUE);
+ }
+ else
+ {
+ if (dirname != NULL)
+ {
+ dirname_markup = g_markup_printf_escaped ("<b>%s</b>", dirname);
+
+ /* Translators: the first %s is a file name (e.g. test.txt) the second one
+ * is a directory (e.g. ssh://master.gnome.org/home/users/paolo).
+ */
+ msg = g_strdup_printf (_("Loading %s from %s"),
+ name_markup,
+ dirname_markup);
+ g_free (dirname_markup);
+ }
+ else
+ {
+ msg = g_strdup_printf (_("Loading %s"), name_markup);
+ }
+
+ info_bar = gedit_progress_info_bar_new ("document-open", msg, TRUE);
+ }
+
+ loader->priv->progress_info_bar = GEDIT_PROGRESS_INFO_BAR (info_bar);
+
+ g_signal_connect (info_bar,
+ "response",
+ G_CALLBACK (load_cancelled),
+ tab);
+
+ g_free (msg);
+ g_free (name);
+ g_free (name_markup);
+ g_free (dirname);
+}
+
+static void
+progress_cb (goffset size,
+ goffset total_size,
+ GTask *task)
+{
+ GeditFileLoader *loader = g_task_get_source_object (task);
+ TaskData *data = g_task_get_task_data (task);
+ gdouble elapsed_time;
+ gdouble total_time;
+ gdouble remaining_time;
+
+ g_return_if_fail (loader->priv->state == GEDIT_TAB_STATE_LOADING ||
+ loader->priv->state == GEDIT_TAB_STATE_REVERTING);
+
+ /* FIXME create timer before beginning the loading? Or is this callback
+ * called with size == 0?
+ */
+ if (data->priv->timer == NULL)
+ {
+ data->priv->timer = g_timer_new ();
+ return;
+ }
+
+ elapsed_time = g_timer_elapsed (data->priv->timer, NULL);
+
+ /* elapsed_time / total_time = size / total_size */
+ total_time = (elapsed_time * total_size) / size;
+
+ remaining_time = total_time - elapsed_time;
+
+ /* Approximately more than 3 seconds remaining. */
+ if (remaining_time > 3.0)
+ {
+ show_loading_info_bar (tab);
+ }
+
+ info_bar_set_progress (tab, size, total_size);
+}
+
+void
+_gedit_file_loader_load_async (GeditFileLoader *loader,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ TaskData *data;
+
+ task = g_task_new (loader, cancellable, callback, user_data);
+
+ data = task_data_new ();
+ g_task_set_task_data (task, data, (GDestroyNotify) task_data_free);
+
+ gtk_source_file_loader_load_async (GTK_SOURCE_FILE_LOADER (loader),
+ io_priority,
+ cancellable,
+ (GFileProgressCallback) progress_cb,
+ task,
+ NULL,
+ (GAsyncReadyCallback) load_cb,
+ task);
+}
+
+void
+_gedit_file_loader_load_finish (GeditFileLoader *loader,
+ GAsyncResult *result)
+{
+ g_return_if_fail (g_task_is_valid (result, loader));
+
+ g_task_propagate_boolean (G_TASK (result), NULL);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-file-loader.h b/gedit/gedit-file-loader.h
new file mode 100644
index 0000000..297ecb9
--- /dev/null
+++ b/gedit/gedit-file-loader.h
@@ -0,0 +1,59 @@
+/*
+ * gedit-file-loader.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_FILE_LOADER_H__
+#define __GEDIT_FILE_LOADER_H__
+
+#include <gtksourceview/gtksource.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_FILE_LOADER (_gedit_file_loader_get_type ())
+#define GEDIT_FILE_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_FILE_LOADER,
GeditFileLoader))
+#define GEDIT_FILE_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_FILE_LOADER,
GeditFileLoaderClass))
+#define GEDIT_IS_FILE_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_FILE_LOADER))
+#define GEDIT_IS_FILE_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_FILE_LOADER))
+#define GEDIT_FILE_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_FILE_LOADER,
GeditFileLoaderClass))
+
+typedef struct _GeditFileLoader GeditFileLoader;
+typedef struct _GeditFileLoaderClass GeditFileLoaderClass;
+typedef struct _GeditFileLoaderPrivate GeditFileLoaderPrivate;
+
+struct _GeditFileLoader
+{
+ GtkSourceFileLoader parent;
+
+ GeditFileLoaderPrivate *priv;
+};
+
+struct _GeditFileLoaderClass
+{
+ GtkSourceFileLoaderClass parent_class;
+};
+
+GType _gedit_file_loader_get_type (void) G_GNUC_CONST;
+
+GeditFileLoader *_gedit_file_loader_new (void);
+
+G_END_DECLS
+
+#endif /* __GEDIT_FILE_LOADER_H__ */
+
+/* ex:set ts=8 noet: */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]