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 $GMODULE_ADD
gthread-2.0 >= 2.13.0 gthread-2.0 >= 2.13.0
gio-2.0 >= 2.40.0 gio-2.0 >= 2.40.0
gtk+-3.0 >= 3.18.0 gtk+-3.0 >= 3.19.3
gtksourceview-3.0 >= 3.18.0 gtksourceview-3.0 >= 3.19.0
libpeas-1.0 >= 1.12.0 libpeas-1.0 >= 1.12.0
libpeas-gtk-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-button.h \
xed-close-confirmation-dialog.h \ xed-close-confirmation-dialog.h \
xed-dirs.h \ xed-dirs.h \
xed-document-private.h \
xed-documents-panel.h \ xed-documents-panel.h \
xed-encodings-dialog.h \ xed-encodings-dialog.h \
xed-history-entry.h \ xed-history-entry.h \
xed-io-error-info-bar.h \ xed-io-error-info-bar.h \
xed-metadata-manager.h \
xed-paned.h \ xed-paned.h \
xed-plugins-engine.h \ xed-plugins-engine.h \
xed-preferences-dialog.h \ xed-preferences-dialog.h \
@ -80,10 +82,6 @@ INST_H_FILES = \
xed-window.h \ xed-window.h \
xed-window-activatable.h xed-window-activatable.h
if !ENABLE_GVFS_METADATA
NOINST_H_FILES += xed-metadata-manager.h
endif
headerdir = $(prefix)/include/xed headerdir = $(prefix)/include/xed
header_DATA = \ header_DATA = \
@ -119,6 +117,7 @@ libxed_c_files = \
xed-message-bus.c \ xed-message-bus.c \
xed-message-type.c \ xed-message-type.c \
xed-message.c \ xed-message.c \
xed-metadata-manager.c \
xed-notebook.c \ xed-notebook.c \
xed-paned.c \ xed-paned.c \
xed-panel.c \ xed-panel.c \
@ -146,10 +145,6 @@ libxed_la_SOURCES = \
$(NOINST_H_FILES) \ $(NOINST_H_FILES) \
$(INST_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) 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)) > $@ $(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> #include <config.h>
#endif #endif
#include "xed-close-confirmation-dialog.h"
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include "xed-close-confirmation-dialog.h"
#include <xed/xed-app.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-utils.h>
#include <xed/xed-window.h> #include <xed/xed-window.h>

View File

@ -38,31 +38,27 @@
#include <gio/gio.h> #include <gio/gio.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "xed-debug.h"
#include "xed-document.h"
#include "xed-document-private.h"
#include "xed-commands.h" #include "xed-commands.h"
#include "xed-window.h" #include "xed-window.h"
#include "xed-window-private.h" #include "xed-window-private.h"
#include "xed-statusbar.h" #include "xed-statusbar.h"
#include "xed-debug.h"
#include "xed-utils.h" #include "xed-utils.h"
#include "xed-file-chooser-dialog.h" #include "xed-file-chooser-dialog.h"
#include "xed-close-confirmation-dialog.h" #include "xed-close-confirmation-dialog.h"
/* Defined constants */ /* Defined constants */
#define XED_OPEN_DIALOG_KEY "xed-open-dialog-key" #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_CLOSING_ALL "xed-is-closing-all"
#define XED_IS_QUITTING "xed-is-quitting" #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" #define XED_IS_QUITTING_ALL "xed-is-quitting-all"
static void tab_state_changed_while_saving (XedTab *tab, static void tab_state_changed_while_saving (XedTab *tab,
GParamSpec *pspec, GParamSpec *pspec,
XedWindow *window); XedWindow *window);
static void save_as_tab (XedTab *tab,
XedWindow *window);
void void
_xed_cmd_file_new (GtkAction *action, _xed_cmd_file_new (GtkAction *action,
XedWindow *window) XedWindow *window)
@ -521,43 +517,44 @@ replace_read_only_file (GtkWindow *parent,
} }
static void static void
save_finish_cb (XedTab *tab, tab_save_as_ready_cb (XedTab *tab,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) 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 static void
save_dialog_response_cb (XedFileChooserDialog *dialog, save_dialog_response_cb (XedFileChooserDialog *dialog,
gint response_id, gint response_id,
XedWindow *window) GTask *task)
{ {
XedTab *tab; XedTab *tab;
gpointer data; XedWindow *window;
GSList *tabs_to_save_as; XedDocument *doc;
GtkSourceFile *file;
GFile *location;
gchar *parse_name;
GtkSourceNewlineType newline_type;
const GtkSourceEncoding *encoding;
xed_debug (DEBUG_COMMANDS); 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) if (response_id != GTK_RESPONSE_OK)
{ {
gtk_widget_destroy (GTK_WIDGET (dialog)); gtk_widget_destroy (GTK_WIDGET (dialog));
goto save_next_tab; g_task_return_boolean (task, FALSE);
g_object_unref (task);
return;
} }
if (tab != NULL)
{
GFile *location;
XedDocument *doc;
gchar *parse_name;
GtkSourceNewlineType newline_type;
const GtkSourceEncoding *encoding;
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
g_return_if_fail (location != NULL); g_return_if_fail (location != NULL);
@ -566,9 +563,6 @@ save_dialog_response_cb (XedFileChooserDialog *dialog,
gtk_widget_destroy (GTK_WIDGET (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); parse_name = g_file_get_parse_name (location);
xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar), xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar),
@ -578,55 +572,20 @@ save_dialog_response_cb (XedFileChooserDialog *dialog,
g_free (parse_name); g_free (parse_name);
/* let's remember the dir we navigated too, /* let's remember the dir we navigated too, even if the saving fails... */
* even if the saving fails... */
_xed_window_set_default_location (window, location); _xed_window_set_default_location (window, location);
_xed_tab_save_as_async (tab, _xed_tab_save_as_async (tab,
location, location,
encoding, encoding,
newline_type, newline_type,
NULL, g_task_get_cancellable (task),
(GAsyncReadyCallback) save_finish_cb, (GAsyncReadyCallback) tab_save_as_ready_cb,
NULL); task);
g_object_unref (location); 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)
{
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));
/* Remove the first item of the list */
tabs_to_save_as = g_slist_delete_link (tabs_to_save_as, tabs_to_save_as);
g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as);
if (tabs_to_save_as != NULL)
{
tab = XED_TAB (tabs_to_save_as->data);
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);
/* 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 GtkFileChooserConfirmation static GtkFileChooserConfirmation
confirm_overwrite_callback (GtkFileChooser *dialog, confirm_overwrite_callback (GtkFileChooser *dialog,
gpointer data) gpointer data)
@ -663,16 +622,20 @@ confirm_overwrite_callback (GtkFileChooser *dialog,
return res; return res;
} }
/* Call save_as_tab_finish() in @callback. */
static void static void
save_as_tab (XedTab *tab, save_as_tab_async (XedTab *tab,
XedWindow *window) XedWindow *window,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{ {
GTask *task;
GtkWidget *save_dialog; GtkWidget *save_dialog;
GtkWindowGroup *wg; GtkWindowGroup *wg;
XedDocument *doc; XedDocument *doc;
GtkSourceFile *file; GtkSourceFile *file;
GFile *location; GFile *location;
gboolean uri_set = FALSE;
const GtkSourceEncoding *encoding; const GtkSourceEncoding *encoding;
GtkSourceNewlineType newline_type; GtkSourceNewlineType newline_type;
@ -681,6 +644,9 @@ save_as_tab (XedTab *tab,
xed_debug (DEBUG_COMMANDS); 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"), save_dialog = xed_file_chooser_dialog_new (_("Save As\342\200\246"),
GTK_WINDOW (window), GTK_WINDOW (window),
GTK_FILE_CHOOSER_ACTION_SAVE, GTK_FILE_CHOOSER_ACTION_SAVE,
@ -706,11 +672,11 @@ save_as_tab (XedTab *tab,
if (location != NULL) 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; GFile *default_path;
gchar *docname; gchar *docname;
@ -734,7 +700,7 @@ save_as_tab (XedTab *tab,
g_free (docname); g_free (docname);
} }
/* Set suggested encoding */ /* Set suggested encoding and newline type */
encoding = gtk_source_file_get_encoding (file); encoding = gtk_source_file_get_encoding (file);
if (encoding == NULL) 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); 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), task);
g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), window);
gtk_widget_show (save_dialog); gtk_widget_show (save_dialog);
} }
static void static gboolean
save_tab (XedTab *tab, save_as_tab_finish (XedTab *tab,
XedWindow *window) 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; gchar *uri_for_display;
xed_debug (DEBUG_COMMANDS); 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 (XED_IS_WINDOW (window));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
doc = xed_tab_get_document (tab); task = g_task_new (document, cancellable, callback, user_data);
g_return_if_fail (XED_IS_DOCUMENT (doc));
if (xed_document_is_untitled (doc) || tab = xed_tab_get_from_document (document);
xed_document_get_readonly (doc))
if (xed_document_is_untitled (document) ||
xed_document_get_readonly (document))
{ {
xed_debug_message (DEBUG_COMMANDS, "Untitled or Readonly"); 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; 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), xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar),
window->priv->generic_message_cid, window->priv->generic_message_cid,
_("Saving file '%s'\342\200\246"), _("Saving file '%s'\342\200\246"),
@ -789,8 +810,52 @@ save_tab (XedTab *tab,
g_free (uri_for_display); g_free (uri_for_display);
_xed_tab_save_async (tab, _xed_tab_save_async (tab,
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, NULL,
(GAsyncReadyCallback) save_finish_cb, (GAsyncReadyCallback) save_tab_ready_cb,
NULL); NULL);
} }
@ -803,12 +868,18 @@ _xed_cmd_file_save (GtkAction *action,
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
tab = xed_window_get_active_tab (window); 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 void
@ -820,12 +891,149 @@ _xed_cmd_file_save_as (GtkAction *action,
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
tab = xed_window_get_active_tab (window); 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; 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, save_documents_list (XedWindow *window,
GList *docs) GList *docs)
{ {
SaveAsData *data = NULL;
GList *l; GList *l;
GSList *tabs_to_save_as = NULL;
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
@ -869,7 +1077,15 @@ save_documents_list (XedWindow *window,
{ {
if (_xed_document_needs_saving (doc)) if (_xed_document_needs_saving (doc))
{ {
tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t); if (data == NULL)
{
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 else
@ -913,23 +1129,21 @@ save_documents_list (XedWindow *window,
l = g_list_next (l); l = g_list_next (l);
} }
if (tabs_to_save_as != NULL) if (data != NULL)
{ {
XedTab *tab; data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
save_as_documents_list (data);
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);
} }
} }
/**
* 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 void
xed_commands_save_all_documents (XedWindow *window) 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_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 void
xed_commands_save_document (XedWindow *window, xed_commands_save_document (XedWindow *window,
XedDocument *document) XedDocument *document)
@ -1161,39 +1383,6 @@ _xed_cmd_file_revert (GtkAction *action,
gtk_widget_show (dialog); 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 static void
tab_state_changed_while_saving (XedTab *tab, tab_state_changed_while_saving (XedTab *tab,
GParamSpec *pspec, GParamSpec *pspec,
@ -1209,26 +1398,9 @@ tab_state_changed_while_saving (XedTab *tab,
finished */ finished */
if (ts == XED_TAB_STATE_NORMAL) if (ts == XED_TAB_STATE_NORMAL)
{ {
XedDocument *doc;
g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (tab_state_changed_while_saving), window); g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (tab_state_changed_while_saving), window);
doc = xed_tab_get_document (tab); close_tab (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);
} }
} }
@ -1244,21 +1416,6 @@ save_and_close (XedTab *tab,
save_tab (tab, window); 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 static void
save_and_close_all_documents (const GList *docs, save_and_close_all_documents (const GList *docs,
XedWindow *window) XedWindow *window)
@ -1266,9 +1423,9 @@ save_and_close_all_documents (const GList *docs,
GList *tabs; GList *tabs;
GList *l; GList *l;
GSList *sl; GSList *sl;
GSList *tabs_to_save_as; SaveAsData *data = NULL;
GSList *tabs_to_save_and_close; GSList *tabs_to_save_and_close = NULL;
GList *tabs_to_close; GList *tabs_to_close = NULL;
xed_debug (DEBUG_COMMANDS); 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 = 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; l = tabs;
while (l != NULL) while (l != NULL)
{ {
XedTab *t; XedTab *t = XED_TAB (l->data);;
XedTabState state; XedTabState state;
XedDocument *doc; XedDocument *doc;
t = XED_TAB (l->data);
state = xed_tab_get_state (t); state = xed_tab_get_state (t);
doc = xed_tab_get_document (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) */ user is running xed - Paolo (Dec. 8, 2005) */
if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc)) 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 else
{ {
@ -1371,20 +1528,11 @@ save_and_close_all_documents (const GList *docs,
} }
g_slist_free (tabs_to_save_and_close); g_slist_free (tabs_to_save_and_close);
/* Save As and close all the files in tabs_to_save_as */ /* Save As and close all the files in data->tabs_to_save_as. */
if (tabs_to_save_as != NULL) if (data != NULL)
{ {
XedTab *tab; data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
save_as_documents_list (data);
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);
} }
} }

View File

@ -12,6 +12,8 @@ void xed_commands_load_location (XedWindow *window, GFile *location, const GtkSo
/* Ignore non-existing URIs */ /* Ignore non-existing URIs */
GSList *xed_commands_load_locations (XedWindow *window, const GSList *locations, const GtkSourceEncoding *encoding, gint line_pos); 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 (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); 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

@ -38,28 +38,13 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define XED_TYPE_DOCUMENT (xed_document_get_type()) #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)) G_DECLARE_DERIVABLE_TYPE (XedDocument, xed_document, XED, DOCUMENT, GtkSourceBuffer)
#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_METADATA_ATTRIBUTE_POSITION "metadata::xed-position" #define XED_METADATA_ATTRIBUTE_POSITION "metadata::xed-position"
#define XED_METADATA_ATTRIBUTE_ENCODING "metadata::xed-encoding" #define XED_METADATA_ATTRIBUTE_ENCODING "metadata::xed-encoding"
#define XED_METADATA_ATTRIBUTE_LANGUAGE "metadata::xed-language" #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 struct _XedDocumentClass
{ {
GtkSourceBufferClass parent_class; GtkSourceBufferClass parent_class;
@ -77,8 +62,6 @@ struct _XedDocumentClass
void (* saved) (XedDocument *document); void (* saved) (XedDocument *document);
}; };
GType xed_document_get_type (void) G_GNUC_CONST;
XedDocument *xed_document_new (void); XedDocument *xed_document_new (void);
GtkSourceFile *xed_document_get_file (XedDocument *doc); 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); 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 G_END_DECLS
#endif /* __XED_DOCUMENT_H__ */ #endif /* __XED_DOCUMENT_H__ */

View File

@ -21,14 +21,6 @@
* Boston, MA 02110-1301, USA. * 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 <libxml/xmlreader.h>
#include "xed-metadata-manager.h" #include "xed-metadata-manager.h"
#include "xed-debug.h" #include "xed-debug.h"
@ -45,7 +37,7 @@ typedef struct _Item Item;
struct _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;
}; };
@ -154,7 +146,7 @@ xed_metadata_manager_shutdown (void)
if (xed_metadata_manager->items != NULL) if (xed_metadata_manager->items != NULL)
g_hash_table_destroy (xed_metadata_manager->items); g_hash_table_destroy (xed_metadata_manager->items);
g_free (gedit_metadata_manager->metadata_filename); g_free (xed_metadata_manager->metadata_filename);
g_free (xed_metadata_manager); g_free (xed_metadata_manager);
xed_metadata_manager = NULL; xed_metadata_manager = NULL;
} }
@ -187,7 +179,7 @@ parseItem (xmlDocPtr doc, xmlNodePtr cur)
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, item->values = g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
@ -244,12 +236,17 @@ load_values (void)
xmlKeepBlanksDefault (0); xmlKeepBlanksDefault (0);
/* FIXME: file locking - Paolo */ /* FIXME: file locking - Paolo */
if ((xed_metadata_manager->metadata_filename == NULL) || if (xed_metadata_manager->metadata_filename == NULL)
(!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS)))
{ {
return FALSE; return FALSE;
} }
/* TODO: avoid races */
if (!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS))
{
return TRUE;
}
doc = xmlParseFile (xed_metadata_manager->metadata_filename); doc = xmlParseFile (xed_metadata_manager->metadata_filename);
if (doc == NULL) if (doc == NULL)
@ -263,7 +260,7 @@ load_values (void)
g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename)); g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename));
xmlFreeDoc (doc); xmlFreeDoc (doc);
return FALSE; return TRUE;
} }
if (xmlStrcmp (cur->name, (const xmlChar *) "metadata")) if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
@ -318,8 +315,11 @@ xed_metadata_manager_get (GFile *location,
res = load_values (); res = load_values ();
if (!res) if (!res)
{
g_free (uri);
return NULL; return NULL;
} }
}
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
uri); uri);
@ -329,7 +329,7 @@ xed_metadata_manager_get (GFile *location,
if (item == NULL) if (item == NULL)
return NULL; return NULL;
item->atime = time (NULL); item->atime = g_get_real_time () / 1000;
if (item->values == NULL) if (item->values == NULL)
return NULL; return NULL;
@ -367,13 +367,16 @@ xed_metadata_manager_set (GFile *location,
if (!xed_metadata_manager->values_loaded) if (!xed_metadata_manager->values_loaded)
{ {
gboolean res; gboolean ok;
res = load_values (); ok = load_values ();
if (!res) if (!ok)
{
g_free (uri);
return; return;
} }
}
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
uri); uri);
@ -400,7 +403,7 @@ xed_metadata_manager_set (GFile *location,
g_hash_table_remove (item->values, g_hash_table_remove (item->values,
key); key);
item->atime = time (NULL); item->atime = g_get_real_time () / 1000;
g_free (uri); g_free (uri);
@ -462,7 +465,7 @@ save_item (const gchar *key, const gpointer *data, xmlNodePtr parent)
xed_debug_message (DEBUG_METADATA, "uri: %s", key); xed_debug_message (DEBUG_METADATA, "uri: %s", key);
#endif #endif
atime = g_strdup_printf ("%ld", item->atime); atime = g_strdup_printf ("%" G_GINT64_FORMAT, item->atime);
xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime); xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
#ifdef XED_METADATA_VERBOSE_DEBUG #ifdef XED_METADATA_VERBOSE_DEBUG
@ -567,4 +570,3 @@ xed_metadata_manager_save (gpointer data)
return FALSE; return FALSE;
} }

View File

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

View File

@ -43,6 +43,8 @@
#include "xed-print-preview.h" #include "xed-print-preview.h"
#include "xed-progress-info-bar.h" #include "xed-progress-info-bar.h"
#include "xed-debug.h" #include "xed-debug.h"
#include "xed-document.h"
#include "xed-document-private.h"
#include "xed-enum-types.h" #include "xed-enum-types.h"
#include "xed-settings.h" #include "xed-settings.h"
#include "xed-view-frame.h" #include "xed-view-frame.h"
@ -1112,39 +1114,39 @@ view_focused_in (GtkWidget *widget,
XedTab *tab) XedTab *tab)
{ {
XedDocument *doc; XedDocument *doc;
GtkSourceFile *file;
g_return_val_if_fail (XED_IS_TAB (tab), FALSE); g_return_val_if_fail (XED_IS_TAB (tab), FALSE);
/* we try to detect file changes only in the normal state */ /* we try to detect file changes only in the normal state */
if (tab->priv->state != XED_TAB_STATE_NORMAL) if (tab->priv->state != XED_TAB_STATE_NORMAL)
{ {
return FALSE; return GDK_EVENT_PROPAGATE;
} }
/* we already asked, don't bug the user again */ /* we already asked, don't bug the user again */
if (!tab->priv->ask_if_externally_modified) if (!tab->priv->ask_if_externally_modified)
{ {
return FALSE; return GDK_EVENT_PROPAGATE;
} }
doc = xed_tab_get_document (tab); 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 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 (_xed_document_check_externally_modified (doc)) if (gtk_source_file_is_externally_modified (file))
{ {
xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION); xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
display_externally_modified_notification (tab); display_externally_modified_notification (tab);
}
return FALSE;
} }
return FALSE; return GDK_EVENT_PROPAGATE;
} }
static void static void

View File

@ -20,6 +20,8 @@
#include "xed-utils.h" #include "xed-utils.h"
#include "xed-commands.h" #include "xed-commands.h"
#include "xed-debug.h" #include "xed-debug.h"
#include "xed-document.h"
#include "xed-document-private.h"
#include "xed-panel.h" #include "xed-panel.h"
#include "xed-documents-panel.h" #include "xed-documents-panel.h"
#include "xed-plugins-engine.h" #include "xed-plugins-engine.h"