[gnome-builder/file-monitor: 1/2] GbEditorDocument: track read-only and file mtimes
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/file-monitor: 1/2] GbEditorDocument: track read-only and file mtimes
- Date: Fri, 12 Dec 2014 02:31:56 +0000 (UTC)
commit a689f2f8bb730f3e555799592eb6644e32a70611
Author: Christian Hergert <christian hergert me>
Date: Thu Dec 11 18:23:35 2014 -0800
GbEditorDocument: track read-only and file mtimes
This can be used to discover changes from the underlying file while
editing a document.
src/editor/gb-editor-document.c | 230 ++++++++++++++++++++++++++++++++++++++-
src/editor/gb-editor-document.h | 2 +
2 files changed, 231 insertions(+), 1 deletions(-)
---
diff --git a/src/editor/gb-editor-document.c b/src/editor/gb-editor-document.c
index 6059fde..c92e66c 100644
--- a/src/editor/gb-editor-document.c
+++ b/src/editor/gb-editor-document.c
@@ -36,9 +36,15 @@ struct _GbEditorDocumentPrivate
GbSourceChangeMonitor *change_monitor;
GbSourceCodeAssistant *code_assistant;
gchar *title;
+ GCancellable *cancellable;
gdouble progress;
guint doc_seq_id;
+ GTimeVal mtime;
+
+ guint file_changed_on_volume : 1;
+ guint mtime_set : 1;
+ guint read_only : 1;
guint trim_trailing_whitespace : 1;
};
@@ -46,8 +52,10 @@ enum {
PROP_0,
PROP_CHANGE_MONITOR,
PROP_FILE,
+ PROP_FILE_CHANGED_ON_VOLUME,
PROP_MODIFIED,
PROP_PROGRESS,
+ PROP_READ_ONLY,
PROP_STYLE_SCHEME_NAME,
PROP_TITLE,
PROP_TRIM_TRAILING_WHITESPACE,
@@ -80,6 +88,116 @@ gb_editor_document_new (void)
return g_object_new (GB_TYPE_EDITOR_DOCUMENT, NULL);
}
+gboolean
+gb_editor_document_get_read_only (GbEditorDocument *document)
+{
+ g_return_val_if_fail (GB_IS_EDITOR_DOCUMENT (document), FALSE);
+
+ return document->priv->read_only;
+}
+
+static void
+gb_editor_document_set_read_only (GbEditorDocument *document,
+ gboolean read_only)
+{
+ g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+
+ if (document->priv->read_only != read_only)
+ {
+ document->priv->read_only = read_only;
+ g_object_notify_by_pspec (G_OBJECT (document),
+ gParamSpecs [PROP_READ_ONLY]);
+ }
+}
+
+gboolean
+gb_editor_document_get_file_changed_on_volume (GbEditorDocument *document)
+{
+ g_return_val_if_fail (GB_IS_EDITOR_DOCUMENT (document), FALSE);
+
+ return document->priv->file_changed_on_volume;
+}
+
+static void
+gb_editor_document_set_file_changed_on_volume (GbEditorDocument *document,
+ gboolean file_changed_on_volume)
+{
+ g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+
+ if (file_changed_on_volume != document->priv->file_changed_on_volume)
+ {
+ document->priv->file_changed_on_volume = file_changed_on_volume;
+ g_object_notify_by_pspec (G_OBJECT (document),
+ gParamSpecs [PROP_FILE_CHANGED_ON_VOLUME]);
+ }
+}
+
+static void
+gb_editor_document_check_modified_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbEditorDocument *document = user_data;
+ GFileInfo *info;
+ GError *error = NULL;
+ GFile *file = (GFile *)object;
+
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+
+ info = g_file_query_info_finish (file, result, &error);
+
+ if (info)
+ {
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
+ {
+ gboolean read_only;
+
+ read_only = g_file_info_get_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+ gb_editor_document_set_read_only (document, read_only);
+ }
+
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED) &&
+ document->priv->mtime_set)
+ {
+ GTimeVal tv;
+
+ g_file_info_get_modification_time (info, &tv);
+
+ if (memcmp (&tv, &document->priv->mtime, sizeof tv) != 0)
+ gb_editor_document_set_file_changed_on_volume (document, TRUE);
+ }
+ }
+
+ g_clear_object (&document);
+ g_clear_object (&info);
+}
+
+void
+gb_editor_document_check_externally_modified (GbEditorDocument *document)
+{
+ GFile *location;
+
+ g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+
+ if (document->priv->file_changed_on_volume)
+ return;
+
+ location = gtk_source_file_get_location (document->priv->file);
+ if (!location)
+ return;
+
+ g_file_query_info_async (location,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED ","
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ document->priv->cancellable,
+ gb_editor_document_check_modified_cb,
+ g_object_ref (document));
+}
+
gdouble
gb_editor_document_get_progress (GbEditorDocument *document)
{
@@ -552,6 +670,47 @@ gb_editor_document_progress_cb (goffset current_num_bytes,
}
static void
+gb_editor_document_load_info_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbEditorDocument *document = user_data;
+ GFileInfo *info;
+ GError *error = NULL;
+ GFile *file = (GFile *)object;
+
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+
+ info = g_file_query_info_finish (file, result, &error);
+
+ if (info)
+ {
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
+ {
+ gboolean read_only;
+
+ read_only = g_file_info_get_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+ gb_editor_document_set_read_only (document, read_only);
+ }
+
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
+ {
+ GTimeVal tv;
+
+ g_file_info_get_modification_time (info, &tv);
+
+ document->priv->mtime = tv;
+ document->priv->mtime_set = TRUE;
+ }
+ }
+
+ g_clear_object (&document);
+ g_clear_object (&info);
+}
+
+static void
gb_editor_document_save_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
@@ -561,6 +720,7 @@ gb_editor_document_save_cb (GObject *object,
GbEditorDocument *document;
GError *error = NULL;
GTask *task = user_data;
+ GFile *location;
ENTRY;
@@ -574,6 +734,8 @@ gb_editor_document_save_cb (GObject *object,
GOTO (cleanup);
}
+ document = g_task_get_source_object (task);
+
/*
* FIXME:
*
@@ -581,9 +743,18 @@ gb_editor_document_save_cb (GObject *object,
* for the buffer during the process or keep a sequence number to
* ensure it hasn't changed since we started the request to save.
*/
- document = g_task_get_source_object (task);
gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (document), FALSE);
+ location = gtk_source_file_saver_get_location (saver);
+ g_file_query_info_async (location,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ document->priv->cancellable,
+ gb_editor_document_load_info_cb,
+ g_object_ref (document));
+
change_monitor = gb_editor_document_get_change_monitor (document);
gb_source_change_monitor_reload (change_monitor);
@@ -644,6 +815,8 @@ gb_editor_document_save_async (GbEditorDocument *document,
gb_editor_document_set_progress (document, 0.0);
+ document->priv->mtime_set = FALSE;
+
gtk_source_file_saver_save_async (saver,
G_PRIORITY_DEFAULT,
cancellable,
@@ -788,6 +961,7 @@ gb_editor_document_load_cb (GObject *object,
{
GtkSourceFileLoader *loader = (GtkSourceFileLoader *)object;
GbEditorDocument *document;
+ GFile *location;
GError *error = NULL;
GTask *task = user_data;
@@ -805,6 +979,19 @@ gb_editor_document_load_cb (GObject *object,
document = g_task_get_source_object (task);
+ document->priv->mtime_set = FALSE;
+ document->priv->file_changed_on_volume = FALSE;
+
+ location = gtk_source_file_loader_get_location (loader);
+ g_file_query_info_async (location,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ document->priv->cancellable,
+ gb_editor_document_load_info_cb,
+ g_object_ref (document));
+
gb_editor_document_restore_insert (document);
gb_editor_document_guess_language (document);
@@ -924,6 +1111,17 @@ gb_editor_document_constructed (GObject *object)
}
static void
+gb_editor_document_dispose (GObject *object)
+{
+ GbEditorDocument *document = (GbEditorDocument *)object;
+
+ if (!g_cancellable_is_cancelled (document->priv->cancellable))
+ g_cancellable_cancel (document->priv->cancellable);
+
+ G_OBJECT_CLASS (gb_editor_document_parent_class)->dispose (object);
+}
+
+static void
gb_editor_document_finalize (GObject *object)
{
GbEditorDocumentPrivate *priv = GB_EDITOR_DOCUMENT (object)->priv;
@@ -933,6 +1131,7 @@ gb_editor_document_finalize (GObject *object)
g_clear_object (&priv->file);
g_clear_object (&priv->change_monitor);
g_clear_object (&priv->code_assistant);
+ g_clear_object (&priv->cancellable);
g_clear_pointer (&priv->title, g_free);
G_OBJECT_CLASS(gb_editor_document_parent_class)->finalize (object);
@@ -963,6 +1162,15 @@ gb_editor_document_get_property (GObject *object,
g_value_set_object (value, gb_editor_document_get_file (self));
break;
+ case PROP_FILE_CHANGED_ON_VOLUME:
+ g_value_set_boolean (value,
+ gb_editor_document_get_file_changed_on_volume (self));
+ break;
+
+ case PROP_READ_ONLY:
+ g_value_set_boolean (value, gb_editor_document_get_read_only (self));
+ break;
+
case PROP_PROGRESS:
g_value_set_double (value, gb_editor_document_get_progress (self));
break;
@@ -1015,6 +1223,7 @@ gb_editor_document_class_init (GbEditorDocumentClass *klass)
GtkTextBufferClass *text_buffer_class = GTK_TEXT_BUFFER_CLASS (klass);
object_class->constructed = gb_editor_document_constructed;
+ object_class->dispose = gb_editor_document_dispose;
object_class->finalize = gb_editor_document_finalize;
object_class->get_property = gb_editor_document_get_property;
object_class->set_property = gb_editor_document_set_property;
@@ -1044,6 +1253,15 @@ gb_editor_document_class_init (GbEditorDocumentClass *klass)
g_object_class_install_property (object_class, PROP_FILE,
gParamSpecs [PROP_FILE]);
+ gParamSpecs [PROP_FILE_CHANGED_ON_VOLUME] =
+ g_param_spec_boolean ("file-changed-on-volume",
+ _("File Changed on Volume"),
+ _("If the file has changed underneath the buffer."),
+ FALSE,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_FILE_CHANGED_ON_VOLUME,
+ gParamSpecs [PROP_FILE_CHANGED_ON_VOLUME]);
+
gParamSpecs [PROP_PROGRESS] =
g_param_spec_double ("progress",
_("Progress"),
@@ -1055,6 +1273,15 @@ gb_editor_document_class_init (GbEditorDocumentClass *klass)
g_object_class_install_property (object_class, PROP_PROGRESS,
gParamSpecs [PROP_PROGRESS]);
+ gParamSpecs [PROP_READ_ONLY] =
+ g_param_spec_boolean ("read-only",
+ _("Read Only"),
+ _("If the buffer is read only."),
+ FALSE,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_READ_ONLY,
+ gParamSpecs [PROP_READ_ONLY]);
+
gParamSpecs [PROP_STYLE_SCHEME_NAME] =
g_param_spec_string ("style-scheme-name",
_("Style Scheme Name"),
@@ -1101,6 +1328,7 @@ gb_editor_document_init (GbEditorDocument *document)
{
document->priv = gb_editor_document_get_instance_private (document);
+ document->priv->cancellable = g_cancellable_new ();
document->priv->trim_trailing_whitespace = TRUE;
document->priv->file = gtk_source_file_new ();
document->priv->change_monitor = gb_source_change_monitor_new (GTK_TEXT_BUFFER (document));
diff --git a/src/editor/gb-editor-document.h b/src/editor/gb-editor-document.h
index d132c16..fff8155 100644
--- a/src/editor/gb-editor-document.h
+++ b/src/editor/gb-editor-document.h
@@ -63,6 +63,8 @@ void gb_editor_document_set_file (GbEditor
gdouble gb_editor_document_get_progress (GbEditorDocument *document);
GbSourceChangeMonitor *gb_editor_document_get_change_monitor (GbEditorDocument *document);
GbSourceCodeAssistant *gb_editor_document_get_code_assistant (GbEditorDocument *document);
+gboolean gb_editor_document_get_read_only (GbEditorDocument *document);
+gboolean gb_editor_document_get_file_changed_on_volume (GbEditorDocument *document);
gboolean gb_editor_document_get_trim_trailing_whitespace (GbEditorDocument *document);
void gb_editor_document_set_trim_trailing_whitespace (GbEditorDocument *document,
gboolean
trim_trailing_whitespace);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]