Pull upstream fixes for gtk and gtksourceview changes

* fix errors in xed-metadata-manager
* upstream changes for file loading and saving
* modernize some code in xed-document

Closes https://github.com/linuxmint/xed/issues/146
This commit is contained in:
JosephMcc 2017-12-04 00:00:51 -08:00
parent 4c813f2c7f
commit ef9294aae2
12 changed files with 1200 additions and 1009 deletions

View File

@ -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
])

View File

@ -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)) > $@

View File

@ -32,10 +32,13 @@
#include <config.h>
#endif
#include "xed-close-confirmation-dialog.h"
#include <glib/gi18n.h>
#include "xed-close-confirmation-dialog.h"
#include <xed/xed-app.h>
#include <xed/xed-document.h>
#include <xed/xed-document-private.h>
#include <xed/xed-utils.h>
#include <xed/xed-window.h>

View File

@ -38,31 +38,27 @@
#include <gio/gio.h>
#include <gtk/gtk.h>
#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);
}
}

View File

@ -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);
/*

View File

@ -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__ */

File diff suppressed because it is too large Load Diff

View File

@ -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__ */

View File

@ -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 <time.h>
#include <stdlib.h>
#include <libxml/xmlreader.h>
#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;
}

View File

@ -30,7 +30,7 @@
#ifndef __XED_METADATA_MANAGER_H__
#define __XED_METADATA_MANAGER_H__
#include <glib.h>
#include <gio/gio.h>
G_BEGIN_DECLS

View File

@ -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

View File

@ -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"