[gedit/wip/loader-saver: 2/2] Port GeditTab and GeditDocument to GtkSourceFile (not finished)
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit/wip/loader-saver: 2/2] Port GeditTab and GeditDocument to GtkSourceFile (not finished)
- Date: Fri, 13 Jun 2014 21:31:05 +0000 (UTC)
commit 3e70458d08c0977ff570f63981c07ee6bdbb3395
Author: Sébastien Wilmet <swilmet gnome org>
Date: Thu Jun 12 23:11:04 2014 +0200
Port GeditTab and GeditDocument to GtkSourceFile (not finished)
gedit/gedit-document.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++
gedit/gedit-document.h | 17 +++
gedit/gedit-tab.c | 127 +++++++++++++---------
3 files changed, 382 insertions(+), 50 deletions(-)
---
diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c
index 1630871..f822d82 100644
--- a/gedit/gedit-document.c
+++ b/gedit/gedit-document.c
@@ -134,6 +134,13 @@ struct _GeditDocumentPrivate
guint empty_search : 1;
};
+typedef struct
+{
+ gint line_pos;
+ gint column_pos;
+ guint create : 1;
+} TaskData;
+
enum {
PROP_0,
@@ -2621,4 +2628,285 @@ gedit_document_get_file (GeditDocument *doc)
return doc->priv->file;
}
+static TaskData *
+task_data_new (void)
+{
+ return g_slice_new (TaskData);
+}
+
+static void
+task_data_free (TaskData *data)
+{
+ if (data != NULL)
+ {
+ g_slice_free (TaskData, data);
+ }
+}
+
+static void
+load_succeeded (GTask *task)
+{
+ GeditDocument *doc = g_task_get_source_object (task);
+ TaskData *data = g_task_get_task_data (task);
+
+ g_get_current_time (&doc->priv->time_of_last_save_or_load);
+
+ doc->priv->externally_modified = FALSE;
+ doc->priv->deleted = FALSE;
+
+ /* move the cursor at the requested line if any */
+ if (data->line_pos > 0)
+ {
+ gedit_document_goto_line_offset (doc,
+ data->line_pos - 1,
+ data->column_pos < 1 ? 0 : data->column_pos - 1);
+ }
+ else
+ {
+ GtkTextIter iter;
+
+ /* if enabled, move to the position stored in the metadata */
+ if (g_settings_get_boolean (doc->priv->editor_settings,
GEDIT_SETTINGS_RESTORE_CURSOR_POSITION))
+ {
+ gchar *pos;
+ gint offset;
+
+ pos = gedit_document_get_metadata (doc, GEDIT_METADATA_ATTRIBUTE_POSITION);
+
+ offset = pos ? atoi (pos) : 0;
+ g_free (pos);
+
+ gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc),
+ &iter,
+ MAX (offset, 0));
+
+ /* make sure it's a valid position, if the file
+ * changed we may have ended up in the middle of
+ * a utf8 character cluster */
+ if (!gtk_text_iter_is_cursor_position (&iter))
+ {
+ gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc),
+ &iter);
+ }
+ }
+
+ /* otherwise to the top */
+ else
+ {
+ gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc),
+ &iter);
+ }
+
+ gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
+ }
+
+ if (!doc->priv->language_set_by_user)
+ {
+ GtkSourceLanguage *language = guess_language (doc, doc->priv->content_type);
+
+ gedit_debug_message (DEBUG_DOCUMENT, "Language: %s",
+ language != NULL ? gtk_source_language_get_name (language) : "None");
+
+ set_language (doc, language, FALSE);
+ }
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+query_info_cb (GFile *location,
+ GAsyncResult *result,
+ GTask *task)
+{
+ GFileInfo *info;
+ GeditDocument *doc = g_task_get_source_object (task);
+ const gchar *content_type = NULL;
+ gboolean read_only = FALSE;
+ GError *error = NULL;
+
+ info = g_file_query_info_finish (location, result, &error);
+
+ if (error != NULL)
+ {
+ g_warning ("Query file info error: %s", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+
+ if (info != NULL)
+ {
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
+ {
+ content_type = g_file_info_get_attribute_string (info,
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
+ }
+
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
+ {
+ read_only = !g_file_info_get_attribute_boolean (info,
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+ }
+
+ g_object_unref (info);
+ }
+
+ set_content_type (doc, content_type);
+ set_readonly (doc, read_only);
+
+ load_succeeded (task);
+}
+
+static void
+load_cb (GtkSourceFileLoader *loader,
+ GAsyncResult *result,
+ GTask *task)
+{
+ TaskData *data = g_task_get_task_data (task);
+ GError *error = NULL;
+
+ gtk_source_file_loader_load_finish (loader, result, &error);
+ g_object_unref (loader);
+
+ /* load was successful */
+ if (error == NULL ||
+ (error->domain == GTK_SOURCE_FILE_LOADER_ERROR &&
+ error->code == GTK_SOURCE_FILE_LOADER_ERROR_CONVERSION_FALLBACK))
+ {
+ GeditDocument *doc = g_task_get_source_object (task);
+ GFile *location = gtk_source_file_get_location (doc->priv->file);
+
+ if (location != NULL)
+ {
+ g_file_query_info_async (location,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ G_FILE_QUERY_INFO_NONE,
+ g_task_get_priority (task),
+ g_task_get_cancellable (task),
+ (GAsyncReadyCallback)query_info_cb,
+ task);
+ }
+
+ /* loaded from stream */
+ else
+ {
+ set_content_type (doc, NULL);
+ set_readonly (doc, FALSE);
+
+ load_succeeded (task);
+ }
+
+ if (error != NULL)
+ {
+ g_error_free (error);
+ }
+ }
+
+ /* special case creating a named new doc */
+ else if (data->create &&
+ error->domain == G_IO_ERROR &&
+ error->code == G_IO_ERROR_NOT_FOUND &&
+ g_file_has_uri_scheme (location, "file"))
+ {
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ }
+
+ else
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ }
+}
+
+void
+_gedit_document_load_async (GeditDocument *doc,
+ GFile *location,
+ GInputStream *stream,
+ const GtkSourceEncoding *encoding,
+ gint line_pos,
+ gint column_pos,
+ gboolean create,
+ GCancellable *cancellable,
+ GFileProgressCallback progress_callback,
+ gpointer progress_callback_data,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ TaskData *data;
+ GtkSourceFileLoader *loader;
+
+ g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
+ g_return_if_fail (location != NULL || stream != NULL);
+ g_return_if_fail (location == NULL || G_IS_FILE (location));
+ g_return_if_fail (stream == NULL || G_IS_INPUT_STREAM (stream));
+ g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (doc, cancellable, callback, user_data);
+ g_task_set_priority (task, G_PRIORITY_HIGH);
+
+ data = task_data_new ();
+ data->line_pos = line_pos;
+ data->column_pos = column_pos;
+ data->create = create != FALSE;
+
+ g_task_set_task_data (task, data, (GDestroyNotify)task_data_free);
+
+ if (location != NULL)
+ {
+ loader = gtk_source_file_loader_new (doc->priv->file, location);
+ }
+ else
+ {
+ loader = gtk_source_file_loader_new_from_stream (doc->priv->file, stream);
+ }
+
+ if (encoding != NULL)
+ {
+ GSList *list = g_slist_append (NULL, (gpointer)encoding);
+ gtk_source_file_loader_set_candidate_encodings (loader, list);
+ g_slist_free (list);
+ }
+ else
+ {
+ /* TODO */
+ }
+
+ gtk_source_file_loader_load_async (loader,
+ g_task_get_priority (task),
+ g_task_get_cancellable (task),
+ progress_callback,
+ progress_callback_data,
+ NULL,
+ (GAsyncReadyCallback)load_cb,
+ task);
+}
+
+gboolean
+_gedit_document_load_finish (GeditDocument *doc,
+ GAsyncResult *result,
+ GError **error)
+{
+ gboolean ok;
+
+ g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, doc), FALSE);
+
+ ok = g_task_propagate_boolean (G_TASK (result), error);
+
+ /* Emit signal only on success. Normally plugins don't need the error,
+ * it is already handled by GeditTab.
+ */
+ if (ok)
+ {
+ g_signal_emit (doc,
+ document_signals[LOADED],
+ 0,
+ NULL);
+ }
+
+ return ok;
+}
+
/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index be122c4..4fdbd76 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -304,6 +304,23 @@ gboolean _gedit_document_get_empty_search (GeditDocument *doc);
GtkSourceFile *gedit_document_get_file (GeditDocument *doc);
+void _gedit_document_load_async (GeditDocument *doc,
+ GFile *location,
+ GInputStream *stream,
+ const GtkSourceEncoding *encoding,
+ gint line_pos,
+ gint column_pos,
+ gboolean create,
+ GCancellable *cancellable,
+ GFileProgressCallback progress_callback,
+ gpointer
progress_callback_data,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean _gedit_document_load_finish (GeditDocument *doc,
+ GAsyncResult *result,
+ GError **error);
+
G_END_DECLS
#endif /* __GEDIT_DOCUMENT_H__ */
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index ba57a04..cdab4e3 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -58,9 +58,10 @@ struct _GeditTabPrivate
GFile *tmp_save_location;
/* tmp data for loading */
+ GCancellable *cancellable;
gint tmp_line_pos;
gint tmp_column_pos;
- const GtkSourceEncoding *tmp_encoding;
+ const GtkSourceEncoding *tmp_encoding; /* TODO remove */
GTimer *timer;
@@ -71,7 +72,6 @@ struct _GeditTabPrivate
gint not_editable : 1;
gint auto_save : 1;
-
gint ask_if_externally_modified : 1;
};
@@ -933,38 +933,6 @@ info_bar_set_progress (GeditTab *tab,
}
}
-static void
-document_loading (GeditDocument *document,
- goffset size,
- goffset total_size,
- GeditTab *tab)
-{
- gdouble et;
- gdouble total_time;
-
- g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_LOADING) ||
- (tab->priv->state == GEDIT_TAB_STATE_REVERTING));
-
- gedit_debug_message (DEBUG_TAB, "%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, size, total_size);
-
- if (tab->priv->timer == NULL)
- {
- tab->priv->timer = g_timer_new ();
- }
-
- et = g_timer_elapsed (tab->priv->timer, NULL);
-
- /* et : total_time = size : total_size */
- total_time = (et * total_size) / size;
-
- if ((total_time - et) > 3.0)
- {
- show_loading_info_bar (tab);
- }
-
- info_bar_set_progress (tab, size, total_size);
-}
-
static gboolean
remove_tab_idle (GeditTab *tab)
{
@@ -1712,10 +1680,6 @@ gedit_tab_init (GeditTab *tab)
G_CALLBACK (document_modified_changed),
tab);
g_signal_connect (doc,
- "loading",
- G_CALLBACK (document_loading),
- tab);
- g_signal_connect (doc,
"loaded",
G_CALLBACK (document_loaded),
tab);
@@ -2031,6 +1995,60 @@ gedit_tab_get_from_document (GeditDocument *doc)
return (res != NULL) ? GEDIT_TAB (res) : NULL;
}
+static void
+progress_cb (goffset current_num_bytes,
+ goffset total_num_bytes,
+ GeditTab *tab)
+{
+ gdouble elapsed_time;
+ gdouble total_time;
+ gdouble remaining_time;
+
+ g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_LOADING) ||
+ (tab->priv->state == GEDIT_TAB_STATE_REVERTING));
+
+ gedit_debug_message (DEBUG_TAB, "%" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT,
+ current_num_bytes,
+ total_num_bytes);
+
+ if (tab->priv->timer == NULL)
+ {
+ tab->priv->timer = g_timer_new ();
+ }
+
+ elapsed_time = g_timer_elapsed (tab->priv->timer, NULL);
+
+ /* elapsed_time / total_time = current_num_bytes / total_num_bytes */
+ total_time = (elapsed_time * total_num_bytes) / current_num_bytes;
+
+ 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, current_num_bytes, total_num_bytes);
+}
+
+static void
+load_cb (GeditDocument *doc,
+ GAsyncResult *result,
+ GeditTab *tab)
+{
+ GError *error = NULL;
+
+ _gedit_document_load_finish (doc, result, &error);
+
+ if (error != NULL)
+ {
+ }
+
+ /* Async operation finished. */
+ g_object_unref (tab);
+}
+
void
_gedit_tab_load (GeditTab *tab,
GFile *location,
@@ -2044,24 +2062,33 @@ _gedit_tab_load (GeditTab *tab,
g_return_if_fail (GEDIT_IS_TAB (tab));
g_return_if_fail (G_IS_FILE (location));
g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL);
-
- doc = gedit_view_frame_get_document (tab->priv->frame);
+ g_return_if_fail (tab->priv->cancellable == NULL);
gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
- tab->priv->tmp_line_pos = line_pos;
- tab->priv->tmp_column_pos = column_pos;
- tab->priv->tmp_encoding = encoding;
-
if (tab->priv->auto_save_timeout > 0)
+ {
remove_auto_save_timeout (tab);
+ }
- gedit_document_load (doc,
- location,
- encoding,
- line_pos,
- column_pos,
- create);
+ doc = gedit_view_frame_get_document (tab->priv->frame);
+ tab->priv->cancellable = g_cancellable_new ();
+
+ /* Keep tab alive during the async operation. */
+ g_object_ref (tab);
+
+ _gedit_document_load_async (doc,
+ location,
+ NULL,
+ encoding,
+ line_pos,
+ column_pos,
+ create,
+ tab->priv->cancellable,
+ (GFileProgressCallback)progress_cb,
+ tab,
+ (GAsyncReadyCallback)load_cb,
+ tab);
}
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]