Revision: 3495 http://geany.svn.sourceforge.net/geany/?rev=3495&view=rev Author: eht16 Date: 2009-01-21 15:50:48 +0000 (Wed, 21 Jan 2009)
Log Message: ----------- Use an unique "monitor" prefix for file monitoring functions. Don't check disk status for files which are marked to be ignored. Reset file disk status when manually reloading a file. Various improvements to the GIO-based file disk checking code.
Modified Paths: -------------- trunk/ChangeLog trunk/src/document.c trunk/src/documentprivate.h
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-01-21 15:50:12 UTC (rev 3494) +++ trunk/ChangeLog 2009-01-21 15:50:48 UTC (rev 3495) @@ -2,6 +2,10 @@
* src/document.c: Reuse the locale-encoded filename in document_save_file(). + Use an unique "monitor" prefix for file monitoring functions. + Don't check disk status for files which are marked to be ignored. + Reset file disk status when manually reloading a file. + Various improvements to the GIO-based file disk checking code.
2009-01-20 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
Modified: trunk/src/document.c =================================================================== --- trunk/src/document.c 2009-01-21 15:50:12 UTC (rev 3494) +++ trunk/src/document.c 2009-01-21 15:50:48 UTC (rev 3495) @@ -387,7 +387,31 @@
#ifdef HAVE_GIO -static void file_monitor_changed_cb(G_GNUC_UNUSED GFileMonitor *monitor, G_GNUC_UNUSED GFile *file, +/* Set the file status to 'changed' after a single 'created' event. */ +static gboolean monitor_finish_pending_create(gpointer doc) +{ + g_return_val_if_fail(doc != NULL, FALSE); + + ((GeanyDocument *)doc)->priv->file_disk_status = FILE_CHANGED; + ui_update_tab_status(doc); + + return FALSE; +} + + +/* Resets the 'ignore' file status after a reload action. */ +static gboolean monitor_reset_ignore(gpointer doc) +{ + g_return_val_if_fail(doc != NULL, FALSE); + + ((GeanyDocument *)doc)->priv->file_disk_status = FILE_OK; + ui_update_tab_status(doc); + + return FALSE; +} + + +static void monitor_file_changed_cb(G_GNUC_UNUSED GFileMonitor *monitor, G_GNUC_UNUSED GFile *file, G_GNUC_UNUSED GFile *other_file, GFileMonitorEvent event, GeanyDocument *doc) { if (file_prefs.disk_check_timeout == 0) @@ -395,11 +419,19 @@
switch (event) { - case G_FILE_MONITOR_EVENT_CHANGED: + case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: { + if (doc->priv->file_disk_status == FILE_CREATED_PENDING) + { + g_source_remove(doc->priv->last_check); + doc->priv->file_disk_status = FILE_IGNORE; + } if (doc->priv->file_disk_status == FILE_IGNORE) { /* ignore this change completely, used after saving a file */ + FileDiskStatus old_status = doc->priv->file_disk_status; doc->priv->file_disk_status = FILE_OK; + if (old_status != FILE_OK) + ui_update_tab_status(doc); return; } doc->priv->file_disk_status = FILE_CHANGED; @@ -407,19 +439,42 @@ } case G_FILE_MONITOR_EVENT_DELETED: { - doc->priv->file_disk_status = FILE_MISSING; + if (doc->priv->file_disk_status != FILE_IGNORE) + doc->priv->file_disk_status = FILE_MISSING; break; } + case G_FILE_MONITOR_EVENT_CREATED: + { + if (doc->priv->file_disk_status == FILE_MISSING) + { /* When the last state was 'missing', we are most probably in a + * delete-create-change set, so set the new state to 'ok' and do the real handling + * in the upcoming G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT event. */ + doc->priv->file_disk_status = FILE_OK; + } + else + { /* In case we have a single 'created' event and not within a set of other events, + * we defer the processing into a timeout function which is removed when a + * G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT event arrives before. */ + doc->priv->file_disk_status = FILE_CREATED_PENDING; + /* re-use otherwise unused 'last_check' field to store the timeout ID, we need it + * to remove the timeout and we need to store it per-document */ + doc->priv->last_check = g_timeout_add(2000, monitor_finish_pending_create, doc); + } + if (doc->real_path == NULL) + { + gchar *locale_filename = g_file_get_path(file); + doc->real_path = tm_get_real_path(locale_filename); + g_free(locale_filename); + } + break; + } /* ignore */ - case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: + case G_FILE_MONITOR_EVENT_CHANGED: case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: case G_FILE_MONITOR_EVENT_PRE_UNMOUNT: case G_FILE_MONITOR_EVENT_UNMOUNTED: - /* we ignore 'created' for now since it causes trouble when renaming files */ - case G_FILE_MONITOR_EVENT_CREATED: return; } - if (doc->priv->file_disk_status != FILE_OK) { ui_update_tab_status(doc); @@ -440,7 +495,7 @@ }
-static void file_monitor_setup(GeanyDocument *doc) +static void monitor_file_setup(GeanyDocument *doc) { g_return_if_fail(doc != NULL); /* Disable file monitoring completely for remote files (i.e. remote GIO files) as GFileMonitor @@ -460,7 +515,8 @@ /* get a file monitor and connect to the 'changed' signal */ file = g_file_new_for_path(locale_filename); doc->priv->monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, NULL); - g_signal_connect(doc->priv->monitor, "changed", G_CALLBACK(file_monitor_changed_cb), doc); + g_signal_connect(doc->priv->monitor, "changed", + G_CALLBACK(monitor_file_changed_cb), doc);
/* we set the rate limit according to the GUI pref but it's most probably not used */ g_file_monitor_set_rate_limit(doc->priv->monitor, file_prefs.disk_check_timeout * 1000); @@ -687,7 +743,7 @@ sci_set_line_numbers(doc->editor->sci, editor_prefs.show_linenumber_margin, 0); sci_goto_pos(doc->editor->sci, 0, TRUE);
- file_monitor_setup(doc); + monitor_file_setup(doc);
/* "the" SCI signal (connect after initial setup(i.e. adding text)) */ g_signal_connect(doc->editor->sci, "sci-notify", G_CALLBACK(editor_sci_notify_cb), doc->editor); @@ -1177,8 +1233,12 @@ doc = document_create(utf8_filename); g_return_val_if_fail(doc != NULL, NULL); /* really should not happen */
+ /* file exists on disk, set real_path */ + g_free(doc->real_path); + doc->real_path = tm_get_real_path(locale_filename); + doc->priv->is_remote = utils_is_remote_path(locale_filename); - file_monitor_setup(doc); + monitor_file_setup(doc); }
sci_set_undo_collection(doc->editor->sci, FALSE); /* avoid creation of an undo action */ @@ -1214,9 +1274,6 @@
if (! reload) { - /* file exists on disk, set real_path */ - g_free(doc->real_path); - doc->real_path = tm_get_real_path(locale_filename);
/* "the" SCI signal (connect after initial setup(i.e. adding text)) */ g_signal_connect(doc->editor->sci, "sci-notify", G_CALLBACK(editor_sci_notify_cb), @@ -1321,7 +1378,6 @@ } }
- /** * Reloads the @a document with the specified file encoding * @a forced_enc or @c NULL to auto-detect the file encoding. @@ -1343,6 +1399,15 @@ pos = sci_get_current_position(doc->editor->sci); new_doc = document_open_file_full(doc, NULL, pos, doc->readonly, doc->file_type, forced_enc); +#ifdef HAVE_GIO + if (new_doc != NULL) + { + doc->priv->file_disk_status = FILE_IGNORE; + /* In case the reload operation didn't produce any events to ignore, + * remove the ignore status. */ + g_timeout_add(5000, monitor_reset_ignore, doc); + } +#endif return (new_doc != NULL); }
@@ -1490,7 +1555,7 @@
/* file monitoring support, add file monitoring after the file has been saved * to ignore any earlier events */ - file_monitor_setup(doc); + monitor_file_setup(doc); doc->priv->file_disk_status = FILE_IGNORE;
if (ret) @@ -2724,7 +2789,7 @@ }
-static gboolean check_reload(GeanyDocument *doc) +static gboolean monitor_reload_file(GeanyDocument *doc) { gchar *base_name = g_path_get_basename(doc->file_name); gboolean want_reload; @@ -2742,7 +2807,7 @@ }
-static gboolean check_resave_missing_file(GeanyDocument *doc) +static gboolean monitor_resave_missing_file(GeanyDocument *doc) { gboolean want_reload = FALSE;
@@ -2762,7 +2827,7 @@ }
-static time_t check_disk_status_real(GeanyDocument *doc, gboolean force) +static time_t monitor_check_status_real(GeanyDocument *doc, gboolean force) { time_t t = 0; #ifndef HAVE_GIO @@ -2813,21 +2878,27 @@ if (doc->real_path == NULL || doc->priv->is_remote) return FALSE;
+ /* when we saved a file recently, we want to ignore any changes */ + if (doc->priv->file_disk_status == FILE_IGNORE) + { + return FALSE; + } + /* check the file's mtime in case we don't have GIO support, otherwise this is a no-op */ - t = check_disk_status_real(doc, force); + t = monitor_check_status_real(doc, force);
switch (doc->priv->file_disk_status) { case FILE_CHANGED: { - check_reload(doc); + monitor_reload_file(doc); doc->priv->mtime = t; ret = TRUE; break; } case FILE_MISSING: { - check_resave_missing_file(doc); + monitor_resave_missing_file(doc); ret = TRUE; break; }
Modified: trunk/src/documentprivate.h =================================================================== --- trunk/src/documentprivate.h 2009-01-21 15:50:12 UTC (rev 3494) +++ trunk/src/documentprivate.h 2009-01-21 15:50:48 UTC (rev 3495) @@ -42,6 +42,7 @@ FILE_OK, FILE_CHANGED, FILE_MISSING, + FILE_CREATED_PENDING, FILE_IGNORE } FileDiskStatus;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.