diff --git a/configure.ac b/configure.ac index fe8d570..90d461b 100644 --- a/configure.ac +++ b/configure.ac @@ -149,8 +149,8 @@ PKG_CHECK_MODULES(XED, [ $GMODULE_ADD gthread-2.0 >= 2.13.0 gio-2.0 >= 2.40.0 - gtk+-3.0 >= 3.18.0 - gtksourceview-3.0 >= 3.18.0 + gtk+-3.0 >= 3.19.3 + gtksourceview-3.0 >= 3.19.0 libpeas-1.0 >= 1.12.0 libpeas-gtk-1.0 >= 1.12.0 ]) diff --git a/xed/Makefile.am b/xed/Makefile.am index bbaec9c..763df73 100644 --- a/xed/Makefile.am +++ b/xed/Makefile.am @@ -40,10 +40,12 @@ NOINST_H_FILES = \ xed-close-button.h \ xed-close-confirmation-dialog.h \ xed-dirs.h \ + xed-document-private.h \ xed-documents-panel.h \ xed-encodings-dialog.h \ xed-history-entry.h \ xed-io-error-info-bar.h \ + xed-metadata-manager.h \ xed-paned.h \ xed-plugins-engine.h \ xed-preferences-dialog.h \ @@ -80,10 +82,6 @@ INST_H_FILES = \ xed-window.h \ xed-window-activatable.h -if !ENABLE_GVFS_METADATA -NOINST_H_FILES += xed-metadata-manager.h -endif - headerdir = $(prefix)/include/xed header_DATA = \ @@ -119,6 +117,7 @@ libxed_c_files = \ xed-message-bus.c \ xed-message-type.c \ xed-message.c \ + xed-metadata-manager.c \ xed-notebook.c \ xed-paned.c \ xed-panel.c \ @@ -146,10 +145,6 @@ libxed_la_SOURCES = \ $(NOINST_H_FILES) \ $(INST_H_FILES) -if !ENABLE_GVFS_METADATA -libxed_la_SOURCES += xed-metadata-manager.c -endif - xed-enum-types.h: xed-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS) $(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template xed-enum-types.h.template $(INST_H_FILES)) > $@ diff --git a/xed/xed-close-confirmation-dialog.c b/xed/xed-close-confirmation-dialog.c index e667ad5..b72f16e 100755 --- a/xed/xed-close-confirmation-dialog.c +++ b/xed/xed-close-confirmation-dialog.c @@ -32,10 +32,13 @@ #include #endif +#include "xed-close-confirmation-dialog.h" + #include -#include "xed-close-confirmation-dialog.h" #include +#include +#include #include #include diff --git a/xed/xed-commands-file.c b/xed/xed-commands-file.c index 2323cab..098dcb4 100644 --- a/xed/xed-commands-file.c +++ b/xed/xed-commands-file.c @@ -38,31 +38,27 @@ #include #include +#include "xed-debug.h" +#include "xed-document.h" +#include "xed-document-private.h" #include "xed-commands.h" #include "xed-window.h" #include "xed-window-private.h" #include "xed-statusbar.h" -#include "xed-debug.h" #include "xed-utils.h" #include "xed-file-chooser-dialog.h" #include "xed-close-confirmation-dialog.h" /* Defined constants */ #define XED_OPEN_DIALOG_KEY "xed-open-dialog-key" -#define XED_TAB_TO_SAVE_AS "xed-tab-to-save-as" -#define XED_LIST_OF_TABS_TO_SAVE_AS "xed-list-of-tabs-to-save-as" #define XED_IS_CLOSING_ALL "xed-is-closing-all" #define XED_IS_QUITTING "xed-is-quitting" -#define XED_IS_CLOSING_TAB "xed-is-closing-tab" #define XED_IS_QUITTING_ALL "xed-is-quitting-all" static void tab_state_changed_while_saving (XedTab *tab, GParamSpec *pspec, XedWindow *window); -static void save_as_tab (XedTab *tab, - XedWindow *window); - void _xed_cmd_file_new (GtkAction *action, XedWindow *window) @@ -521,110 +517,73 @@ replace_read_only_file (GtkWindow *parent, } static void -save_finish_cb (XedTab *tab, - GAsyncResult *result, - gpointer user_data) +tab_save_as_ready_cb (XedTab *tab, + GAsyncResult *result, + GTask *task) { - _xed_tab_save_finish (tab, result); + gboolean success = _xed_tab_save_finish (tab, result); + g_task_return_boolean (task, success); + g_object_unref (task); } static void save_dialog_response_cb (XedFileChooserDialog *dialog, gint response_id, - XedWindow *window) + GTask *task) { XedTab *tab; - gpointer data; - GSList *tabs_to_save_as; + XedWindow *window; + XedDocument *doc; + GtkSourceFile *file; + GFile *location; + gchar *parse_name; + GtkSourceNewlineType newline_type; + const GtkSourceEncoding *encoding; xed_debug (DEBUG_COMMANDS); - tab = XED_TAB (g_object_get_data (G_OBJECT (dialog), XED_TAB_TO_SAVE_AS)); + tab = g_task_get_source_object (task); + window = g_task_get_task_data (task); if (response_id != GTK_RESPONSE_OK) { gtk_widget_destroy (GTK_WIDGET (dialog)); - goto save_next_tab; - } - - if (tab != NULL) - { - GFile *location; - XedDocument *doc; - gchar *parse_name; - GtkSourceNewlineType newline_type; - const GtkSourceEncoding *encoding; - - doc = xed_tab_get_document (tab); - - location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); - g_return_if_fail (location != NULL); - - encoding = xed_file_chooser_dialog_get_encoding (dialog); - newline_type = xed_file_chooser_dialog_get_newline_type (dialog); - - gtk_widget_destroy (GTK_WIDGET (dialog)); - - doc = xed_tab_get_document (tab); - g_return_if_fail (XED_IS_DOCUMENT (doc)); - - parse_name = g_file_get_parse_name (location); - - xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar), - window->priv->generic_message_cid, - _("Saving file '%s'\342\200\246"), - parse_name); - - g_free (parse_name); - - /* let's remember the dir we navigated too, - * even if the saving fails... */ - _xed_window_set_default_location (window, location); - - _xed_tab_save_as_async (tab, - location, - encoding, - newline_type, - NULL, - (GAsyncReadyCallback) save_finish_cb, - NULL); - - g_object_unref (location); - } - -save_next_tab: - - data = g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS); - if (data == NULL) - { + g_task_return_boolean (task, FALSE); + g_object_unref (task); return; } - /* Save As the next tab of the list (we are Saving All files) */ - tabs_to_save_as = (GSList *)data; - g_return_if_fail (tab == XED_TAB (tabs_to_save_as->data)); + doc = xed_tab_get_document (tab); + location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); + g_return_if_fail (location != NULL); - /* Remove the first item of the list */ - tabs_to_save_as = g_slist_delete_link (tabs_to_save_as, tabs_to_save_as); + encoding = xed_file_chooser_dialog_get_encoding (dialog); + newline_type = xed_file_chooser_dialog_get_newline_type (dialog); - g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as); + gtk_widget_destroy (GTK_WIDGET (dialog)); - if (tabs_to_save_as != NULL) - { - tab = XED_TAB (tabs_to_save_as->data); + parse_name = g_file_get_parse_name (location); - if (GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (tab), XED_IS_CLOSING_TAB)) == TRUE) - { - g_object_set_data (G_OBJECT (tab), XED_IS_CLOSING_TAB, NULL); + xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar), + window->priv->generic_message_cid, + _("Saving file '%s'\342\200\246"), + parse_name); - /* Trace tab state changes */ - g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window); - } + g_free (parse_name); - xed_window_set_active_tab (window, tab); - save_as_tab (tab, window); - } + /* let's remember the dir we navigated too, even if the saving fails... */ + _xed_window_set_default_location (window, location); + + _xed_tab_save_as_async (tab, + location, + encoding, + newline_type, + g_task_get_cancellable (task), + (GAsyncReadyCallback) tab_save_as_ready_cb, + task); + + g_object_unref (location); } static GtkFileChooserConfirmation @@ -663,16 +622,20 @@ confirm_overwrite_callback (GtkFileChooser *dialog, return res; } +/* Call save_as_tab_finish() in @callback. */ static void -save_as_tab (XedTab *tab, - XedWindow *window) +save_as_tab_async (XedTab *tab, + XedWindow *window, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { + GTask *task; GtkWidget *save_dialog; GtkWindowGroup *wg; XedDocument *doc; GtkSourceFile *file; GFile *location; - gboolean uri_set = FALSE; const GtkSourceEncoding *encoding; GtkSourceNewlineType newline_type; @@ -681,6 +644,9 @@ save_as_tab (XedTab *tab, xed_debug (DEBUG_COMMANDS); + task = g_task_new (tab, cancellable, callback, user_data); + g_task_set_task_data (task, g_object_ref (window), g_object_unref); + save_dialog = xed_file_chooser_dialog_new (_("Save As\342\200\246"), GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_SAVE, @@ -706,11 +672,11 @@ save_as_tab (XedTab *tab, if (location != NULL) { - uri_set = gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog), location, NULL); + gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog), location, NULL); } - if (!uri_set) + else { GFile *default_path; gchar *docname; @@ -734,7 +700,7 @@ save_as_tab (XedTab *tab, g_free (docname); } - /* Set suggested encoding */ + /* Set suggested encoding and newline type */ encoding = gtk_source_file_get_encoding (file); if (encoding == NULL) @@ -748,39 +714,94 @@ save_as_tab (XedTab *tab, xed_file_chooser_dialog_set_newline_type (XED_FILE_CHOOSER_DIALOG (save_dialog), newline_type); - g_object_set_data (G_OBJECT (save_dialog), XED_TAB_TO_SAVE_AS, tab); - - g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), window); + g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), task); gtk_widget_show (save_dialog); } -static void -save_tab (XedTab *tab, - XedWindow *window) +static gboolean +save_as_tab_finish (XedTab *tab, + GAsyncResult *result) { - XedDocument *doc; + g_return_val_if_fail (g_task_is_valid (result, tab), FALSE); + + return g_task_propagate_boolean (G_TASK (result), NULL); +} + +static void +save_as_tab_ready_cb (XedTab *tab, + GAsyncResult *result, + GTask *task) +{ + gboolean success = save_as_tab_finish (tab, result); + + g_task_return_boolean (task, success); + g_object_unref (task); +} + +static void +tab_save_ready_cb (XedTab *tab, + GAsyncResult *result, + GTask *task) +{ + gboolean success = _xed_tab_save_finish (tab, result); + + g_task_return_boolean (task, success); + g_object_unref (task); +} + +/** + * xed_commands_save_document_async: + * @document: the #XedDocument to save. + * @window: a #XedWindow. + * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. + * @callback: (scope async): a #GAsyncReadyCallback to call when the operation + * is finished. + * @user_data: (closure): the data to pass to the @callback function. + * + * Asynchronously save the @document. @document must belong to @window. The + * source object of the async task is @document (which will be the first + * parameter of the #GAsyncReadyCallback). + * + * When the operation is finished, @callback will be called. You can then call + * xed_commands_save_document_finish() to get the result of the operation. + */ +void +xed_commands_save_document_async (XedDocument *document, + XedWindow *window, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + XedTab *tab; gchar *uri_for_display; xed_debug (DEBUG_COMMANDS); - g_return_if_fail (XED_IS_TAB (tab)); + g_return_if_fail (XED_IS_DOCUMENT (document)); g_return_if_fail (XED_IS_WINDOW (window)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); - doc = xed_tab_get_document (tab); - g_return_if_fail (XED_IS_DOCUMENT (doc)); + task = g_task_new (document, cancellable, callback, user_data); - if (xed_document_is_untitled (doc) || - xed_document_get_readonly (doc)) + tab = xed_tab_get_from_document (document); + + if (xed_document_is_untitled (document) || + xed_document_get_readonly (document)) { xed_debug_message (DEBUG_COMMANDS, "Untitled or Readonly"); - save_as_tab (tab, window); + save_as_tab_async (tab, + window, + cancellable, + (GAsyncReadyCallback) save_as_tab_ready_cb, + task); return; } - uri_for_display = xed_document_get_uri_for_display (doc); + uri_for_display = xed_document_get_uri_for_display (document); xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar), window->priv->generic_message_cid, _("Saving file '%s'\342\200\246"), @@ -789,9 +810,53 @@ save_tab (XedTab *tab, g_free (uri_for_display); _xed_tab_save_async (tab, - NULL, - (GAsyncReadyCallback) save_finish_cb, - NULL); + cancellable, + (GAsyncReadyCallback) tab_save_ready_cb, + task); +} + +/** + * xed_commands_save_document_finish: + * @document: a #XedDocument. + * @result: a #GAsyncResult. + * + * Finishes an asynchronous document saving operation started with + * xed_commands_save_document_async(). + * + * Note that there is no error parameter because the errors are already handled + * by xed. + * + * Returns: %TRUE if the document has been correctly saved, %FALSE otherwise. + */ +gboolean +xed_commands_save_document_finish (XedDocument *document, + GAsyncResult *result) +{ + g_return_val_if_fail (g_task_is_valid (result, document), FALSE); + + return g_task_propagate_boolean (G_TASK (result), NULL); +} + +static void +save_tab_ready_cb (XedDocument *doc, + GAsyncResult *result, + gpointer user_data) +{ + xed_commands_save_document_finish (doc, result); +} + +/* Save tab asynchronously, but without results. */ +static void +save_tab (XedTab *tab, + XedWindow *window) +{ + XedDocument *doc = xed_tab_get_document (tab); + + xed_commands_save_document_async (doc, + window, + NULL, + (GAsyncReadyCallback) save_tab_ready_cb, + NULL); } void @@ -803,12 +868,18 @@ _xed_cmd_file_save (GtkAction *action, xed_debug (DEBUG_COMMANDS); tab = xed_window_get_active_tab (window); - if (tab == NULL) + if (tab != NULL) { - return; + save_tab (tab, window); } +} - save_tab (tab, window); +static void +_xed_cmd_file_save_as_cb (XedTab *tab, + GAsyncResult *result, + gpointer user_data) +{ + save_as_tab_finish (tab, result); } void @@ -820,12 +891,149 @@ _xed_cmd_file_save_as (GtkAction *action, xed_debug (DEBUG_COMMANDS); tab = xed_window_get_active_tab (window); - if (tab == NULL) + if (tab != NULL) + { + save_as_tab_async (tab, + window, + NULL, + (GAsyncReadyCallback) _xed_cmd_file_save_as_cb, + NULL); + } +} + +static void +quit_if_needed (XedWindow *window) +{ + gboolean is_quitting; + gboolean is_quitting_all; + + is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING)); + + is_quitting_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING_ALL)); + + if (is_quitting) + { + gtk_widget_destroy (GTK_WIDGET (window)); + } + + if (is_quitting_all) + { + GtkApplication *app; + + app = GTK_APPLICATION (g_application_get_default ()); + + if (gtk_application_get_windows (app) == NULL) + { + g_application_quit (G_APPLICATION (app)); + } + } +} + +static gboolean +really_close_tab (XedTab *tab) +{ + GtkWidget *toplevel; + XedWindow *window; + + xed_debug (DEBUG_COMMANDS); + + g_return_val_if_fail (xed_tab_get_state (tab) == XED_TAB_STATE_CLOSING, FALSE); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab)); + g_return_val_if_fail (XED_IS_WINDOW (toplevel), FALSE); + + window = XED_WINDOW (toplevel); + + xed_window_close_tab (window, tab); + + if (xed_window_get_active_tab (window) == NULL) + { + quit_if_needed (window); + } + + return FALSE; +} + +static void +close_tab (XedTab *tab) +{ + XedDocument *doc; + + doc = xed_tab_get_document (tab); + g_return_if_fail (doc != NULL); + + /* If the user has modified again the document, do not close the tab. */ + if (_xed_document_needs_saving (doc)) { return; } - save_as_tab (tab, window); + /* Close the document only if it has been succesfully saved. + * Tab state is set to CLOSING (it is a state without exiting + * transitions) and the tab is closed in an idle handler. + */ + _xed_tab_mark_for_closing (tab); + + g_idle_add_full (G_PRIORITY_HIGH_IDLE, + (GSourceFunc) really_close_tab, + tab, + NULL); +} + +typedef struct _SaveAsData SaveAsData; + +struct _SaveAsData +{ + /* Reffed */ + XedWindow *window; + + /* List of reffed GeditTab's */ + GSList *tabs_to_save_as; + + guint close_tabs : 1; +}; + +static void save_as_documents_list (SaveAsData *data); + +static void +save_as_documents_list_cb (XedTab *tab, + GAsyncResult *result, + SaveAsData *data) +{ + gboolean saved = save_as_tab_finish (tab, result); + + if (saved && data->close_tabs) + { + close_tab (tab); + } + + g_return_if_fail (tab == XED_TAB (data->tabs_to_save_as->data)); + g_object_unref (data->tabs_to_save_as->data); + data->tabs_to_save_as = g_slist_delete_link (data->tabs_to_save_as, data->tabs_to_save_as); + + if (data->tabs_to_save_as != NULL) + { + save_as_documents_list (data); + } + else + { + g_object_unref (data->window); + g_slice_free (SaveAsData, data); + } +} + +static void +save_as_documents_list (SaveAsData *data) +{ + XedTab *next_tab = XED_TAB (data->tabs_to_save_as->data); + + xed_window_set_active_tab (data->window, next_tab); + + save_as_tab_async (next_tab, + data->window, + NULL, + (GAsyncReadyCallback) save_as_documents_list_cb, + data); } /* @@ -835,8 +1043,8 @@ static void save_documents_list (XedWindow *window, GList *docs) { + SaveAsData *data = NULL; GList *l; - GSList *tabs_to_save_as = NULL; xed_debug (DEBUG_COMMANDS); @@ -868,9 +1076,17 @@ save_documents_list (XedWindow *window, if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc)) { if (_xed_document_needs_saving (doc)) + { + if (data == NULL) { - tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t); + data = g_slice_new (SaveAsData); + data->window = g_object_ref (window); + data->tabs_to_save_as = NULL; + data->close_tabs = FALSE; } + + data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as, g_object_ref (t)); + } } else { @@ -913,23 +1129,21 @@ save_documents_list (XedWindow *window, l = g_list_next (l); } - if (tabs_to_save_as != NULL) + if (data != NULL) { - XedTab *tab; - - tabs_to_save_as = g_slist_reverse (tabs_to_save_as ); - - g_return_if_fail (g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS) == NULL); - - g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as); - - tab = XED_TAB (tabs_to_save_as->data); - - xed_window_set_active_tab (window, tab); - save_as_tab (tab, window); + data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as); + save_as_documents_list (data); } } +/** + * xed_commands_save_all_documents: + * @window: a #XedWindow. + * + * Asynchronously save all documents belonging to @window. The result of the + * operation is not available, so it's difficult to know whether all the + * documents are correctly saved. + */ void xed_commands_save_all_documents (XedWindow *window) { @@ -953,6 +1167,14 @@ _xed_cmd_file_save_all (GtkAction *action, xed_commands_save_all_documents (window); } +/** + * xed_commands_save_document: + * @window: a #XedWindow. + * @document: the #XedDocument to save. + * + * Asynchronously save @document. @document must belong to @window. If you need + * the result of the operation, use xed_commands_save_document_async(). + */ void xed_commands_save_document (XedWindow *window, XedDocument *document) @@ -1161,39 +1383,6 @@ _xed_cmd_file_revert (GtkAction *action, gtk_widget_show (dialog); } -/* Close tab */ -static gboolean -really_close_tab (XedTab *tab) -{ - GtkWidget *toplevel; - XedWindow *window; - - xed_debug (DEBUG_COMMANDS); - - g_return_val_if_fail (xed_tab_get_state (tab) == XED_TAB_STATE_CLOSING, FALSE); - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab)); - g_return_val_if_fail (XED_IS_WINDOW (toplevel), FALSE); - - window = XED_WINDOW (toplevel); - - xed_window_close_tab (window, tab); - - if (xed_window_get_active_tab (window) == NULL) - { - gboolean is_quitting; - - is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING)); - - if (is_quitting) - { - gtk_widget_destroy (GTK_WIDGET (window)); - } - } - - return FALSE; -} - static void tab_state_changed_while_saving (XedTab *tab, GParamSpec *pspec, @@ -1209,26 +1398,9 @@ tab_state_changed_while_saving (XedTab *tab, finished */ if (ts == XED_TAB_STATE_NORMAL) { - XedDocument *doc; - g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (tab_state_changed_while_saving), window); - doc = xed_tab_get_document (tab); - g_return_if_fail (doc != NULL); - - /* If the saving operation failed or was interrupted, then the - document is still "modified" -> do not close the tab */ - if (_xed_document_needs_saving (doc)) - { - return; - } - - /* Close the document only if it has been succesfully saved. - Tab state is set to CLOSING (it is a state without exiting - transitions) and the tab is closed in a idle handler */ - _xed_tab_mark_for_closing (tab); - - g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc)really_close_tab, tab, NULL); + close_tab (tab); } } @@ -1244,21 +1416,6 @@ save_and_close (XedTab *tab, save_tab (tab, window); } -static void -save_as_and_close (XedTab *tab, - XedWindow *window) -{ - xed_debug (DEBUG_COMMANDS); - - g_object_set_data (G_OBJECT (tab), XED_IS_CLOSING_TAB, NULL); - - /* Trace tab state changes */ - g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window); - - xed_window_set_active_tab (window, tab); - save_as_tab (tab, window); -} - static void save_and_close_all_documents (const GList *docs, XedWindow *window) @@ -1266,9 +1423,9 @@ save_and_close_all_documents (const GList *docs, GList *tabs; GList *l; GSList *sl; - GSList *tabs_to_save_as; - GSList *tabs_to_save_and_close; - GList *tabs_to_close; + SaveAsData *data = NULL; + GSList *tabs_to_save_and_close = NULL; + GList *tabs_to_close = NULL; xed_debug (DEBUG_COMMANDS); @@ -1276,19 +1433,13 @@ save_and_close_all_documents (const GList *docs, tabs = gtk_container_get_children (GTK_CONTAINER (_xed_window_get_notebook (window))); - tabs_to_save_as = NULL; - tabs_to_save_and_close = NULL; - tabs_to_close = NULL; - l = tabs; while (l != NULL) { - XedTab *t; + XedTab *t = XED_TAB (l->data);; XedTabState state; XedDocument *doc; - t = XED_TAB (l->data); - state = xed_tab_get_state (t); doc = xed_tab_get_document (t); @@ -1337,9 +1488,15 @@ save_and_close_all_documents (const GList *docs, user is running xed - Paolo (Dec. 8, 2005) */ if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc)) { - g_object_set_data (G_OBJECT (t), XED_IS_CLOSING_TAB, GBOOLEAN_TO_POINTER (TRUE)); + if (data == NULL) + { + data = g_slice_new (SaveAsData); + data->window = g_object_ref (window); + data->tabs_to_save_as = NULL; + data->close_tabs = TRUE; + } - tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t); + data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as, g_object_ref (t)); } else { @@ -1371,20 +1528,11 @@ save_and_close_all_documents (const GList *docs, } g_slist_free (tabs_to_save_and_close); - /* Save As and close all the files in tabs_to_save_as */ - if (tabs_to_save_as != NULL) + /* Save As and close all the files in data->tabs_to_save_as. */ + if (data != NULL) { - XedTab *tab; - - tabs_to_save_as = g_slist_reverse (tabs_to_save_as ); - - g_return_if_fail (g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS) == NULL); - - g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as); - - tab = XED_TAB (tabs_to_save_as->data); - - save_as_and_close (tab, window); + data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as); + save_as_documents_list (data); } } diff --git a/xed/xed-commands.h b/xed/xed-commands.h index 1ff5ae9..679bc1e 100644 --- a/xed/xed-commands.h +++ b/xed/xed-commands.h @@ -12,6 +12,8 @@ void xed_commands_load_location (XedWindow *window, GFile *location, const GtkSo /* Ignore non-existing URIs */ GSList *xed_commands_load_locations (XedWindow *window, const GSList *locations, const GtkSourceEncoding *encoding, gint line_pos); void xed_commands_save_document (XedWindow *window, XedDocument *document); +void xed_commands_save_document_async (XedDocument *document, XedWindow *window, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); +gboolean xed_commands_save_document_finish (XedDocument *document, GAsyncResult *result); void xed_commands_save_all_documents (XedWindow *window); /* diff --git a/xed/xed-document-private.h b/xed/xed-document-private.h new file mode 100644 index 0000000..9693eb9 --- /dev/null +++ b/xed/xed-document-private.h @@ -0,0 +1,21 @@ +#ifndef __XED_DOCUMENT_PRIVATE_H__ +#define __XED_DOCUMENT_PRIVATE_H__ + +#include "xed-document.h" + +G_BEGIN_DECLS + +glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc); + +gboolean _xed_document_needs_saving (XedDocument *doc); + +gboolean _xed_document_get_empty_search (XedDocument *doc); + +void _xed_document_set_create (XedDocument *doc, + gboolean create); + +gboolean _xed_document_get_create (XedDocument *doc); + +G_END_DECLS + +#endif /* __XED_DOCUMENT_PRIVATE_H__ */ diff --git a/xed/xed-document.c b/xed/xed-document.c index 44f27f3..470e831 100644 --- a/xed/xed-document.c +++ b/xed/xed-document.c @@ -41,26 +41,20 @@ #include #include "xed-document.h" +#include "xed-document-private.h" #include "xed-settings.h" #include "xed-debug.h" #include "xed-utils.h" -#include "xed-marshal.h" -#include "xed-enum-types.h" - -#ifndef ENABLE_GVFS_METADATA #include "xed-metadata-manager.h" -#else + #define METADATA_QUERY "metadata::*" -#endif #define NO_LANGUAGE_NAME "_NORMAL_" -#define XED_DOCUMENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XED_TYPE_DOCUMENT, XedDocumentPrivate)) - static void xed_document_loaded_real (XedDocument *doc); static void xed_document_saved_real (XedDocument *doc); -struct _XedDocumentPrivate +typedef struct { GtkSourceFile *file; @@ -73,24 +67,22 @@ struct _XedDocumentPrivate gchar *content_type; - GTimeVal mtime; GTimeVal time_of_last_save_or_load; GtkSourceSearchContext *search_context; - guint readonly : 1; - guint externally_modified : 1; - guint deleted : 1; + guint user_action; + guint last_save_was_manually : 1; guint language_set_by_user : 1; guint stop_cursor_moved_emission : 1; - guint mtime_set : 1; + guint use_gvfs_metadata : 1; /* Create file if location points to a non existing file (for example * when opened from the command line). */ guint create : 1; -}; +} XedDocumentPrivate; enum { @@ -98,9 +90,13 @@ enum PROP_SHORTNAME, PROP_CONTENT_TYPE, PROP_MIME_TYPE, - PROP_READ_ONLY + PROP_READ_ONLY, + PROP_USE_GVFS_METADATA, + LAST_PROP }; +static GParamSpec *properties[LAST_PROP]; + enum { CURSOR_MOVED, @@ -111,11 +107,11 @@ enum LAST_SIGNAL }; -static guint document_signals[LAST_SIGNAL] = { 0 }; +static guint document_signals[LAST_SIGNAL]; static GHashTable *allocated_untitled_numbers = NULL; -G_DEFINE_TYPE(XedDocument, xed_document, GTK_SOURCE_TYPE_BUFFER) +G_DEFINE_TYPE_WITH_PRIVATE (XedDocument, xed_document, GTK_SOURCE_TYPE_BUFFER) static gint get_untitled_number (void) @@ -161,11 +157,13 @@ get_language_string (XedDocument *doc) static void save_metadata (XedDocument *doc) { + XedDocumentPrivate *priv; const gchar *language = NULL; GtkTextIter iter; gchar *position; - if (doc->priv->language_set_by_user) + priv = xed_document_get_instance_private (doc); + if (priv->language_set_by_user) { language = get_language_string (doc); } @@ -196,24 +194,26 @@ save_metadata (XedDocument *doc) static void xed_document_dispose (GObject *object) { - XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; xed_debug (DEBUG_DOCUMENT); + priv = xed_document_get_instance_private (XED_DOCUMENT (object)); + /* Metadata must be saved here and not in finalize because the language * is gone by the time finalize runs. */ - if (doc->priv->file != NULL) + if (priv->file != NULL) { - save_metadata (doc); + save_metadata (XED_DOCUMENT (object)); - g_object_unref (doc->priv->file); - doc->priv->file = NULL; + g_object_unref (priv->file); + priv->file = NULL; } - g_clear_object (&doc->priv->editor_settings); - g_clear_object (&doc->priv->metadata_info); - g_clear_object (&doc->priv->search_context); + g_clear_object (&priv->editor_settings); + g_clear_object (&priv->metadata_info); + g_clear_object (&priv->search_context); G_OBJECT_CLASS (xed_document_parent_class)->dispose (object); } @@ -221,17 +221,19 @@ xed_document_dispose (GObject *object) static void xed_document_finalize (GObject *object) { - XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; xed_debug (DEBUG_DOCUMENT); - if (doc->priv->untitled_number > 0) + priv = xed_document_get_instance_private (XED_DOCUMENT (object)); + + if (priv->untitled_number > 0) { - release_untitled_number (doc->priv->untitled_number); + release_untitled_number (priv->untitled_number); } - g_free (doc->priv->content_type); - g_free (doc->priv->short_name); + g_free (priv->content_type); + g_free (priv->short_name); G_OBJECT_CLASS (xed_document_parent_class)->finalize (object); } @@ -243,6 +245,9 @@ xed_document_get_property (GObject *object, GParamSpec *pspec) { XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); switch (prop_id) { @@ -256,7 +261,10 @@ xed_document_get_property (GObject *object, g_value_take_string (value, xed_document_get_mime_type (doc)); break; case PROP_READ_ONLY: - g_value_set_boolean (value, doc->priv->readonly); + g_value_set_boolean (value, gtk_source_file_is_readonly (priv->file)); + break; + case PROP_USE_GVFS_METADATA: + g_value_set_boolean (value, priv->use_gvfs_metadata); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -271,6 +279,9 @@ xed_document_set_property (GObject *object, GParamSpec *pspec) { XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); switch (prop_id) { @@ -280,16 +291,53 @@ xed_document_set_property (GObject *object, case PROP_CONTENT_TYPE: xed_document_set_content_type (doc, g_value_get_string (value)); break; + case PROP_USE_GVFS_METADATA: + priv->use_gvfs_metadata = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +static void +xed_document_begin_user_action (GtkTextBuffer *buffer) +{ + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (XED_DOCUMENT (buffer)); + + ++priv->user_action; + + if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->begin_user_action != NULL) + { + GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->begin_user_action (buffer); + } +} + +static void +xed_document_end_user_action (GtkTextBuffer *buffer) +{ + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (XED_DOCUMENT (buffer)); + + --priv->user_action; + + if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->end_user_action != NULL) + { + GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->end_user_action (buffer); + } +} + static void emit_cursor_moved (XedDocument *doc) { - if (!doc->priv->stop_cursor_moved_emission) + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); + + if (!priv->stop_cursor_moved_emission) { g_signal_emit (doc, document_signals[CURSOR_MOVED], 0); } @@ -301,13 +349,16 @@ xed_document_mark_set (GtkTextBuffer *buffer, GtkTextMark *mark) { XedDocument *doc = XED_DOCUMENT (buffer); + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); if (GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->mark_set != NULL) { GTK_TEXT_BUFFER_CLASS (xed_document_parent_class)->mark_set (buffer, iter, mark); } - if (mark == gtk_text_buffer_get_insert (buffer)) + if (mark == gtk_text_buffer_get_insert (buffer) && (priv->user_action == 0)) { emit_cursor_moved (doc); } @@ -325,8 +376,11 @@ static void xed_document_constructed (GObject *object) { XedDocument *doc = XED_DOCUMENT (object); + XedDocumentPrivate *priv; - g_settings_bind (doc->priv->editor_settings, + priv = xed_document_get_instance_private (doc); + + g_settings_bind (priv->editor_settings, XED_SETTINGS_ENSURE_TRAILING_NEWLINE, doc, "implicit-trailing-newline", @@ -347,43 +401,77 @@ xed_document_class_init (XedDocumentClass *klass) object_class->set_property = xed_document_set_property; object_class->constructed = xed_document_constructed; + buf_class->begin_user_action = xed_document_begin_user_action; + buf_class->end_user_action = xed_document_end_user_action; buf_class->mark_set = xed_document_mark_set; buf_class->changed = xed_document_changed; klass->loaded = xed_document_loaded_real; klass->saved = xed_document_saved_real; - g_object_class_install_property (object_class, PROP_SHORTNAME, - g_param_spec_string ("shortname", - "Short Name", - "The document's short name", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + /** + * XedDocument:shortname: + * + * The documents short name. + */ + properties[PROP_SHORTNAME] = + g_param_spec_string ("shortname", + "Short Name", + "The documents short name", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_CONTENT_TYPE, - g_param_spec_string ("content-type", - "Content Type", - "The document's Content Type", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + /** + * XedDocument:content-type: + * + * The documents content type. + */ + properties[PROP_CONTENT_TYPE] = + g_param_spec_string ("content-type", + "Content Type", + "The documents content type", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_MIME_TYPE, - g_param_spec_string ("mime-type", - "MIME Type", - "The document's MIME Type", - "text/plain", - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + /** + * XedDocument:mime-type: + * + * The documents MIME type. + */ + properties[PROP_MIME_TYPE] = + g_param_spec_string ("mime-type", + "MIME Type", + "The documents MIME type", + "text/plain", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_READ_ONLY, - g_param_spec_boolean ("read-only", - "Read Only", - "Whether the document is read only or not", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + properties[PROP_READ_ONLY] = + g_param_spec_boolean ("read-only", + "Read Only", + "Whether the document is read-only or not", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * XedDocument:use-gvfs-metadata: + * + * Whether to use GVFS metadata. If %FALSE, use the xed metadata + * manager that stores the metadata in an XML file in the user cache + * directory. + * + * + * The property is used internally by xed. It must not be used in a + * xed plugin. The property can be modified or removed at any time. + * + */ + properties[PROP_USE_GVFS_METADATA] = + g_param_spec_boolean ("use-gvfs-metadata", + "Use GVFS metadata", + "", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, LAST_PROP, properties); /* This signal is used to update the cursor position is the statusbar, * it's emitted either when the insert mark is moved explicitely or @@ -396,8 +484,7 @@ xed_document_class_init (XedDocumentClass *klass) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (XedDocumentClass, cursor_moved), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -424,7 +511,7 @@ xed_document_class_init (XedDocumentClass *klass) document_signals[LOADED] = g_signal_new ("loaded", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (XedDocumentClass, loaded), NULL, NULL, NULL, G_TYPE_NONE, 0); @@ -452,12 +539,10 @@ xed_document_class_init (XedDocumentClass *klass) document_signals[SAVED] = g_signal_new ("saved", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (XedDocumentClass, saved), NULL, NULL, NULL, G_TYPE_NONE, 0); - - g_type_class_add_private (object_class, sizeof (XedDocumentPrivate)); } static void @@ -465,10 +550,13 @@ set_language (XedDocument *doc, GtkSourceLanguage *lang, gboolean set_by_user) { + XedDocumentPrivate *priv; GtkSourceLanguage *old_lang; xed_debug (DEBUG_DOCUMENT); + priv = xed_document_get_instance_private (doc); + old_lang = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (doc)); if (old_lang == lang) @@ -478,19 +566,6 @@ set_language (XedDocument *doc, gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (doc), lang); - if (lang != NULL) - { - gboolean syntax_hl; - - syntax_hl = g_settings_get_boolean (doc->priv->editor_settings, - XED_SETTINGS_SYNTAX_HIGHLIGHTING); - gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (doc), syntax_hl); - } - else - { - gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (doc), FALSE); - } - if (set_by_user) { const gchar *language = get_language_string (doc); @@ -498,18 +573,21 @@ set_language (XedDocument *doc, xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE, language, NULL); } - doc->priv->language_set_by_user = set_by_user; + priv->language_set_by_user = set_by_user; } static void save_encoding_metadata (XedDocument *doc) { + XedDocumentPrivate *priv; const GtkSourceEncoding *encoding; const gchar *charset; xed_debug (DEBUG_DOCUMENT); - encoding = gtk_source_file_get_encoding (doc->priv->file); + priv = xed_document_get_instance_private (doc); + + encoding = gtk_source_file_get_encoding (priv->file); if (encoding == NULL) { @@ -551,10 +629,13 @@ get_default_style_scheme (GSettings *editor_settings) static GtkSourceLanguage * guess_language (XedDocument *doc) { + XedDocumentPrivate *priv; gchar *data; GtkSourceLanguageManager *manager = gtk_source_language_manager_get_default (); GtkSourceLanguage *language = NULL; + priv = xed_document_get_instance_private (doc); + data = xed_document_get_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE); if (data != NULL) @@ -573,19 +654,19 @@ guess_language (XedDocument *doc) GFile *location; gchar *basename = NULL; - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); xed_debug_message (DEBUG_DOCUMENT, "Sniffing Language"); if (location != NULL) { basename = g_file_get_basename (location); } - else if (doc->priv->short_name != NULL) + else if (priv->short_name != NULL) { - basename = g_strdup (doc->priv->short_name); + basename = g_strdup (priv->short_name); } - language = gtk_source_language_manager_guess_language (manager, basename, doc->priv->content_type); + language = gtk_source_language_manager_guess_language (manager, basename, priv->content_type); g_free (basename); } @@ -598,7 +679,11 @@ on_content_type_changed (XedDocument *doc, GParamSpec *pspec, gpointer useless) { - if (!doc->priv->language_set_by_user) + XedDocumentPrivate *priv; + + priv = xed_document_get_instance_private (doc); + + if (!priv->language_set_by_user) { GtkSourceLanguage *language = guess_language (doc); @@ -620,61 +705,74 @@ on_location_changed (GtkSourceFile *file, GParamSpec *pspec, XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; xed_debug (DEBUG_DOCUMENT); + priv = xed_document_get_instance_private (doc); + location = gtk_source_file_get_location (file); - if (location != NULL && doc->priv->untitled_number > 0) + if (location != NULL && priv->untitled_number > 0) { - release_untitled_number (doc->priv->untitled_number); - doc->priv->untitled_number = 0; + release_untitled_number (priv->untitled_number); + priv->untitled_number = 0; } - if (doc->priv->short_name == NULL) + if (priv->short_name == NULL) { - g_object_notify (G_OBJECT (doc), "shortname"); + g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_SHORTNAME]); } -#ifdef ENABLE_GVFS_METADATA - - /* load metadata for this location: we load sync since metadata is - * always local so it should be fast and we need the information - * right after the location was set. - */ - if (location != NULL) + /* Load metadata for this location: we load sync since metadata is + * always local so it should be fast and we need the information + * right after the location was set. + */ + if (priv->use_gvfs_metadata && location != NULL) { GError *error = NULL; - if (doc->priv->metadata_info != NULL) + if (priv->metadata_info != NULL) { - g_object_unref (doc->priv->metadata_info); + g_object_unref (priv->metadata_info); } - doc->priv->metadata_info = g_file_query_info (location, - METADATA_QUERY, - G_FILE_QUERY_INFO_NONE, - NULL, - &error); + priv->metadata_info = g_file_query_info (location, + METADATA_QUERY, + G_FILE_QUERY_INFO_NONE, + NULL, + &error); if (error != NULL) { - /* TODO document why the warning is not displayed in - * certain cases. + /* Do not complain about metadata if we are opening a + * non existing file. */ - if (error->domain != G_FILE_ERROR || - (error->code != G_FILE_ERROR_ISDIR && - error->code != G_FILE_ERROR_NOTDIR && - error->code != G_FILE_ERROR_NOENT)) + if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_ISDIR) && + !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR) && + !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_warning ("%s", error->message); } g_error_free (error); } + + if (priv->metadata_info == NULL) + { + priv->metadata_info = g_file_info_new (); + } } -#endif +} + +static void +on_readonly_changed (GtkSourceFile *file, + GParamSpec *pspec, + XedDocument *doc) +{ + g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_READ_ONLY]); } static void @@ -685,40 +783,43 @@ xed_document_init (XedDocument *doc) xed_debug (DEBUG_DOCUMENT); - doc->priv = XED_DOCUMENT_GET_PRIVATE (doc); - priv = doc->priv; + priv = xed_document_get_instance_private (doc); priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor"); - priv->untitled_number = get_untitled_number (); - priv->content_type = get_default_content_type (); - - priv->readonly = FALSE; - priv->stop_cursor_moved_emission = FALSE; - priv->last_save_was_manually = TRUE; priv->language_set_by_user = FALSE; - g_get_current_time (&doc->priv->time_of_last_save_or_load); + g_get_current_time (&priv->time_of_last_save_or_load); priv->file = gtk_source_file_new (); + priv->metadata_info = g_file_info_new (); g_signal_connect_object (priv->file, "notify::location", G_CALLBACK (on_location_changed), doc, 0); + g_signal_connect_object (priv->file, "notify::read-only", + G_CALLBACK (on_readonly_changed), doc, 0); + + g_settings_bind (priv->editor_settings, + XED_SETTINGS_SYNTAX_HIGHLIGHTING, + doc, + "highlight-syntax", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); + g_settings_bind (priv->editor_settings, XED_SETTINGS_MAX_UNDO_ACTIONS, doc, "max-undo-levels", - G_SETTINGS_BIND_GET); + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); g_settings_bind (priv->editor_settings, XED_SETTINGS_BRACKET_MATCHING, doc, "highlight-matching-brackets", - G_SETTINGS_BIND_GET); + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); style_scheme = get_default_style_scheme (priv->editor_settings); if (style_scheme != NULL) @@ -732,34 +833,46 @@ xed_document_init (XedDocument *doc) XedDocument * xed_document_new (void) { - return g_object_new (XED_TYPE_DOCUMENT, NULL); + gboolean use_gvfs_metadata; + +#ifdef ENABLE_GVFS_METADATA + use_gvfs_metadata = TRUE; +#else + use_gvfs_metadata = FALSE; +#endif + + return g_object_new (XED_TYPE_DOCUMENT, + "use-gvfs-metadata", use_gvfs_metadata, + NULL); } static void set_content_type_no_guess (XedDocument *doc, const gchar *content_type) { + XedDocumentPrivate *priv; xed_debug (DEBUG_DOCUMENT); - if (doc->priv->content_type != NULL && - content_type != NULL && - g_str_equal (doc->priv->content_type, content_type)) + priv = xed_document_get_instance_private (doc); + + if (priv->content_type != NULL && content_type != NULL && + g_str_equal (priv->content_type, content_type)) { return; } - g_free (doc->priv->content_type); + g_free (priv->content_type); if (content_type == NULL || g_content_type_is_unknown (content_type)) { - doc->priv->content_type = get_default_content_type (); + priv->content_type = get_default_content_type (); } else { - doc->priv->content_type = g_strdup (content_type); + priv->content_type = g_strdup (content_type); } - g_object_notify (G_OBJECT (doc), "content-type"); + g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_CONTENT_TYPE]); } /** @@ -771,17 +884,21 @@ void xed_document_set_content_type (XedDocument *doc, const gchar *content_type) { + XedDocumentPrivate *priv; + g_return_if_fail (XED_IS_DOCUMENT (doc)); xed_debug (DEBUG_DOCUMENT); + priv = xed_document_get_instance_private (doc); + if (content_type == NULL) { GFile *location; gchar *guessed_type = NULL; /* If content type is null, we guess from the filename */ - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); if (location != NULL) { gchar *basename; @@ -810,11 +927,14 @@ xed_document_set_content_type (XedDocument *doc, GFile * xed_document_get_location (XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; + priv = xed_document_get_instance_private (doc); + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); return location != NULL ? g_object_ref (location) : NULL; } @@ -823,10 +943,12 @@ void xed_document_set_location (XedDocument *doc, GFile *location) { + XedDocumentPrivate *priv; + g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (G_IS_FILE (location)); - gtk_source_file_set_location (doc->priv->file, location); + gtk_source_file_set_location (priv->file, location); xed_document_set_content_type (doc, NULL); } @@ -839,15 +961,18 @@ xed_document_set_location (XedDocument *doc, gchar * xed_document_get_uri_for_display (XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup ("")); - location = gtk_source_file_get_location (doc->priv->file); + priv = xed_document_get_instance_private (doc); + + location = gtk_source_file_get_location (priv->file); if (location == NULL) { - return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number); + return g_strdup_printf (_("Unsaved Document %d"), priv->untitled_number); } else { @@ -864,19 +989,22 @@ xed_document_get_uri_for_display (XedDocument *doc) gchar * xed_document_get_short_name_for_display (XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup ("")); - location = gtk_source_file_get_location (doc->priv->file); + priv = xed_document_get_instance_private (doc); - if (doc->priv->short_name != NULL) + location = gtk_source_file_get_location (priv->file); + + if (priv->short_name != NULL) { - return g_strdup (doc->priv->short_name); + return g_strdup (priv->short_name); } else if (location == NULL) { - return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number); + return g_strdup_printf (_("Unsaved Document %d"), priv->untitled_number); } else { @@ -893,20 +1021,28 @@ void xed_document_set_short_name_for_display (XedDocument *doc, const gchar *short_name) { + XedDocumentPrivate *priv; + g_return_if_fail (XED_IS_DOCUMENT (doc)); - g_free (doc->priv->short_name); - doc->priv->short_name = g_strdup (short_name); + priv = xed_document_get_instance_private (doc); - g_object_notify (G_OBJECT (doc), "shortname"); + g_free (priv->short_name); + priv->short_name = g_strdup (short_name); + + g_object_notify_by_pspec (G_OBJECT (doc), properties[PROP_SHORTNAME]); } gchar * xed_document_get_content_type (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - return g_strdup (doc->priv->content_type); + priv = xed_document_get_instance_private (doc); + + return g_strdup (priv->content_type); } /** @@ -918,40 +1054,31 @@ xed_document_get_content_type (XedDocument *doc) gchar * xed_document_get_mime_type (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup ("text/plain")); - if (doc->priv->content_type != NULL && - !g_content_type_is_unknown (doc->priv->content_type)) + priv = xed_document_get_instance_private (doc); + + if (priv->content_type != NULL && + !g_content_type_is_unknown (priv->content_type)) { - return g_content_type_get_mime_type (doc->priv->content_type); + return g_content_type_get_mime_type (priv->content_type); } return g_strdup ("text/plain"); } -static void -set_readonly (XedDocument *doc, - gboolean readonly) -{ - xed_debug (DEBUG_DOCUMENT); - - g_return_if_fail (XED_IS_DOCUMENT (doc)); - - readonly = readonly != FALSE; - - if (doc->priv->readonly != readonly) - { - doc->priv->readonly = readonly; - g_object_notify (G_OBJECT (doc), "read-only"); - } -} - gboolean xed_document_get_readonly (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE); - return doc->priv->readonly; + priv = xed_document_get_instance_private (doc); + + return gtk_source_file_is_readonly (priv->file); } static void @@ -978,33 +1105,17 @@ loaded_query_info_cb (GFile *location, error = NULL; } - if (info != NULL) + if (info != NULL && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) { - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) - { - const gchar *content_type; + const gchar *content_type; - content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); - xed_document_set_content_type (doc, 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)) - { - gboolean read_only; - - read_only = !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE); - set_readonly (doc, read_only); - } - - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED)) - { - g_file_info_get_modification_time (info, &doc->priv->mtime); - doc->priv->mtime_set = TRUE; - } - - g_object_unref (info); + xed_document_set_content_type (doc, content_type); } + g_clear_object (&info); + /* Async operation finished. */ g_object_unref (doc); } @@ -1012,9 +1123,12 @@ loaded_query_info_cb (GFile *location, static void xed_document_loaded_real (XedDocument *doc) { - GFile *location; + XedDocumentPrivate *priv; + GFile *location; - if (!doc->priv->language_set_by_user) + priv = xed_document_get_instance_private (doc); + + if (!priv->language_set_by_user) { GtkSourceLanguage *language = guess_language (doc); @@ -1024,17 +1138,11 @@ xed_document_loaded_real (XedDocument *doc) set_language (doc, language, FALSE); } - doc->priv->mtime_set = FALSE; - doc->priv->externally_modified = FALSE; - doc->priv->deleted = FALSE; - - g_get_current_time (&doc->priv->time_of_last_save_or_load); - - set_readonly (doc, FALSE); + g_get_current_time (&priv->time_of_last_save_or_load); xed_document_set_content_type (doc, NULL); - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); if (location != NULL) { @@ -1043,8 +1151,7 @@ xed_document_loaded_real (XedDocument *doc) g_file_query_info_async (location, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," - G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," - G_FILE_ATTRIBUTE_TIME_MODIFIED, + G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, NULL, @@ -1058,10 +1165,13 @@ saved_query_info_cb (GFile *location, GAsyncResult *result, XedDocument *doc) { + XedDocumentPrivate *priv; GFileInfo *info; const gchar *content_type = NULL; GError *error = NULL; + priv = xed_document_get_instance_private (doc); + info = g_file_query_info_finish (location, result, &error); if (error != NULL) @@ -1071,20 +1181,9 @@ saved_query_info_cb (GFile *location, error = NULL; } - doc->priv->mtime_set = FALSE; - - if (info != NULL) + if (info != NULL && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) { - 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_TIME_MODIFIED)) - { - g_file_info_get_modification_time (info, &doc->priv->mtime); - doc->priv->mtime_set = TRUE; - } + content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); } xed_document_set_content_type (doc, content_type); @@ -1094,15 +1193,9 @@ saved_query_info_cb (GFile *location, g_object_unref (info); } - g_get_current_time (&doc->priv->time_of_last_save_or_load); + g_get_current_time (&priv->time_of_last_save_or_load); - doc->priv->externally_modified = FALSE; - doc->priv->deleted = FALSE; - doc->priv->create = FALSE; - - set_readonly (doc, FALSE); - - gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), FALSE); + priv->create = FALSE; save_encoding_metadata (doc); @@ -1113,14 +1206,18 @@ saved_query_info_cb (GFile *location, static void xed_document_saved_real (XedDocument *doc) { - GFile *location = gtk_source_file_get_location (doc->priv->file); + XedDocumentPrivate *priv; + GFile *location; + + priv = xed_document_get_instance_private (doc); + + location = gtk_source_file_get_location (priv->file); /* Keep the doc alive during the async operation. */ g_object_ref (doc); g_file_query_info_async (location, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," - G_FILE_ATTRIBUTE_TIME_MODIFIED, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, NULL, @@ -1131,11 +1228,14 @@ xed_document_saved_real (XedDocument *doc) gboolean xed_document_is_untouched (XedDocument *doc) { + XedDocumentPrivate *priv; GFile *location; + priv = xed_document_get_instance_private (doc); + g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE); - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); return location == NULL && !gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)); } @@ -1143,107 +1243,37 @@ xed_document_is_untouched (XedDocument *doc) gboolean xed_document_is_untitled (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE); - return gtk_source_file_get_location (doc->priv->file) == NULL; + priv = xed_document_get_instance_private (doc); + + return gtk_source_file_get_location (priv->file) == NULL; } gboolean xed_document_is_local (XedDocument *doc) { - GFile *location; + XedDocumentPrivate *priv; g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); - location = gtk_source_file_get_location (doc->priv->file); + priv = xed_document_get_instance_private (doc); - if (location == NULL) - { - return FALSE; - } - - return g_file_has_uri_scheme (location, "file"); -} - -static void -check_file_on_disk (XedDocument *doc) -{ - GFile *location; - GFileInfo *info; - - location = gtk_source_file_get_location (doc->priv->file); - - if (location == NULL) - { - return; - } - - info = g_file_query_info (location, - G_FILE_ATTRIBUTE_TIME_MODIFIED "," \ - G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, - G_FILE_QUERY_INFO_NONE, - NULL, NULL); - - if (info != NULL) - { - /* While at it also check if permissions changed */ - 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); - - set_readonly (doc, read_only); - } - - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED) && doc->priv->mtime_set) - { - GTimeVal timeval; - - g_file_info_get_modification_time (info, &timeval); - - /* Note that mtime can even go backwards if the - * user is copying over a file with an old mtime - */ - if (timeval.tv_sec != doc->priv->mtime.tv_sec || - timeval.tv_usec != doc->priv->mtime.tv_usec) - { - doc->priv->externally_modified = TRUE; - } - } - - g_object_unref (info); - } - else - { - doc->priv->deleted = TRUE; - } -} - -gboolean -_xed_document_check_externally_modified (XedDocument *doc) -{ - g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); - - if (!doc->priv->externally_modified) - { - check_file_on_disk (doc); - } - - return doc->priv->externally_modified; + return gtk_source_file_is_local (priv->file); } gboolean xed_document_get_deleted (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); - if (!doc->priv->deleted) - { - check_file_on_disk (doc); - } + priv = xed_document_get_instance_private (doc); - return doc->priv->deleted; + return gtk_source_file_is_deleted (priv->file); } /* @@ -1252,29 +1282,27 @@ xed_document_get_deleted (XedDocument *doc) gboolean _xed_document_needs_saving (XedDocument *doc) { + XedDocumentPrivate *priv; + gboolean externally_modified = FALSE; + gboolean deleted = FALSE; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); + priv = xed_document_get_instance_private (doc); + if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc))) { return TRUE; } - if (doc->priv->externally_modified || doc->priv->deleted) + if (gtk_source_file_is_local (priv->file)) { - return TRUE; + gtk_source_file_check_file_on_disk (priv->file); + externally_modified = gtk_source_file_is_externally_modified (priv->file); + deleted = gtk_source_file_is_deleted (priv->file); } - if (xed_document_is_local (doc)) - { - check_file_on_disk (doc); - - if (doc->priv->externally_modified || doc->priv->deleted) - { - return TRUE; - } - } - - return FALSE; + return (externally_modified || deleted) && !priv->create; } /* @@ -1285,8 +1313,6 @@ gboolean xed_document_goto_line (XedDocument *doc, gint line) { - gboolean ret = TRUE; - guint line_count; GtkTextIter iter; xed_debug (DEBUG_DOCUMENT); @@ -1294,21 +1320,11 @@ xed_document_goto_line (XedDocument *doc, g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); g_return_val_if_fail (line >= -1, FALSE); - line_count = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (doc)); - - if (line >= line_count) - { - ret = FALSE; - gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); - } - else - { - gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, line); - } + gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, line); gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter); - return ret; + return gtk_text_iter_get_line (&iter) == line; } gboolean @@ -1316,29 +1332,17 @@ xed_document_goto_line_offset (XedDocument *doc, gint line, gint line_offset) { - gboolean ret = TRUE; - guint offset_count; GtkTextIter iter; g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); g_return_val_if_fail (line >= -1, FALSE); g_return_val_if_fail (line_offset >= -1, FALSE); - gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (doc), &iter, line); - - offset_count = gtk_text_iter_get_chars_in_line (&iter); - if (line_offset > offset_count) - { - ret = FALSE; - } - else - { - gtk_text_iter_set_line_offset (&iter, line_offset); - } + gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER (doc), &iter, line, line_offset); gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter); - return ret; + return (gtk_text_iter_get_line (&iter) == line && gtk_text_iter_get_line_offset (&iter) == line_offset); } /** @@ -1372,44 +1376,54 @@ xed_document_get_language (XedDocument *doc) const GtkSourceEncoding * xed_document_get_encoding (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - return gtk_source_file_get_encoding (doc->priv->file); + xed_document_get_instance_private (doc); + + return gtk_source_file_get_encoding (priv->file); } glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc) { + XedDocumentPrivate *priv; GTimeVal current_time; xed_debug (DEBUG_DOCUMENT); g_return_val_if_fail (XED_IS_DOCUMENT (doc), -1); + priv = xed_document_get_instance_private (doc); + g_get_current_time (¤t_time); - return (current_time.tv_sec - doc->priv->time_of_last_save_or_load.tv_sec); + return (current_time.tv_sec - priv->time_of_last_save_or_load.tv_sec); } GtkSourceNewlineType xed_document_get_newline_type (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), 0); - return gtk_source_file_get_newline_type (doc->priv->file); + priv = xed_document_get_instance_private (doc); + + return gtk_source_file_get_newline_type (priv->file); } -#ifndef ENABLE_GVFS_METADATA -gchar * -xed_document_get_metadata (XedDocument *doc, - const gchar *key) +static gchar * +get_metadata_from_metadata_manager (XedDocument *doc, + const gchar *key) { + XedDocumentPrivate *priv; GFile *location; - g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - g_return_val_if_fail (key != NULL, NULL); + priv = xed_document_get_instance_private (doc); - location = gtk_source_file_get_location (doc->priv->file); + location = gtk_source_file_get_location (priv->file); if (location != NULL) { @@ -1419,40 +1433,41 @@ xed_document_get_metadata (XedDocument *doc, return NULL; } -void -xed_document_set_metadata (XedDocument *doc, - const gchar *first_key, - ...) +static gchar * +get_metadata_from_gvfs (XedDocument *doc, + const gchar *key) { - GFile *location; - const gchar *key; - const gchar *value; - va_list var_args; + XedDocumentPrivate *priv; - g_return_if_fail (XED_IS_DOCUMENT (doc)); - g_return_if_fail (first_key != NULL); + priv = xed_document_get_instance_private (doc); - location = gtk_source_file_get_location (doc->priv->file); - - if (location == NULL) + if (priv->metadata_info != NULL && + g_file_info_has_attribute (priv->metadata_info, key) && + g_file_info_get_attribute_type (priv->metadata_info, key) == G_FILE_ATTRIBUTE_TYPE_STRING) { - /* Can't set metadata for untitled documents */ - return; + return g_strdup (g_file_info_get_attribute_string (priv->metadata_info, key)); } - va_start (var_args, first_key); - - for (key = first_key; key; key = va_arg (var_args, const gchar *)) - { - value = va_arg (var_args, const gchar *); - - xed_metadata_manager_set (location, key, value); - } - - va_end (var_args); + return NULL; } -#else +static void +set_gvfs_metadata (GFileInfo *info, + const gchar *key, + const gchar *value) +{ + g_return_if_fail (G_IS_FILE_INFO (info)); + + if (value != NULL) + { + g_file_info_set_attribute_string (info, key, value); + } + else + { + /* Unset the key */ + g_file_info_set_attribute (info, key, G_FILE_ATTRIBUTE_TYPE_INVALID, NULL); + } +} /** * xed_document_get_metadata: @@ -1467,15 +1482,19 @@ gchar * xed_document_get_metadata (XedDocument *doc, const gchar *key) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); g_return_val_if_fail (key != NULL, NULL); - if (doc->priv->metadata_info && g_file_info_has_attribute (doc->priv->metadata_info, key)) + priv = xed_document_get_instance_private (doc); + + if (priv->use_gvfs_metadata) { - return g_strdup (g_file_info_get_attribute_string (doc->priv->metadata_info, key)); + return get_metadata_from_gvfs (doc, key); } - return NULL; + return get_metadata_from_metadata_manager (doc, key); } static void @@ -1507,44 +1526,57 @@ xed_document_set_metadata (XedDocument *doc, const gchar *first_key, ...) { - const gchar *key; - const gchar *value; - va_list var_args; - GFileInfo *info; + XedDocumentPrivate *priv; GFile *location; + const gchar *key; + va_list var_args; + GFileInfo *info = NULL; g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (first_key != NULL); - info = g_file_info_new (); + priv = xed_document_get_instance_private (doc); + + location = gtk_source_file_get_location (priv->file); + + /* With the metadata manager, can't set metadata for untitled documents. + * With GVFS metadata, if the location is NULL the metadata is stored in + * priv->metadata_info, so that it can be saved later if the document is + * saved. + */ + + if (!priv->use_gvfs_metadata && location == NULL) + { + return; + } + + if (priv->use_gvfs_metadata) + { + info = g_file_info_new (); + } va_start (var_args, first_key); for (key = first_key; key; key = va_arg (var_args, const gchar *)) { - value = va_arg (var_args, const gchar *); + const gchar *value = va_arg (var_args, const gchar *); - if (value != NULL) + if (priv->use_gvfs_metadata) { - g_file_info_set_attribute_string (info, key, value); + /* Collect the metadata into @info. */ + set_gvfs_metadata (info, key, value); + set_gvfs_metadata (priv->metadata_info, key, value); } else { /* Unset the key */ - g_file_info_remove_attribute (info, key); + xed_metadata_manager_set (location, key, value); } } va_end (var_args); - if (doc->priv->metadata_info != NULL) - { - g_file_info_copy_into (info, doc->priv->metadata_info); - } - - location = gtk_source_file_get_location (doc->priv->file); - - if (location != NULL) + if (priv->use_gvfs_metadata && location != NULL) { g_file_set_attributes_async (location, info, @@ -1555,9 +1587,8 @@ xed_document_set_metadata (XedDocument *doc, NULL); } - g_object_unref (info); + g_clear_object (&info); } -#endif /** * xed_document_set_search_context: @@ -1570,19 +1601,23 @@ void xed_document_set_search_context (XedDocument *doc, GtkSourceSearchContext *search_context) { - g_return_if_fail (XED_IS_DOCUMENT (doc)); + XedDocumentPrivate *priv; - g_clear_object (&doc->priv->search_context); - doc->priv->search_context = search_context; + g_return_if_fail (XED_IS_DOCUMENT (doc)); - if (search_context != NULL) - { - gboolean highlight = g_settings_get_boolean (doc->priv->editor_settings, XED_SETTINGS_SEARCH_HIGHLIGHTING); + priv = xed_document_get_instance_private (doc); + + g_clear_object (&priv->search_context); + priv->search_context = search_context; + + if (search_context != NULL) + { + gboolean highlight = g_settings_get_boolean (priv->editor_settings, XED_SETTINGS_SEARCH_HIGHLIGHTING); gtk_source_search_context_set_highlight (search_context, highlight); g_object_ref (search_context); - } + } } /** @@ -1595,9 +1630,13 @@ xed_document_set_search_context (XedDocument *doc, GtkSourceSearchContext * xed_document_get_search_context (XedDocument *doc) { + XedDocumentPrivate *priv; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); - return doc->priv->search_context; + priv = xed_document_get_instance_private (doc); + + return priv->search_context; } /** @@ -1618,24 +1657,36 @@ xed_document_get_search_context (XedDocument *doc) GtkSourceFile * xed_document_get_file (XedDocument *doc) { - g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); + XedDocumentPrivate *priv; - return doc->priv->file; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); + + priv = xed_document_get_instance_private (doc); + + return priv->file; } void _xed_document_set_create (XedDocument *doc, gboolean create) { + XedDocumentPrivate *priv; + g_return_if_fail (XED_IS_DOCUMENT (doc)); - doc->priv->create = create != FALSE; + priv = xed_document_get_instance_private (doc); + + priv->create = create != FALSE; } gboolean _xed_document_get_create (XedDocument *doc) { - g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); + XedDocumentPrivate *priv; - return doc->priv->create; + g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); + + priv = xed_document_get_instance_private (doc); + + return priv->create; } diff --git a/xed/xed-document.h b/xed/xed-document.h index f8bb270..a1fbf6d 100644 --- a/xed/xed-document.h +++ b/xed/xed-document.h @@ -37,29 +37,14 @@ G_BEGIN_DECLS -#define XED_TYPE_DOCUMENT (xed_document_get_type()) -#define XED_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_DOCUMENT, XedDocument)) -#define XED_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_DOCUMENT, XedDocumentClass)) -#define XED_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_DOCUMENT)) -#define XED_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_DOCUMENT)) -#define XED_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_DOCUMENT, XedDocumentClass)) +#define XED_TYPE_DOCUMENT (xed_document_get_type()) + +G_DECLARE_DERIVABLE_TYPE (XedDocument, xed_document, XED, DOCUMENT, GtkSourceBuffer) #define XED_METADATA_ATTRIBUTE_POSITION "metadata::xed-position" #define XED_METADATA_ATTRIBUTE_ENCODING "metadata::xed-encoding" #define XED_METADATA_ATTRIBUTE_LANGUAGE "metadata::xed-language" -typedef struct _XedDocument XedDocument; -typedef struct _XedDocumentPrivate XedDocumentPrivate; -typedef struct _XedDocumentClass XedDocumentClass; - -struct _XedDocument -{ - GtkSourceBuffer buffer; - - /*< private > */ - XedDocumentPrivate *priv; -}; - struct _XedDocumentClass { GtkSourceBufferClass parent_class; @@ -77,8 +62,6 @@ struct _XedDocumentClass void (* saved) (XedDocument *document); }; -GType xed_document_get_type (void) G_GNUC_CONST; - XedDocument *xed_document_new (void); GtkSourceFile *xed_document_get_file (XedDocument *doc); @@ -138,24 +121,6 @@ void xed_document_set_search_context (XedDocument *doc, GtkSourceSearchContext *xed_document_get_search_context (XedDocument *doc); -/* Non exported functions */ - -glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc); - -void _xed_document_apply_error_style (XedDocument *doc, - GtkTextIter *start, - GtkTextIter *end); - -/* Note: this is a sync stat: use only on local files */ -gboolean _xed_document_check_externally_modified (XedDocument *doc); - -gboolean _xed_document_needs_saving (XedDocument *doc); - -void _xed_document_set_create (XedDocument *doc, - gboolean create); - -gboolean _xed_document_get_create (XedDocument *doc); - G_END_DECLS #endif /* __XED_DOCUMENT_H__ */ diff --git a/xed/xed-metadata-manager.c b/xed/xed-metadata-manager.c index 01d491e..d92ff87 100644 --- a/xed/xed-metadata-manager.c +++ b/xed/xed-metadata-manager.c @@ -21,23 +21,15 @@ * Boston, MA 02110-1301, USA. */ -/* - * Modified by the xed Team, 2003-2007. See the AUTHORS file for a - * list of people on the xed Team. - * See the ChangeLog files for a list of changes. - */ - -#include -#include #include #include "xed-metadata-manager.h" #include "xed-debug.h" /* -#define XED_METADATA_VERBOSE_DEBUG 1 +#define XED_METADATA_VERBOSE_DEBUG 1 */ -#define MAX_ITEMS 50 +#define MAX_ITEMS 50 typedef struct _XedMetadataManager XedMetadataManager; @@ -45,21 +37,21 @@ typedef struct _Item Item; struct _Item { - time_t atime; /* time of last access */ + gint64 atime; /* time of last access in seconds since January 1, 1970 UTC */ - GHashTable *values; + GHashTable *values; }; struct _XedMetadataManager { - gboolean values_loaded; /* It is true if the file - has been read */ + gboolean values_loaded; /* It is true if the file + has been read */ - guint timeout_id; + guint timeout_id; - GHashTable *items; + GHashTable *items; - gchar *metadata_filename; + gchar *metadata_filename; }; static gboolean xed_metadata_manager_save (gpointer data); @@ -70,34 +62,34 @@ static XedMetadataManager *xed_metadata_manager = NULL; static void item_free (gpointer data) { - Item *item; + Item *item; - g_return_if_fail (data != NULL); + g_return_if_fail (data != NULL); #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); #endif - item = (Item *)data; + item = (Item *)data; - if (item->values != NULL) - g_hash_table_destroy (item->values); + if (item->values != NULL) + g_hash_table_destroy (item->values); - g_free (item); + g_free (item); } static void xed_metadata_manager_arm_timeout (void) { - if (xed_metadata_manager->timeout_id == 0) - { - xed_metadata_manager->timeout_id = - g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE, - 2, - (GSourceFunc)xed_metadata_manager_save, - NULL, - NULL); - } + if (xed_metadata_manager->timeout_id == 0) + { + xed_metadata_manager->timeout_id = + g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE, + 2, + (GSourceFunc)xed_metadata_manager_save, + NULL, + NULL); + } } /** @@ -110,22 +102,22 @@ xed_metadata_manager_arm_timeout (void) void xed_metadata_manager_init (const gchar *metadata_filename) { - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); - if (xed_metadata_manager != NULL) - return; + if (xed_metadata_manager != NULL) + return; - xed_metadata_manager = g_new0 (XedMetadataManager, 1); + xed_metadata_manager = g_new0 (XedMetadataManager, 1); - xed_metadata_manager->values_loaded = FALSE; + xed_metadata_manager->values_loaded = FALSE; - xed_metadata_manager->items = - g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - item_free); + xed_metadata_manager->items = + g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + item_free); - xed_metadata_manager->metadata_filename = g_strdup (metadata_filename); + xed_metadata_manager->metadata_filename = g_strdup (metadata_filename); return; } @@ -139,154 +131,159 @@ xed_metadata_manager_init (const gchar *metadata_filename) void xed_metadata_manager_shutdown (void) { - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); - if (xed_metadata_manager == NULL) - return; + if (xed_metadata_manager == NULL) + return; - if (xed_metadata_manager->timeout_id) - { - g_source_remove (xed_metadata_manager->timeout_id); - xed_metadata_manager->timeout_id = 0; - xed_metadata_manager_save (NULL); - } + if (xed_metadata_manager->timeout_id) + { + g_source_remove (xed_metadata_manager->timeout_id); + xed_metadata_manager->timeout_id = 0; + xed_metadata_manager_save (NULL); + } - if (xed_metadata_manager->items != NULL) - g_hash_table_destroy (xed_metadata_manager->items); + if (xed_metadata_manager->items != NULL) + g_hash_table_destroy (xed_metadata_manager->items); - g_free (gedit_metadata_manager->metadata_filename); - g_free (xed_metadata_manager); - xed_metadata_manager = NULL; + g_free (xed_metadata_manager->metadata_filename); + g_free (xed_metadata_manager); + xed_metadata_manager = NULL; } static void parseItem (xmlDocPtr doc, xmlNodePtr cur) { - Item *item; + Item *item; - xmlChar *uri; - xmlChar *atime; + xmlChar *uri; + xmlChar *atime; #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); #endif - if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0) - return; + if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0) + return; - uri = xmlGetProp (cur, (const xmlChar *)"uri"); - if (uri == NULL) - return; + uri = xmlGetProp (cur, (const xmlChar *)"uri"); + if (uri == NULL) + return; - atime = xmlGetProp (cur, (const xmlChar *)"atime"); - if (atime == NULL) - { - xmlFree (uri); - return; - } + atime = xmlGetProp (cur, (const xmlChar *)"atime"); + if (atime == NULL) + { + xmlFree (uri); + return; + } - item = g_new0 (Item, 1); + item = g_new0 (Item, 1); - item->atime = g_ascii_strtoull ((char *)atime, NULL, 0); + item->atime = g_ascii_strtoll ((char *)atime, NULL, 0); - item->values = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); + item->values = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); - cur = cur->xmlChildrenNode; + cur = cur->xmlChildrenNode; - while (cur != NULL) - { - if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0) - { - xmlChar *key; - xmlChar *value; + while (cur != NULL) + { + if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0) + { + xmlChar *key; + xmlChar *value; - key = xmlGetProp (cur, (const xmlChar *)"key"); - value = xmlGetProp (cur, (const xmlChar *)"value"); + key = xmlGetProp (cur, (const xmlChar *)"key"); + value = xmlGetProp (cur, (const xmlChar *)"value"); - if ((key != NULL) && (value != NULL)) - g_hash_table_insert (item->values, - g_strdup ((gchar *)key), - g_strdup ((gchar *)value)); + if ((key != NULL) && (value != NULL)) + g_hash_table_insert (item->values, + g_strdup ((gchar *)key), + g_strdup ((gchar *)value)); - if (key != NULL) - xmlFree (key); - if (value != NULL) - xmlFree (value); - } + if (key != NULL) + xmlFree (key); + if (value != NULL) + xmlFree (value); + } - cur = cur->next; - } + cur = cur->next; + } - g_hash_table_insert (xed_metadata_manager->items, - g_strdup ((gchar *)uri), - item); + g_hash_table_insert (xed_metadata_manager->items, + g_strdup ((gchar *)uri), + item); - xmlFree (uri); - xmlFree (atime); + xmlFree (uri); + xmlFree (atime); } static gboolean load_values (void) { - xmlDocPtr doc; - xmlNodePtr cur; + xmlDocPtr doc; + xmlNodePtr cur; - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); - g_return_val_if_fail (xed_metadata_manager != NULL, FALSE); - g_return_val_if_fail (xed_metadata_manager->values_loaded == FALSE, FALSE); + g_return_val_if_fail (xed_metadata_manager != NULL, FALSE); + g_return_val_if_fail (xed_metadata_manager->values_loaded == FALSE, FALSE); - xed_metadata_manager->values_loaded = TRUE; + xed_metadata_manager->values_loaded = TRUE; - xmlKeepBlanksDefault (0); + xmlKeepBlanksDefault (0); - /* FIXME: file locking - Paolo */ - if ((xed_metadata_manager->metadata_filename == NULL) || - (!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS))) - { - return FALSE; - } + /* FIXME: file locking - Paolo */ + if (xed_metadata_manager->metadata_filename == NULL) + { + return FALSE; + } - doc = xmlParseFile (xed_metadata_manager->metadata_filename); + /* TODO: avoid races */ + if (!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS)) + { + return TRUE; + } - if (doc == NULL) - { - return FALSE; - } + doc = xmlParseFile (xed_metadata_manager->metadata_filename); - cur = xmlDocGetRootElement (doc); - if (cur == NULL) - { - g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename)); - xmlFreeDoc (doc); + if (doc == NULL) + { + return FALSE; + } - return FALSE; - } + cur = xmlDocGetRootElement (doc); + if (cur == NULL) + { + g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename)); + xmlFreeDoc (doc); - if (xmlStrcmp (cur->name, (const xmlChar *) "metadata")) - { - g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename)); - xmlFreeDoc (doc); + return TRUE; + } - return FALSE; - } + if (xmlStrcmp (cur->name, (const xmlChar *) "metadata")) + { + g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename)); + xmlFreeDoc (doc); - cur = xmlDocGetRootElement (doc); - cur = cur->xmlChildrenNode; + return FALSE; + } - while (cur != NULL) - { - parseItem (doc, cur); + cur = xmlDocGetRootElement (doc); + cur = cur->xmlChildrenNode; - cur = cur->next; - } + while (cur != NULL) + { + parseItem (doc, cur); - xmlFreeDoc (doc); + cur = cur->next; + } - return TRUE; + xmlFreeDoc (doc); + + return TRUE; } /** @@ -298,48 +295,51 @@ load_values (void) */ gchar * xed_metadata_manager_get (GFile *location, - const gchar *key) + const gchar *key) { - Item *item; - gchar *value; - gchar *uri; + Item *item; + gchar *value; + gchar *uri; - g_return_val_if_fail (G_IS_FILE (location), NULL); - g_return_val_if_fail (key != NULL, NULL); + g_return_val_if_fail (G_IS_FILE (location), NULL); + g_return_val_if_fail (key != NULL, NULL); - uri = g_file_get_uri (location); + uri = g_file_get_uri (location); - xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key ); + xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key ); - if (!xed_metadata_manager->values_loaded) - { - gboolean res; + if (!xed_metadata_manager->values_loaded) + { + gboolean res; - res = load_values (); + res = load_values (); - if (!res) - return NULL; - } + if (!res) + { + g_free (uri); + return NULL; + } + } - item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, - uri); + item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, + uri); - g_free (uri); + g_free (uri); - if (item == NULL) - return NULL; + if (item == NULL) + return NULL; - item->atime = time (NULL); + item->atime = g_get_real_time () / 1000; - if (item->values == NULL) - return NULL; + if (item->values == NULL) + return NULL; - value = g_hash_table_lookup (item->values, key); + value = g_hash_table_lookup (item->values, key); - if (value == NULL) - return NULL; - else - return g_strdup (value); + if (value == NULL) + return NULL; + else + return g_strdup (value); } /** @@ -352,219 +352,221 @@ xed_metadata_manager_get (GFile *location, */ void xed_metadata_manager_set (GFile *location, - const gchar *key, - const gchar *value) + const gchar *key, + const gchar *value) { - Item *item; - gchar *uri; + Item *item; + gchar *uri; - g_return_if_fail (G_IS_FILE (location)); - g_return_if_fail (key != NULL); + g_return_if_fail (G_IS_FILE (location)); + g_return_if_fail (key != NULL); - uri = g_file_get_uri (location); + uri = g_file_get_uri (location); - xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value); + xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value); - if (!xed_metadata_manager->values_loaded) - { - gboolean res; + if (!xed_metadata_manager->values_loaded) + { + gboolean ok; - res = load_values (); + ok = load_values (); - if (!res) - return; - } + if (!ok) + { + g_free (uri); + return; + } + } - item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, - uri); + item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, + uri); - if (item == NULL) - { - item = g_new0 (Item, 1); + if (item == NULL) + { + item = g_new0 (Item, 1); - g_hash_table_insert (xed_metadata_manager->items, - g_strdup (uri), - item); - } + g_hash_table_insert (xed_metadata_manager->items, + g_strdup (uri), + item); + } - if (item->values == NULL) - item->values = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); - if (value != NULL) - g_hash_table_insert (item->values, - g_strdup (key), - g_strdup (value)); - else - g_hash_table_remove (item->values, - key); + if (item->values == NULL) + item->values = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + if (value != NULL) + g_hash_table_insert (item->values, + g_strdup (key), + g_strdup (value)); + else + g_hash_table_remove (item->values, + key); - item->atime = time (NULL); + item->atime = g_get_real_time () / 1000; - g_free (uri); + g_free (uri); - xed_metadata_manager_arm_timeout (); + xed_metadata_manager_arm_timeout (); } static void save_values (const gchar *key, const gchar *value, xmlNodePtr parent) { - xmlNodePtr xml_node; + xmlNodePtr xml_node; #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); #endif - g_return_if_fail (key != NULL); + g_return_if_fail (key != NULL); - if (value == NULL) - return; + if (value == NULL) + return; - xml_node = xmlNewChild (parent, - NULL, - (const xmlChar *)"entry", - NULL); + xml_node = xmlNewChild (parent, + NULL, + (const xmlChar *)"entry", + NULL); - xmlSetProp (xml_node, - (const xmlChar *)"key", - (const xmlChar *)key); - xmlSetProp (xml_node, - (const xmlChar *)"value", - (const xmlChar *)value); + xmlSetProp (xml_node, + (const xmlChar *)"key", + (const xmlChar *)key); + xmlSetProp (xml_node, + (const xmlChar *)"value", + (const xmlChar *)value); #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value); + xed_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value); #endif } static void save_item (const gchar *key, const gpointer *data, xmlNodePtr parent) { - xmlNodePtr xml_node; - const Item *item = (const Item *)data; - gchar *atime; + xmlNodePtr xml_node; + const Item *item = (const Item *)data; + gchar *atime; #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); #endif - g_return_if_fail (key != NULL); + g_return_if_fail (key != NULL); - if (item == NULL) - return; + if (item == NULL) + return; - xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL); + xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL); - xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key); + xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key); #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug_message (DEBUG_METADATA, "uri: %s", key); + xed_debug_message (DEBUG_METADATA, "uri: %s", key); #endif - atime = g_strdup_printf ("%ld", item->atime); - xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime); + atime = g_strdup_printf ("%" G_GINT64_FORMAT, item->atime); + xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime); #ifdef XED_METADATA_VERBOSE_DEBUG - xed_debug_message (DEBUG_METADATA, "atime: %s", atime); + xed_debug_message (DEBUG_METADATA, "atime: %s", atime); #endif - g_free (atime); + g_free (atime); - g_hash_table_foreach (item->values, - (GHFunc)save_values, - xml_node); + g_hash_table_foreach (item->values, + (GHFunc)save_values, + xml_node); } static void get_oldest (const gchar *key, const gpointer value, const gchar ** key_to_remove) { - const Item *item = (const Item *)value; + const Item *item = (const Item *)value; - if (*key_to_remove == NULL) - { - *key_to_remove = key; - } - else - { - const Item *item_to_remove = - g_hash_table_lookup (xed_metadata_manager->items, - *key_to_remove); + if (*key_to_remove == NULL) + { + *key_to_remove = key; + } + else + { + const Item *item_to_remove = + g_hash_table_lookup (xed_metadata_manager->items, + *key_to_remove); - g_return_if_fail (item_to_remove != NULL); + g_return_if_fail (item_to_remove != NULL); - if (item->atime < item_to_remove->atime) - { - *key_to_remove = key; - } - } + if (item->atime < item_to_remove->atime) + { + *key_to_remove = key; + } + } } static void resize_items (void) { - while (g_hash_table_size (xed_metadata_manager->items) > MAX_ITEMS) - { - gpointer key_to_remove = NULL; + while (g_hash_table_size (xed_metadata_manager->items) > MAX_ITEMS) + { + gpointer key_to_remove = NULL; - g_hash_table_foreach (xed_metadata_manager->items, - (GHFunc)get_oldest, - &key_to_remove); + g_hash_table_foreach (xed_metadata_manager->items, + (GHFunc)get_oldest, + &key_to_remove); - g_return_if_fail (key_to_remove != NULL); + g_return_if_fail (key_to_remove != NULL); - g_hash_table_remove (xed_metadata_manager->items, - key_to_remove); - } + g_hash_table_remove (xed_metadata_manager->items, + key_to_remove); + } } static gboolean xed_metadata_manager_save (gpointer data) { - xmlDocPtr doc; - xmlNodePtr root; + xmlDocPtr doc; + xmlNodePtr root; - xed_debug (DEBUG_METADATA); + xed_debug (DEBUG_METADATA); - xed_metadata_manager->timeout_id = 0; + xed_metadata_manager->timeout_id = 0; - resize_items (); + resize_items (); - xmlIndentTreeOutput = TRUE; + xmlIndentTreeOutput = TRUE; - doc = xmlNewDoc ((const xmlChar *)"1.0"); - if (doc == NULL) - return TRUE; + doc = xmlNewDoc ((const xmlChar *)"1.0"); + if (doc == NULL) + return TRUE; - /* Create metadata root */ - root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL); - xmlDocSetRootElement (doc, root); + /* Create metadata root */ + root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL); + xmlDocSetRootElement (doc, root); - g_hash_table_foreach (xed_metadata_manager->items, - (GHFunc)save_item, - root); + g_hash_table_foreach (xed_metadata_manager->items, + (GHFunc)save_item, + root); - /* FIXME: lock file - Paolo */ - if (xed_metadata_manager->metadata_filename != NULL) - { - gchar *cache_dir; - int res; + /* FIXME: lock file - Paolo */ + if (xed_metadata_manager->metadata_filename != NULL) + { + gchar *cache_dir; + int res; - /* make sure the cache dir exists */ - cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename); - res = g_mkdir_with_parents (cache_dir, 0755); - if (res != -1) - { - xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1); - } + /* make sure the cache dir exists */ + cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename); + res = g_mkdir_with_parents (cache_dir, 0755); + if (res != -1) + { + xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1); + } - g_free (cache_dir); - } + g_free (cache_dir); + } - xmlFreeDoc (doc); + xmlFreeDoc (doc); - xed_debug_message (DEBUG_METADATA, "DONE"); + xed_debug_message (DEBUG_METADATA, "DONE"); - return FALSE; + return FALSE; } - diff --git a/xed/xed-metadata-manager.h b/xed/xed-metadata-manager.h index dd682f7..c794a2a 100644 --- a/xed/xed-metadata-manager.h +++ b/xed/xed-metadata-manager.h @@ -30,7 +30,7 @@ #ifndef __XED_METADATA_MANAGER_H__ #define __XED_METADATA_MANAGER_H__ -#include +#include G_BEGIN_DECLS diff --git a/xed/xed-tab.c b/xed/xed-tab.c index 5c89645..7dc4986 100644 --- a/xed/xed-tab.c +++ b/xed/xed-tab.c @@ -43,6 +43,8 @@ #include "xed-print-preview.h" #include "xed-progress-info-bar.h" #include "xed-debug.h" +#include "xed-document.h" +#include "xed-document-private.h" #include "xed-enum-types.h" #include "xed-settings.h" #include "xed-view-frame.h" @@ -1112,39 +1114,39 @@ view_focused_in (GtkWidget *widget, XedTab *tab) { XedDocument *doc; + GtkSourceFile *file; g_return_val_if_fail (XED_IS_TAB (tab), FALSE); /* we try to detect file changes only in the normal state */ if (tab->priv->state != XED_TAB_STATE_NORMAL) { - return FALSE; + return GDK_EVENT_PROPAGATE; } /* we already asked, don't bug the user again */ if (!tab->priv->ask_if_externally_modified) { - return FALSE; + return GDK_EVENT_PROPAGATE; } doc = xed_tab_get_document (tab); + file = xed_document_get_file (doc); /* If file was never saved or is remote we do not check */ - if (!xed_document_is_local (doc)) + if (gtk_source_file_is_local (file)) { - return FALSE; + gtk_source_file_check_file_on_disk (file); + + if (gtk_source_file_is_externally_modified (file)) + { + xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION); + + display_externally_modified_notification (tab); + } } - if (_xed_document_check_externally_modified (doc)) - { - xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION); - - display_externally_modified_notification (tab); - - return FALSE; - } - - return FALSE; + return GDK_EVENT_PROPAGATE; } static void diff --git a/xed/xed-window.c b/xed/xed-window.c index 9d8e369..7227c1a 100644 --- a/xed/xed-window.c +++ b/xed/xed-window.c @@ -20,6 +20,8 @@ #include "xed-utils.h" #include "xed-commands.h" #include "xed-debug.h" +#include "xed-document.h" +#include "xed-document-private.h" #include "xed-panel.h" #include "xed-documents-panel.h" #include "xed-plugins-engine.h"